From 6de7db07cecd7f6f86452cdc64270c83b5bef212 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 19 Jun 2010 13:25:37 -0400 Subject: [PATCH] - a mixin class can now define a column that matches one which is present on a __table__ defined on a subclass. It cannot, however, define one that is not present in the __table__, and the error message here now works. [ticket:1821] --- CHANGES | 7 ++++ lib/sqlalchemy/ext/declarative.py | 6 ++-- test/ext/test_declarative.py | 57 +++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 8d1b3207db..f41bac381d 100644 --- a/CHANGES +++ b/CHANGES @@ -87,6 +87,13 @@ CHANGES - Fixed incorrect signature in do_execute(), error introduced in 0.6.1. [ticket:1823] +- declarative + - a mixin class can now define a column that matches + one which is present on a __table__ defined on a + subclass. It cannot, however, define one that is + not present in the __table__, and the error message + here now works. [ticket:1821] + - documentation - Added documentation for the Inspector. [ticket:1820] diff --git a/lib/sqlalchemy/ext/declarative.py b/lib/sqlalchemy/ext/declarative.py index 8a28bb07cc..385e0a309d 100755 --- a/lib/sqlalchemy/ext/declarative.py +++ b/lib/sqlalchemy/ext/declarative.py @@ -645,7 +645,7 @@ def _as_declarative(cls, classname, dict_): mapper_args ={} table_args = inherited_table_args = None tablename = None - parent_columns = None + parent_columns = () for base in cls.__mro__: if _is_mapped_class(base): @@ -670,7 +670,9 @@ def _as_declarative(cls, classname, dict_): "Columns with foreign keys to other columns " "are not allowed on declarative mixins at this time." ) - if name not in dict_: + if name not in dict_ and not ( + '__table__' in dict_ and name in dict_['__table__'].c + ): potential_columns[name]=column_copies[obj]=obj.copy() elif isinstance(obj, RelationshipProperty): raise exceptions.InvalidRequestError( diff --git a/test/ext/test_declarative.py b/test/ext/test_declarative.py index 87793658df..04ce401e58 100644 --- a/test/ext/test_declarative.py +++ b/test/ext/test_declarative.py @@ -2365,3 +2365,60 @@ class DeclarativeMixinTest(DeclarativeTestBase): __mapper_args__ = dict(polymorphic_identity='specific') eq_(BaseType.__table__.c.keys(),['type', 'id', 'timestamp']) + + def test_table_in_model_and_same_column_in_mixin(self): + + class ColumnMixin: + data = Column(Integer) + + class Model(Base, ColumnMixin): + __table__ = Table( + 'foo', + Base.metadata, + Column('data', Integer), + Column('id', Integer, primary_key=True) + ) + + model_col = Model.__table__.c.data + mixin_col = ColumnMixin.data + assert model_col is not mixin_col + eq_(model_col.name, 'data') + assert model_col.type.__class__ is mixin_col.type.__class__ + + def test_table_in_model_and_different_named_column_in_mixin(self): + + class ColumnMixin: + tada = Column(Integer) + + def go(): + class Model(Base, ColumnMixin): + __table__ = Table( + 'foo', + Base.metadata, + Column('data', Integer), + Column('id', Integer, primary_key=True) + ) + + assert_raises_message( + sa.exc.ArgumentError, + "Can't add additional column 'tada' when specifying __table__", + go) + + def test_table_in_model_overrides_different_typed_column_in_mixin(self): + + class ColumnMixin: + data = Column(String) + + class Model(Base, ColumnMixin): + __table__ = Table( + 'foo', + Base.metadata, + Column('data', Integer), + Column('id', Integer, primary_key=True) + ) + + model_col = Model.__table__.c.data + mixin_col = ColumnMixin.data + assert model_col is not mixin_col + eq_(model_col.name, 'data') + assert model_col.type.__class__ is Integer -- 2.47.2