diff options
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | lib/sqlalchemy/ext/declarative.py | 2 | ||||
-rw-r--r-- | test/ext/test_declarative.py | 35 |
3 files changed, 39 insertions, 3 deletions
@@ -71,6 +71,11 @@ CHANGES - The psycopg2 dialect will log NOTICE messages via the "sqlalchemy.dialects.postgresql" logger name. [ticket:877] + +- declarative + - Using a mixin won't break if the mixin implements an + unpredictable __getattribute__(), i.e. Zope interfaces. + [ticket:1746] 0.6beta2 ======== diff --git a/lib/sqlalchemy/ext/declarative.py b/lib/sqlalchemy/ext/declarative.py index 775efbff1..435d38161 100644 --- a/lib/sqlalchemy/ext/declarative.py +++ b/lib/sqlalchemy/ext/declarative.py @@ -545,7 +545,7 @@ def _as_declarative(cls, classname, dict_): names = dir(base) if not _is_mapped_class(base): for name in names: - obj = getattr(base,name) + 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) diff --git a/test/ext/test_declarative.py b/test/ext/test_declarative.py index a6f3f7a79..fbe47ee7f 100644 --- a/test/ext/test_declarative.py +++ b/test/ext/test_declarative.py @@ -6,7 +6,9 @@ import sqlalchemy as sa from sqlalchemy.test import testing from sqlalchemy import MetaData, Integer, String, ForeignKey, ForeignKeyConstraint, asc, Index from sqlalchemy.test.schema import Table, Column -from sqlalchemy.orm import relationship, create_session, class_mapper, joinedload, compile_mappers, backref, clear_mappers, polymorphic_union, deferred +from sqlalchemy.orm import relationship, create_session, class_mapper, \ + joinedload, compile_mappers, backref, clear_mappers, \ + polymorphic_union, deferred from sqlalchemy.test.testing import eq_ from sqlalchemy.util import classproperty @@ -75,7 +77,9 @@ class DeclarativeTest(DeclarativeTestBase): __table__ = t foo = Column(Integer, primary_key=True) # can't specify new columns not already in the table - assert_raises_message(sa.exc.ArgumentError, "Can't add additional column 'foo' when specifying __table__", go) + assert_raises_message(sa.exc.ArgumentError, + "Can't add additional column 'foo' when specifying __table__", + go) # regular re-mapping works tho class Bar(Base): @@ -84,6 +88,33 @@ class DeclarativeTest(DeclarativeTestBase): assert class_mapper(Bar).get_property('some_data').columns[0] is t.c.data + def test_difficult_class(self): + """test no getattr() errors with a customized class""" + + # metaclass to mock the way zope.interface breaks getattr() + class BrokenMeta(type): + def __getattribute__(self, attr): + if attr == 'xyzzy': + raise AttributeError, 'xyzzy' + else: + return object.__getattribute__(self,attr) + + # even though this class has an xyzzy attribute, getattr(cls,"xyzzy") + # fails + class BrokenParent(object): + __metaclass__ = BrokenMeta + xyzzy = "magic" + + # _as_declarative() inspects obj.__class__.__bases__ + class User(BrokenParent,ComparableEntity): + __tablename__ = 'users' + id = Column('id', Integer, primary_key=True, + test_needs_autoincrement=True) + name = Column('name', String(50)) + + decl.instrument_declarative(User,{},Base.metadata) + + def test_undefer_column_name(self): # TODO: not sure if there was an explicit # test for this elsewhere |