def proxied_attribute_factory(descriptor): """Create an InstrumentedAttribute / user descriptor hybrid. Returns a new InstrumentedAttribute type that delegates descriptor behavior and getattr() to the given descriptor. """ class ProxyImpl(object): accepts_scalar_loader = False def __init__(self, key): self.key = key class Proxy(InstrumentedAttribute): """A combination of InsturmentedAttribute and a regular descriptor.""" def __init__(self, key, descriptor, comparator): self.key = key # maintain ProxiedAttribute.user_prop compatability. self.descriptor = self.user_prop = descriptor self._comparator = comparator self.impl = ProxyImpl(key) def comparator(self): if callable(self._comparator): self._comparator = self._comparator() return self._comparator comparator = property(comparator) def __get__(self, instance, owner): """Delegate __get__ to the original descriptor.""" if instance is None: descriptor.__get__(instance, owner) return self return descriptor.__get__(instance, owner) def __set__(self, instance, value): """Delegate __set__ to the original descriptor.""" return descriptor.__set__(instance, value) def __delete__(self, instance): """Delegate __delete__ to the original descriptor.""" return descriptor.__delete__(instance) def __getattr__(self, attribute): """Delegate __getattr__ to the original descriptor.""" return getattr(descriptor, attribute) Proxy.__name__ = type(descriptor).__name__ + 'Proxy' util.monkeypatch_proxied_specials(Proxy, type(descriptor), name='descriptor', from_instance=descriptor) return Proxy
def proxied_attribute_factory(descriptor): """Create an InstrumentedAttribute / user descriptor hybrid. Returns a new InstrumentedAttribute type that delegates descriptor behavior and getattr() to the given descriptor. """ class ProxyImpl(object): accepts_scalar_loader = False def __init__(self, key): self.key = key class Proxy(InstrumentedAttribute): """A combination of InsturmentedAttribute and a regular descriptor.""" def __init__(self, key, descriptor, comparator): self.key = key # maintain ProxiedAttribute.user_prop compatability. self.descriptor = self.user_prop = descriptor self._comparator = comparator self.impl = ProxyImpl(key) def comparator(self): if callable(self._comparator): self._comparator = self._comparator() return self._comparator comparator = property(comparator) def __get__(self, instance, owner): """Delegate __get__ to the original descriptor.""" if instance is None: descriptor.__get__(instance, owner) return self return descriptor.__get__(instance, owner) def __set__(self, instance, value): """Delegate __set__ to the original descriptor.""" return descriptor.__set__(instance, value) def __delete__(self, instance): """Delegate __delete__ to the original descriptor.""" return descriptor.__delete__(instance) def __getattr__(self, attribute): """Delegate __getattr__ to the original descriptor.""" return getattr(descriptor, attribute) Proxy.__name__ = type(descriptor).__name__ + "Proxy" util.monkeypatch_proxied_specials(Proxy, type(descriptor), name="descriptor", from_instance=descriptor) return Proxy
def create_proxied_attribute(descriptor): """Create an QueryableAttribute / user descriptor hybrid. Returns a new QueryableAttribute type that delegates descriptor behavior and getattr() to the given descriptor. """ # TODO: can move this to descriptor_props if the need for this # function is removed from ext/hybrid.py class Proxy(QueryableAttribute): """Presents the :class:`.QueryableAttribute` interface as a proxy on top of a Python descriptor / :class:`.PropComparator` combination. """ def __init__(self, class_, key, descriptor, comparator, adapter=None, doc=None): self.class_ = class_ self.key = key self.descriptor = descriptor self._comparator = comparator self.adapter = adapter self.__doc__ = doc @util.memoized_property def comparator(self): if util.callable(self._comparator): self._comparator = self._comparator() if self.adapter: self._comparator = self._comparator.adapted(self.adapter) return self._comparator def adapted(self, adapter): """Proxy adapted() for the use case of AliasedClass calling adapted.""" return self.__class__(self.class_, self.key, self.descriptor, self._comparator, adapter) def __get__(self, instance, owner): if instance is None: return self else: return self.descriptor.__get__(instance, owner) def __str__(self): return self.key def __getattr__(self, attribute): """Delegate __getattr__ to the original descriptor and/or comparator.""" try: return getattr(descriptor, attribute) except AttributeError: try: return getattr(self.comparator, attribute) except AttributeError: raise AttributeError( 'Neither %r object nor %r object has an attribute %r' % ( type(descriptor).__name__, type(self.comparator).__name__, attribute) ) Proxy.__name__ = type(descriptor).__name__ + 'Proxy' util.monkeypatch_proxied_specials(Proxy, type(descriptor), name='descriptor', from_instance=descriptor) return Proxy