Skip to content

Commit cbb41d4

Browse files
Allow passing module-level non-constants against either constant or variable regexes
1 parent aff9dc5 commit cbb41d4

17 files changed

+156
-143
lines changed

doc/user_guide/configuration/all-options.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ Standard Checkers
428428
""""""""""""
429429
*Good variable names which should always be accepted, separated by a comma.*
430430

431-
**Default:** ``('i', 'j', 'k', 'logger', 'ex', 'Run', '_')``
431+
**Default:** ``('i', 'j', 'k', 'ex', 'Run', '_')``
432432

433433

434434
--good-names-rgxs
@@ -588,7 +588,7 @@ Standard Checkers
588588
589589
# function-rgx =
590590
591-
good-names = ["i", "j", "k", "logger", "ex", "Run", "_"]
591+
good-names = ["i", "j", "k", "ex", "Run", "_"]
592592
593593
good-names-rgxs = []
594594
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
`invalid-name` now distinguishes module-level names that are assigned only once
2-
from those that are reassigned and now applies `--variable-rgx` to the latter.
1+
`invalid-name` now distinguishes module-level constants that are assigned only once
2+
from those that are reassigned and now applies `--variable-rgx` to the latter. Values
3+
other than literals (lists, sets, objects) can pass against either the constant or
4+
variable regexes (e.g. "LOGGER" or "logger" but not "LoGgEr").
35

46
Remember that `--good-names` or `--good-names-rgxs` can be provided to explicitly
5-
allow good names. `logger` has been added to the default `--good-names`.
6-
7-
Also, `invalid-name` is triggered for module-level names for additional types
8-
(e.g. lists and sets).
7+
allow good names.
98

109
Closes #3585

examples/pylintrc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ function-naming-style=snake_case
193193
good-names=i,
194194
j,
195195
k,
196-
logger,
197196
ex,
198197
Run,
199198
_

examples/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ function-naming-style = "snake_case"
167167
# function-rgx =
168168

169169
# Good variable names which should always be accepted, separated by a comma.
170-
good-names = [ "i", "j", "k", "logger", "ex", "Run", "_" ]
170+
good-names = [ "i", "j", "k", "ex", "Run", "_" ]
171171

172172
# Good variable names regexes, separated by a comma. If names match any regex,
173173
# they will always be accepted

pylint/checkers/base/name_checker/checker.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import astroid
2020
from astroid import nodes
21+
from astroid.typing import InferenceResult
2122

2223
from pylint import constants, interfaces
2324
from pylint.checkers import utils
@@ -199,7 +200,7 @@ class NameChecker(_BasicChecker):
199200
(
200201
"good-names",
201202
{
202-
"default": ("i", "j", "k", "logger", "ex", "Run", "_"),
203+
"default": ("i", "j", "k", "ex", "Run", "_"),
203204
"type": "csv",
204205
"metavar": "<names>",
205206
"help": "Good variable names which should always be accepted,"
@@ -399,7 +400,7 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
399400
"typevar-double-variance",
400401
"typevar-name-mismatch",
401402
)
402-
def visit_assignname( # pylint: disable=too-many-branches
403+
def visit_assignname( # pylint: disable=too-many-branches, too-many-statements
403404
self, node: nodes.AssignName
404405
) -> None:
405406
"""Check module level assigned names."""
@@ -477,7 +478,10 @@ def visit_assignname( # pylint: disable=too-many-branches
477478
node, (nodes.For, nodes.While)
478479
)
479480
):
480-
self._check_name("const", node.name, node)
481+
if not self._meets_exception_for_non_consts(
482+
inferred_assign_type, node.name
483+
):
484+
self._check_name("const", node.name, node)
481485
else:
482486
node_type = "variable"
483487
if (
@@ -524,6 +528,17 @@ def visit_assignname( # pylint: disable=too-many-branches
524528
else:
525529
self._check_name("class_attribute", node.name, node)
526530

531+
def _meets_exception_for_non_consts(
532+
self, inferred_assign_type: InferenceResult | None, name: str
533+
) -> bool:
534+
if isinstance(inferred_assign_type, nodes.Const):
535+
return False
536+
if self._name_allowed_by_regex(name=name):
537+
return True
538+
regexp = self._name_regexps["variable"]
539+
match = regexp.match(name)
540+
return match is not None
541+
527542
def _recursive_check_names(self, args: list[nodes.AssignName]) -> None:
528543
"""Check names in a possibly recursive list <arg>."""
529544
for arg in args:

pylintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ expected-line-ending-format=
231231
[BASIC]
232232

233233
# Good variable names which should always be accepted, separated by a comma
234-
good-names=i,j,k,logger,ex,Run,_
234+
good-names=i,j,k,ex,Run,_
235235

236236
# Good variable names regexes, separated by a comma. If names match any regex,
237237
# they will always be accepted

tests/functional/a/arguments.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,9 @@ def _print_selection(self):
275275
pick_apple = _pick_fruit("apple")
276276
pick_pear = _pick_fruit("pear")
277277

278-
PICKER = FruitPicker()
279-
PICKER.pick_apple()
280-
PICKER.pick_pear()
278+
picker = FruitPicker()
279+
picker.pick_apple()
280+
picker.pick_pear()
281281

282282

283283
def name1(apple, /, **kwargs):

tests/functional/c/condition_evals_to_constant.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def func(_):
2020
while CONSTANT and False: # [condition-evals-to-constant]
2121
break
2222
1 if CONSTANT or True else 2 # [condition-evals-to-constant]
23-
Z = [x for x in range(10) if x or True] # [condition-evals-to-constant]
23+
z = [x for x in range(10) if x or True] # [condition-evals-to-constant]
2424

2525
# Simplifies recursively
2626
assert True or CONSTANT or OTHER # [condition-evals-to-constant]

tests/functional/c/consider/consider_using_enumerate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class MyClass:
7878
def __init__(self):
7979
self.my_list = []
8080

81-
MY_OBJ = MyClass()
81+
my_obj = MyClass()
8282
def my_function(instance: MyClass):
8383
for i in range(len(instance.my_list)): # [consider-using-enumerate]
8484
var = instance.my_list[i]

tests/functional/m/modified_iterating.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,29 @@
44
import copy
55
from enum import Enum
66

7-
ITEM_LIST = [1, 2, 3]
8-
for item in ITEM_LIST:
9-
ITEM_LIST.append(item) # [modified-iterating-list]
7+
item_list = [1, 2, 3]
8+
for item in item_list:
9+
item_list.append(item) # [modified-iterating-list]
1010

11-
for item in ITEM_LIST:
12-
ITEM_LIST.remove(item) # [modified-iterating-list]
11+
for item in item_list:
12+
item_list.remove(item) # [modified-iterating-list]
1313

14-
for item in ITEM_LIST.copy():
15-
ITEM_LIST.append(item)
16-
ITEM_LIST.remove(item)
14+
for item in item_list.copy():
15+
item_list.append(item)
16+
item_list.remove(item)
1717

18-
for item in copy(ITEM_LIST):
19-
ITEM_LIST.append(item)
20-
ITEM_LIST.remove(item)
18+
for item in copy(item_list):
19+
item_list.append(item)
20+
item_list.remove(item)
2121

22-
for item in [k for k in ITEM_LIST]:
23-
ITEM_LIST.append(item)
24-
ITEM_LIST.remove(item)
22+
for item in [k for k in item_list]:
23+
item_list.append(item)
24+
item_list.remove(item)
2525

2626
MY_DICT = {"1": 1, "2": 2, "3": 3}
2727
i = 1
2828
for item in MY_DICT:
29-
ITEM_LIST[0] = i # for coverage, see reference at /pull/5628#discussion_r792181642
29+
item_list[0] = i # for coverage, see reference at /pull/5628#discussion_r792181642
3030
MY_DICT[i] = 1 # [modified-iterating-dict]
3131
i += 1
3232

@@ -58,11 +58,11 @@
5858
for item in item_set.copy():
5959
item_set.add(item + 10)
6060

61-
for l in ITEM_LIST:
61+
for l in item_list:
6262
for s in item_set:
63-
ITEM_LIST.append(1) # [modified-iterating-list]
63+
item_list.append(1) # [modified-iterating-list]
6464
item_set.remove(4) # [modified-iterating-set]
65-
ITEM_LIST.remove(1) # [modified-iterating-list]
65+
item_list.remove(1) # [modified-iterating-list]
6666

6767
for item in [1, 2, 3]:
6868
del item # [modified-iterating-list]
@@ -77,13 +77,13 @@
7777
del element # [modified-iterating-set]
7878

7979
# Check for nested for loops and changes to iterators
80-
for l in ITEM_LIST:
81-
ITEM_LIST.append(1) # [modified-iterating-list]
80+
for l in item_list:
81+
item_list.append(1) # [modified-iterating-list]
8282
for _ in []:
8383
for _ in []:
84-
ITEM_LIST.remove(1) # [modified-iterating-list]
84+
item_list.remove(1) # [modified-iterating-list]
8585
for _ in []:
86-
ITEM_LIST.append(1) # [modified-iterating-list]
86+
item_list.append(1) # [modified-iterating-list]
8787

8888

8989
def format_manifest_serializer_errors(errors):

0 commit comments

Comments
 (0)