def _is_userland_descriptor(self, obj):
return not isinstance(obj,
-- (MapperProperty, attributes.InstrumentedAttribute)) and \
- hasattr(obj, '__get__')
-
++ (MapperProperty, attributes.QueryableAttribute)) and \
+ hasattr(obj, '__get__') and not \
+ isinstance(obj.__get__(None, obj),
+ attributes.QueryableAttribute)
+
def _should_exclude(self, name, assigned_name, local):
"""determine whether a particular property should be implicitly
present on the class.
def __str__(self):
return str(self.parent.class_.__name__) + "." + self.key
-
class DescriptorProperty(MapperProperty):
""":class:`MapperProperty` which proxies access to a
- plain descriptor."""
+ user-defined descriptor."""
+
+ def instrument_class(self, mapper):
+ from sqlalchemy.ext import hybrid
+
+ # hackety hack hack
+ class _ProxyImpl(object):
+ accepts_scalar_loader = False
+ expire_missing = True
+
+ def __init__(self, key):
+ self.key = key
+
+ if self.descriptor is None:
+ desc = getattr(mapper.class_, self.key, None)
+ if mapper._is_userland_descriptor(desc):
+ self.descriptor = desc
+
+ if self.descriptor is None:
+ def fset(obj, value):
+ setattr(obj, self.name, value)
+ def fdel(obj):
+ delattr(obj, self.name)
+ def fget(obj):
+ return getattr(obj, self.name)
+ fget.__doc__ = self.doc
+
+ descriptor = hybrid.property_(
+ fget=fget,
+ fset=fset,
+ fdel=fdel,
+ )
+ elif isinstance(self.descriptor, property):
+ descriptor = hybrid.property_(
+ fget=self.descriptor.fget,
+ fset=self.descriptor.fset,
+ fdel=self.descriptor.fdel,
+ )
+ else:
+ descriptor = hybrid.property_(
+ fget=self.descriptor.__get__,
+ fset=self.descriptor.__set__,
+ fdel=self.descriptor.__delete__,
+ )
+
+ proxy_attr = attributes.\
+ create_proxied_attribute(self.descriptor or descriptor)\
+ (
+ self.key,
+ self.descriptor or descriptor,
+ lambda: self._comparator_factory(mapper)
+ )
+ def get_comparator(owner):
+ return proxy_attr
+ descriptor.expr = get_comparator
+ descriptor.impl = _ProxyImpl(self.key)
+ mapper.class_manager.instrument_attribute(self.key, descriptor)
def setup(self, context, entity, path, adapter, **kwargs):
pass
def merge(self, session, source_state, source_dict,
dest_state, dest_dict, load, _recursive):
pass
-
+
-
class ConcreteInheritedProperty(DescriptorProperty):
"""A 'do nothing' :class:`MapperProperty` that disables
an attribute on a concrete subclass that is only present
self.doc = doc or (descriptor and descriptor.__doc__) or None
util.set_creation_order(self)
+ def _comparator_factory(self, mapper):
+ prop = getattr(mapper.class_, self.name).property
+
+ if self.comparator_factory:
+ comp = self.comparator_factory(prop, mapper)
+ else:
+ comp = prop.comparator_factory(prop, mapper)
+ return comp
+
def set_parent(self, parent, init):
if self.map_column:
+ # implement the 'map_column' option.
if self.key not in parent.mapped_table.c:
raise sa_exc.ArgumentError(
"Can't compile synonym '%s': no column on table "