Chromium Code Reviews| Index: infra/libs/decorators/decorators.py |
| diff --git a/infra/libs/decorators/decorators.py b/infra/libs/decorators/decorators.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f3b48f03a8aef4cd3c7195cd4c7dcf10f8604a8e |
| --- /dev/null |
| +++ b/infra/libs/decorators/decorators.py |
| @@ -0,0 +1,56 @@ |
| +# Copyright 2014 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +import functools |
| + |
| + |
| +class cached_property(object): |
| + """Like @property, except that the result of get is cached on |
| + self.{'_' + fn.__name__}. |
| + |
| + NOTE: This implementation is not threadsafe. |
| + |
| + >>> class Test(object): |
|
agable
2014/07/25 21:03:38
Too bad we're not actually testing these interpret
iannucci
2014/07/26 00:18:42
yeah
|
| + ... @cached_property |
| + ... def foo(self): |
| + ... print "hello" |
| + ... return 10 |
| + ... |
| + >>> t = Test() |
| + >>> t.foo |
| + hello |
| + 10 |
| + >>> t.foo |
| + 10 |
| + >>> t.foo = 20 |
| + >>> t.foo |
| + 20 |
| + >>> del t.foo |
| + >>> t.foo |
| + hello |
| + 10 |
| + >>> |
| + """ |
| + def __init__(self, fn): |
| + self.func = fn |
| + self._iname = "_" + fn.__name__ |
| + functools.update_wrapper(self, fn) |
| + |
| + def __get__(self, inst, cls=None): |
|
agable
2014/07/25 21:03:38
pylint unusued argument cls
iannucci
2014/07/26 00:18:42
It's part of the function signature so pylint does
|
| + if inst is None: |
| + return self |
| + if not hasattr(inst, self._iname): |
| + val = self.func(inst) |
| + # Some methods call out to another layer to calculate the value. This |
| + # higher layer will assign directly to the property, so we have to do |
| + # the extra hasattr here to determine if the value has been set as a side |
| + # effect of func() |
| + if not hasattr(inst, self._iname): |
| + setattr(inst, self._iname, val) |
| + return getattr(inst, self._iname) |
| + |
| + def __delete__(self, inst): |
| + assert inst is not None |
| + if hasattr(inst, self._iname): |
| + delattr(inst, self._iname) |