sqlalchemy2-stubs icon indicating copy to clipboard operation
sqlalchemy2-stubs copied to clipboard

dataclass constructor expects `Mapped[]` values when using _mypy_mapped_attrs

Open iamnoah opened this issue 4 years ago • 0 comments
trafficstars

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",
)

iamnoah avatar Jun 30 '21 03:06 iamnoah