summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sqlalchemy/orm/attributes.py6
-rw-r--r--lib/sqlalchemy/orm/interfaces.py3
-rw-r--r--test/orm/pickled.py19
3 files changed, 26 insertions, 2 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py
index 2b2760208..5c242aa7e 100644
--- a/lib/sqlalchemy/orm/attributes.py
+++ b/lib/sqlalchemy/orm/attributes.py
@@ -1269,6 +1269,9 @@ class ClassManager(dict):
def setup_instance(self, instance, state=None):
setattr(instance, self.STATE_ATTR, state or self.instance_state_factory(instance, self))
+
+ def teardown_instance(self, instance):
+ delattr(instance, self.STATE_ATTR)
def _new_state_if_none(self, instance):
"""Install a default InstanceState if none is present.
@@ -1381,6 +1384,9 @@ class _ClassInstrumentationAdapter(ClassManager):
state.dict = self._adapted.get_instance_dict(self.class_, instance)
return state
+ def teardown_instance(self, instance):
+ self._adapted.remove_state(self.class_, instance)
+
def state_of(self, instance):
if hasattr(self._adapted, 'state_of'):
return self._adapted.state_of(self.class_, instance)
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py
index 25664f258..b210e577f 100644
--- a/lib/sqlalchemy/orm/interfaces.py
+++ b/lib/sqlalchemy/orm/interfaces.py
@@ -889,5 +889,8 @@ class InstrumentationManager(object):
def install_state(self, class_, instance, state):
setattr(instance, '_default_state', state)
+ def remove_state(self, class_, instance):
+ delattr(instance, '_default_state', state)
+
def state_getter(self, class_):
return lambda instance: getattr(instance, '_default_state')
diff --git a/test/orm/pickled.py b/test/orm/pickled.py
index a4eadf5a9..d14acdc50 100644
--- a/test/orm/pickled.py
+++ b/test/orm/pickled.py
@@ -2,7 +2,7 @@ import testenv; testenv.configure_for_tests()
import pickle
from testlib import sa, testing
from testlib.sa import Table, Column, Integer, String, ForeignKey
-from testlib.sa.orm import mapper, relation, create_session
+from testlib.sa.orm import mapper, relation, create_session, attributes
from orm import _base, _fixtures
@@ -141,6 +141,21 @@ class PolymorphicDeferredTest(_base.MappedTest):
assert 'email_address' not in eu2.__dict__
self.assertEquals(eu2.email_address, 'foo@bar.com')
-
+class CustomSetupTeardowntest(_fixtures.FixtureTest):
+ @testing.resolve_artifact_names
+ def test_rebuild_state(self):
+ """not much of a 'test', but illustrate how to
+ remove instance-level state before pickling.
+
+ """
+ mapper(User, users)
+
+ u1 = User()
+ attributes.manager_of_class(User).teardown_instance(u1)
+ assert not u1.__dict__
+ u2 = pickle.loads(pickle.dumps(u1))
+ attributes.manager_of_class(User).setup_instance(u2)
+ assert attributes.instance_state(u2)
+
if __name__ == '__main__':
testenv.main()