summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-01-22 15:38:00 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2014-01-22 15:38:00 -0500
commit1732414076677e8fb84134325635729691f3d26d (patch)
treed77745e4843f03d5412cb3f2bff3435ca88bd7ee
parentee1f4d21037690ad996c5eacf7e1200e92f2fbaa (diff)
downloadsqlalchemy-1732414076677e8fb84134325635729691f3d26d.tar.gz
- Added new test coverage for so-called "down adaptions" of SQL types,
where a more specific type is adapted to a more generic one - this use case is needed by some third party tools such as ``sqlacodegen``. The specific cases that needed repair within this test suite were that of :class:`.mysql.ENUM` being downcast into a :class:`.types.Enum`, and that of SQLite date types being cast into generic date types. The ``adapt()`` method needed to become more specific here to counteract the removal of a "catch all" ``**kwargs`` collection on the base :class:`.TypeEngine` class that was removed in 0.9. [ticket:2917]
-rw-r--r--doc/build/changelog/changelog_09.rst14
-rw-r--r--lib/sqlalchemy/dialects/mysql/base.py7
-rw-r--r--lib/sqlalchemy/dialects/sqlite/base.py11
-rw-r--r--test/sql/test_types.py22
4 files changed, 43 insertions, 11 deletions
diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst
index d59f3ec60..768326528 100644
--- a/doc/build/changelog/changelog_09.rst
+++ b/doc/build/changelog/changelog_09.rst
@@ -15,6 +15,20 @@
:version: 0.9.2
.. change::
+ :tags: bug, mysql, sql
+ :tickets: 2917
+
+ Added new test coverage for so-called "down adaptions" of SQL types,
+ where a more specific type is adapted to a more generic one - this
+ use case is needed by some third party tools such as ``sqlacodegen``.
+ The specific cases that needed repair within this test suite were that
+ of :class:`.mysql.ENUM` being downcast into a :class:`.types.Enum`,
+ and that of SQLite date types being cast into generic date types.
+ The ``adapt()`` method needed to become more specific here to counteract
+ the removal of a "catch all" ``**kwargs`` collection on the base
+ :class:`.TypeEngine` class that was removed in 0.9.
+
+ .. change::
:tags: feature, sql
:tickets: 2910
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index e45f6ecd8..61698b038 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -1189,9 +1189,10 @@ class ENUM(sqltypes.Enum, _EnumeratedValues):
return value
return process
- def adapt(self, impltype, **kw):
- kw['strict'] = self.strict
- return sqltypes.Enum.adapt(self, impltype, **kw)
+ def adapt(self, cls, **kw):
+ if issubclass(cls, ENUM):
+ kw['strict'] = self.strict
+ return sqltypes.Enum.adapt(self, cls, **kw)
class SET(_EnumeratedValues):
diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py
index 579a61046..d8aa58c2c 100644
--- a/lib/sqlalchemy/dialects/sqlite/base.py
+++ b/lib/sqlalchemy/dialects/sqlite/base.py
@@ -154,11 +154,12 @@ class _DateTimeMixin(object):
self._storage_format = storage_format
def adapt(self, cls, **kw):
- if self._storage_format:
- kw["storage_format"] = self._storage_format
- if self._reg:
- kw["regexp"] = self._reg
- return util.constructor_copy(self, cls, **kw)
+ if issubclass(cls, _DateTimeMixin):
+ if self._storage_format:
+ kw["storage_format"] = self._storage_format
+ if self._reg:
+ kw["regexp"] = self._reg
+ return super(_DateTimeMixin, self).adapt(cls, **kw)
def literal_processor(self, dialect):
bp = self.bind_processor(dialect)
diff --git a/test/sql/test_types.py b/test/sql/test_types.py
index 3a263aab2..3df19874b 100644
--- a/test/sql/test_types.py
+++ b/test/sql/test_types.py
@@ -114,21 +114,37 @@ class AdaptTest(fixtures.TestBase):
"""
- for typ in self._all_types():
+ def adaptions():
+ for typ in self._all_types():
+ up_adaptions = [typ] + typ.__subclasses__()
+ yield False, typ, up_adaptions
+ for subcl in typ.__subclasses__():
+ if subcl is not typ and \
+ typ is not TypeDecorator and \
+ "sqlalchemy" in subcl.__module__:
+ yield True, subcl, [typ]
+
+ for is_down_adaption, typ, target_adaptions in adaptions():
if typ in (types.TypeDecorator, types.TypeEngine, types.Variant):
continue
elif typ is dialects.postgresql.ARRAY:
t1 = typ(String)
else:
t1 = typ()
- for cls in [typ] + typ.__subclasses__():
+ for cls in target_adaptions:
if not issubclass(typ, types.Enum) and \
issubclass(cls, types.Enum):
continue
+
+ # print("ADAPT %s -> %s" % (t1.__class__, cls))
t2 = t1.adapt(cls)
assert t1 is not t2
+
+ if is_down_adaption:
+ t2, t1 = t1, t2
+
for k in t1.__dict__:
- if k == 'impl':
+ if k in ('impl', '_is_oracle_number'):
continue
# assert each value was copied, or that
# the adapted type has a more specific