From c33844e98dab1759960f27dad1dfa4b3c3fead25 Mon Sep 17 00:00:00 2001 From: hut Date: Sun, 16 Jul 2017 06:28:25 +0200 Subject: ext.lazy_property: don't redefine resetter function Without this change, binding a signal to a resetter function with a weak reference would delete the signal after it's called, because the function would be disconnected from the object and market for garbage collection. Also adapted the test cases to check for this problem. For example, commit 22ffd78ef654cd7ae4357a908408ac19 binds vcs__reset() to the signal "setopt.vcs_aware" with a weak ref. Because of that, the signal is only triggered the first time the setting is changed. --- ranger/ext/lazy_property.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/ranger/ext/lazy_property.py b/ranger/ext/lazy_property.py index ccd1586e..bb54bd5e 100644 --- a/ranger/ext/lazy_property.py +++ b/ranger/ext/lazy_property.py @@ -9,32 +9,30 @@ class lazy_property(object): # pylint: disable=invalid-name,too-few-public-meth """A @property-like decorator with lazy evaluation >>> class Foo: + ... counter = 0 ... @lazy_property ... def answer(self): - ... print("calculating answer...") - ... return 2*3*7 + ... Foo.counter += 1 + ... return Foo.counter >>> foo = Foo() >>> foo.answer - calculating answer... - 42 + 1 >>> foo.answer - 42 + 1 >>> foo.answer__reset() >>> foo.answer - calculating answer... - 42 + 2 >>> foo.answer - 42 + 2 Avoid interaction between multiple objects: >>> bar = Foo() >>> bar.answer - calculating answer... - 42 + 3 >>> foo.answer__reset() >>> bar.answer - 42 + 3 """ def __init__(self, method): @@ -46,11 +44,14 @@ class lazy_property(object): # pylint: disable=invalid-name,too-few-public-meth if obj is None: # to fix issues with pydoc return None - def reset_function(): - setattr(obj, self.__name__, self) - del obj.__dict__[self.__name__] # force "__get__" being called + reset_function_name = self.__name__ + "__reset" + + if not hasattr(obj, reset_function_name): + def reset_function(): + setattr(obj, self.__name__, self) + del obj.__dict__[self.__name__] # force "__get__" being called + obj.__dict__[reset_function_name] = reset_function - obj.__dict__[self.__name__ + "__reset"] = reset_function result = self._method(obj) obj.__dict__[self.__name__] = result return result -- cgit 1.4.1-2-gfad0