Skip to content

Commit 01df3f3

Browse files
committed
Pass 'parents' as a parameter when walking the tree
Rather than storing the 'parents' deque as an instance attribute, pass it as a parameter as we walk the tree. This gives us more explicit control of this stack's lifetime (and no more mutable state on the object itself), and it allows us to better restrict the typed interface we present to visitor methods (`Iterable`). It also might result in a micro-optimization because read a parameter value is less involved (faster) than loading an instance attribute, but that isn't the goal of this change.
1 parent de0963c commit 01df3f3

File tree

1 file changed

+22
-23
lines changed

1 file changed

+22
-23
lines changed

src/pep8ext_naming.py

+22-23
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import ast
33
from ast import iter_child_nodes
44
from collections import deque
5+
from collections.abc import Iterable
56
from fnmatch import fnmatchcase
67
from functools import partial
78
from itertools import chain
@@ -107,8 +108,7 @@ class NamingChecker:
107108
ignore_names = frozenset(_default_ignore_names)
108109

109110
def __init__(self, tree, filename):
110-
self.parents = deque()
111-
self._node = tree
111+
self.tree = tree
112112

113113
@classmethod
114114
def add_options(cls, parser):
@@ -157,23 +157,22 @@ def parse_options(cls, options):
157157
)
158158

159159
def run(self):
160-
return self.visit_tree(self._node) if self._node else ()
160+
return self.visit_tree(self.tree, deque()) if self.tree else ()
161161

162-
def visit_tree(self, node):
163-
yield from self.visit_node(node)
164-
self.parents.append(node)
162+
def visit_tree(self, node, parents: deque):
163+
yield from self.visit_node(node, parents)
164+
parents.append(node)
165165
for child in iter_child_nodes(node):
166-
yield from self.visit_tree(child)
167-
self.parents.pop()
166+
yield from self.visit_tree(child, parents)
167+
parents.pop()
168168

169-
def visit_node(self, node):
169+
def visit_node(self, node, parents: Iterable):
170170
if isinstance(node, ast.ClassDef):
171171
self.tag_class_functions(node)
172172
elif isinstance(node, FUNC_NODES):
173173
self.find_global_defs(node)
174174

175175
method = 'visit_' + node.__class__.__name__.lower()
176-
parents = self.parents
177176
ignore_names = self.ignore_names
178177
for visitor in self.visitors:
179178
visitor_method = getattr(visitor, method, None)
@@ -263,14 +262,14 @@ class ClassNameCheck(BaseASTCheck):
263262
N818 = "exception name '{name}' should be named with an Error suffix"
264263

265264
@classmethod
266-
def get_classdef(cls, name, parents):
265+
def get_classdef(cls, name, parents: Iterable):
267266
for parent in parents:
268267
for node in parent.body:
269268
if isinstance(node, ast.ClassDef) and node.name == name:
270269
return node
271270

272271
@classmethod
273-
def superclass_names(cls, name, parents, _names=None):
272+
def superclass_names(cls, name, parents: Iterable, _names=None):
274273
names = _names or set()
275274
classdef = cls.get_classdef(name, parents)
276275
if not classdef:
@@ -281,7 +280,7 @@ def superclass_names(cls, name, parents, _names=None):
281280
names.update(cls.superclass_names(base.id, parents, names))
282281
return names
283282

284-
def visit_classdef(self, node, parents, ignore=None):
283+
def visit_classdef(self, node, parents: Iterable, ignore=None):
285284
name = node.name
286285
if _ignored(name, ignore):
287286
return
@@ -316,7 +315,7 @@ def has_override_decorator(node):
316315
return True
317316
return False
318317

319-
def visit_functiondef(self, node, parents, ignore=None):
318+
def visit_functiondef(self, node, parents: Iterable, ignore=None):
320319
function_type = getattr(node, 'function_type', _FunctionType.FUNCTION)
321320
name = node.name
322321
if _ignored(name, ignore):
@@ -347,7 +346,7 @@ class FunctionArgNamesCheck(BaseASTCheck):
347346
N804 = "first argument of a classmethod should be named 'cls'"
348347
N805 = "first argument of a method should be named 'self'"
349348

350-
def visit_functiondef(self, node, parents, ignore=None):
349+
def visit_functiondef(self, node, parents: Iterable, ignore=None):
351350

352351
def arg_name(arg):
353352
return (arg, arg.arg) if arg else (node, arg)
@@ -389,7 +388,7 @@ class ImportAsCheck(BaseASTCheck):
389388
N814 = "camelcase '{name}' imported as constant '{asname}'"
390389
N817 = "camelcase '{name}' imported as acronym '{asname}'"
391390

392-
def visit_importfrom(self, node, parents, ignore=None):
391+
def visit_importfrom(self, node, parents: Iterable, ignore=None):
393392
for name in node.names:
394393
asname = name.asname
395394
if not asname:
@@ -421,7 +420,7 @@ class VariablesCheck(BaseASTCheck):
421420
N815 = "variable '{name}' in class scope should not be mixedCase"
422421
N816 = "variable '{name}' in global scope should not be mixedCase"
423422

424-
def _find_errors(self, assignment_target, parents, ignore):
423+
def _find_errors(self, assignment_target, parents: Iterable, ignore):
425424
for parent_func in reversed(parents):
426425
if isinstance(parent_func, ast.ClassDef):
427426
checker = self.class_variable_check
@@ -449,36 +448,36 @@ def is_namedtupe(node_value):
449448
return True
450449
return False
451450

452-
def visit_assign(self, node, parents, ignore=None):
451+
def visit_assign(self, node, parents: Iterable, ignore=None):
453452
if self.is_namedtupe(node.value):
454453
return
455454
for target in node.targets:
456455
yield from self._find_errors(target, parents, ignore)
457456

458-
def visit_namedexpr(self, node, parents, ignore):
457+
def visit_namedexpr(self, node, parents: Iterable, ignore):
459458
if self.is_namedtupe(node.value):
460459
return
461460
yield from self._find_errors(node.target, parents, ignore)
462461

463462
visit_annassign = visit_namedexpr
464463

465-
def visit_with(self, node, parents, ignore):
464+
def visit_with(self, node, parents: Iterable, ignore):
466465
for item in node.items:
467466
yield from self._find_errors(
468467
item.optional_vars, parents, ignore)
469468

470469
visit_asyncwith = visit_with
471470

472-
def visit_for(self, node, parents, ignore):
471+
def visit_for(self, node, parents: Iterable, ignore):
473472
yield from self._find_errors(node.target, parents, ignore)
474473

475474
visit_asyncfor = visit_for
476475

477-
def visit_excepthandler(self, node, parents, ignore):
476+
def visit_excepthandler(self, node, parents: Iterable, ignore):
478477
if node.name:
479478
yield from self._find_errors(node, parents, ignore)
480479

481-
def visit_generatorexp(self, node, parents, ignore):
480+
def visit_generatorexp(self, node, parents: Iterable, ignore):
482481
for gen in node.generators:
483482
yield from self._find_errors(gen.target, parents, ignore)
484483

0 commit comments

Comments
 (0)