diff options
Diffstat (limited to 'lib/sqlalchemy/orm/dynamic.py')
-rw-r--r-- | lib/sqlalchemy/orm/dynamic.py | 208 |
1 files changed, 134 insertions, 74 deletions
diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py index 087e7dcc6..e5c6b80b6 100644 --- a/lib/sqlalchemy/orm/dynamic.py +++ b/lib/sqlalchemy/orm/dynamic.py @@ -15,8 +15,13 @@ basic add/delete mutation. from .. import log, util, exc from ..sql import operators from . import ( - attributes, object_session, util as orm_util, strategies, - object_mapper, exc as orm_exc, properties + attributes, + object_session, + util as orm_util, + strategies, + object_mapper, + exc as orm_exc, + properties, ) from .query import Query @@ -30,7 +35,8 @@ class DynaLoader(strategies.AbstractRelationshipLoader): raise exc.InvalidRequestError( "On relationship %s, 'dynamic' loaders cannot be used with " "many-to-one/one-to-one relationships and/or " - "uselist=False." % self.parent_property) + "uselist=False." % self.parent_property + ) strategies._register_attribute( self.parent_property, mapper, @@ -49,11 +55,20 @@ class DynamicAttributeImpl(attributes.AttributeImpl): collection = False dynamic = True - def __init__(self, class_, key, typecallable, - dispatch, - target_mapper, order_by, query_class=None, **kw): - super(DynamicAttributeImpl, self).\ - __init__(class_, key, typecallable, dispatch, **kw) + def __init__( + self, + class_, + key, + typecallable, + dispatch, + target_mapper, + order_by, + query_class=None, + **kw + ): + super(DynamicAttributeImpl, self).__init__( + class_, key, typecallable, dispatch, **kw + ) self.target_mapper = target_mapper self.order_by = order_by if not query_class: @@ -66,15 +81,20 @@ class DynamicAttributeImpl(attributes.AttributeImpl): def get(self, state, dict_, passive=attributes.PASSIVE_OFF): if not passive & attributes.SQL_OK: return self._get_collection_history( - state, attributes.PASSIVE_NO_INITIALIZE).added_items + state, attributes.PASSIVE_NO_INITIALIZE + ).added_items else: return self.query_class(self, state) - def get_collection(self, state, dict_, user_data=None, - passive=attributes.PASSIVE_NO_INITIALIZE): + def get_collection( + self, + state, + dict_, + user_data=None, + passive=attributes.PASSIVE_NO_INITIALIZE, + ): if not passive & attributes.SQL_OK: - return self._get_collection_history(state, - passive).added_items + return self._get_collection_history(state, passive).added_items else: history = self._get_collection_history(state, passive) return history.added_plus_unchanged @@ -87,8 +107,9 @@ class DynamicAttributeImpl(attributes.AttributeImpl): def _remove_token(self): return attributes.Event(self, attributes.OP_REMOVE) - def fire_append_event(self, state, dict_, value, initiator, - collection_history=None): + def fire_append_event( + self, state, dict_, value, initiator, collection_history=None + ): if collection_history is None: collection_history = self._modified_event(state, dict_) @@ -100,8 +121,9 @@ class DynamicAttributeImpl(attributes.AttributeImpl): if self.trackparent and value is not None: self.sethasparent(attributes.instance_state(value), state, True) - def fire_remove_event(self, state, dict_, value, initiator, - collection_history=None): + def fire_remove_event( + self, state, dict_, value, initiator, collection_history=None + ): if collection_history is None: collection_history = self._modified_event(state, dict_) @@ -118,18 +140,24 @@ class DynamicAttributeImpl(attributes.AttributeImpl): if self.key not in state.committed_state: state.committed_state[self.key] = CollectionHistory(self, state) - state._modified_event(dict_, - self, - attributes.NEVER_SET) + state._modified_event(dict_, self, attributes.NEVER_SET) # this is a hack to allow the fixtures.ComparableEntity fixture # to work dict_[self.key] = True return state.committed_state[self.key] - def set(self, state, dict_, value, initiator=None, - passive=attributes.PASSIVE_OFF, - check_old=None, pop=False, _adapt=True): + def set( + self, + state, + dict_, + value, + initiator=None, + passive=attributes.PASSIVE_OFF, + check_old=None, + pop=False, + _adapt=True, + ): if initiator and initiator.parent_token is self.parent_token: return @@ -146,7 +174,8 @@ class DynamicAttributeImpl(attributes.AttributeImpl): old_collection = collection_history.added_items else: old_collection = old_collection.union( - collection_history.added_items) + collection_history.added_items + ) idset = util.IdentitySet constants = old_collection.intersection(new_values) @@ -155,33 +184,40 @@ class DynamicAttributeImpl(attributes.AttributeImpl): for member in new_values: if member in additions: - self.fire_append_event(state, dict_, member, None, - collection_history=collection_history) + self.fire_append_event( + state, + dict_, + member, + None, + collection_history=collection_history, + ) for member in removals: - self.fire_remove_event(state, dict_, member, None, - collection_history=collection_history) + self.fire_remove_event( + state, + dict_, + member, + None, + collection_history=collection_history, + ) def delete(self, *args, **kwargs): raise NotImplementedError() def set_committed_value(self, state, dict_, value): - raise NotImplementedError("Dynamic attributes don't support " - "collection population.") + raise NotImplementedError( + "Dynamic attributes don't support " "collection population." + ) def get_history(self, state, dict_, passive=attributes.PASSIVE_OFF): c = self._get_collection_history(state, passive) return c.as_history() - def get_all_pending(self, state, dict_, - passive=attributes.PASSIVE_NO_INITIALIZE): - c = self._get_collection_history( - state, passive) - return [ - (attributes.instance_state(x), x) - for x in - c.all_items - ] + def get_all_pending( + self, state, dict_, passive=attributes.PASSIVE_NO_INITIALIZE + ): + c = self._get_collection_history(state, passive) + return [(attributes.instance_state(x), x) for x in c.all_items] def _get_collection_history(self, state, passive=attributes.PASSIVE_OFF): if self.key in state.committed_state: @@ -194,18 +230,21 @@ class DynamicAttributeImpl(attributes.AttributeImpl): else: return c - def append(self, state, dict_, value, initiator, - passive=attributes.PASSIVE_OFF): + def append( + self, state, dict_, value, initiator, passive=attributes.PASSIVE_OFF + ): if initiator is not self: self.fire_append_event(state, dict_, value, initiator) - def remove(self, state, dict_, value, initiator, - passive=attributes.PASSIVE_OFF): + def remove( + self, state, dict_, value, initiator, passive=attributes.PASSIVE_OFF + ): if initiator is not self: self.fire_remove_event(state, dict_, value, initiator) - def pop(self, state, dict_, value, initiator, - passive=attributes.PASSIVE_OFF): + def pop( + self, state, dict_, value, initiator, passive=attributes.PASSIVE_OFF + ): self.remove(state, dict_, value, initiator, passive=passive) @@ -229,30 +268,36 @@ class AppenderMixin(object): # doesn't fail, and secondary is then in _from_obj[1]. self._from_obj = (prop.mapper.selectable, prop.secondary) - self._criterion = prop._with_parent( - instance, - alias_secondary=False) + self._criterion = prop._with_parent(instance, alias_secondary=False) if self.attr.order_by: self._order_by = self.attr.order_by def session(self): sess = object_session(self.instance) - if sess is not None and self.autoflush and sess.autoflush \ - and self.instance in sess: + if ( + sess is not None + and self.autoflush + and sess.autoflush + and self.instance in sess + ): sess.flush() if not orm_util.has_identity(self.instance): return None else: return sess + session = property(session, lambda s, x: None) def __iter__(self): sess = self.session if sess is None: - return iter(self.attr._get_collection_history( - attributes.instance_state(self.instance), - attributes.PASSIVE_NO_INITIALIZE).added_items) + return iter( + self.attr._get_collection_history( + attributes.instance_state(self.instance), + attributes.PASSIVE_NO_INITIALIZE, + ).added_items + ) else: return iter(self._clone(sess)) @@ -261,16 +306,20 @@ class AppenderMixin(object): if sess is None: return self.attr._get_collection_history( attributes.instance_state(self.instance), - attributes.PASSIVE_NO_INITIALIZE).indexed(index) + attributes.PASSIVE_NO_INITIALIZE, + ).indexed(index) else: return self._clone(sess).__getitem__(index) def count(self): sess = self.session if sess is None: - return len(self.attr._get_collection_history( - attributes.instance_state(self.instance), - attributes.PASSIVE_NO_INITIALIZE).added_items) + return len( + self.attr._get_collection_history( + attributes.instance_state(self.instance), + attributes.PASSIVE_NO_INITIALIZE, + ).added_items + ) else: return self._clone(sess).count() @@ -285,8 +334,9 @@ class AppenderMixin(object): raise orm_exc.DetachedInstanceError( "Parent instance %s is not bound to a Session, and no " "contextual session is established; lazy load operation " - "of attribute '%s' cannot proceed" % ( - orm_util.instance_str(instance), self.attr.key)) + "of attribute '%s' cannot proceed" + % (orm_util.instance_str(instance), self.attr.key) + ) if self.query_class: query = self.query_class(self.attr.target_mapper, session=sess) @@ -303,17 +353,26 @@ class AppenderMixin(object): for item in iterator: self.attr.append( attributes.instance_state(self.instance), - attributes.instance_dict(self.instance), item, None) + attributes.instance_dict(self.instance), + item, + None, + ) def append(self, item): self.attr.append( attributes.instance_state(self.instance), - attributes.instance_dict(self.instance), item, None) + attributes.instance_dict(self.instance), + item, + None, + ) def remove(self, item): self.attr.remove( attributes.instance_state(self.instance), - attributes.instance_dict(self.instance), item, None) + attributes.instance_dict(self.instance), + item, + None, + ) class AppenderQuery(AppenderMixin, Query): @@ -322,8 +381,8 @@ class AppenderQuery(AppenderMixin, Query): def mixin_user_query(cls): """Return a new class with AppenderQuery functionality layered over.""" - name = 'Appender' + cls.__name__ - return type(name, (AppenderMixin, cls), {'query_class': cls}) + name = "Appender" + cls.__name__ + return type(name, (AppenderMixin, cls), {"query_class": cls}) class CollectionHistory(object): @@ -348,8 +407,11 @@ class CollectionHistory(object): @property def all_items(self): - return list(self.added_items.union( - self.unchanged_items).union(self.deleted_items)) + return list( + self.added_items.union(self.unchanged_items).union( + self.deleted_items + ) + ) def as_history(self): if self._reconcile_collection: @@ -357,14 +419,12 @@ class CollectionHistory(object): deleted = self.deleted_items.intersection(self.unchanged_items) unchanged = self.unchanged_items.difference(deleted) else: - added, unchanged, deleted = self.added_items,\ - self.unchanged_items,\ - self.deleted_items - return attributes.History( - list(added), - list(unchanged), - list(deleted), - ) + added, unchanged, deleted = ( + self.added_items, + self.unchanged_items, + self.deleted_items, + ) + return attributes.History(list(added), list(unchanged), list(deleted)) def indexed(self, index): return list(self.added_items)[index] |