Skip to content

Commit 92a13df

Browse files
[Backport maintenance/4.0.x] Fix FP for invalid-name on module-level constant with multiple branches (#10684)
Fix FP for `invalid-name` on module-level constant with multiple branches (#10677) (cherry picked from commit 6678c90) Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>
1 parent 4c913c0 commit 92a13df

File tree

5 files changed

+33
-11
lines changed

5 files changed

+33
-11
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fix a false positive for ``invalid-name`` on exclusive module-level assignments
2+
composed of three or more branches. We won't raise ``disallowed-name`` on module-level names that can't be inferred
3+
until a further refactor to remove this false negative is done.
4+
5+
Closes #10664

pylint/checkers/base/name_checker/checker.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -523,16 +523,22 @@ def visit_assignname( # pylint: disable=too-many-branches,too-many-statements
523523
if (
524524
(iattrs := tuple(node.frame().igetattr(node.name)))
525525
and util.Uninferable not in iattrs
526-
and len(iattrs) == 2
527-
and astroid.are_exclusive(*iattrs)
526+
and len(iattrs) > 1
527+
and all(
528+
astroid.are_exclusive(*combo)
529+
for combo in itertools.combinations(iattrs, 2)
530+
)
528531
):
529532
node_type = "const"
530-
self._check_name(
531-
node_type,
532-
node.name,
533-
node,
534-
disallowed_check_only=redefines_import,
535-
)
533+
if not self._meets_exception_for_non_consts(
534+
inferred_assign_type, node.name
535+
):
536+
self._check_name(
537+
node_type,
538+
node.name,
539+
node,
540+
disallowed_check_only=redefines_import,
541+
)
536542

537543
# Check names defined in function scopes
538544
elif isinstance(frame, nodes.FunctionDef):

tests/functional/d/disallowed_name.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ def baz(): # [disallowed-name]
66
class foo(): # [disallowed-name]
77
pass
88

9-
foo = {}.keys() # [disallowed-name]
9+
foo = {}.keys() # Should raise disallowed-name once _check_name() is refactored.
1010
foo = 42 # [disallowed-name]
1111
aaa = 42 # [invalid-name]
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
disallowed-name:3:0:3:7:baz:"Disallowed name ""baz""":HIGH
22
disallowed-name:6:0:6:9:foo:"Disallowed name ""foo""":HIGH
3-
disallowed-name:9:0:9:3::"Disallowed name ""foo""":HIGH
43
disallowed-name:10:0:10:3::"Disallowed name ""foo""":HIGH
54
invalid-name:11:0:11:3::"Constant name ""aaa"" doesn't conform to UPPER_CASE naming style":HIGH

tests/functional/i/invalid/invalid_name/invalid_name_module_level.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,19 @@ def A(): # [invalid-name]
2626
ASSIGNMENT_THAT_CRASHED_PYLINT = type(float.__new__.__code__)
2727

2828

29+
# Exclusive assignment: uses const regex
2930
if CONST:
3031
OTHER_CONST = 1
31-
else:
32+
elif CONSTA:
3233
OTHER_CONST = 2
34+
else:
35+
OTHER_CONST = 3
36+
37+
38+
# Lists, sets, and objects can pass against the variable OR const regexes.
39+
if CONST:
40+
other_const = [1]
41+
elif CONSTA:
42+
other_const = [2]
43+
else:
44+
other_const = [3]

0 commit comments

Comments
 (0)