]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- The ``__mapper_args__`` dictionary is copied from a declarative
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 30 May 2014 19:36:13 +0000 (15:36 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 30 May 2014 19:36:47 +0000 (15:36 -0400)
mixin or abstract class when accessed, so that modifications made
to this dictionary by declarative itself won't conflict with that
of other mappings.  The dictionary is modified regarding the
``version_id_col`` and ``polymorphic_on`` arguments, replacing the
column within with the one that is officially mapped to the local
class/table. fixes #3062

doc/build/changelog/changelog_08.rst
lib/sqlalchemy/ext/declarative/base.py
test/ext/declarative/test_mixin.py

index 8b00ce1faa780305412ebf1fbd05d24da514b28f..7736f779963b47e6309a493685c8ac3540776c7d 100644 (file)
 .. changelog::
     :version: 0.8.7
 
+    .. change::
+        :tags: bug, declarative
+        :versions: 1.0.0, 0.9.5
+        :tickets: 3062
+
+        The ``__mapper_args__`` dictionary is copied from a declarative
+        mixin or abstract class when accessed, so that modifications made
+        to this dictionary by declarative itself won't conflict with that
+        of other mappings.  The dictionary is modified regarding the
+        ``version_id_col`` and ``polymorphic_on`` arguments, replacing the
+        column within with the one that is officially mapped to the local
+        class/table.
+
     .. change::
         :tags: bug, sql
         :versions: 0.9.5, 1.0.0
index cfcd13a1816691c8191bd89f7c500500c322be6f..9da2ed7271e0958b2862d9a69d0957d886bc7b3a 100644 (file)
@@ -66,7 +66,10 @@ def _as_declarative(cls, classname, dict_):
                     # don't even invoke __mapper_args__ until
                     # after we've determined everything about the
                     # mapped table.
-                    mapper_args_fn = lambda: cls.__mapper_args__
+                    # make a copy of it so a class-level dictionary
+                    # is not overwritten when we update column-based
+                    # arguments.
+                    mapper_args_fn = lambda: dict(cls.__mapper_args__)
             elif name == '__tablename__':
                 if not tablename and (
                                         not class_mapped or
index fb674f27a2f6f0d7969c864f238bd53dcf2dabc0..70fe115fb5a5923d8d1466616957654c83eb8207 100644 (file)
@@ -1173,6 +1173,33 @@ class DeclarativeMixinPropertyTest(DeclarativeTestBase):
         eq_(col.name, 'type_')
         assert col.table is not None
 
+    def test_column_in_mapper_args_used_multiple_times(self):
+
+        class MyMixin(object):
+
+            version_id = Column(Integer)
+            __mapper_args__ = {'version_id_col': version_id}
+
+        class ModelOne(Base, MyMixin):
+
+            __tablename__ = 'm1'
+            id = Column(Integer, primary_key=True)
+
+        class ModelTwo(Base, MyMixin):
+
+            __tablename__ = 'm2'
+            id = Column(Integer, primary_key=True)
+
+        is_(
+            ModelOne.__mapper__.version_id_col,
+            ModelOne.__table__.c.version_id
+        )
+        is_(
+            ModelTwo.__mapper__.version_id_col,
+            ModelTwo.__table__.c.version_id
+        )
+
+
     def test_deferred(self):
 
         class MyMixin(object):