summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2008-10-26 20:02:19 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2008-10-26 20:02:19 +0000
commitc36271e23b81a161772183cc95532c124e76f5a4 (patch)
tree9d7837e4f2949d2ef19fa92ec8d565acb58cc7e4
parent76e8175971a5fa5abb7f7e1f85ccd3068f04aff5 (diff)
downloadsqlalchemy-c36271e23b81a161772183cc95532c124e76f5a4.tar.gz
- InstanceState object now removes circular references to
itself upon disposal to keep it outside of cyclic garbage collection.
-rw-r--r--CHANGES4
-rw-r--r--lib/sqlalchemy/orm/attributes.py21
-rw-r--r--lib/sqlalchemy/orm/session.py6
3 files changed, 25 insertions, 6 deletions
diff --git a/CHANGES b/CHANGES
index 19524ca50..7518c61c2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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)