diff options
| -rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 9 | ||||
| -rw-r--r-- | test/orm/test_mapper.py | 37 |
2 files changed, 45 insertions, 1 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index e98740287..2405d91c0 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 2de77fd2c..be135316d 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): |
