diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-08-21 18:10:35 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-08-21 18:10:35 +0000 |
commit | 3c80e59ebce9ae404b092011dce70598b563ff23 (patch) | |
tree | 0e525cb3c554e9103a5f254fc16e94c8beb72c67 /lib | |
parent | d08821ee5ec566132cb813d2e65e20052c1f712a (diff) | |
download | sqlalchemy-3c80e59ebce9ae404b092011dce70598b563ff23.tar.gz |
- column_property() and synonym() both accept comparator_factory argument, allowing
custom comparison functionality
- made the mapper's checks for user-based descriptors when defining synonym or comparable property
stronger, such that a synonym can be used with declarative without having a user-based descriptor
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sqlalchemy/orm/__init__.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 18 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/properties.py | 13 |
3 files changed, 21 insertions, 14 deletions
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py index e405d76a2..da9134b11 100644 --- a/lib/sqlalchemy/orm/__init__.py +++ b/lib/sqlalchemy/orm/__init__.py @@ -642,7 +642,7 @@ def mapper(class_, local_table=None, *args, **params): """ return Mapper(class_, local_table, *args, **params) -def synonym(name, map_column=False, descriptor=None, proxy=False): +def synonym(name, map_column=False, descriptor=None, comparator_factory=None, proxy=False): """Set up `name` as a synonym to another mapped property. Used with the ``properties`` dictionary sent to [sqlalchemy.orm#mapper()]. @@ -684,7 +684,7 @@ def synonym(name, map_column=False, descriptor=None, proxy=False): is not already available. """ - return SynonymProperty(name, map_column=map_column, descriptor=descriptor) + return SynonymProperty(name, map_column=map_column, descriptor=descriptor, comparator_factory=comparator_factory) def comparable_property(comparator_factory, descriptor=None): """Provide query semantics for an unmanaged attribute. diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index d1713e6f9..921d08b83 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -640,6 +640,9 @@ class Mapper(object): return getattr(getattr(cls, clskey), key) + def _is_userland_descriptor(self, obj): + return not isinstance(obj, (MapperProperty, attributes.InstrumentedAttribute)) and hasattr(obj, '__get__') + def _should_exclude(self, name, local): """determine whether a particular property should be implicitly present on the class. @@ -648,18 +651,15 @@ class Mapper(object): """ - def is_userland_descriptor(obj): - return not isinstance(obj, attributes.InstrumentedAttribute) and hasattr(obj, '__get__') - # check for descriptors, either local or from # an inherited class if local: if self.class_.__dict__.get(name, None)\ - and is_userland_descriptor(self.class_.__dict__[name]): + and self._is_userland_descriptor(self.class_.__dict__[name]): return True else: if getattr(self.class_, name, None)\ - and is_userland_descriptor(getattr(self.class_, name)): + and self._is_userland_descriptor(getattr(self.class_, name)): return True if (self.include_properties is not None and @@ -786,9 +786,11 @@ class Mapper(object): elif isinstance(prop, (ComparableProperty, SynonymProperty)) and setparent: if prop.descriptor is None: - prop.descriptor = getattr(self.class_, key, None) - if isinstance(prop.descriptor, Mapper._CompileOnAttr): - prop.descriptor = object.__getattribute__(prop.descriptor, 'existing_prop') + desc = getattr(self.class_, key, None) + if isinstance(desc, Mapper._CompileOnAttr): + desc = object.__getattribute__(desc, 'existing_prop') + if self._is_userland_descriptor(desc): + prop.descriptor = desc if getattr(prop, 'map_column', False): if key not in self.mapped_table.c: raise sa_exc.ArgumentError("Can't compile synonym '%s': no column on table '%s' named '%s'" % (prop.name, self.mapped_table.description, key)) diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 3d717cae0..ceabc2792 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -41,7 +41,7 @@ class ColumnProperty(StrategizedProperty): self.columns = [expression._labeled(c) for c in columns] self.group = kwargs.pop('group', None) self.deferred = kwargs.pop('deferred', False) - self.comparator_factory = ColumnProperty.ColumnComparator + self.comparator_factory = kwargs.pop('comparator_factory', ColumnProperty.ColumnComparator) util.set_creation_order(self) if self.deferred: self.strategy_class = strategies.DeferredColumnLoader @@ -161,10 +161,11 @@ class CompositeProperty(ColumnProperty): return str(self.parent.class_.__name__) + "." + self.key class SynonymProperty(MapperProperty): - def __init__(self, name, map_column=None, descriptor=None): + def __init__(self, name, map_column=None, descriptor=None, comparator_factory=None): self.name = name self.map_column = map_column self.descriptor = descriptor + self.comparator_factory = comparator_factory util.set_creation_order(self) def setup(self, context, entity, path, adapter, **kwargs): @@ -192,10 +193,14 @@ class SynonymProperty(MapperProperty): def comparator_callable(prop, mapper): def comparator(): prop = self.parent._get_property(self.key, resolve_synonyms=True) - return prop.comparator_factory(prop, mapper) + if self.comparator_factory: + return self.comparator_factory(prop, mapper) + else: + return prop.comparator_factory(prop, mapper) return comparator - strategies.DefaultColumnLoader(self)._register_attribute(None, None, False, comparator_callable, proxy_property=self.descriptor) + strategies.DefaultColumnLoader(self)._register_attribute( + None, None, False, comparator_callable, proxy_property=self.descriptor) def merge(self, session, source, dest, dont_load, _recursive): pass |