Skip to content

Commit bdd017f

Browse files
[Backport maintenance/4.0.x] Fix too-many-locals counting PEP 695 type parameters as local variables (#11142)
Fix `too-many-locals` counting PEP 695 type parameters as local variables (#11138) Fix too-many-locals counting PEP 695 type parameters as locals astroid places PEP 695 type-param names in node.locals, so R0914 over-counted (def f[T1..T16](x) reported 17/15 for one real local). Exclude type params from the count. Closes #11136 (cherry picked from commit e628929) Co-authored-by: Hibi <hibin.m@gmail.com> Co-authored-by: Synvoya <16019863+Synvoya@users.noreply.github.com>
1 parent 5153a7c commit bdd017f

5 files changed

Lines changed: 41 additions & 1 deletion

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a false positive for ``too-many-locals`` (``R0914``): PEP 695 type parameters (e.g. ``def f[T1, T2](...)``) were counted as local variables. They are type-system constructs, not runtime locals, and are now excluded from the local-variable count.
2+
3+
Closes #11136

pylint/checkers/design_analysis.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,10 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
577577
)
578578

579579
# check number of local variables
580-
locnum = len(node.locals) - ignored_args_num
580+
# PEP 695 type parameters live in the function's ``locals`` but are
581+
# type-system constructs, not runtime local variables, so exclude them.
582+
type_param_names = {param.name.name for param in node.type_params}
583+
locnum = len(set(node.locals) - type_param_names) - ignored_args_num
581584

582585
# decrement number of local variables if '_' is one of them
583586
if "_" in node.locals:
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# pylint: disable=missing-docstring,unused-variable,line-too-long
2+
3+
4+
# PEP 695 type parameters live in the function's locals but are type-system
5+
# constructs, not runtime local variables, so they must not be counted towards
6+
# ``too-many-locals``. This function has 16 type parameters but only one real
7+
# local variable, so it must NOT emit ``too-many-locals``.
8+
def build[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16](arg):
9+
result = arg
10+
return result
11+
12+
13+
# Mixed case: 16 type parameters plus 16 genuine local variables. Only the real
14+
# locals are counted, so this emits ``too-many-locals`` at 16/15 (not 32/15).
15+
def mixed[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16](start): # [too-many-locals]
16+
loc0 = start
17+
loc1 = loc0 * 1
18+
loc2 = loc1 * 2
19+
loc3 = loc2 * 3
20+
loc4 = loc3 * 4
21+
loc5 = loc4 * 5
22+
loc6 = loc5 * 6
23+
loc7 = loc6 * 7
24+
loc8 = loc7 * 8
25+
loc9 = loc8 * 9
26+
loc10 = loc9 * 10
27+
loc11 = loc10 * 11
28+
loc12 = loc11 * 12
29+
loc13 = loc12 * 13
30+
loc14 = loc13 * 14
31+
return loc14
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[testoptions]
2+
min_pyver=3.12
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
too-many-locals:15:0:15:9:mixed:Too many local variables (16/15):UNDEFINED

0 commit comments

Comments
 (0)