From 50176cf290767b6dbd2e361b4440d308328be173 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 8 Jul 2010 10:50:13 -0400 Subject: [PATCH] added an extra check for the correct class when __init__ is called, to fix the second half of [ticket:1846] --- lib/sqlalchemy/orm/attributes.py | 9 ++++++++ test/orm/test_mapper.py | 37 +++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index e987402871..2405d91c0b 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -1118,6 +1118,15 @@ class ClassManager(dict): """ if hasattr(instance, self.STATE_ATTR): return False + elif self.class_ is not instance.__class__ and \ + self.is_mapped: + # this will create a new ClassManager for the + # subclass, without a mapper. This is likely a + # user error situation but allow the object + # to be constructed, so that it is usable + # in a non-ORM context at least. + return self._subclass_manager(instance.__class__).\ + _new_state_if_none(instance) else: state = self._create_instance_state(instance) setattr(instance, self.STATE_ATTR, state) diff --git a/test/orm/test_mapper.py b/test/orm/test_mapper.py index 2de77fd2c5..be135316d5 100644 --- a/test/orm/test_mapper.py +++ b/test/orm/test_mapper.py @@ -1076,7 +1076,7 @@ class MapperTest(_fixtures.FixtureTest): assert_raises(sa.orm.exc.UnmappedClassError, sa.orm.compile_mappers) @testing.resolve_artifact_names - def test_unmapped_subclass_error(self): + def test_unmapped_subclass_error_postmap(self): class Base(object): pass class Sub(Base): @@ -1084,9 +1084,44 @@ class MapperTest(_fixtures.FixtureTest): mapper(Base, users) sa.orm.compile_mappers() + + # we can create new instances, set attributes. + s = Sub() + s.name = 'foo' + eq_(s.name, 'foo') + eq_( + attributes.get_history(s, 'name'), + (['foo'], (), ()) + ) + + # using it with an ORM operation, raises assert_raises(sa.orm.exc.UnmappedClassError, create_session().add, Sub()) + + @testing.resolve_artifact_names + def test_unmapped_subclass_error_premap(self): + class Base(object): + pass + + mapper(Base, users) + class Sub(Base): + pass + + sa.orm.compile_mappers() + + # we can create new instances, set attributes. + s = Sub() + s.name = 'foo' + eq_(s.name, 'foo') + eq_( + attributes.get_history(s, 'name'), + (['foo'], (), ()) + ) + + # using it with an ORM operation, raises + assert_raises(sa.orm.exc.UnmappedClassError, + create_session().add, Sub()) @testing.resolve_artifact_names def test_oldstyle_mixin(self): -- 2.47.2