From 8fca3067a84f7c77958871b55ec28a4f8f901e5a Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 23 Sep 2021 16:19:11 +0900 Subject: [PATCH 1/2] Fix error message for dataclasses.field with positional argument --- mypy/plugins/dataclasses.py | 19 ++++++++++--------- test-data/unit/check-dataclasses.test | 13 +++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 9c615f857731a..be8fe81e4b15d 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -460,15 +460,16 @@ def _collect_field_args(expr: Expression, ): # field() only takes keyword arguments. args = {} - for name, arg in zip(expr.arg_names, expr.args): - if name is None: - # This means that `field` is used with `**` unpacking, - # the best we can do for now is not to fail. - # TODO: we can infer what's inside `**` and try to collect it. - ctx.api.fail( - 'Unpacking **kwargs in "field()" is not supported', - expr, - ) + for name, arg, kind in zip(expr.arg_names, expr.args, expr.arg_kinds): + if not kind.is_named(): + if kind.is_named(star=True): + # This means that `field` is used with `**` unpacking, + # the best we can do for now is not to fail. + # TODO: we can infer what's inside `**` and try to collect it. + message = 'Unpacking **kwargs in "field()" is not supported' + else: + message = '"field()" does not accept positional arguments' + ctx.api.fail(message, expr) return True, {} args[name] = arg return True, args diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 57ed2813c54bf..2e5e1cfd53838 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1320,6 +1320,19 @@ main:7: note: def [_T] field(*, default_factory: Callable[[], _T], init: boo main:7: note: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any [builtins fixtures/dataclasses.pyi] +[case testDataclassFieldWithPositionalArguments] +# flags: --python-version 3.7 +from dataclasses import dataclass, field + +@dataclass +class C: + x: int = field(0) # E: "field()" does not accept positional arguments \ + # E: No overload variant of "field" matches argument type "int" \ + # N: Possible overload variants: \ + # N: def [_T] field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ + # N: def [_T] field(*, default_factory: Callable[[], _T], init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ + # N: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any +[builtins fixtures/dataclasses.pyi] [case testDataclassFieldWithTypedDictUnpacking] # flags: --python-version 3.7 From c1f55f460ae05c6d097d6e8ba08f039c87df7c13 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 23 Sep 2021 19:59:37 +0900 Subject: [PATCH 2/2] Fix type error with assertion --- mypy/plugins/dataclasses.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index be8fe81e4b15d..5f149713cd39c 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -471,6 +471,7 @@ def _collect_field_args(expr: Expression, message = '"field()" does not accept positional arguments' ctx.api.fail(message, expr) return True, {} + assert name is not None args[name] = arg return True, args return False, {}