diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 7e66197448bfd..af0153b2f56cd 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -4,7 +4,7 @@ from typing_extensions import Final from mypy.nodes import ( - ARG_OPT, ARG_POS, MDEF, Argument, AssignmentStmt, CallExpr, + ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_POS, MDEF, Argument, AssignmentStmt, CallExpr, Context, Expression, JsonDict, NameExpr, RefExpr, SymbolTableNode, TempNode, TypeInfo, Var, TypeVarExpr, PlaceholderNode ) @@ -49,11 +49,18 @@ def __init__( self.kw_only = kw_only def to_argument(self) -> Argument: + arg_kind = ARG_POS + if self.kw_only and self.has_default: + arg_kind = ARG_NAMED_OPT + elif self.kw_only and not self.has_default: + arg_kind = ARG_NAMED + elif not self.kw_only and self.has_default: + arg_kind = ARG_OPT return Argument( variable=self.to_var(), type_annotation=self.type, initializer=None, - kind=ARG_OPT if self.has_default else ARG_POS, + kind=arg_kind, ) def to_var(self) -> Var: diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index c93556e915cbb..4aea51be0e8c9 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -321,6 +321,13 @@ class Application: rating: int Application(rating=5) +Application(name='name', rating=5) +Application() # E: Missing named argument "rating" for "Application" +Application('name') # E: Too many positional arguments for "Application" # E: Missing named argument "rating" for "Application" +Application('name', 123) # E: Too many positional arguments for "Application" +Application('name', rating=123) # E: Too many positional arguments for "Application" +Application(name=123, rating='name') # E: Argument "name" to "Application" has incompatible type "int"; expected "str" # E: Argument "rating" to "Application" has incompatible type "str"; expected "int" +Application(rating='name', name=123) # E: Argument "rating" to "Application" has incompatible type "str"; expected "int" # E: Argument "name" to "Application" has incompatible type "int"; expected "str" [builtins fixtures/list.pyi] @@ -334,6 +341,12 @@ class Application: rating: int = field(kw_only=True) Application(rating=5) +Application('name', rating=123) +Application(name='name', rating=5) +Application() # E: Missing named argument "rating" for "Application" +Application('name') # E: Missing named argument "rating" for "Application" +Application('name', 123) # E: Too many positional arguments for "Application" +Application(123, rating='name') # E: Argument 1 to "Application" has incompatible type "int"; expected "str" # E: Argument "rating" to "Application" has incompatible type "str"; expected "int" [builtins fixtures/list.pyi] @@ -346,6 +359,12 @@ class Application: name: str = 'Unnamed' rating: int = field(kw_only=False) # E: Attributes without a default cannot follow attributes with one +Application(name='name', rating=5) +Application('name', 123) +Application('name', rating=123) +Application() # E: Missing positional argument "name" in call to "Application" +Application('name') # E: Too few arguments for "Application" + [builtins fixtures/list.pyi] [case testDataclassesOrderingKwOnlyWithSentinel] @@ -359,6 +378,11 @@ class Application: rating: int Application(rating=5) +Application(name='name', rating=5) +Application() # E: Missing named argument "rating" for "Application" +Application('name') # E: Too many positional arguments for "Application" # E: Missing named argument "rating" for "Application" +Application('name', 123) # E: Too many positional arguments for "Application" +Application('name', rating=123) # E: Too many positional arguments for "Application" [builtins fixtures/list.pyi] @@ -372,6 +396,12 @@ class Application: name: str = 'Unnamed' rating: int = field(kw_only=False) # E: Attributes without a default cannot follow attributes with one +Application(name='name', rating=5) +Application() # E: Missing positional argument "name" in call to "Application" +Application('name') # E: Too many positional arguments for "Application" # E: Too few arguments for "Application" +Application('name', 123) # E: Too many positional arguments for "Application" +Application('name', rating=123) # E: Too many positional arguments for "Application" + [builtins fixtures/list.pyi] [case testDataclassesOrderingKwOnlyWithSentinelAndSubclass] @@ -391,6 +421,10 @@ class D(Base): a: str = "a" D("Hello", "World") +D(x="Hello", z="World") +D("Hello", "World", y=1, w=2, a="b") +D("Hello") # E: Missing positional argument "z" in call to "D" +D() # E: Missing positional arguments "x", "z" in call to "D" [case testDataclassesOrderingKwOnlyWithMultipleSentinel] # flags: --python-version 3.10