From: Mike Bayer Date: Mon, 4 Dec 2017 21:40:20 +0000 (-0500) Subject: Propagate attachment events for ARRAY X-Git-Tag: rel_1_2_0~16^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=36d0a27770efdebb0b1891083cb72d8ac65c4788;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Propagate attachment events for ARRAY Fixed regression in :class:`.ARRAY` datatype caused by :ticket:`3964`, which is essentially the same issue as that of :ticket:`3832`, where column attachment events for :class:`.ARRAY` would not be invoked. This breaks the use case of using declarative mixins that declare a :class:`.Column` which makes use of :meth:`.MutableList.as_mutable`. Change-Id: If8c57615860883837f6cf72661e46180a77778c1 Fixes: #4141 --- diff --git a/doc/build/changelog/unreleased_12/4141.rst b/doc/build/changelog/unreleased_12/4141.rst new file mode 100644 index 0000000000..24e04b9a89 --- /dev/null +++ b/doc/build/changelog/unreleased_12/4141.rst @@ -0,0 +1,10 @@ +.. change:: + :tags: bug, sql, ext + :tickets: 4141 + + Fixed issue in :class:`.ARRAY` datatype which is essentially the same + issue as that of :ticket:`3832`, except not a regression, where + column attachment events on top of :class:`.ARRAY` would not fire + correctly, thus interfering with systems which rely upon this. A key + use case that was broken by this is the use of mixins to declare + columns that make use of :meth:`.MutableList.as_mutable`. diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index 2a30bf8321..872ccfe744 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -2411,6 +2411,8 @@ class ARRAY(SchemaEventTarget, Indexable, Concatenable, TypeEngine): def _set_parent_with_dispatch(self, parent): """Support SchemaEventTarget""" + super(ARRAY, self)._set_parent_with_dispatch(parent) + if isinstance(self.item_type, SchemaEventTarget): self.item_type._set_parent_with_dispatch(parent) diff --git a/test/ext/test_mutable.py b/test/ext/test_mutable.py index e90ea7af27..16fd52d97b 100644 --- a/test/ext/test_mutable.py +++ b/test/ext/test_mutable.py @@ -846,6 +846,26 @@ class MutableColumnCopyJSONTest(_MutableDictTestBase, fixtures.MappedTest): self._test_non_mutable() +class MutableColumnCopyArrayTest(_MutableListTestBase, fixtures.MappedTest): + __requires__ = 'array_type', + + @classmethod + def define_tables(cls, metadata): + from sqlalchemy.ext.declarative import declarative_base + from sqlalchemy.sql.sqltypes import ARRAY + + MutableList = cls._type_fixture() + + Base = declarative_base(metadata=metadata) + + class Mixin(object): + data = Column(MutableList.as_mutable(ARRAY(Integer))) + + class Foo(Mixin, Base): + __tablename__ = 'foo' + id = Column(Integer, primary_key=True) + + class MutableListWithScalarPickleTest(_MutableListTestBase, fixtures.MappedTest): diff --git a/test/sql/test_metadata.py b/test/sql/test_metadata.py index 7071782c41..45eb594534 100644 --- a/test/sql/test_metadata.py +++ b/test/sql/test_metadata.py @@ -7,7 +7,7 @@ from sqlalchemy import Integer, String, UniqueConstraint, \ ForeignKeyConstraint, PrimaryKeyConstraint, ColumnDefault, Index, event,\ events, Unicode, types as sqltypes, bindparam, \ Table, Column, Boolean, Enum, func, text, TypeDecorator, \ - BLANK_SCHEMA + BLANK_SCHEMA, ARRAY from sqlalchemy import schema, exc from sqlalchemy.engine import default from sqlalchemy.sql import elements, naming @@ -1650,6 +1650,14 @@ class SchemaTypeTest(fixtures.TestBase): typ = MyType() self._test_before_parent_attach(typ, target_typ, double=True) + def test_before_parent_attach_array_enclosing_schematype(self): + # test for [ticket:4141] which is the same idea as [ticket:3832] + # for ARRAY + + typ = ARRAY(String) + + self._test_before_parent_attach(typ) + def test_before_parent_attach_typedec_of_schematype(self): class MyType(TypeDecorator, sqltypes.SchemaType): impl = String