diff --git a/alkali/__init__.py b/alkali/__init__.py index 29d7764..affd80a 100644 --- a/alkali/__init__.py +++ b/alkali/__init__.py @@ -13,46 +13,3 @@ from .query import Query from .utils import tznow, tzadd, fromts from . import fields - -class reify(object): - """ Use as a class method decorator. It operates almost exactly like the - Python ``@property`` decorator, but it puts the result of the method it - decorates into the instance dict after the first call, effectively - replacing the function it decorates with an instance variable. It is, in - Python parlance, a non-data descriptor. The following is an example and - its usage: - - .. doctest:: - - >>> from pyramid.decorator import reify - - >>> class Foo(object): - ... @reify - ... def jammy(self): - ... print('jammy called') - ... return 1 - - >>> f = Foo() - >>> v = f.jammy - jammy called - >>> print(v) - 1 - >>> f.jammy - 1 - >>> # jammy func not called the second time; it replaced itself with 1 - >>> # Note: reassignment is possible - >>> f.jammy = 2 - >>> f.jammy - 2 - """ - def __init__(self, wrapped): - self.wrapped = wrapped - from functools import update_wrapper - update_wrapper(self, wrapped) - - def __get__(self, inst, objtype=None): - if inst is None: - return self - val = self.wrapped(inst) - setattr(inst, self.wrapped.__name__, val) - return val diff --git a/alkali/fields.py b/alkali/fields.py index c551dd0..2d352d6 100644 --- a/alkali/fields.py +++ b/alkali/fields.py @@ -345,7 +345,6 @@ class OneToOneField(ForeignKey): """ """ # TODO maybe use reify - # https://docs.pylonsproject.org/projects/pyramid/en/latest/_modules/pyramid/decorator.html#reify # I forsee a problem where you load the primary table and either # create the OneToOneField table entries and replace the as the real file is loaded # or maybe you have some wierd race condition in the other direction diff --git a/alkali/reify.py b/alkali/reify.py new file mode 100644 index 0000000..cfe4aef --- /dev/null +++ b/alkali/reify.py @@ -0,0 +1,46 @@ +# from: https://docs.pylonsproject.org/projects/pyramid/en/latest/_modules/pyramid/decorator.html#reify + +from functools import update_wrapper + +class reify: + """ + Use as a class method decorator. It operates almost exactly like + the Python ``@property`` decorator, but it puts the result of the + method it decorates into the instance dict after the first call, + effectively replacing the function it decorates with an instance + variable. It is, in Python parlance, a non-data descriptor. The + following is an example and its usage: + + .. doctest:: + + >>> from pyramid.decorator import reify + + >>> class Foo(object): + ... @reify + ... def jammy(self): + ... print('jammy called') + ... return 1 + + >>> f = Foo() + >>> v = f.jammy + jammy called + >>> print(v) + 1 + >>> f.jammy + 1 + >>> # jammy func not called the second time; it replaced itself with 1 + >>> # Note: reassignment is possible + >>> f.jammy = 2 + >>> f.jammy + 2 + """ + def __init__(self, wrapped): + self.wrapped = wrapped + update_wrapper(self, wrapped) + + def __get__(self, inst, objtype=None): + if inst is None: + return self + val = self.wrapped(inst) + setattr(inst, self.wrapped.__name__, val) + return val diff --git a/alkali/tests/test_reify.py b/alkali/tests/test_reify.py new file mode 100644 index 0000000..194bcca --- /dev/null +++ b/alkali/tests/test_reify.py @@ -0,0 +1,17 @@ +import unittest + +from alkali.reify import reify + +class Class: + + @reify + def x(self): + return list(range(5)) + +class TestReify( unittest.TestCase ): + + def test_1(self): + Class.x # for test coverage + + c = Class() + self.assertTrue(isinstance(c.x, list))