.. changelog::
: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
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):
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)
"""
- 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