diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-11-30 20:25:22 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-11-30 20:25:22 -0500 |
| commit | 3c9d2d7b2f76fc18c0f1141a813a7045ac8cb853 (patch) | |
| tree | db44f0c0edec5bfcea4009e5d0a457f6e1d04933 /lib | |
| parent | 79fc3cdc1b0be99e138580905290823463766944 (diff) | |
| download | sqlalchemy-3c9d2d7b2f76fc18c0f1141a813a7045ac8cb853.tar.gz | |
- replace GenericBackrefExtension with straight events
- add "backref" argument to register_attribute_impl
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 48 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/properties.py | 4 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 4 |
3 files changed, 26 insertions, 30 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index 9ae885bf9..d80a7fe5a 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -791,21 +791,10 @@ class CollectionAttributeImpl(AttributeImpl): return getattr(user_data, '_sa_adapter') -class GenericBackrefExtension(interfaces.AttributeExtension): - """An extension which synchronizes a two-way relationship. +def backref_listeners(attribute, key, uselist): + """Apply listeners to synchronize a two-way relationship.""" - A typical two-way relationship is a parent object containing a list of - child objects, where each child object references the parent. The other - are two objects which contain scalar references to each other. - - """ - - active_history = False - - def __init__(self, key): - self.key = key - - def set(self, state, child, oldchild, initiator): + def set_(state, child, oldchild, initiator): if oldchild is child: return child @@ -814,7 +803,7 @@ class GenericBackrefExtension(interfaces.AttributeExtension): # present when updating via a backref. old_state, old_dict = instance_state(oldchild),\ instance_dict(oldchild) - impl = old_state.get_impl(self.key) + impl = old_state.get_impl(key) try: impl.remove(old_state, old_dict, @@ -826,7 +815,7 @@ class GenericBackrefExtension(interfaces.AttributeExtension): if child is not None: child_state, child_dict = instance_state(child),\ instance_dict(child) - child_state.get_impl(self.key).append( + child_state.get_impl(key).append( child_state, child_dict, state.obj(), @@ -834,10 +823,10 @@ class GenericBackrefExtension(interfaces.AttributeExtension): passive=PASSIVE_NO_FETCH) return child - def append(self, state, child, initiator): + def append(state, child, initiator): child_state, child_dict = instance_state(child), \ instance_dict(child) - child_state.get_impl(self.key).append( + child_state.get_impl(key).append( child_state, child_dict, state.obj(), @@ -845,18 +834,24 @@ class GenericBackrefExtension(interfaces.AttributeExtension): passive=PASSIVE_NO_FETCH) return child - def remove(self, state, child, initiator): + def remove(state, child, initiator): if child is not None: child_state, child_dict = instance_state(child),\ instance_dict(child) - child_state.get_impl(self.key).remove( + child_state.get_impl(key).remove( child_state, child_dict, state.obj(), initiator, passive=PASSIVE_NO_FETCH) - - + + if uselist: + event.listen(append, "on_append", attribute, retval=False, raw=True) + else: + event.listen(set_, "on_set", attribute, retval=False, raw=True) + # TODO: need coverage in test/orm/ of remove event + event.listen(remove, "on_remove", attribute, retval=False, raw=True) + class History(tuple): """A 3-tuple of added, unchanged and deleted values, representing the changes which have occured on an instrumented @@ -1010,14 +1005,15 @@ def register_attribute(class_, key, **kw): comparator = kw.pop('comparator', None) parententity = kw.pop('parententity', None) doc = kw.pop('doc', None) - register_descriptor(class_, key, + desc = register_descriptor(class_, key, comparator, parententity, doc=doc) register_attribute_impl(class_, key, **kw) + return desc def register_attribute_impl(class_, key, uselist=False, callable_=None, useobject=False, mutable_scalars=False, - impl_class=None, **kw): + impl_class=None, backref=None, **kw): manager = manager_of_class(class_) if uselist: @@ -1044,6 +1040,9 @@ def register_attribute_impl(class_, key, impl = ScalarAttributeImpl(class_, key, callable_, dispatch, **kw) manager[key].impl = impl + + if backref: + backref_listeners(manager[key], backref, uselist) manager.post_configure_attribute(key) @@ -1058,6 +1057,7 @@ def register_descriptor(class_, key, comparator=None, descriptor.__doc__ = doc manager.instrument_attribute(key, descriptor) + return descriptor def unregister_attribute(class_, key): manager_of_class(class_).uninstrument_attribute(key) diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index b68290dbd..81ac9262c 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -1347,10 +1347,6 @@ class RelationshipProperty(StrategizedProperty): ) mapper._configure_property(backref_key, relationship) if self.back_populates: - self.extension = list(util.to_list(self.extension, - default=[])) - self.extension.append( - attributes.GenericBackrefExtension(self.back_populates)) self._add_reverse_property(self.back_populates) def _post_init(self): diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index d8d4afc37..f23145da5 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -47,7 +47,6 @@ def _register_attribute(strategy, mapper, useobject, if useobject: attribute_ext.append(sessionlib.UOWEventHandler(prop.key)) - for m in mapper.self_and_descendants: if prop is m._props.get(prop.key): @@ -60,7 +59,7 @@ def _register_attribute(strategy, mapper, useobject, uselist=uselist, copy_function=copy_function, compare_function=compare_function, - useobject=useobject, + useobject=useobject, extension=attribute_ext, trackparent=useobject, typecallable=typecallable, @@ -398,6 +397,7 @@ class LazyLoader(AbstractRelationshipLoader): useobject=True, callable_=self._class_level_loader, uselist = self.parent_property.uselist, + backref = self.parent_property.back_populates, typecallable = self.parent_property.collection_class, active_history = \ self.parent_property.active_history or \ |
