Skip to content

Commit 553fd50

Browse files
Fix FN for invalid-name for type-annotated module constants
1 parent 2bb1a44 commit 553fd50

13 files changed

+39
-30
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Check module-level constants with type annotations for ``invalid-name``.
2+
Remember to adjust ``const-naming-style`` or ``const-rgx`` to your liking.
3+
4+
Closes #9770

pylint/checkers/base/name_checker/checker.py

+11-10
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
400400
"typevar-double-variance",
401401
"typevar-name-mismatch",
402402
)
403-
def visit_assignname( # pylint: disable=too-many-branches, too-many-statements
403+
def visit_assignname( # pylint: disable=too-many-branches
404404
self, node: nodes.AssignName
405405
) -> None:
406406
"""Check module level assigned names."""
@@ -419,9 +419,17 @@ def visit_assignname( # pylint: disable=too-many-branches, too-many-statements
419419

420420
# Check names defined in module scope
421421
elif isinstance(frame, nodes.Module):
422+
# Check names defined in AnnAssign nodes
423+
if isinstance(assign_type, nodes.AnnAssign) and self._assigns_typealias(
424+
assign_type.annotation
425+
):
426+
self._check_name("typealias", node.name, node)
427+
422428
# Check names defined in Assign nodes
423-
if isinstance(assign_type, nodes.Assign):
424-
inferred_assign_type = utils.safe_infer(assign_type.value)
429+
elif isinstance(assign_type, (nodes.Assign, nodes.AnnAssign)):
430+
inferred_assign_type = (
431+
utils.safe_infer(assign_type.value) if assign_type.value else None
432+
)
425433

426434
# Check TypeVar's and TypeAliases assigned alone or in tuple assignment
427435
if isinstance(node.parent, nodes.Assign):
@@ -498,13 +506,6 @@ def visit_assignname( # pylint: disable=too-many-branches, too-many-statements
498506
disallowed_check_only=redefines_import,
499507
)
500508

501-
# Check names defined in AnnAssign nodes
502-
elif isinstance(assign_type, nodes.AnnAssign):
503-
if utils.is_assign_name_annotated_with(node, "Final"):
504-
self._check_name("const", node.name, node)
505-
elif self._assigns_typealias(assign_type.annotation):
506-
self._check_name("typealias", node.name, node)
507-
508509
# Check names defined in function scopes
509510
elif isinstance(frame, nodes.FunctionDef):
510511
# global introduced variable aren't in the function locals

tests/functional/ext/private_import/private_import.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ def c2_func() -> _TypeContainerC.C:
7979
# This is allowed since all the imports are used for typing
8080
from _TypeContainerExtra import TypeExtraA, TypeExtraB
8181
from MakerContainerExtra import GetA, GetB
82-
extraA: TypeExtraA = GetA()
83-
extraB: TypeExtraB = GetB()
82+
extra_a: TypeExtraA = GetA()
83+
extra_b: TypeExtraB = GetB()
8484

8585
# This is not allowed because there is an import not used for typing
8686
from _TypeContainerExtra2 import TypeExtra2, NotTypeExtra # [import-private-name]
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
[MAIN]
22
load-plugins=pylint.extensions.private_import,
3+
const-naming-style=snake_case

tests/functional/g/generic_alias/generic_alias_collections.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class CustomImplementation(CustomAbstractCls2): # [abstract-method,abstract-met
110110
# Type annotations
111111
var_tuple: tuple[int, int]
112112
var_dict: dict[int, str]
113-
var_orderedDict: collections.OrderedDict[int, str]
113+
var_ordereddict: collections.OrderedDict[int, str]
114114
var_container: collections.abc.Container[int]
115115
var_sequence: collections.abc.Sequence[int]
116116
var_iterable: collections.abc.Iterable[int]

tests/functional/g/generic_alias/generic_alias_mixed_py39.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
import typing
1010

1111
# Type annotations
12-
var_orderedDict: collections.OrderedDict[int, str]
12+
var_ordered_dict: collections.OrderedDict[int, str]
1313
var_container: collections.abc.Container[int]
1414
var_sequence: collections.abc.Sequence[int]
1515
var_iterable: collections.abc.Iterable[int]
1616
var_awaitable: collections.abc.Awaitable[int]
1717
var_pattern: re.Pattern[int]
1818
var_bytestring: collections.abc.ByteString
1919
var_hashable: collections.abc.Hashable
20-
var_ContextManager: contextlib.AbstractContextManager[int]
20+
var_context_manager: contextlib.AbstractContextManager[int]
2121

2222

2323
# No implementation required for 'builtins'

tests/functional/i/invalid/invalid_name.py

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
except ValueError:
1616
time = None # [invalid-name]
1717

18+
bbb: int = 42 # [invalid-name]
19+
1820
try:
1921
from sys import argv, executable as python
2022
except ImportError:
+8-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
invalid-name:12:0:12:3::"Constant name ""aaa"" doesn't conform to UPPER_CASE naming style":HIGH
22
invalid-name:16:4:16:8::"Constant name ""time"" doesn't conform to UPPER_CASE naming style":HIGH
3-
invalid-name:36:0:36:5:A:"Function name ""A"" doesn't conform to snake_case naming style":HIGH
4-
invalid-name:50:4:50:13::"Variable name ""Foocapfor"" doesn't conform to snake_case naming style":HIGH
5-
invalid-name:72:0:72:68:a_very_very_very_long_function_name_WithCamelCase_to_make_it_sad:"Function name ""a_very_very_very_long_function_name_WithCamelCase_to_make_it_sad"" doesn't conform to snake_case naming style":HIGH
6-
invalid-name:80:23:80:29:FooBar.__init__:"Argument name ""fooBar"" doesn't conform to snake_case naming style":HIGH
7-
invalid-name:86:8:86:14:FooBar.func1:"Argument name ""fooBar"" doesn't conform to snake_case naming style":HIGH
8-
invalid-name:106:8:106:15:FooBar.test_disable_mixed:"Argument name ""fooBar2"" doesn't conform to snake_case naming style":HIGH
9-
invalid-name:117:4:117:25:FooBarSubclass:"Class attribute name ""tearDownNotInAncestor"" doesn't conform to snake_case naming style":HIGH
3+
invalid-name:18:0:18:3::"Constant name ""bbb"" doesn't conform to UPPER_CASE naming style":HIGH
4+
invalid-name:38:0:38:5:A:"Function name ""A"" doesn't conform to snake_case naming style":HIGH
5+
invalid-name:52:4:52:13::"Variable name ""Foocapfor"" doesn't conform to snake_case naming style":HIGH
6+
invalid-name:74:0:74:68:a_very_very_very_long_function_name_WithCamelCase_to_make_it_sad:"Function name ""a_very_very_very_long_function_name_WithCamelCase_to_make_it_sad"" doesn't conform to snake_case naming style":HIGH
7+
invalid-name:82:23:82:29:FooBar.__init__:"Argument name ""fooBar"" doesn't conform to snake_case naming style":HIGH
8+
invalid-name:88:8:88:14:FooBar.func1:"Argument name ""fooBar"" doesn't conform to snake_case naming style":HIGH
9+
invalid-name:108:8:108:15:FooBar.test_disable_mixed:"Argument name ""fooBar2"" doesn't conform to snake_case naming style":HIGH
10+
invalid-name:119:4:119:25:FooBarSubclass:"Class attribute name ""tearDownNotInAncestor"" doesn't conform to snake_case naming style":HIGH
+3-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
invalid-name:3:0:3:13::"Constant name ""SOME_CONSTANT"" doesn't conform to camelCase naming style ('([^\\W\\dA-Z][^\\W_]*|__.*__)$' pattern)":HIGH
2-
invalid-name:10:0:10:13:MyClass:"Class name ""MyClass"" doesn't conform to camelCase naming style ('[^\\W\\dA-Z][^\\W_]*$' pattern)":HIGH
3-
invalid-name:27:0:27:13:say_hello:"Function name ""say_hello"" doesn't conform to camelCase naming style ('(?:__)?([^\\W\\dA-Z][^\\W_]*|__[^\\W\\dA-Z_]\\w+__)$' pattern)":HIGH
1+
invalid-name:3:0:3:13::"Constant name ""SOME_CONSTANT"" doesn't conform to camelCase naming style ('([^\\W\\dA-Z][^\\W_]*|__.*__)$' pattern)":HIGH
2+
invalid-name:10:0:10:13:MyClass:"Class name ""MyClass"" doesn't conform to camelCase naming style ('[^\\W\\dA-Z][^\\W_]*$' pattern)":HIGH
3+
invalid-name:27:0:27:13:say_hello:"Function name ""say_hello"" doesn't conform to camelCase naming style ('(?:__)?([^\\W\\dA-Z][^\\W_]*|__[^\\W\\dA-Z_]\\w+__)$' pattern)":HIGH

tests/functional/r/regression_02/regression_3979.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010
else:
1111
BasePathLike = os.PathLike
1212

13-
Foo: Union[str, BasePathLike] = "bar"
13+
FOO: Union[str, BasePathLike] = "bar"

tests/functional/t/type/typealias_naming_style_default.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727

2828
# Regression tests
2929
# They are not TypeAlias, and thus shouldn't flag the message
30-
x: Union[str, int] = 42
31-
y: Union[str, int]
30+
X: Union[str, int] = 42
31+
Y: Union[str, int]
3232
# But the following, using a good TypeAlias name, is:
3333
GoodTypeAliasToUnion: TypeAlias = Union[str, int]
3434

tests/functional/u/unused/unused_import.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class SomeClass:
3939
import xml
4040

4141

42-
example: t.Annotated[str, "Path"] = "/foo/bar"
42+
EXAMPLE: t.Annotated[str, "Path"] = "/foo/bar"
4343

4444
def get_ordered_dict() -> "collections.OrderedDict":
4545
return []

tests/functional/u/unused/unused_name_in_string_literal_type_annotation_py38.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def unused_variable_example():
1919

2020

2121
# pylint shouldn't crash with the following strings in a type annotation context
22-
example3: Lit["", " ", "?"] = "?"
22+
EXAMPLE3: Lit["", " ", "?"] = "?"
2323

2424

2525
# See https://peps.python.org/pep-0586/#literals-enums-and-forward-references

0 commit comments

Comments
 (0)