@@ -338,10 +338,10 @@ def inspect_class(self, node: ObjectNode) -> None:
338338 name = node .name ,
339339 docstring = self ._get_docstring (node ),
340340 bases = bases ,
341- type_parameters = TypeParameters (* _convert_type_parameters (node .obj , self .current )),
342341 lineno = lineno ,
343342 endlineno = endlineno ,
344343 )
344+ class_ .type_parameters = TypeParameters (* _convert_type_parameters (node .obj , self .current , class_ ))
345345 self .current .set_member (node .name , class_ )
346346 self .current = class_
347347 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:
446446 except Exception : # noqa: BLE001
447447 # so many exceptions can be raised here:
448448 # AttributeError, NameError, RuntimeError, ValueError, TokenError, TypeError
449- parameters = None
450- returns = None
449+ signature = None
450+ return_annotation = None
451451 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]
461453
462454 lineno , endlineno = self ._get_linenos (node )
463455
@@ -467,21 +459,41 @@ def handle_function(self, node: ObjectNode, labels: set | None = None) -> None:
467459 obj = Attribute (
468460 name = node .name ,
469461 value = None ,
470- annotation = returns ,
471462 docstring = self ._get_docstring (node ),
472463 lineno = lineno ,
473464 endlineno = endlineno ,
474465 )
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+ )
475476 else :
476477 obj = Function (
477478 name = node .name ,
478- parameters = parameters ,
479- returns = returns ,
480- type_parameters = TypeParameters (* _convert_type_parameters (node .obj , self .current )),
481479 docstring = self ._get_docstring (node ),
482480 lineno = lineno ,
483481 endlineno = endlineno ,
484482 )
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+
485497 obj .labels |= labels
486498 self .current .set_member (node .name , obj )
487499 self .extensions .call ("on_instance" , node = node , obj = obj , agent = self )
@@ -503,13 +515,13 @@ def inspect_type_alias(self, node: ObjectNode) -> None:
503515
504516 type_alias = TypeAlias (
505517 name = node .name ,
506- value = _convert_type_to_annotation (node .obj .__value__ , self .current ),
507518 lineno = lineno ,
508519 endlineno = endlineno ,
509- type_parameters = TypeParameters (* _convert_type_parameters (node .obj , self .current )),
510520 docstring = self ._get_docstring (node ),
511521 parent = self .current ,
512522 )
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 ))
513525 self .current .set_member (node .name , type_alias )
514526 self .extensions .call ("on_instance" , node = node , obj = type_alias , agent = self )
515527 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
579591}
580592
581593
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 :
583599 name = parameter .name
584600 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 )
586604 )
587605 kind = _parameter_kind_map [parameter .kind ]
588606 if parameter .default is _empty :
@@ -595,7 +613,11 @@ def _convert_parameter(parameter: SignatureParameter, parent: Module | Class) ->
595613 return Parameter (name , annotation = annotation , kind = kind , default = default )
596614
597615
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 :
599621 # even when *we* import future annotations,
600622 # the object from which we get a signature
601623 # 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
612634 annotation_node = compile (obj , mode = "eval" , filename = "<>" , flags = ast .PyCF_ONLY_AST , optimize = 2 )
613635 except SyntaxError :
614636 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]
616638
617639
618640_type_parameter_kind_map = {
@@ -630,6 +652,7 @@ def _convert_object_to_annotation(obj: Any, parent: Module | Class) -> str | Exp
630652def _convert_type_parameters (
631653 obj : Any ,
632654 parent : Module | Class ,
655+ annotation_scope : Function | Class | TypeAlias ,
633656) -> list [TypeParameter ]:
634657 obj = unwrap (obj )
635658
@@ -640,16 +663,17 @@ def _convert_type_parameters(
640663 for type_parameter in obj .__type_params__ :
641664 bound = getattr (type_parameter , "__bound__" , None )
642665 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 )
644667 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]
646669 for constraint in getattr (type_parameter , "__constraints__" , ())
647670 ]
648671
649672 if getattr (type_parameter , "has_default" , lambda : False )():
650673 default = _convert_type_to_annotation (
651674 type_parameter .__default__ ,
652675 parent = parent ,
676+ annotation_scope = annotation_scope ,
653677 )
654678 else :
655679 default = None
@@ -667,22 +691,27 @@ def _convert_type_parameters(
667691 return type_parameters
668692
669693
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 :
671699 origin = typing .get_origin (obj )
672700
673701 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 )
675703
676704 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 )
678707 ]
679708
680709 # YORE: EOL 3.9: Replace block with lines 2-3.
681710 if sys .version_info >= (3 , 10 ):
682711 if origin is types .UnionType :
683712 return functools .reduce (lambda left , right : ExprBinOp (left , "|" , right ), args ) # type: ignore[arg-type]
684713
685- origin = _convert_type_to_annotation (origin , parent = parent )
714+ origin = _convert_type_to_annotation (origin , parent = parent , annotation_scope = annotation_scope )
686715 if origin is None :
687716 return None
688717
0 commit comments