1cdef class reify:
2    """Use as a class method decorator.  It operates almost exactly like
3    the Python `@property` decorator, but it puts the result of the
4    method it decorates into the instance dict after the first call,
5    effectively replacing the function it decorates with an instance
6    variable.  It is, in Python parlance, a data descriptor.
7
8    """
9
10    cdef object wrapped
11    cdef object name
12
13    def __init__(self, wrapped):
14        self.wrapped = wrapped
15        self.name = wrapped.__name__
16
17    @property
18    def __doc__(self):
19        return self.wrapped.__doc__
20
21    def __get__(self, inst, owner):
22        try:
23            try:
24                return inst._cache[self.name]
25            except KeyError:
26                val = self.wrapped(inst)
27                inst._cache[self.name] = val
28                return val
29        except AttributeError:
30            if inst is None:
31                return self
32            raise
33
34    def __set__(self, inst, value):
35        raise AttributeError("reified property is read-only")
36