Skip to content

dataclass constructor expects Mapped[] values when using _mypy_mapped_attrs #129

Open
@iamnoah

Description

@iamnoah

Describe the bug

Following the mypy support instructions here and trying variations from here, I cannot find a way to get type checking to work for both the fields as clause elements and the dataclass constructor. Removing _mypy_mapped_attrs results in a usable constructor, but unusable fields for constructing a query.

Expected behavior

That the dataclass constructor would be type checked according to the actual field type annotations. Instead, the presence of _mypy_mapped_attrs causes mypy to expect Mapped values to be passed to the constructor, so creating an instance does not pass type checking.

To Reproduce

from dataclasses import dataclass, field

from sqlalchemy import Column
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import registry

mapper_registry: registry = registry()

@mapper_registry.mapped
@dataclass
class Foo:
    __tablename__ = "foo"
    __table_args__ = {"schema": "public"}

    __sa_dataclass_metadata_key__ = "sa"

    uuid: str = field(
        metadata={
            "sa": Column(
                UUID,
                primary_key=True,
                nullable=False,
            )
        }
    )

    _mypy_mapped_attrs = [uuid]


foo = Foo(
    uuid="123",
)
[mypy]
plugins = sqlalchemy.ext.mypy.plugin

Error

mypy_test.py:31: error: Argument "uuid" to "Foo" has incompatible type "str"; expected "Mapped[str]"

Versions.

  • OS: Mac OS X
  • Python: 3.9.5
  • SQLAlchemy: 1.4.20
  • mypy: 0.910
  • SQLAlchemy2-stubs: 0.0.2a4

Additional context

Alternative mapping that produces the same error:

from dataclasses import dataclass, field
from typing import TYPE_CHECKING

from sqlalchemy import Column, Table
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import registry

mapper_registry: registry = registry()


@mapper_registry.mapped
@dataclass
class Foo:
    __table__ = Table(
        "foo",
        mapper_registry.metadata,
        Column(
            UUID,
            primary_key=True,
            nullable=False,
        ),
    )
    uuid: str = field()

    if TYPE_CHECKING:
        _mypy_mapped_attrs = [uuid]


foo = Foo(
    uuid="123",
)

Metadata

Metadata

Assignees

No one assigned

    Labels

    mypy pluginsomething that has to do with the sqlalchemy mypy plugin

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions