def test_function_type_with_invalidation(): foo_instances = [] @lazy class foo(): def __init__(self): self.i = 0 foo_instances.append(self) def watch(self, callback): self.callback = callback def __call__(self): self.i += 1 return self.i with lazy_invalidation(): assert len(foo_instances) == 1 assert foo_instances[0].i == 0 assert not hasattr(foo_instances[0], 'callback') assert foo() == 1 assert foo_instances[0].i == 1 assert hasattr(foo_instances[0], 'callback') assert foo() == 1 foo_instances[0].callback() assert foo_instances[0].i == 1 assert foo() == 2 assert foo_instances[0].i == 2 assert foo() == 2 assert foo_instances[0].i == 2 assert len(foo_instances) == 1
def test_dependency_still_watched_when_no_explicit_references_remain(): listener = DummyListener() @lazy(listener = listener) def foo(): return 5 @lazy def bar(): return foo() with lazy_invalidation(): foo_ref = weakref.ref(foo) assert listener.retain_calls == 0 assert listener.release_calls == 0 assert bar() == 5 foo = lambda : 6 assert listener.retain_calls == 1 assert listener.release_calls == 0 assert bar() == 5 listener.callback() assert listener.retain_calls == 1 assert listener.release_calls == 1 assert bar() == 6
def test_lazy_values_can_be_garbage_collected_with_invalidation(): @lazy def foo(): return 5 with lazy_invalidation(): foo_ref = weakref.ref(foo) assert foo() == 5 foo = None assert foo_ref() is None
def test_unwatch_called_after_garbage_collection(): listener = DummyListener() @lazy(listener = listener) def foo(): return 5 with lazy_invalidation(): foo_ref = weakref.ref(foo) assert listener.retain_calls == 0 assert listener.release_calls == 0 assert foo() == 5 assert listener.retain_calls == 1 assert listener.release_calls == 0 assert foo_ref() is not None foo = None assert listener.retain_calls == 1 assert listener.release_calls == 1 assert foo_ref() is None listener.callback()
def test_watchable_property(): values = count() watched = {} class Bar(property): def __init__(self): property.__init__(self, fget = self.getter) def getter(self, obj): if obj is None: return self return values.next() def watch(self, obj, storage, callback): watched[obj] = callback storage.obj = obj def unwatch(self, storage): del watched[storage.obj] class Foo(object): BAR = lazy(Bar()) with lazy_invalidation(): assert hasattr(Foo.BAR, '__get__') foo = Foo() assert not watched assert foo.BAR == 0 assert watched callback = watched.itervalues().next() assert foo.BAR == 0 callback() assert foo.BAR == 1 assert foo.BAR == 1 callback() assert foo.BAR == 2 assert foo.BAR == 2 assert watched assert not watched