Issues

Issue #3122 resolved

TypeError: unbound method _compiler_dispatch() must be called with Text instance as first argument

Martijn van Oosterhout
created an issue

There appears to be a problem using with_variant with sqlite. Consider this example program:

import sqlalchemy
from sqlalchemy import Text, Column, create_engine
from sqlalchemy.ext.declarative import declarative_base

#MyType = Text().with_variant(Text, 'postgresql')   # works
MyType = Text().with_variant(Text, 'sqlite')    # breaks

Base = declarative_base()

Base.metadata.bind = create_engine('sqlite://')

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

print sqlalchemy.__version__
Base.metadata.create_all()

Dies for me with the following error on 0.8.4 and 0.9.6:

Traceback (most recent call last):
  File "test2.py", line 17, in <module>
    Base.metadata.create_all()
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/schema.py", line 2848, in create_all
    tables=tables)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1479, in _run_visitor
    conn._run_visitor(visitorcallable, element, **kwargs)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1122, in _run_visitor
    **kwargs).traverse_single(element)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py", line 122, in traverse_single
    return meth(obj, **kw)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/ddl.py", line 70, in visit_metadata
    self.traverse_single(table, create_ok=True)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py", line 122, in traverse_single
    return meth(obj, **kw)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/ddl.py", line 89, in visit_table
    self.connection.execute(schema.CreateTable(table))
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 662, in execute
    params)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 714, in _execute_ddl
    compiled = ddl.compile(dialect=dialect)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/sql/expression.py", line 1920, in compile
    return self._compiler(dialect, bind=bind, **kw)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/schema.py", line 2954, in _compiler
    return dialect.ddl_compiler(dialect, self, **kw)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/interfaces.py", line 804, in __init__
    self.string = self.process(self.statement, **compile_kwargs)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/interfaces.py", line 823, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py", line 80, in _compiler_dispatch
    return meth(self, **kw)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/sql/compiler.py", line 1941, in visit_create_table
    and not first_pk)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/interfaces.py", line 823, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py", line 80, in _compiler_dispatch
    return meth(self, **kw)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/sql/compiler.py", line 1980, in visit_create_column
    first_pk=first_pk
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/dialects/sqlite/base.py", line 484, in get_column_specification
    coltype = self.dialect.type_compiler.process(column.type)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/interfaces.py", line 869, in process
    return type_._compiler_dispatch(self)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py", line 80, in _compiler_dispatch
    return meth(self, **kw)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/sql/compiler.py", line 2366, in visit_type_decorator
    return self.process(type_.type_engine(self.dialect))
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/engine/interfaces.py", line 869, in process
    return type_._compiler_dispatch(self)
TypeError: unbound method _compiler_dispatch() must be called with Text instance as first argument (got SQLiteTypeCompiler instance instead)

If you use the line involving 'postgresql' instead, it works just fine.

Comments (7)

  1. Mike Bayer repo owner
    • The :meth:.TypeEngine.with_variant method will now accept a type class as an argument which is internally converted to an instance, using the same convention long established by other constructs such as :class:.Column. fixes #3122

    → <<cset e5d0fa94937b>>

  2. Mike Bayer repo owner
    • The :meth:.TypeEngine.with_variant method will now accept a type class as an argument which is internally converted to an instance, using the same convention long established by other constructs such as :class:.Column. fixes #3122

    → <<cset 6ef47a46c1cd>>

  3. Martijn van Oosterhout reporter

    Hmm, I thought I tested that but that works.

    Why it happened to work for PostgreSQL who knows. But that might explain why this went unnoticed for so long: SQLite only supports basic types, so the variant would almost always have been for another database.

    I see in the test you use 'postgresql', I hope that doesn't mask anything.

    Thanks for the quick fix.

    (sorry if you get this twice, the interface is confusing me)

  4. Mike Bayer repo owner

    if you take the patch out and run the test, it fails with the above stack trace. that's how we know the test covers the issue. (also I know what the issue is).

  5. Log in to comment