Fix fields arg type in dataclass.make_dataclass (#7761)

The `fields` arg of `dataclass.make_dataclass` should have type:

```
Iterable[str | tuple[str, type] | tuple[str, type, Any]]
```

Previously the 3-tuple had type `tuple[str, type, Field[Any]]`, which
was incorrect for two reasons:

- The third element in the tuple doesn't have to be a ``Field``, it can
be any RHS value valid when defining a dataclass field (e.g.
``myfield: type = ...``). This may be a ``Field``, but it may also be a
default value like ``0``. ``Any`` is the proper type here.
- The type stubs for ``dataclass.field`` lie and say that this function
returns a value with the same type as ``default``. This avoids the need
for a mypy/pyright plugin that understands dataclasses, but also means
there is no way to create a ``Field`` object that these tools
understand, since they don't think ``dataclasses.field`` returns a
``Field`` instance.

With this change, the following valid dataclasses code passes both mypy
and pyright:

```python
from dataclasses import field, make_dataclass

Point = make_dataclass("Point", [("x", int), ("y", int), ("z", int, 0)])
Point2 = make_dataclass("Point2", [("x", int), ("y", int), ("z", int, field(default=0))])
```
This commit is contained in:
Jim Crist-Harif
2022-05-01 00:02:40 -05:00
committed by GitHub
parent f05bfe0315
commit 23e77931f9

View File

@@ -227,7 +227,7 @@ class InitVar(Generic[_T]):
if sys.version_info >= (3, 10):
def make_dataclass(
cls_name: str,
fields: Iterable[str | tuple[str, type] | tuple[str, type, Field[Any]]],
fields: Iterable[str | tuple[str, type] | tuple[str, type, Any]],
*,
bases: tuple[type, ...] = ...,
namespace: dict[str, Any] | None = ...,
@@ -245,7 +245,7 @@ if sys.version_info >= (3, 10):
else:
def make_dataclass(
cls_name: str,
fields: Iterable[str | tuple[str, type] | tuple[str, type, Field[Any]]],
fields: Iterable[str | tuple[str, type] | tuple[str, type, Any]],
*,
bases: tuple[type, ...] = ...,
namespace: dict[str, Any] | None = ...,