summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/dynamic.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm/dynamic.py')
-rw-r--r--lib/sqlalchemy/orm/dynamic.py208
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]