-
-
Notifications
You must be signed in to change notification settings - Fork 296
Handle dataclass
kw_only
keyword correctly
#1764
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Pull Request Test Coverage Report for Build 2993872918
π - Coveralls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good, but I think the string contains test for the argument names needs to be more robust.
new_params_string = ", ".join(params) | ||
|
||
try: | ||
base: ClassDef = next(next(iter(node.bases)).infer()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that it works, but for my understanding can you explain the iteration going on here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
node.bases
are nodes.Name
. So, I get the first base node which then gets inferred, of which I get the first inference result. This should be the ClassDef
.
This works because we mangle the __init__
of each dataclass
so there is no need to iterate over all base classes, the last base is fine.
I use next(iter(
as it is a nice safe guard against not finding any bases using the try ... except
I needed anyway for the call to .infer()
.
astroid/brain/brain_dataclasses.py
Outdated
arguments = ", ".join( | ||
i for i in all_arguments if i.split(":")[0] not in new_params_string | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I managed to break this assumption because "e" is contained in "ee":
This test will now fail:
diff --git a/tests/unittest_brain_dataclasses.py b/tests/unittest_brain_dataclasses.py
index a2077d1c..92a61a85 100644
--- a/tests/unittest_brain_dataclasses.py
+++ b/tests/unittest_brain_dataclasses.py
@@ -761,7 +761,7 @@ def test_kw_only_decorator() -> None:
@dataclass(kw_only=True)
class Foo:
a: int
- b: str
+ e: str
@dataclass(kw_only=False)
@@ -776,7 +776,7 @@ def test_kw_only_decorator() -> None:
@dataclass(kw_only=True)
class Dee(Cee):
- e: int
+ ee: int
Foo.__init__ #@
@@ -789,31 +789,31 @@ def test_kw_only_decorator() -> None:
foo_init: bases.UnboundMethod = next(foodef.infer())
if PY310_PLUS:
assert [a.name for a in foo_init.args.args] == ["self"]
- assert [a.name for a in foo_init.args.kwonlyargs] == ["a", "b"]
+ assert [a.name for a in foo_init.args.kwonlyargs] == ["a", "e"]
else:
- assert [a.name for a in foo_init.args.args] == ["self", "a", "b"]
+ assert [a.name for a in foo_init.args.args] == ["self", "a", "e"]
assert [a.name for a in foo_init.args.kwonlyargs] == []
bar_init: bases.UnboundMethod = next(bardef.infer())
if PY310_PLUS:
assert [a.name for a in bar_init.args.args] == ["self", "c"]
- assert [a.name for a in bar_init.args.kwonlyargs] == ["a", "b"]
+ assert [a.name for a in bar_init.args.kwonlyargs] == ["a", "e"]
else:
- assert [a.name for a in bar_init.args.args] == ["self", "a", "b", "c"]
+ assert [a.name for a in bar_init.args.args] == ["self", "a", "e", "c"]
assert [a.name for a in bar_init.args.kwonlyargs] == []
cee_init: bases.UnboundMethod = next(cee.infer())
if PY310_PLUS:
assert [a.name for a in cee_init.args.args] == ["self", "c", "d"]
- assert [a.name for a in cee_init.args.kwonlyargs] == ["a", "b"]
+ assert [a.name for a in cee_init.args.kwonlyargs] == ["a", "e"]
else:
- assert [a.name for a in cee_init.args.args] == ["self", "a", "b", "c", "d"]
+ assert [a.name for a in cee_init.args.args] == ["self", "a", "e", "c", "d"]
assert [a.name for a in cee_init.args.kwonlyargs] == []
dee_init: bases.UnboundMethod = next(dee.infer())
if PY310_PLUS:
assert [a.name for a in dee_init.args.args] == ["self", "c", "d"]
- assert [a.name for a in dee_init.args.kwonlyargs] == ["a", "b", "e"]
+ assert [a.name for a in dee_init.args.kwonlyargs] == ["a", "e", "e"]
else:
- assert [a.name for a in dee_init.args.args] == ["self", "a", "b", "c", "d", "e"]
+ assert [a.name for a in dee_init.args.args] == ["self", "a", "e", "c", "d", "ee"]
assert [a.name for a in dee_init.args.kwonlyargs] == []
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π
Co-authored-by: Jacob Walls <[email protected]>
β¦astroid into dataclasses-KW-ONLY
Co-authored-by: Jacob Walls <[email protected]>
This also closed pylint-dev/pylint#6550 and pylint-dev/pylint#5857 |
Co-authored-by: Jacob Walls <[email protected]>
Co-authored-by: Jacob Walls <[email protected]>
Steps
Description
Type of Changes
Related Issue
Closes pylint-dev/pylint#7290
Edit after merge: Closes pylint-dev/pylint#6550