mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-12 03:38:35 -04:00
mypy 1.2 has fixed dataclass descriptor support
Currently using the PR for test. Change-Id: Idc4c475587f5151ef79046d24ca3ac274c2cb2ca References: https://github.com/python/mypy/issues/14868
This commit is contained in:
Vendored
+5
-44
@@ -37,53 +37,14 @@ as having Dataclass-specific behaviors, most notably by taking advantage of :pe
|
||||
as though it were explicitly decorated using the ``@dataclasses.dataclass``
|
||||
decorator.
|
||||
|
||||
.. note:: Support for :pep:`681` in typing tools as of **March 11, 2023** is
|
||||
limited and is currently known to be supported by Pyright_, but
|
||||
**not correctly supported** by Mypy_ version 1.1.1. Mypy 1.1.1 introduced
|
||||
:pep:`681` support but failed to accommodate for Python descriptors
|
||||
correctly (see Github issue below).
|
||||
|
||||
In order to resolve errors when using :class:`_orm.MappedAsDataclass` with
|
||||
Mypy version 1.1.1 or other typing tools that have similar errors, the
|
||||
following workaround may be used, which uses a plain non-pep681 mixin within
|
||||
``TYPE_CHECKING`` to avoid errors::
|
||||
|
||||
import typing
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
|
||||
class MappedAsDataclass:
|
||||
"""Mixin class which works in the same way as
|
||||
:class:`_orm.MappedAsDataclass`,
|
||||
but does not include :pep:`681` directives.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, *arg: typing.Any, **kw: typing.Any):
|
||||
pass
|
||||
|
||||
else:
|
||||
from sqlalchemy.orm import MappedAsDataclass
|
||||
|
||||
Above, the SQLAlchemy :class:`_orm.MappedAsDataclass` mixin is hidden
|
||||
from typing tools and replaced with a plain mixin that sets up an
|
||||
``__init__`` constructor that accommodates any arguments.
|
||||
|
||||
When using the :meth:`_orm.registry.mapped_as_dataclass` method,
|
||||
similar approaches can be taken using a plain decorator, however classes
|
||||
would need to also include an explicit ``__init__()`` method on a mixin
|
||||
like the one indicated above for the workaround to work completely::
|
||||
|
||||
|
||||
def mapped_as_dataclass(registry, cls, **kw):
|
||||
"""Will conceal the pep-681 enabled methods from typing tools"""
|
||||
|
||||
return registry.mapped_as_dataclass(cls, **kw)
|
||||
.. note:: Support for :pep:`681` in typing tools as of **April 4, 2023** is
|
||||
limited and is currently known to be supported by Pyright_ as well
|
||||
as Mypy_ as of **version 1.2**. Note that Mypy 1.1.1 introduced
|
||||
:pep:`681` support but did not correctly accommodate Python descriptors
|
||||
which will lead to errors when using SQLAlhcemy's ORM mapping scheme.
|
||||
|
||||
.. seealso::
|
||||
|
||||
https://github.com/python/mypy/issues/13856 - Mypy issue on github
|
||||
|
||||
https://peps.python.org/pep-0681/#the-dataclass-transform-decorator - background
|
||||
on how libraries like SQLAlchemy enable :pep:`681` support
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy.orm import DeclarativeBase
|
||||
from sqlalchemy.orm import Mapped
|
||||
from sqlalchemy.orm import mapped_column
|
||||
from sqlalchemy.orm import MappedAsDataclass
|
||||
|
||||
|
||||
class Base(MappedAsDataclass, DeclarativeBase):
|
||||
pass
|
||||
|
||||
|
||||
class A(Base):
|
||||
__tablename__ = "a"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, init=False)
|
||||
data: Mapped[str]
|
||||
x: Mapped[Optional[int]] = mapped_column(default=None)
|
||||
y: Mapped[Optional[int]] = mapped_column(kw_only=True)
|
||||
|
||||
|
||||
a1 = A(data="some data", y=5)
|
||||
|
||||
# EXPECTED_TYPE: str
|
||||
reveal_type(a1.data)
|
||||
|
||||
# EXPECTED_RE_TYPE: .*Union\[builtins.int, None\]
|
||||
reveal_type(a1.y)
|
||||
|
||||
a1.data = "some other data"
|
||||
Reference in New Issue
Block a user