-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add message name is parameter and nonlocal #7577
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Added ``name-is-parameter-and-nonlocal`` which flags when a nonlocal variable is also a paremeter. | ||
|
||
Closes #6882 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -204,6 +204,11 @@ class BasicErrorChecker(_BasicChecker): | |
"which results in an error since Python 3.6.", | ||
{"minversion": (3, 6)}, | ||
), | ||
"E0134": ( | ||
"Name %r is both parameter and nonlocal", | ||
"name-is-parameter-and-nonlocal", | ||
"Emitted when a nonlocal variable is also a parameter.", | ||
), | ||
} | ||
|
||
def open(self) -> None: | ||
|
@@ -264,9 +269,11 @@ def visit_starred(self, node: nodes.Starred) -> None: | |
"duplicate-argument-name", | ||
"nonlocal-and-global", | ||
"used-prior-global-declaration", | ||
"name-is-parameter-and-nonlocal", | ||
) | ||
def visit_functiondef(self, node: nodes.FunctionDef) -> None: | ||
self._check_nonlocal_and_global(node) | ||
self._check_nonlocal_and_parameter(node) | ||
self._check_name_used_prior_global(node) | ||
if not redefined_by_decorator( | ||
node | ||
|
@@ -327,6 +334,19 @@ def _check_name_used_prior_global(self, node: nodes.FunctionDef) -> None: | |
"used-prior-global-declaration", node=node_name, args=(name,) | ||
) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can probably optimize by using |
||
def _check_nonlocal_and_parameter(self, node: nodes.FunctionDef) -> None: | ||
"""Check if a name is both parameter and nonlocal.""" | ||
node_arg_names = {arg.name for arg in node.args.args} | ||
for body_node in node.nodes_of_class(nodes.Nonlocal): | ||
for non_local_name in body_node.names: | ||
if non_local_name in node_arg_names: | ||
self.add_message( | ||
"name-is-parameter-and-nonlocal", | ||
args=(non_local_name,), | ||
node=body_node, | ||
confidence=HIGH, | ||
) | ||
|
||
def _check_nonlocal_and_global(self, node: nodes.FunctionDef) -> None: | ||
"""Check that a name is both nonlocal and global.""" | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,6 @@ | ||||||||||||||
# pylint: disable=missing-docstring,invalid-name,nonlocal-without-binding | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
def tomato(is_tasty: bool = True): | ||||||||||||||
nonlocal color | ||||||||||||||
nonlocal is_tasty # [name-is-parameter-and-nonlocal] | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think this would also raise a syntax error, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess for that I can do something like node_arg_names = {arg.name for arg in node.args.args}
for local_name, local_nodes in node.locals.items():
for local_node in local_nodes:
if isinstance(local_node, nodes.Arguments):
node_arg_names.add(local_name) Not sure if there's an easier way to retrieve locals that are considered arguments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For nested scopes and functions, are you looking for something like this? def grape(is_tasty: bool = True):
nonlocal is_tasty # [name-is-parameter-and-nonlocal]
def grape_juice(is_tasty: bool = True):
nonlocal is_tasty # [name-is-parameter-and-nonlocal]
grape_juice() There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, and variants of it. I haven't tested this out locally to see which combinations return a syntax error, but I think it is good to add some (regression tests) for possible combinations:
Scoping rules can create annoying false positives for messages like this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Cool, I'll be coming back to this later today. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shit, that means that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure! I can attempt that later today, this might also be related pylint-dev/astroid#761 - but not totally sure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar issue for
I wouldn't be against separating these astroid issues into an independent workflow so we can let the current issue proceed to merge. We could add a maintenance issue and update the code here once they are resolved? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed let's not block this on too much refactoring and fix stuff as we run into them. I think this is a very clear use-case for a potential fix and I'd be happy to help release a patch version of |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
name-is-parameter-and-nonlocal:6:4:6:21:tomato:Name 'is_tasty' is both parameter and nonlocal:HIGH |
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.