Reputation: 1021
mypy reports an error in the following code:
import enum
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Enum
Base = declarative_base()
class MyEnum(enum.Enum):
A = 1
B = 2
class MyTable(Base):
__tablename__ = 'my_table'
col = Column(Enum(MyEnum), nullable=False)
c = MyTable(col=MyEnum.A)
Following is the error:
a.py:16: error: Incompatible type for "col" of "MyTable" (got "MyEnum", expected "str")
How do I make this error go away without adding a "type: ignore" ? I could also replace MyEnum.A with MyEnum.A.name to make the error go away. But this doesn't look clean and is also not suggested in sqlalchemy documentation.
Upvotes: 11
Views: 7145
Reputation: 830
You have to introduce them yourself in your script. The dynamically created Base
class is of type DeclarativeMeta
. If you type annotate the variable Base, mypy does not show the error any more.
from sqlalchemy.orm.decl_api import DeclarativeMeta
Base: DeclarativeMeta = declarative_base()
Now the Base variable is properly type annotated. I think that the DeclarativeMeta class is not to be exposed in the API, so I'm not sure how sustainable this solution will be.
Upvotes: 4
Reputation: 2331
You have to import the base class:
SQLAlchemy <v2:
from sqlalchemy.orm.decl_api import DeclarativeMeta
Base: DeclarativeMeta = declarative_base()
see https://docs.sqlalchemy.org/en/13/orm/extensions/declarative/basic_use.html
Or SQLAlchemy v2+:
from sqlalchemy.orm import DeclarativeBase
class Base(DeclarativeBase):
pass
See: https://docs.sqlalchemy.org/en/20/orm/mapping_styles.html#mapped-class-essential-components
NB the first method also works for v2, but the latter is probably preferable, and certainly easier to understand as it follows Python's normal inheritance system..
Upvotes: 3
Reputation: 578
I don't know what exactly makes this error go away but on my setup after some refactoring and mypy
configuring this error disappeared.
I installed sqlalchemy-stubs
pip install sqlalchemy-stubs
and created setup.cfg file:
[mypy]
files = **/*.py
plugins =
sqlalchemy.ext.mypy.plugin
import enum
from sqlalchemy import Column, Enum
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class MyEnum(enum.Enum):
"""My enum."""
ONE = 1
TWO = 2
class MyTable(Base):
"""My table."""
__tablename__ = 'my_table'
col = Column(Enum(MyEnum), nullable=False)
table = MyTable(col=MyEnum.ONE)
Upvotes: 6