Skip to content

Mypy type errors when using union's of model types #9419

@sjschaff

Description

@sjschaff

Ensure stubs packages are not installed

  • No sqlalchemy stub packages is installed (both sqlalchemy-stubs and sqlalchemy2-stubs are not compatible with v2)

Verify if the api is typed

  • The api is not in a module listed in #6810 so it should pass type checking

Describe the typing issue

When trying to write code which can run on multiple models, type checking can fail if you use a Union type. This appears to be because the types of columns get reduced from sqlalchemy.orm.attributes.InstrumentedAttribute[<type>] to just <type> (see provided repro for better explanation). I'm not sure if this is an issue with mypy, or the sqlalchemy mypy plugin but the latter seemed more likely to me.

To Reproduce

from typing import Type, Union
from sqlalchemy.orm import DeclarativeBase, Mapped, Session

""" Models """
class ModelBase(DeclarativeBase):
  pass

class Model1(ModelBase):
  column_a: Mapped[str]

class Model2(ModelBase):
  column_a: Mapped[str]

ModelUnionType = Union[Type[Model1], Type[Model2]]


""" Repro """
# these would be provided from elsewhere
session = Session()
model_union: ModelUnionType = Model1


session.query(Model1).filter(Model1.column_a == 'foobar') # ok
session.query(model_union).filter(model_union.column_a == 'foobar') # fails type checking


reveal_type(Model1.column_a)
reveal_type(Model2.column_a)
reveal_type(model_union.column_a)

Error

# Output of mypy running on the repro above
type_test.py:26:35: error: Argument 1 to "filter" of "Query" has incompatible type "bool"; expected
"Union[ColumnElement[bool], _HasClauseElement, SQLCoreOperations[bool], ExpressionElementRole[bool], Callable[[], ColumnElement[bool]], LambdaElement]"  [arg-type]
    session.query(model_union).filter(model_union.column_a == 'foobar') # fails type checking
                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type_test.py:29:13: note: Revealed type is "sqlalchemy.orm.attributes.InstrumentedAttribute[builtins.str]"
type_test.py:30:13: note: Revealed type is "sqlalchemy.orm.attributes.InstrumentedAttribute[builtins.str]"
type_test.py:31:13: note: Revealed type is "builtins.str"
Found 1 error in 1 file (checked 1 source file)

Versions

  • OS: macOS 12.6
  • Python: 3.8.13
  • SQLAlchemy: 2.0.4
  • Type checker: mypy 1.0.1

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    great mcveAn issue with a great mcvethird party integration issuesissues to do with other libraries and frameworkstypingpep -484 typing issues. independent of "mypy"

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions