From d1ac6cb33af3b105db7cdb51411e10ac3bafff1f Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 19 Dec 2014 12:14:52 -0500 Subject: [PATCH] - Fixed bug where using a :class:`.TypeDecorator` that implemented a type that was also a :class:`.TypeDecorator` would fail with Python's "Cannot create a consistent method resolution order (MRO)" error, when any kind of SQL comparison expression were used against an object using this type. --- doc/build/changelog/changelog_09.rst | 11 +++++++++++ lib/sqlalchemy/sql/type_api.py | 10 +++++++--- test/sql/test_operators.py | 25 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst index b2c876141e..4ff73c45df 100644 --- a/doc/build/changelog/changelog_09.rst +++ b/doc/build/changelog/changelog_09.rst @@ -13,6 +13,17 @@ .. changelog:: :version: 0.9.9 + .. change:: + :tags: bug, sql + :versions: 1.0.0 + :tickets: 3278 + + Fixed bug where using a :class:`.TypeDecorator` that implemented + a type that was also a :class:`.TypeDecorator` would fail with + Python's "Cannot create a consistent method resolution order (MRO)" + error, when any kind of SQL comparison expression were used against + an object using this type. + .. change:: :tags: bug, mysql :versions: 1.0.0 diff --git a/lib/sqlalchemy/sql/type_api.py b/lib/sqlalchemy/sql/type_api.py index d3e0a008ec..d414daf2ab 100644 --- a/lib/sqlalchemy/sql/type_api.py +++ b/lib/sqlalchemy/sql/type_api.py @@ -630,9 +630,13 @@ class TypeDecorator(TypeEngine): @property def comparator_factory(self): - return type("TDComparator", - (TypeDecorator.Comparator, self.impl.comparator_factory), - {}) + if TypeDecorator.Comparator in self.impl.comparator_factory.__mro__: + return self.impl.comparator_factory + else: + return type("TDComparator", + (TypeDecorator.Comparator, + self.impl.comparator_factory), + {}) def _gen_dialect_impl(self, dialect): """ diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py index f8ac1528f0..3b8b205138 100644 --- a/test/sql/test_operators.py +++ b/test/sql/test_operators.py @@ -393,6 +393,31 @@ class TypeDecoratorComparatorTest(_CustomComparatorTests, fixtures.TestBase): return MyInteger +class TypeDecoratorTypeDecoratorComparatorTest( + _CustomComparatorTests, fixtures.TestBase): + + def _add_override_factory(self): + + class MyIntegerOne(TypeDecorator): + impl = Integer + + class comparator_factory(TypeDecorator.Comparator): + + def __init__(self, expr): + self.expr = expr + + def __add__(self, other): + return self.expr.op("goofy")(other) + + def __and__(self, other): + return self.expr.op("goofy_and")(other) + + class MyIntegerTwo(TypeDecorator): + impl = MyIntegerOne + + return MyIntegerTwo + + class TypeDecoratorWVariantComparatorTest( _CustomComparatorTests, fixtures.TestBase): -- 2.47.3