-
-
Notifications
You must be signed in to change notification settings - Fork 290
Fix Arguments.arguments so it actually returns all arguments #2240
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
Fix Arguments.arguments so it actually returns all arguments #2240
Conversation
Started out writing a test to verify the behavior, apparently I broke everything else with the changes, will look into fixing that. |
c4a3452
to
08ace25
Compare
Not so destructive now, with only 13 tests failing. At least some of them seem to fail because of this: Lines 267 to 288 in a7ab088
Previously the code would get up to that point ( Line 237 in a7ab088
The specific test that goes through that code is: astroid/tests/test_inference.py Line 4969 in a7ab088
|
Seems like we need to change how we determine |
Yes, seems like it. I stopped there for the day and haven't had the chance to look into it, but any insights or tips are appreciated. Probably I will be able to work on this tomorrow. |
08ace25
to
c5f0b8f
Compare
Fixed (I think?) the inference stuff related to arg index and also some other mechanics caused by the original fix, like considering vararg and kwarg for obtaining default values (I excluded them from the computation). Just two tests failing now, light at the end of the tunnel seems closer. |
6a4b8f7
to
a9e0dce
Compare
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #2240 +/- ##
==========================================
- Coverage 92.78% 92.78% -0.01%
==========================================
Files 94 94
Lines 10937 10947 +10
==========================================
+ Hits 10148 10157 +9
- Misses 789 790 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
|
All tests working now, so at least we have a functioning implementation. Can you review? |
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.
Thanks!
I found a case that breaks and should be added, potentially in a new test method.
setup
from astroid import extract_node
node = extract_node("def fruit(eat=True, *, peel=False, trim=False, **kwargs): ...")
main
>>> node.args.default_value('eat')
<Const.bool l.1 at 0x1054a9730>
pr
>>> node.args.default_value('eat')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/<user>/astroid/astroid/nodes/node_classes.py", line 934, in default_value
raise NoDefault(func=self.parent, name=argname)
astroid.exceptions.NoDefault: <FunctionDef.fruit l.1 at 0x10f5c2510> has no default for 'eat'.
main
a9e0dce
to
7a7c6f1
Compare
Will first try to improve |
c044314
to
f377242
Compare
I changed the PR a little bit to provide more info on the arguments since before they were just a name wrapped in AssignName, now they have their lineno and col offsets set. What do you think? |
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!
Oh, and don't forget to add a changelog. |
Closes pylint-dev#2213. Arguments.arguments() has been modified so that it returns all arguments as it should (according to its own doc). A test case was also added to verify this. Methods which counted on arguments() not containing vararg and kwonlyargs have also been modified so they work with this new change.
* All arguments returned by arguments() are of type AssignName. * default_value() was revered to the old way (substraction to index) with improvement suggested by Jacob. * List comprehension used instead of list(filter...)
If available, these nodes (accessed through arguments()) now contain lineno and col offset information.
f377242
to
1f17be2
Compare
I made all the suggested changes and added the change log. If you want me to |
* find_argname now works when requesting vararg or kwargs. * Fixed some annotations in code and documentation. * Added changelog.
1f17be2
to
b0d2153
Compare
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.
Thank you for this helpful contribution!
This causes a new error with pylint. A code sample is below. The pylint functional test suite does also fail. class Sensor:
def __init__(self, *, description):
self._id = description.key ...
File "/.../astroid/astroid/decorators.py", line 49, in wrapped
for res in _func(node, context, **kwargs):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/.../astroid/astroid/nodes/node_classes.py", line 457, in _infer
stmts = list(self.assigned_stmts(context=context))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/.../astroid/astroid/protocols.py", line 406, in _arguments_infer_argname
yield from self.default_value(name).infer(context)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/.../astroid/astroid/nodes/node_classes.py", line 957, in default_value
return self.defaults[idx]
~~~~~~~~~~~~~^^^^^
IndexError: list index out of range A more complete example (although not necessary to reproduce the failure)from dataclasses import dataclass
@dataclass
class EntityDescription:
key: str
class Sensor:
def __init__(self, *, description: EntityDescription) -> None:
self._id = description.key |
Yes, I expected changes to be needed in pylint. I'm eager for a new alpha of astroid soon. |
But maybe some of the fixes will involve astroid changes? |
@crazybolillo Would you like to take the lead on the necessary follow-ups? |
Sure, I will try to reproduce and add it to astroid's test suite. |
Thank you! |
It seems like this was a scare. I fixed it with the following diff: diff --git a/astroid/nodes/node_classes.py b/astroid/nodes/node_classes.py
index 014955cf..6e78a7b1 100644
--- a/astroid/nodes/node_classes.py
+++ b/astroid/nodes/node_classes.py
@@ -947,8 +947,11 @@ class Arguments(
]
index = _find_arg(argname, self.kwonlyargs)[0]
- if index is not None and self.kw_defaults[index] is not None:
- return self.kw_defaults[index]
+ if (index is not None) and (len(self.kw_defaults) > index):
+ if self.kw_defaults[index] is not None:
+ return self.kw_defaults[index]
+ else:
+ raise NoDefault(func=self.parent, name=argname)
index = _find_arg(argname, args)[0]
if index is not None: Should I make a new PR and reference the same issue? |
Yes, and I'll take a look. No change log will be necessary. |
Refs pylint-dev#2213. Requesting the default value for a kwonlyarg with no default would fail with an IndexError, it now correctly raises a NoDefault exception. This issue arised after changes in PR pylint-dev#2240.
Refs pylint-dev#2213. Requesting the default value for a kwonlyarg with no default would fail with an IndexError, it now correctly raises a NoDefault exception. This issue arised after changes in PR pylint-dev#2240.
Closes #2213.
Arguments.arguments() has been modified so that it returns all arguments as it should (according to its own doc). A test case was also added to verify this.
Type of Changes