Rahul
Rahul

Reputation: 1021

How to resolve mypy error with sqlalchemy enum?

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

Answers (3)

marscher
marscher

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

toonarmycaptain
toonarmycaptain

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

Konstantin
Konstantin

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

Related Questions