summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/dynamic.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-09-22 16:55:36 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-09-22 16:55:36 +0000
commit6b0a907fbdd33b9d9333ec1b72287580a2568d07 (patch)
tree89303fa82c0e239ea855ff7f19f0f7a1c8a27e03 /lib/sqlalchemy/orm/dynamic.py
parent7f6bf93da869a5b59c53d0d10a50da3c23c4b738 (diff)
downloadsqlalchemy-6b0a907fbdd33b9d9333ec1b72287580a2568d07.tar.gz
- merged sa_entity branch. the big change here is the attributes system
deals primarily with the InstanceState and almost never with the instrumented object directly. This reduces lookups and complexity since we need the state for just about everything, now its the one place for everything internally. we also merged the new weak referencing identity map, which will go out in beta6 and we'll see how that goes !
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