from typing import Any
import asyncio
[docs]class cached_property:
"""A property decorator that is only computed once per instance and then
replaces itself with an ordinary attribute.
Deleting the attribute resets the property.
Example:
Code::
from flutils import cached_property
class MyClass:
def __init__(self):
self.x = 5
@cached_property
def y(self):
return self.x + 1
Usage:
>>> obj = MyClass()
>>> obj.y
6
>>> obj.y
6
*New in version 0.2.0*
This decorator is a derivative work of
`cached_property <https://bit.ly/2R9U3Qa>`_ and is:
`Copyright © 2015 Daniel Greenfeld; All Rights Reserved
<https://bit.ly/2CwtJM1>`_
Also this decorator is a derivative work of
`cached_property <https://bit.ly/2JbYB5L>`_ and is:
`Copyright © 2011 Marcel Hellkamp <https://bit.ly/2ECEO0M>`_
"""
def __init__(self, func):
self.__doc__ = getattr(func, "__doc__")
self.func = func
def __get__(self, obj: Any, cls):
if obj is None:
return self
if asyncio.iscoroutinefunction(self.func):
return self._wrap_in_coroutine(obj)
value = obj.__dict__[self.func.__name__] = self.func(obj)
return value
def _wrap_in_coroutine(self, obj):
@asyncio.coroutine
def wrapper():
future = asyncio.ensure_future(self.func(obj))
obj.__dict__[self.func.__name__] = future
return future
return wrapper()