diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-03-30 17:52:10 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-03-30 17:52:10 -0400 |
commit | 07b63894cb8ff9529b406f196b5d7cb9af209e9e (patch) | |
tree | 066391964b639e4cba8e74e0808082f896f9937c /lib/sqlalchemy/ext/mutable.py | |
parent | 4eb4010c1a1c3e5c2529b9be9d8d56f1d6a4ec00 (diff) | |
download | sqlalchemy-07b63894cb8ff9529b406f196b5d7cb9af209e9e.tar.gz |
Track SchemaEventTarget types in as_mutable()
Fixed bug in :mod:`sqlalchemy.ext.mutable` where the
:meth:`.Mutable.as_mutable` method would not track a type that had
been copied using :meth:`.TypeEngine.copy`. This became more of
a regression in 1.1 compared to 1.0 because the :class:`.TypeDecorator`
class is now a subclass of :class:`.SchemaEventTarget`, which among
other things indicates to the parent :class:`.Column` that the type
should be copied when the :class:`.Column` is. These copies are
common when using declarative with mixins or abstract classes.
Change-Id: Ib04df862c58263185dbae686c548fea3e12c46f1
Fixes: #3950
Diffstat (limited to 'lib/sqlalchemy/ext/mutable.py')
-rw-r--r-- | lib/sqlalchemy/ext/mutable.py | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/lib/sqlalchemy/ext/mutable.py b/lib/sqlalchemy/ext/mutable.py index 79459b39c..a133f950d 100644 --- a/lib/sqlalchemy/ext/mutable.py +++ b/lib/sqlalchemy/ext/mutable.py @@ -352,6 +352,7 @@ from ..orm.attributes import flag_modified from .. import event, types from ..orm import mapper, object_mapper, Mapper from ..util import memoized_property +from ..sql.base import SchemaEventTarget import weakref @@ -584,9 +585,26 @@ class Mutable(MutableBase): """ sqltype = types.to_instance(sqltype) + # a SchemaType will be copied when the Column is copied, + # and we'll lose our ability to link that type back to the original. + # so track our original type w/ columns + if isinstance(sqltype, SchemaEventTarget): + @event.listens_for(sqltype, "before_parent_attach") + def _add_column_memo(sqltyp, parent): + parent.info['_ext_mutable_orig_type'] = sqltyp + schema_event_check = True + else: + schema_event_check = False + def listen_for_type(mapper, class_): for prop in mapper.column_attrs: - if prop.columns[0].type is sqltype: + if ( + schema_event_check and + prop.columns[0].info.get('_ext_mutable_orig_type') + is sqltype + ) or ( + prop.columns[0].type is sqltype + ): cls.associate_with_attribute(getattr(class_, prop.key)) event.listen(mapper, 'mapper_configured', listen_for_type) |