From 0aaf7fffba7be327cc8286196c35193d766d110b Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Fri, 1 Sep 2023 23:19:22 -0400 Subject: [PATCH 1/5] docs: document dataclass_transform behavior --- docs/source/additional_features.rst | 43 +++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/docs/source/additional_features.rst b/docs/source/additional_features.rst index 5dd136476eaa..ecbb39d4fb34 100644 --- a/docs/source/additional_features.rst +++ b/docs/source/additional_features.rst @@ -71,12 +71,12 @@ and :pep:`557`. Caveats/Known Issues ==================== -Some functions in the :py:mod:`dataclasses` module, such as :py:func:`~dataclasses.replace` and :py:func:`~dataclasses.asdict`, +Some functions in the :py:mod:`dataclasses` module, such as :py:func:`~dataclasses.asdict`, have imprecise (too permissive) types. This will be fixed in future releases. Mypy does not yet recognize aliases of :py:func:`dataclasses.dataclass `, and will -probably never recognize dynamically computed decorators. The following examples -do **not** work: +probably never recognize dynamically computed decorators. The following example +does **not** work: .. code-block:: python @@ -94,16 +94,35 @@ do **not** work: """ attribute: int - @dataclass_wrapper - class DynamicallyDecorated: - """ - Mypy doesn't recognize this as a dataclass because it is decorated by a - function returning `dataclass` rather than by `dataclass` itself. - """ - attribute: int - AliasDecorated(attribute=1) # error: Unexpected keyword argument - DynamicallyDecorated(attribute=1) # error: Unexpected keyword argument + + +To have Mypy recognize a wrapper of :py:func:`dataclasses.dataclass ` +as a dataclass decorator, consider using the :py:func:`~typing.dataclass_transform` decorator: + +.. code-block:: python + + from dataclasses import dataclass, Field + from typing import dataclass_transform + + @dataclass_transform(fields=(Field,)) + def my_dataclass(cls: type[T]) -> type[T]: + ... + return dataclass(cls) + + +Data Class Transforms +********************* + +Mypy supports the :py:func:`~typing.dataclass_transform` decorator as described in +`PEP 681 `_. + +.. note:: + + Pragmatically, such classes would appear to have the internal attribute :code:`__dataclass_fields__` + (even though they might lack it in runtime) and dataclass functions such as :py:func:`dataclasses.is_dataclass` + and :py:func:`dataclasses.fields` would appear to accept them as if they were dataclasses + (even though they may fail at runtime). .. _attrs_package: From 54948ee7dff3f8822f6d65862f5ca15b9b499c08 Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 2 Sep 2023 10:34:57 -0400 Subject: [PATCH 2/5] Apply suggestions from code review Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> --- docs/source/additional_features.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/additional_features.rst b/docs/source/additional_features.rst index ecbb39d4fb34..708b81a4465a 100644 --- a/docs/source/additional_features.rst +++ b/docs/source/additional_features.rst @@ -105,7 +105,7 @@ as a dataclass decorator, consider using the :py:func:`~typing.dataclass_transfo from dataclasses import dataclass, Field from typing import dataclass_transform - @dataclass_transform(fields=(Field,)) + @dataclass_transform(field_specifiers=(Field,)) def my_dataclass(cls: type[T]) -> type[T]: ... return dataclass(cls) @@ -119,9 +119,9 @@ Mypy supports the :py:func:`~typing.dataclass_transform` decorator as described .. note:: - Pragmatically, such classes would appear to have the internal attribute :code:`__dataclass_fields__` - (even though they might lack it in runtime) and dataclass functions such as :py:func:`dataclasses.is_dataclass` - and :py:func:`dataclasses.fields` would appear to accept them as if they were dataclasses + Pragmatically, mypy will assume such classes have the internal attribute :code:`__dataclass_fields__` + (even though they might lack it in runtime) and will assume functions such as :py:func:`dataclasses.is_dataclass` + and :py:func:`dataclasses.fields` to treat them as if they were dataclasses (even though they may fail at runtime). .. _attrs_package: From 646104fc3dd7a12c8216d7a603f346e841c685bd Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 2 Sep 2023 13:07:29 -0700 Subject: [PATCH 3/5] Update docs/source/additional_features.rst --- docs/source/additional_features.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/additional_features.rst b/docs/source/additional_features.rst index 708b81a4465a..610b51dc7239 100644 --- a/docs/source/additional_features.rst +++ b/docs/source/additional_features.rst @@ -121,7 +121,7 @@ Mypy supports the :py:func:`~typing.dataclass_transform` decorator as described Pragmatically, mypy will assume such classes have the internal attribute :code:`__dataclass_fields__` (even though they might lack it in runtime) and will assume functions such as :py:func:`dataclasses.is_dataclass` - and :py:func:`dataclasses.fields` to treat them as if they were dataclasses + and :py:func:`dataclasses.fields` treat them as if they were dataclasses (even though they may fail at runtime). .. _attrs_package: From 5a3fcc057bc5555ecd37bd46b428bcc1789651b7 Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 2 Sep 2023 16:46:43 -0400 Subject: [PATCH 4/5] Code example nits --- docs/source/additional_features.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/source/additional_features.rst b/docs/source/additional_features.rst index 610b51dc7239..481209a252bc 100644 --- a/docs/source/additional_features.rst +++ b/docs/source/additional_features.rst @@ -103,12 +103,14 @@ as a dataclass decorator, consider using the :py:func:`~typing.dataclass_transfo .. code-block:: python from dataclasses import dataclass, Field - from typing import dataclass_transform + from typing import TypeVar, dataclass_transform + + T = TypeVar('T') @dataclass_transform(field_specifiers=(Field,)) def my_dataclass(cls: type[T]) -> type[T]: - ... - return dataclass(cls) + ... + return dataclass(cls) Data Class Transforms From 043e7cddec918ea807ea6c7ed97c112f1900667d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 2 Sep 2023 20:47:51 +0000 Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/source/additional_features.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/additional_features.rst b/docs/source/additional_features.rst index 481209a252bc..ae625c157654 100644 --- a/docs/source/additional_features.rst +++ b/docs/source/additional_features.rst @@ -104,7 +104,7 @@ as a dataclass decorator, consider using the :py:func:`~typing.dataclass_transfo from dataclasses import dataclass, Field from typing import TypeVar, dataclass_transform - + T = TypeVar('T') @dataclass_transform(field_specifiers=(Field,))