dropbox / sqlalchemy-stubs

Mypy plugin and stubs for SQLAlchemy
Apache License 2.0
570 stars 101 forks source link

Why does sqlalchemy not infer the correct type if the custom type is used with a module import? #242

Closed danielmoessner closed 2 years ago

danielmoessner commented 2 years ago

I've got the following init.py file in src/database:

from .uuid import UUID

And I've got the following custom type in src/database/uuid.py:

if TYPE_CHECKING:
    UUIDTypeDecorator = TypeDecorator[uuid.UUID]
else:
    UUIDTypeDecorator = TypeDecorator

class UUID(UUIDTypeDecorator):
    """
    Platform-independent UUID type.
    Uses PostgreSQL's UUID type, otherwise uses CHAR(32), storing as stringified hex values.
    Taken from SQLAlchemy docs: https://docs.sqlalchemy.org/en/13/core/custom_types.html#backend-agnostic-guid-type
    """

    impl = CHAR
    cache_ok = True

    ...

Now I get an error when I try to use it as database.UUID but not with UUID: image

Code:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column
from uuid import UUID

from src.database.uuid import UUID as DUUID
from src import database

Base = declarative_base()

class BaseModel(Base):
    __abstract__ = True

    id: UUID = Column(database.UUID, primary_key=True, index=True)
    user_id: UUID = Column(DUUID, index=True, nullable=False)

Why does mypy work correctly with user_id: UUID = Column(DUUID, index=True, nullable=False) but not with id: UUID = Column(database.UUID, primary_key=True, index=True)?

danielmoessner commented 2 years ago

A circular import error seems to have caused the problem. Interesting how this changed the type inference.