33import argparse
44import ast
55import sys
6+ from typing import Any
67from typing import Sequence
8+ from typing import Tuple
79
810SEP_SYMBOLS = frozenset (('(' , ')' , ',' , ':' ))
11+ # name, lineno, col_offset, end_lineno, end_col_offset
12+ Token = Tuple [str , int , int , int , int ]
913
1014
11- def name_lineno_coloffset (tokens ):
12- if isinstance (tokens , list ):
13- return [(i [0 ], i [1 ], i [2 ]) for i in tokens ]
15+ def name_lineno_coloffset_list (
16+ tokens : list [Token ],
17+ ) -> list [tuple [str , int , int ]]:
18+ return [(i [0 ], i [1 ], i [2 ]) for i in tokens ]
19+
20+
21+ def name_lineno_coloffset (tokens : Token ) -> tuple [str , int , int ]:
1422 return (tokens [0 ], tokens [1 ], tokens [2 ])
1523
1624
17- def record_name_lineno_coloffset (node , end_lineno = None , end_col_offset = None ):
25+ def record_name_lineno_coloffset (
26+ node : Any ,
27+ end_lineno : int | None = None ,
28+ end_col_offset : int | None = None ,
29+ ) -> Token :
1830 return (
1931 node .id , node .lineno , node .col_offset ,
2032 end_lineno or node .end_lineno ,
2133 end_col_offset or node .end_col_offset ,
2234 )
2335
2436
25- def find_names (node , end_lineno = None , end_col_offset = None ):
37+ def find_names (
38+ node : Any ,
39+ end_lineno : int | None = None ,
40+ end_col_offset : int | None = None ,
41+ ) -> set [Token ]:
2642 names = set ()
2743 for _node in ast .walk (node ):
2844 if isinstance (_node , ast .Name ):
@@ -34,7 +50,7 @@ def find_names(node, end_lineno=None, end_col_offset=None):
3450 return names
3551
3652
37- def visit_function_def (node , path ) :
53+ def visit_function_def (node : Any , path : str ) -> list [ tuple [ Token , Token ]] :
3854 names = set ()
3955 assignments = set ()
4056 ifs = set ()
@@ -64,35 +80,35 @@ def visit_function_def(node, path):
6480 elif isinstance (_node , (ast .If , ast .While )):
6581 ifs .update (find_names (_node .test ))
6682
67- names = sorted (names , key = lambda x : (x [1 ], x [2 ]))
68- assignments = sorted (assignments , key = lambda x : (x [1 ], x [2 ]))
69- ifs = sorted (ifs , key = lambda x : (x [1 ], x [2 ]))
83+ sorted_names = sorted (names , key = lambda x : (x [1 ], x [2 ]))
84+ sorted_assignments = sorted (assignments , key = lambda x : (x [1 ], x [2 ]))
85+ sorted_ifs = sorted (ifs , key = lambda x : (x [1 ], x [2 ]))
7086 walrus = []
7187
72- for _assignment in assignments :
73- _if_statements = [i for i in ifs if i [0 ] == _assignment [0 ]]
88+ for _assignment in sorted_assignments :
89+ _if_statements = [i for i in sorted_ifs if i [0 ] == _assignment [0 ]]
7490 if len (_if_statements ) != 1 :
7591 continue
7692 _if_statement = _if_statements [0 ]
77- assignment_idx = name_lineno_coloffset (
78- names ,
93+ assignment_idx = name_lineno_coloffset_list (
94+ sorted_names ,
7995 ).index (name_lineno_coloffset (_assignment ))
80- if_statement_idx = name_lineno_coloffset (
81- names ,
96+ if_statement_idx = name_lineno_coloffset_list (
97+ sorted_names ,
8298 ).index (name_lineno_coloffset (_if_statement ))
8399 _other_assignments = [
84100 name_lineno_coloffset (i )
85- for i in assignments if i [0 ] == _assignment [0 ]
101+ for i in sorted_assignments if i [0 ] == _assignment [0 ]
86102 ]
87103 _other_usages = [
88104 name_lineno_coloffset (
89105 i ,
90- ) for i in names if i [0 ] == _assignment [0 ]
106+ ) for i in sorted_names if i [0 ] == _assignment [0 ]
91107 ]
92108 if (
93109 # check name doesn't appear between assignment and if statement
94110 _assignment [0 ] not in [
95- names [i ][0 ]
111+ sorted_names [i ][0 ]
96112 for i in range (assignment_idx + 1 , if_statement_idx )
97113 ]
98114 # check it's the variable's only assignment
@@ -107,10 +123,13 @@ def visit_function_def(node, path):
107123 related = related_vars [_assignment [0 ]]
108124 should_break = False
109125 for rel in related :
110- usages = [i for i in names if i [0 ] == rel [0 ] if i != rel ]
126+ usages = [
127+ i for i in sorted_names if i [0 ]
128+ == rel [0 ] if i != rel
129+ ]
111130 for usage in usages :
112- rel_used_idx = name_lineno_coloffset (
113- names ,
131+ rel_used_idx = name_lineno_coloffset_list (
132+ sorted_names ,
114133 ).index (name_lineno_coloffset (usage ))
115134 if assignment_idx < rel_used_idx < if_statement_idx :
116135 should_break = True
@@ -120,12 +139,12 @@ def visit_function_def(node, path):
120139 return walrus
121140
122141
123- def auto_walrus (content , path , line_length ) :
142+ def auto_walrus (content : str , path : str , line_length : int ) -> str | None :
124143 lines = content .splitlines ()
125144 try :
126145 tree = ast .parse (content )
127146 except SyntaxError : # pragma: no cover
128- return 0
147+ return None
129148
130149 walruses = []
131150 for node in ast .walk (tree ):
0 commit comments