TypeError: Cannot create a consistent method resolution order (MRO) for bases Comparator, TDComparator

Issue #3102 resolved
Martijn van Oosterhout created an issue

I received the above error trying to generate query comparing a variant type. Test program:

import sqlalchemy
from sqlalchemy.types import TypeDecorator
from sqlalchemy import Text, Column
from sqlalchemy.ext.declarative import declarative_base

class TestType(TypeDecorator):
    impl = Text

MyType = TestType().with_variant(Text, 'postgresql')

Base = declarative_base()

class TestTable(Base):
    __tablename__ = 'test'
    column = Column('test', MyType, primary_key=True)

print sqlalchemy.__version__
TestTable.column == None    # Dies

Exception:

0.9.6
Traceback (most recent call last):
  File "test.py", line 18, in <module>
    TestTable.column == None
  File "/tmp/test/local/lib/python2.7/site-packages/sqlalchemy/sql/operators.py", line 296, in __eq__
    return self.operate(eq, other)
  File "/tmp/test/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 171, in operate
    return op(self.comparator, *other, **kwargs)
  File "/tmp/test/local/lib/python2.7/site-packages/sqlalchemy/sql/operators.py", line 296, in __eq__
    return self.operate(eq, other)
  File "/tmp/test/local/lib/python2.7/site-packages/sqlalchemy/orm/properties.py", line 251, in operate
    return op(self.__clause_element__(), *other, **kwargs)
  File "/tmp/test/local/lib/python2.7/site-packages/sqlalchemy/sql/annotation.py", line 90, in __eq__
    return self.__element.__class__.__eq__(self, other)
  File "/tmp/test/local/lib/python2.7/site-packages/sqlalchemy/sql/operators.py", line 296, in __eq__
    return self.operate(eq, other)
  File "/tmp/test/local/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", line 664, in operate
    return op(self.comparator, *other, **kwargs)
  File "/tmp/test/local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 712, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/tmp/test/local/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", line 650, in comparator
    return self.type.comparator_factory(self)
  File "/tmp/test/local/lib/python2.7/site-packages/sqlalchemy/sql/type_api.py", line 635, in comparator_factory
    {})
TypeError: Cannot create a consistent method resolution
order (MRO) for bases Comparator, TDComparator

I can fix it in type_api.py by reversing the order of the bases classes, but I'm not sure if that has any other effects.

class TypeDecorator(TypeEngine):
    @property
    def comparator_factory(self):
        return type("TDComparator",
                    (self.impl.comparator_factory, TypeDecorator.Comparator,),  # <- Order reversed
                    {})

Tested on 0.8.4 and 0.9.6.

Comments (10)

  1. Mike Bayer repo owner

    interesting, this may be just a general TypeDecorator problem. always surprising what's not tested!

  2. Mike Bayer repo owner
    • Fixed a bug within the custom operator plus :meth:.TypeEngine.with_variant system, whereby using a :class:.TypeDecorator in conjunction with variant would fail with an MRO error when a comparison operator was used. fixes #3102

    → <<cset 01215cdaef45>>

  3. Mike Bayer repo owner
    • Fixed a bug within the custom operator plus :meth:.TypeEngine.with_variant system, whereby using a :class:.TypeDecorator in conjunction with variant would fail with an MRO error when a comparison operator was used. fixes #3102

    → <<cset c0ca5a990744>>

  4. Mike Bayer repo owner
    • Fixed a bug within the custom operator plus :meth:.TypeEngine.with_variant system, whereby using a :class:.TypeDecorator in conjunction with variant would fail with an MRO error when a comparison operator was used. fixes #3102

    Conflicts: lib/sqlalchemy/sql/type_api.py

    → <<cset a96267639a91>>

  5. Log in to comment