@@ -364,39 +364,39 @@ def nodefault_not_used_for_typing(file_obj: IO[str]) -> Iterable[Tuple[int, str]
364
364
Yields
365
365
------
366
366
line_number : int
367
- Line number of unconcatenated string .
367
+ Line number of misused lib.NoDefault .
368
368
msg : str
369
369
Explanation of the error.
370
370
"""
371
371
contents = file_obj .read ()
372
372
tree = ast .parse (contents )
373
- for node in ast .walk (tree ):
374
- for child in ast .iter_child_nodes (node ):
375
- child .parent = node
376
-
377
- def child_of (node , types ):
378
- """Check if any ancestor of the node has the specified type.
379
-
380
- Parameters
381
- ----------
382
- node : AST
383
- A node in the AST.
384
- types : tuple of classes
385
- The types as in `ininstance(xxx, types)`.
386
- """
387
- curnode = getattr (node , "parent" , None )
388
- while curnode is not None :
389
- if isinstance (curnode , types ):
390
- return True
391
- curnode = getattr (curnode , "parent" , None )
392
- return False
393
-
394
- for node in ast .walk (tree ):
395
- if (isinstance (node , ast .Name ) and node .id == "NoDefault" ) or (
396
- isinstance (node , ast .Attribute ) and node .attr == "NoDefault"
373
+ in_annotation = False
374
+ nodes : List [tuple [bool , ast .AST ]] = [(in_annotation , tree )]
375
+
376
+ while nodes :
377
+ in_annotation , node = nodes .pop ()
378
+ if not in_annotation and (
379
+ isinstance (node , ast .Name ) # Case `NoDefault`
380
+ and node .id == "NoDefault"
381
+ or isinstance (node , ast .Attribute ) # Cases e.g. `lib.NoDefault`
382
+ and node .attr == "NoDefault"
397
383
):
398
- if not child_of (node , (ast .AnnAssign , ast .arg )):
399
- yield (node .lineno , "NoDefault is not used for typing" )
384
+ yield (node .lineno , "NoDefault is not used for typing" )
385
+
386
+ # This part is adapted from
387
+ # https://github.com/asottile/pyupgrade/blob/5495a248f2165941c5d3b82ac3226ba7ad1fa59d/pyupgrade/_data.py#L70-L113
388
+ for name in reversed (node ._fields ):
389
+ value = getattr (node , name )
390
+ if name in {"annotation" , "returns" }:
391
+ next_in_annotation = True
392
+ else :
393
+ next_in_annotation = in_annotation
394
+ if isinstance (value , ast .AST ):
395
+ nodes .append ((next_in_annotation , value ))
396
+ elif isinstance (value , list ):
397
+ for value in reversed (value ):
398
+ if isinstance (value , ast .AST ):
399
+ nodes .append ((next_in_annotation , value ))
400
400
401
401
402
402
def main (
@@ -460,7 +460,7 @@ def main(
460
460
parser .add_argument (
461
461
"--format" ,
462
462
"-f" ,
463
- default = "{source_path}:{line_number}:{msg}" ,
463
+ default = "{source_path}:{line_number}: {msg}" ,
464
464
help = "Output format of the error message." ,
465
465
)
466
466
parser .add_argument (
0 commit comments