summaryrefslogtreecommitdiff
path: root/test/sql/test_metadata.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2016-10-17 00:22:38 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2016-10-17 12:13:01 -0400
commit8ef4f6a53864ce9c57c4879d6b2aa0f81ddbf596 (patch)
tree69575ef2f444ca2c9818956a6b0c561c0c55a6d0 /test/sql/test_metadata.py
parentc02675b407b8326643b559770d6d9686b880c113 (diff)
downloadsqlalchemy-8ef4f6a53864ce9c57c4879d6b2aa0f81ddbf596.tar.gz
Add explicit copy() to Enum
The Boolean and Enum types both place SchemaType second in the inheritance hierarchy. In the case of Enum, this works out that the copy() method is called from the base TypeEngine which fails to transfer _create_events. The test suite doesn't seem to work with the inhertance hierarchy set up like this as the event listeners don't work out, the _on_metadata_create and _on_table_create hooks cause the production of an adapted type which then adds event listeners that cause deque changed while iteration. It's not clear why Enum /Boolean don't have this problem. But in any case it seems like the class mechanics for these types remains fragile and would benefit from yet another refactor someday. Change-Id: Ib641a5d2321b00f58bbe98dd0c5e789374db32b2 Fixes: #3827
Diffstat (limited to 'test/sql/test_metadata.py')
-rw-r--r--test/sql/test_metadata.py47
1 files changed, 41 insertions, 6 deletions
diff --git a/test/sql/test_metadata.py b/test/sql/test_metadata.py
index af291b842..f2df4da06 100644
--- a/test/sql/test_metadata.py
+++ b/test/sql/test_metadata.py
@@ -1,7 +1,6 @@
from sqlalchemy.testing import assert_raises
from sqlalchemy.testing import assert_raises_message
from sqlalchemy.testing import emits_warning
-
import pickle
from sqlalchemy import Integer, String, UniqueConstraint, \
CheckConstraint, ForeignKey, MetaData, Sequence, \
@@ -16,7 +15,7 @@ import sqlalchemy as tsa
from sqlalchemy.testing import fixtures
from sqlalchemy import testing
from sqlalchemy.testing import ComparesTables, AssertsCompiledSQL
-from sqlalchemy.testing import eq_, is_, mock
+from sqlalchemy.testing import eq_, is_, mock, is_true
from contextlib import contextmanager
from sqlalchemy import util
@@ -1534,26 +1533,39 @@ class PKAutoIncrementTest(fixtures.TestBase):
class SchemaTypeTest(fixtures.TestBase):
- class MyType(sqltypes.SchemaType, sqltypes.TypeEngine):
+ class TrackEvents(object):
column = None
table = None
evt_targets = ()
def _set_table(self, column, table):
- super(SchemaTypeTest.MyType, self)._set_table(column, table)
+ super(SchemaTypeTest.TrackEvents, self)._set_table(column, table)
self.column = column
self.table = table
def _on_table_create(self, target, bind, **kw):
- super(SchemaTypeTest.MyType, self)._on_table_create(
+ super(SchemaTypeTest.TrackEvents, self)._on_table_create(
target, bind, **kw)
self.evt_targets += (target,)
def _on_metadata_create(self, target, bind, **kw):
- super(SchemaTypeTest.MyType, self)._on_metadata_create(
+ super(SchemaTypeTest.TrackEvents, self)._on_metadata_create(
target, bind, **kw)
self.evt_targets += (target,)
+ # TODO: Enum and Boolean put TypeEngine first. Changing that here
+ # causes collection-mutate-while-iterated errors in the event system
+ # since the hooks here call upon the adapted type. Need to figure out
+ # why Enum and Boolean don't have this problem.
+ class MyType(TrackEvents, sqltypes.SchemaType, sqltypes.TypeEngine):
+ pass
+
+ class WrapEnum(TrackEvents, Enum):
+ pass
+
+ class WrapBoolean(TrackEvents, Boolean):
+ pass
+
class MyTypeWImpl(MyType):
def _gen_dialect_impl(self, dialect):
@@ -1656,6 +1668,29 @@ class SchemaTypeTest(fixtures.TestBase):
eq_(t1.c.y.type.evt_targets, (t1,))
eq_(t2.c.y.type.evt_targets, (t2, t2))
+ def test_enum_column_copy_transfers_events(self):
+ m = MetaData()
+
+ type_ = self.WrapEnum('a', 'b', 'c', name='foo')
+ y = Column('y', type_)
+ y_copy = y.copy()
+ t1 = Table('x', m, y_copy)
+
+ is_true(y_copy.type._create_events)
+
+ m.dispatch.before_create(t1, testing.db)
+ eq_(t1.c.y.type.evt_targets, (t1, ))
+
+ def test_boolean_column_copy_transfers_events(self):
+ m = MetaData()
+
+ type_ = self.WrapBoolean()
+ y = Column('y', type_)
+ y_copy = y.copy()
+ t1 = Table('x', m, y_copy)
+
+ is_true(y_copy.type._create_events)
+
def test_metadata_dispatch_no_new_impl(self):
m1 = MetaData()
typ = self.MyType(metadata=m1)