@@ -338,10 +338,10 @@ def inspect_class(self, node: ObjectNode) -> None:
338
338
name = node .name ,
339
339
docstring = self ._get_docstring (node ),
340
340
bases = bases ,
341
- type_parameters = TypeParameters (* _convert_type_parameters (node .obj , self .current )),
342
341
lineno = lineno ,
343
342
endlineno = endlineno ,
344
343
)
344
+ class_ .type_parameters = TypeParameters (* _convert_type_parameters (node .obj , self .current , class_ ))
345
345
self .current .set_member (node .name , class_ )
346
346
self .current = class_
347
347
self .extensions .call ("on_instance" , node = node , obj = class_ , agent = self )
@@ -446,18 +446,10 @@ def handle_function(self, node: ObjectNode, labels: set | None = None) -> None:
446
446
except Exception : # noqa: BLE001
447
447
# so many exceptions can be raised here:
448
448
# AttributeError, NameError, RuntimeError, ValueError, TokenError, TypeError
449
- parameters = None
450
- returns = None
449
+ signature = None
450
+ return_annotation = None
451
451
else :
452
- parameters = Parameters (
453
- * [_convert_parameter (parameter , parent = self .current ) for parameter in signature .parameters .values ()],
454
- )
455
- return_annotation = signature .return_annotation
456
- returns = (
457
- None
458
- if return_annotation is _empty
459
- else _convert_object_to_annotation (return_annotation , parent = self .current )
460
- )
452
+ return_annotation = signature .return_annotation # type: ignore[union-attr]
461
453
462
454
lineno , endlineno = self ._get_linenos (node )
463
455
@@ -467,21 +459,41 @@ def handle_function(self, node: ObjectNode, labels: set | None = None) -> None:
467
459
obj = Attribute (
468
460
name = node .name ,
469
461
value = None ,
470
- annotation = returns ,
471
462
docstring = self ._get_docstring (node ),
472
463
lineno = lineno ,
473
464
endlineno = endlineno ,
474
465
)
466
+ if return_annotation is not None :
467
+ obj .annotation = (
468
+ None
469
+ if return_annotation is _empty
470
+ else _convert_object_to_annotation (
471
+ return_annotation ,
472
+ parent = self .current ,
473
+ annotation_scope = self .current if self .current .is_class else None , # type: ignore[arg-type]
474
+ )
475
+ )
475
476
else :
476
477
obj = Function (
477
478
name = node .name ,
478
- parameters = parameters ,
479
- returns = returns ,
480
- type_parameters = TypeParameters (* _convert_type_parameters (node .obj , self .current )),
481
479
docstring = self ._get_docstring (node ),
482
480
lineno = lineno ,
483
481
endlineno = endlineno ,
484
482
)
483
+ obj .type_parameters = TypeParameters (* _convert_type_parameters (node .obj , self .current , obj ))
484
+ if signature is not None :
485
+ obj .parameters = Parameters (
486
+ * [
487
+ _convert_parameter (parameter , parent = self .current , annotation_scope = obj )
488
+ for parameter in signature .parameters .values ()
489
+ ],
490
+ )
491
+ obj .returns = (
492
+ None
493
+ if return_annotation is _empty
494
+ else _convert_object_to_annotation (return_annotation , parent = self .current , annotation_scope = obj )
495
+ )
496
+
485
497
obj .labels |= labels
486
498
self .current .set_member (node .name , obj )
487
499
self .extensions .call ("on_instance" , node = node , obj = obj , agent = self )
@@ -503,13 +515,13 @@ def inspect_type_alias(self, node: ObjectNode) -> None:
503
515
504
516
type_alias = TypeAlias (
505
517
name = node .name ,
506
- value = _convert_type_to_annotation (node .obj .__value__ , self .current ),
507
518
lineno = lineno ,
508
519
endlineno = endlineno ,
509
- type_parameters = TypeParameters (* _convert_type_parameters (node .obj , self .current )),
510
520
docstring = self ._get_docstring (node ),
511
521
parent = self .current ,
512
522
)
523
+ type_alias .value = _convert_type_to_annotation (node .obj .__value__ , self .current , type_alias )
524
+ type_alias .type_parameters = TypeParameters (* _convert_type_parameters (node .obj , self .current , type_alias ))
513
525
self .current .set_member (node .name , type_alias )
514
526
self .extensions .call ("on_instance" , node = node , obj = type_alias , agent = self )
515
527
self .extensions .call ("on_type_alias_instance" , node = node , type_alias = type_alias , agent = self )
@@ -579,10 +591,16 @@ def handle_attribute(self, node: ObjectNode, annotation: str | Expr | None = Non
579
591
}
580
592
581
593
582
- def _convert_parameter (parameter : SignatureParameter , parent : Module | Class ) -> Parameter :
594
+ def _convert_parameter (
595
+ parameter : SignatureParameter ,
596
+ parent : Module | Class ,
597
+ annotation_scope : Function | Class | TypeAlias ,
598
+ ) -> Parameter :
583
599
name = parameter .name
584
600
annotation = (
585
- None if parameter .annotation is _empty else _convert_object_to_annotation (parameter .annotation , parent = parent )
601
+ None
602
+ if parameter .annotation is _empty
603
+ else _convert_object_to_annotation (parameter .annotation , parent = parent , annotation_scope = annotation_scope )
586
604
)
587
605
kind = _parameter_kind_map [parameter .kind ]
588
606
if parameter .default is _empty :
@@ -595,7 +613,11 @@ def _convert_parameter(parameter: SignatureParameter, parent: Module | Class) ->
595
613
return Parameter (name , annotation = annotation , kind = kind , default = default )
596
614
597
615
598
- def _convert_object_to_annotation (obj : Any , parent : Module | Class ) -> str | Expr | None :
616
+ def _convert_object_to_annotation (
617
+ obj : Any ,
618
+ parent : Module | Class ,
619
+ annotation_scope : Function | Class | TypeAlias | None ,
620
+ ) -> str | Expr | None :
599
621
# even when *we* import future annotations,
600
622
# the object from which we get a signature
601
623
# can come from modules which did *not* import them,
@@ -612,7 +634,7 @@ def _convert_object_to_annotation(obj: Any, parent: Module | Class) -> str | Exp
612
634
annotation_node = compile (obj , mode = "eval" , filename = "<>" , flags = ast .PyCF_ONLY_AST , optimize = 2 )
613
635
except SyntaxError :
614
636
return obj
615
- return safe_get_annotation (annotation_node .body , parent = parent ) # type: ignore[attr-defined]
637
+ return safe_get_annotation (annotation_node .body , parent = parent , annotation_scope = annotation_scope ) # type: ignore[attr-defined]
616
638
617
639
618
640
_type_parameter_kind_map = {
@@ -630,6 +652,7 @@ def _convert_object_to_annotation(obj: Any, parent: Module | Class) -> str | Exp
630
652
def _convert_type_parameters (
631
653
obj : Any ,
632
654
parent : Module | Class ,
655
+ annotation_scope : Function | Class | TypeAlias ,
633
656
) -> list [TypeParameter ]:
634
657
obj = unwrap (obj )
635
658
@@ -640,16 +663,17 @@ def _convert_type_parameters(
640
663
for type_parameter in obj .__type_params__ :
641
664
bound = getattr (type_parameter , "__bound__" , None )
642
665
if bound is not None :
643
- bound = _convert_type_to_annotation (bound , parent = parent )
666
+ bound = _convert_type_to_annotation (bound , parent = parent , annotation_scope = annotation_scope )
644
667
constraints : list [str | Expr ] = [
645
- _convert_type_to_annotation (constraint , parent = parent ) # type: ignore[misc]
668
+ _convert_type_to_annotation (constraint , parent = parent , annotation_scope = annotation_scope ) # type: ignore[misc]
646
669
for constraint in getattr (type_parameter , "__constraints__" , ())
647
670
]
648
671
649
672
if getattr (type_parameter , "has_default" , lambda : False )():
650
673
default = _convert_type_to_annotation (
651
674
type_parameter .__default__ ,
652
675
parent = parent ,
676
+ annotation_scope = annotation_scope ,
653
677
)
654
678
else :
655
679
default = None
@@ -667,22 +691,27 @@ def _convert_type_parameters(
667
691
return type_parameters
668
692
669
693
670
- def _convert_type_to_annotation (obj : Any , parent : Module | Class ) -> str | Expr | None :
694
+ def _convert_type_to_annotation (
695
+ obj : Any ,
696
+ parent : Module | Class ,
697
+ annotation_scope : Function | Class | TypeAlias ,
698
+ ) -> str | Expr | None :
671
699
origin = typing .get_origin (obj )
672
700
673
701
if origin is None :
674
- return _convert_object_to_annotation (obj , parent = parent )
702
+ return _convert_object_to_annotation (obj , parent = parent , annotation_scope = annotation_scope )
675
703
676
704
args : Sequence [str | Expr | None ] = [
677
- _convert_type_to_annotation (arg , parent = parent ) for arg in typing .get_args (obj )
705
+ _convert_type_to_annotation (arg , parent = parent , annotation_scope = annotation_scope )
706
+ for arg in typing .get_args (obj )
678
707
]
679
708
680
709
# YORE: EOL 3.9: Replace block with lines 2-3.
681
710
if sys .version_info >= (3 , 10 ):
682
711
if origin is types .UnionType :
683
712
return functools .reduce (lambda left , right : ExprBinOp (left , "|" , right ), args ) # type: ignore[arg-type]
684
713
685
- origin = _convert_type_to_annotation (origin , parent = parent )
714
+ origin = _convert_type_to_annotation (origin , parent = parent , annotation_scope = annotation_scope )
686
715
if origin is None :
687
716
return None
688
717
0 commit comments