Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit fb0fe5d

Browse files
committedMar 11, 2022
Add boilerplate to allow checking TypeVar names
1 parent d01e5e1 commit fb0fe5d

File tree

6 files changed

+32
-9
lines changed

6 files changed

+32
-9
lines changed
 

‎doc/user_guide/options.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ name is found in, and not the type of object assigned.
3939
+--------------------+---------------------------------------------------------------------------------------------------+
4040
| ``inlinevar`` | Loop variables in list comprehensions and generator expressions. |
4141
+--------------------+---------------------------------------------------------------------------------------------------+
42+
| ``typevar`` | Type variable declared with ``TypeVar``. |
43+
+--------------------+---------------------------------------------------------------------------------------------------+
4244

4345
Default behavior
4446
~~~~~~~~~~~~~~~~
@@ -82,6 +84,8 @@ Following options are exposed:
8284

8385
.. option:: --inlinevar-naming-style=<style>
8486

87+
.. option:: --typevar-naming-style=<style>
88+
8589

8690
Custom regular expressions
8791
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -118,6 +122,8 @@ expression will lead to an instance of ``invalid-name``.
118122

119123
.. option:: --inlinevar-rgx=<regex>
120124

125+
.. option:: --typevar-rgx=<regex>
126+
121127
Multiple naming styles for custom regular expressions
122128
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
123129

‎pylint/checkers/base.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ def get_regex(cls, name_type):
128128
"class_attribute": cls.CLASS_ATTRIBUTE_RGX,
129129
"class_const": cls.CONST_NAME_RGX,
130130
"inlinevar": cls.COMP_VAR_RGX,
131+
# TODO: Create dedicated TypeVar pattern # pylint: disable=fixme
132+
"typevar": cls.CLASS_NAME_RGX,
131133
}[name_type]
132134

133135

@@ -1672,6 +1674,7 @@ def visit_for(self, node: nodes.For) -> None:
16721674
"class_attribute",
16731675
"class_const",
16741676
"inlinevar",
1677+
"typevar",
16751678
}
16761679

16771680
DEFAULT_NAMING_STYLES = {
@@ -1686,6 +1689,7 @@ def visit_for(self, node: nodes.For) -> None:
16861689
"class_attribute": "any",
16871690
"class_const": "UPPER_CASE",
16881691
"inlinevar": "any",
1692+
"typevar": "PascalCase",
16891693
}
16901694

16911695

@@ -2078,14 +2082,6 @@ def _name_disallowed_by_regex(self, name: str) -> bool:
20782082
def _check_name(self, node_type, name, node, confidence=interfaces.HIGH):
20792083
"""Check for a name using the type's regexp."""
20802084

2081-
# pylint: disable=fixme
2082-
# TODO: move this down in the function and check TypeVar
2083-
# for name patterns as well.
2084-
# Check TypeVar names for variance suffixes
2085-
if node_type == "typevar":
2086-
self._check_typevar_variance(name, node)
2087-
return
2088-
20892085
def _should_exempt_from_invalid_name(node):
20902086
if node_type == "variable":
20912087
inferred = utils.safe_infer(node)
@@ -2111,6 +2107,10 @@ def _should_exempt_from_invalid_name(node):
21112107
if match is None and not _should_exempt_from_invalid_name(node):
21122108
self._raise_name_warning(None, node, node_type, name, confidence)
21132109

2110+
# Check TypeVar names for variance suffixes
2111+
if node_type == "typevar":
2112+
self._check_typevar_variance(name, node)
2113+
21142114
def _check_assign_to_new_keyword_violation(self, name, node):
21152115
keyword_first_version = self._name_became_keyword_in_version(
21162116
name, self.KEYWORD_ONSET

‎pylint/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class WarningScope:
7171
"class_attribute": "class attribute",
7272
"class_const": "class constant",
7373
"inlinevar": "inline iteration",
74+
"typevar": "type variable",
7475
}
7576

7677

‎pylint/utils/linterstats.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class BadNames(TypedDict):
2626
method: int
2727
module: int
2828
variable: int
29+
typevar: int
2930

3031

3132
class CodeTypeCount(TypedDict):
@@ -102,6 +103,7 @@ def __init__(
102103
method=0,
103104
module=0,
104105
variable=0,
106+
typevar=0,
105107
)
106108
self.by_module: Dict[str, ModuleStats] = by_module or {}
107109
self.by_msg: Dict[str, int] = by_msg or {}
@@ -171,6 +173,7 @@ def get_bad_names(
171173
"method",
172174
"module",
173175
"variable",
176+
"typevar",
174177
],
175178
) -> int:
176179
"""Get a bad names node count."""
@@ -192,6 +195,7 @@ def increase_bad_name(self, node_name: str, increase: int) -> None:
192195
"method",
193196
"module",
194197
"variable",
198+
"typevar",
195199
}:
196200
raise ValueError("Node type not part of the bad_names stat")
197201

@@ -208,6 +212,7 @@ def increase_bad_name(self, node_name: str, increase: int) -> None:
208212
"method",
209213
"module",
210214
"variable",
215+
"typevar",
211216
],
212217
node_name,
213218
)
@@ -230,6 +235,7 @@ def reset_bad_names(self) -> None:
230235
method=0,
231236
module=0,
232237
variable=0,
238+
typevar=0,
233239
)
234240

235241
def get_code_count(
@@ -317,6 +323,7 @@ def merge_stats(stats: List[LinterStats]):
317323
merged.bad_names["method"] += stat.bad_names["method"]
318324
merged.bad_names["module"] += stat.bad_names["module"]
319325
merged.bad_names["variable"] += stat.bad_names["variable"]
326+
merged.bad_names["typevar"] += stat.bad_names["typevar"]
320327

321328
for mod_key, mod_value in stat.by_module.items():
322329
merged.by_module[mod_key] = mod_value

‎pylintrc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,13 @@ method-rgx=[a-z_][a-z0-9_]{2,}$
353353
# Naming hint for method names
354354
method-name-hint=[a-z_][a-z0-9_]{2,}$
355355

356+
# Naming style used for type variables. Default is PascalCase.
357+
typevar-naming-style=PascalCase
358+
359+
# Regular expression which can overwrite the naming style set by typevar-naming-style.
360+
# If left empty, type variables will be checked with the set naming style.
361+
typevar-rgx=
362+
356363
# Regular expression which should only match function or class names that do
357364
# not require a docstring. Use ^(?!__init__$)_ to also check __init__.
358365
no-docstring-rgx=__.*__
@@ -364,7 +371,6 @@ docstring-min-length=-1
364371
# List of decorators that define properties, such as abc.abstractproperty.
365372
property-classes=abc.abstractproperty
366373

367-
368374
[TYPECHECK]
369375

370376
# Tells whether missing members accessed in mixin class should be ignored.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[BASIC]
2+
# TODO: Remove this option and use default style
3+
typevar-rgx=^_{0,2}(?:[^\W\da-z_]+|(?:[^\W\da-z_][^\WA-Z_]+)+T?(?<!Type))(?:_co(?:ntra)?)?$

0 commit comments

Comments
 (0)
Please sign in to comment.