Source code for lazyutils.core

[docs]class delegate_to: """ Property that delegates attribute access to a inner variable. Args: attribute: Name of the inner variable that receives delegation. readonly: If true, makes the the delegate readonly. """ def __init__(self, attribute, readonly=False): self.attribute = attribute self.readonly = readonly def __get__(self, obj, cls=None): if obj is None: return self owner = getattr(obj, self.attribute) try: attr = self._name except AttributeError: attr = self._name = self._get_name(cls) return getattr(owner, attr) def __set__(self, obj, value): if self.readonly: raise AttributeError owner = getattr(obj, self.attribute) try: attr = self._name except AttributeError: attr = self._name = self._get_name(type(obj)) setattr(owner, attr, value) def _get_name(self, cls): for attr in dir(cls): value = getattr(cls, attr, None) if value is self: return attr raise RuntimeError('not a member of class')
[docs]class delegate_ro(delegate_to): """ A read-only version of delegate_to() """ def __init__(self, attribute): super().__init__(attribute, readonly=True) print(self.__dict__)
[docs]class lazy: """ Decorator that defines an attribute that is initialized as first usage rather than at instance creation. Usage is similar to the ``@property`` decorator, although lazy attributes do not override the *setter* and *deleter* methods. """ def __init__(self, method): self.method = method self.__name__ = getattr(method, '__name__', None) def __get__(self, obj, cls): if obj is None: return self result = self.method(obj) try: attr_name = self._attr except AttributeError: attr_name = self._get_attribute_name(cls) setattr(obj, attr_name, result) return result def _get_attribute_name(self, cls): """Inspect live object for some attributes.""" try: if getattr(cls, self.__name__) is self: return self.__name__ except AttributeError: pass for attr in dir(cls): method = getattr(cls, attr, None) if method is self: self._attr = attr return attr raise TypeError('lazy accessor not found in %s' % cls.__name__)