diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 21 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/session.py | 6 |
3 files changed, 25 insertions, 6 deletions
@@ -38,6 +38,10 @@ CHANGES a lazy-load later on. Backref events still initialize attrbutes and collections for pending instances. [ticket:1202] + + - InstanceState object now removes circular references to + itself upon disposal to keep it outside of cyclic garbage + collection. - sql - Further simplified SELECT compilation and its relationship diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index 4429d44f4..bc8f701e7 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -794,13 +794,13 @@ class GenericBackrefExtension(interfaces.AttributeExtension): class InstanceState(object): """tracks state information at the instance level.""" - _cleanup = None session_id = None key = None runid = None expired_attributes = EMPTY_SET insert_order = None - + dict = None + def __init__(self, obj, manager): self.class_ = obj.__class__ self.manager = manager @@ -813,10 +813,22 @@ class InstanceState(object): self.pending = {} self.expired = False - def dispose(self): + def detach(self): if self.session_id: del self.session_id + def dispose(self): + if self.session_id: + del self.session_id + del self.dict + del self.obj + + def _cleanup(self, ref): + self.dispose() + + def obj(self): + return None + @property def sort_key(self): return self.key and self.key[1] or self.insert_order @@ -960,6 +972,9 @@ class InstanceState(object): if key not in self.committed_state and key not in self.dict) def expire_attributes(self, attribute_names): + if self.dict is None: + return + self.expired_attributes = set(self.expired_attributes) if attribute_names is None: diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index 9eee0e3e1..9292ef3f3 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -787,7 +787,7 @@ class Session(object): """ for state in self.identity_map.all_states() + list(self._new): - state.dispose() + state.detach() self.identity_map = self._identity_cls() self._new = {} @@ -1012,11 +1012,11 @@ class Session(object): def _expunge_state(self, state): if state in self._new: self._new.pop(state) - state.dispose() + state.detach() elif self.identity_map.contains_state(state): self.identity_map.discard(state) self._deleted.pop(state, None) - state.dispose() + state.detach() def _register_newly_persistent(self, state): mapper = _state_mapper(state) |