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.py79
1 files changed, 40 insertions, 39 deletions
diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py
index aa5105150..1b91bd977 100644
--- a/lib/sqlalchemy/orm/dynamic.py
+++ b/lib/sqlalchemy/orm/dynamic.py
@@ -6,32 +6,30 @@ from sqlalchemy.orm import attributes, object_session
from sqlalchemy.orm.query import Query
from sqlalchemy.orm.mapper import has_identity, object_mapper
-class DynamicCollectionAttribute(attributes.InstrumentedAttribute):
+class DynamicAttributeImpl(attributes.AttributeImpl):
def __init__(self, class_, attribute_manager, key, typecallable, target_mapper, **kwargs):
- super(DynamicCollectionAttribute, self).__init__(class_, attribute_manager, key, typecallable, **kwargs)
+ super(DynamicAttributeImpl, self).__init__(class_, attribute_manager, key, typecallable, **kwargs)
self.target_mapper = target_mapper
- def get(self, obj, passive=False):
+ def get(self, state, passive=False):
if passive:
- return self.get_history(obj, passive=True).added_items()
+ return self.get_history(state, passive=True).added_items()
else:
- return AppenderQuery(self, obj)
+ return AppenderQuery(self, state)
- def commit_to_state(self, state, obj, value=attributes.NO_VALUE):
+ def commit_to_state(self, state, value=attributes.NO_VALUE):
# we have our own AttributeHistory therefore dont need CommittedState
# instead, we reset the history stored on the attribute
- obj.__dict__[self.key] = CollectionHistory(self, obj)
+ state.dict[self.key] = CollectionHistory(self, state)
- def get_collection(self, obj, user_data=None):
- return self.get_history(obj)._added_items
+ def get_collection(self, state, user_data=None):
+ return self.get_history(state)._added_items
- def set(self, obj, value, initiator):
+ def set(self, state, value, initiator):
if initiator is self:
return
- state = obj._state
-
- old_collection = self.get(obj).assign(value)
+ old_collection = self.get(state).assign(value)
# TODO: emit events ???
state.modified = True
@@ -39,35 +37,36 @@ class DynamicCollectionAttribute(attributes.InstrumentedAttribute):
def delete(self, *args, **kwargs):
raise NotImplementedError()
- def get_history(self, obj, passive=False):
+ def get_history(self, state, passive=False):
try:
- return obj.__dict__[self.key]
+ return state.dict[self.key]
except KeyError:
- obj.__dict__[self.key] = c = CollectionHistory(self, obj)
+ state.dict[self.key] = c = CollectionHistory(self, state)
return c
- def append(self, obj, value, initiator):
+ def append(self, state, value, initiator):
if initiator is not self:
- self.get_history(obj)._added_items.append(value)
- self.fire_append_event(obj, value, self)
+ self.get_history(state)._added_items.append(value)
+ self.fire_append_event(state, value, self)
- def remove(self, obj, value, initiator):
+ def remove(self, state, value, initiator):
if initiator is not self:
- self.get_history(obj)._deleted_items.append(value)
- self.fire_remove_event(obj, value, self)
+ self.get_history(state)._deleted_items.append(value)
+ self.fire_remove_event(state, value, self)
class AppenderQuery(Query):
- def __init__(self, attr, instance):
+ def __init__(self, attr, state):
super(AppenderQuery, self).__init__(attr.target_mapper, None)
- self.instance = instance
+ self.state = state
self.attr = attr
def __session(self):
- sess = object_session(self.instance)
- if sess is not None and self.instance in sess and sess.autoflush:
+ instance = self.state.obj()
+ sess = object_session(instance)
+ if sess is not None and instance in sess and sess.autoflush:
sess.flush()
- if not has_identity(self.instance):
+ if not has_identity(instance):
return None
else:
return sess
@@ -75,21 +74,21 @@ class AppenderQuery(Query):
def __len__(self):
sess = self.__session()
if sess is None:
- return len(self.attr.get_history(self.instance)._added_items)
+ return len(self.attr.get_history(self.state)._added_items)
else:
return self._clone(sess).count()
def __iter__(self):
sess = self.__session()
if sess is None:
- return iter(self.attr.get_history(self.instance)._added_items)
+ return iter(self.attr.get_history(self.state)._added_items)
else:
return iter(self._clone(sess))
def __getitem__(self, index):
sess = self.__session()
if sess is None:
- return self.attr.get_history(self.instance)._added_items.__getitem__(index)
+ return self.attr.get_history(self.state)._added_items.__getitem__(index)
else:
return self._clone(sess).__getitem__(index)
@@ -97,39 +96,41 @@ class AppenderQuery(Query):
# note we're returning an entirely new Query class instance here
# without any assignment capabilities;
# the class of this query is determined by the session.
+ instance = self.state.obj()
if sess is None:
- sess = object_session(self.instance)
+ sess = object_session(instance)
if sess is None:
try:
- sess = object_mapper(self.instance).get_session()
+ sess = object_mapper(instance).get_session()
except exceptions.InvalidRequestError:
raise exceptions.InvalidRequestError("Parent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed" % (self.instance.__class__, self.key))
- return sess.query(self.attr.target_mapper).with_parent(self.instance)
+ return sess.query(self.attr.target_mapper).with_parent(instance)
def assign(self, collection):
- if has_identity(self.instance):
+ instance = self.state.obj()
+ if has_identity(instance):
oldlist = list(self)
else:
oldlist = []
- self.attr.get_history(self.instance).replace(oldlist, collection)
+ self.attr.get_history(self.state).replace(oldlist, collection)
return oldlist
def append(self, item):
- self.attr.append(self.instance, item, None)
+ self.attr.append(self.state, item, None)
def remove(self, item):
- self.attr.remove(self.instance, item, None)
+ self.attr.remove(self.state, item, None)
class CollectionHistory(attributes.AttributeHistory):
"""Overrides AttributeHistory to receive append/remove events directly."""
- def __init__(self, attr, obj):
+ def __init__(self, attr, state):
self._deleted_items = []
self._added_items = []
self._unchanged_items = []
- self._obj = obj
+ self._state = state
def replace(self, olditems, newitems):
self._added_items = newitems