Skip to content

Commit fae605d

Browse files
committed
Add check for name-is-parameter-and-nonlocal
1 parent 0e26e30 commit fae605d

File tree

6 files changed

+26
-0
lines changed

6 files changed

+26
-0
lines changed

doc/user_guide/checkers/features.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ Basic checker Messages
6565
Emitted when a name is used prior a global declaration, which results in an
6666
error since Python 3.6. This message can't be emitted when using Python <
6767
3.6.
68+
:name-is-parameter-and-nonlocal (E0134): *Name %r is parameter and nonlocal*
69+
Emitted when a nonlocal variable is also a parameter.
6870
:return-outside-function (E0104): *Return outside function*
6971
Used when a "return" statement is found outside a function or method.
7072
:return-arg-in-generator (E0106): *Return with argument inside generator*

doc/user_guide/messages/messages_overview.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ All messages in the error category:
120120
error/mixed-format-string
121121
error/modified-iterating-dict
122122
error/modified-iterating-set
123+
error/name-is-parameter-and-nolocal
123124
error/no-member
124125
error/no-method-argument
125126
error/no-name-in-module

doc/whatsnew/fragments/6882.new_check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added ``name-is-parameter-and-nonlocal`` which flags when a nonlocal variable is also a paremeter.
2+
3+
Closes #6682

pylint/checkers/base/basic_error_checker.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,11 @@ class BasicErrorChecker(_BasicChecker):
204204
"which results in an error since Python 3.6.",
205205
{"minversion": (3, 6)},
206206
),
207+
"E0134": (
208+
"Name %r is parameter and nonlocal",
209+
"name-is-parameter-and-nonlocal",
210+
"Emitted when a nonlocal variable is also a parameter.",
211+
),
207212
}
208213

209214
def open(self) -> None:
@@ -267,6 +272,7 @@ def visit_starred(self, node: nodes.Starred) -> None:
267272
)
268273
def visit_functiondef(self, node: nodes.FunctionDef) -> None:
269274
self._check_nonlocal_and_global(node)
275+
self._check_nonlocal_and_parameter(node)
270276
self._check_name_used_prior_global(node)
271277
if not redefined_by_decorator(
272278
node
@@ -327,6 +333,14 @@ def _check_name_used_prior_global(self, node: nodes.FunctionDef) -> None:
327333
"used-prior-global-declaration", node=node_name, args=(name,)
328334
)
329335

336+
def _check_nonlocal_and_parameter(self, node: nodes.FunctionDef) -> None:
337+
"""Check that a name is both parameter and nonlocal."""
338+
node_arg_names = {arg.name for arg in node.args.args}
339+
for body_node in node.nodes_of_class(nodes.Nonlocal):
340+
for non_local_name in body_node.names:
341+
if non_local_name in node_arg_names:
342+
self.add_message("name-is-parameter-and-nonlocal", node=body_node)
343+
330344
def _check_nonlocal_and_global(self, node: nodes.FunctionDef) -> None:
331345
"""Check that a name is both nonlocal and global."""
332346

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# pylint: disable=missing-docstring,invalid-name,nonlocal-without-binding
2+
3+
4+
def tomato(is_tasty: bool = True):
5+
nonlocal is_tasty # [name-is-parameter-and-nonlocal]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
name-is-parameter-and-nonlocal:5:4:5:21:tomato:Name %r is parameter and nonlocal:UNDEFINED

0 commit comments

Comments
 (0)