- Using a mixin won't break if the mixin implements an
unpredictable __getattribute__(), i.e. Zope interfaces.
[ticket:1746]
+
+ - Using @classdecorator and similar on mixins to define
+ __tablename__, __table_args__, etc. now works if
+ the method references attributes on the ultimate
+ subclass. [ticket:1749]
0.6beta2
========
def _as_declarative(cls, classname, dict_):
- # doing it this way enables these attributes to be descriptors,
- # see below...
- get_mapper_args = '__mapper_args__' in dict_
- get_table_args = '__table_args__' in dict_
-
# dict_ will be a dictproxy, which we can't write to, and we need to!
dict_ = dict(dict_)
column_copies = dict()
-
+ unmapped_mixins = False
for base in cls.__bases__:
names = dir(base)
if not _is_mapped_class(base):
+ unmapped_mixins = True
for name in names:
obj = getattr(base,name, None)
if isinstance(obj, Column):
dict_[name]=column_copies[obj]=obj.copy()
- get_mapper_args = get_mapper_args or getattr(base,'__mapper_args__',None)
- get_table_args = get_table_args or getattr(base,'__table_args__',None)
- tablename = getattr(base,'__tablename__',None)
- if tablename:
- # subtle: if tablename is a descriptor here, we actually
- # put the wrong value in, but it serves as a marker to get
- # the right value value...
- dict_['__tablename__']=tablename
+
+ # doing it this way enables these attributes to be descriptors
+ get_mapper_args = '__mapper_args__' in dict_
+ get_table_args = '__table_args__' in dict_
+ if unmapped_mixins:
+ get_mapper_args = get_mapper_args or getattr(cls,'__mapper_args__',None)
+ get_table_args = get_table_args or getattr(cls,'__table_args__',None)
+ tablename = getattr(cls,'__tablename__',None)
+ if tablename:
+ # subtle: if tablename is a descriptor here, we actually
+ # put the wrong value in, but it serves as a marker to get
+ # the right value value...
+ dict_['__tablename__']=tablename
# now that we know whether or not to get these, get them from the class
# if we should, enabling them to be decorators
eq_(MyModel.__table__.name,'mymodel1')
+ def test_table_name_dependent_on_subclass(self):
+ class MyHistoryMixin:
+ @classproperty
+ def __tablename__(cls):
+ return cls.parent_name + '_changelog'
+
+ class MyModel(Base, MyHistoryMixin):
+ parent_name = 'foo'
+ id = Column(Integer, primary_key=True)
+
+ eq_(MyModel.__table__.name, 'foo_changelog')
+
def test_table_args_inherited(self):
class MyMixin: