@@ -588,74 +588,100 @@ def _inject_types_to_docstring(
588
588
name : str ,
589
589
lines : list [str ],
590
590
) -> None :
591
-
592
591
if signature is not None :
593
- for arg_name in signature .parameters :
594
- annotation = type_hints .get (arg_name , None )
592
+ _inject_signature (type_hints , signature , app , lines )
593
+ if "return" in type_hints :
594
+ _inject_rtype (type_hints , original_obj , app , what , name , lines )
595
595
596
- default = signature .parameters [arg_name ].default
597
596
598
- if arg_name .endswith ("_" ):
599
- arg_name = f"{ arg_name [:- 1 ]} \\ _"
597
+ def _inject_signature (
598
+ type_hints : dict [str , Any ],
599
+ signature : inspect .Signature ,
600
+ app : Sphinx ,
601
+ lines : list [str ],
602
+ ) -> None :
603
+ for arg_name in signature .parameters :
604
+ annotation = type_hints .get (arg_name , None )
600
605
601
- insert_index = None
602
- for at , line in enumerate (lines ):
603
- if _line_is_param_line_for_arg (line , arg_name ):
604
- # Get the arg_name from the doc to match up for type in case it has a star prefix.
605
- # Line is in the correct format so this is guaranteed to return tuple[str, str].
606
- _ , arg_name = _get_sphinx_line_keyword_and_argument (line ) # type: ignore[assignment, misc]
607
- insert_index = at
608
- break
609
-
610
- if annotation is not None and insert_index is None and app .config .always_document_param_types :
611
- lines .append (f":param { arg_name } :" )
612
- insert_index = len (lines )
613
-
614
- if insert_index is not None :
615
- if annotation is None :
616
- type_annotation = f":type { arg_name } : "
617
- else :
618
- formatted_annotation = format_annotation (annotation , app .config )
619
- type_annotation = f":type { arg_name } : { formatted_annotation } "
620
-
621
- if app .config .typehints_defaults :
622
- formatted_default = format_default (app , default , annotation is not None )
623
- if formatted_default :
624
- if app .config .typehints_defaults .endswith ("after" ):
625
- lines [insert_index ] += formatted_default
626
- else : # add to last param doc line
627
- type_annotation += formatted_default
628
-
629
- lines .insert (insert_index , type_annotation )
630
-
631
- if "return" in type_hints and not inspect .isclass (original_obj ) and not inspect .isdatadescriptor (original_obj ):
632
- if what == "method" and name .endswith (".__init__" ): # avoid adding a return type for data class __init__
633
- return
634
- formatted_annotation = format_annotation (type_hints ["return" ], app .config )
635
- insert_index = len (lines )
606
+ default = signature .parameters [arg_name ].default
607
+
608
+ if arg_name .endswith ("_" ):
609
+ arg_name = f"{ arg_name [:- 1 ]} \\ _"
610
+
611
+ insert_index = None
636
612
for at , line in enumerate (lines ):
637
- if line .startswith (":rtype:" ):
638
- insert_index = None
639
- break
640
- elif line .startswith (":return:" ) or line .startswith (":returns:" ):
641
- if " -- " in line and not app .config .typehints_use_rtype :
642
- insert_index = None
643
- break
644
- insert_index = at
645
- elif line .startswith (".." ):
646
- # Make sure that rtype comes before any usage or examples section
613
+ if _line_is_param_line_for_arg (line , arg_name ):
614
+ # Get the arg_name from the doc to match up for type in case it has a star prefix.
615
+ # Line is in the correct format so this is guaranteed to return tuple[str, str].
616
+ _ , arg_name = _get_sphinx_line_keyword_and_argument (line ) # type: ignore[assignment, misc]
647
617
insert_index = at
648
618
break
649
619
650
- if insert_index is not None and app .config .typehints_document_rtype :
651
- if insert_index == len (lines ): # ensure that :rtype: doesn't get joined with a paragraph of text
652
- lines .append ("" )
653
- insert_index += 1
654
- if app .config .typehints_use_rtype or insert_index == len (lines ):
655
- lines .insert (insert_index , f":rtype: { formatted_annotation } " )
620
+ if annotation is not None and insert_index is None and app .config .always_document_param_types :
621
+ lines .append (f":param { arg_name } :" )
622
+ insert_index = len (lines )
623
+
624
+ if insert_index is not None :
625
+ if annotation is None :
626
+ type_annotation = f":type { arg_name } : "
627
+ else :
628
+ formatted_annotation = format_annotation (annotation , app .config )
629
+ type_annotation = f":type { arg_name } : { formatted_annotation } "
630
+
631
+ if app .config .typehints_defaults :
632
+ formatted_default = format_default (app , default , annotation is not None )
633
+ if formatted_default :
634
+ if app .config .typehints_defaults .endswith ("after" ):
635
+ lines [insert_index ] += formatted_default
636
+ else : # add to last param doc line
637
+ type_annotation += formatted_default
638
+
639
+ lines .insert (insert_index , type_annotation )
640
+
641
+
642
+ def _inject_rtype (
643
+ type_hints : dict [str , Any ],
644
+ original_obj : Any ,
645
+ app : Sphinx ,
646
+ what : str ,
647
+ name : str ,
648
+ lines : list [str ],
649
+ ) -> None :
650
+ if inspect .isclass (original_obj ) or inspect .isdatadescriptor (original_obj ):
651
+ return
652
+ if what == "method" and name .endswith (".__init__" ): # avoid adding a return type for data class __init__
653
+ return
654
+ formatted_annotation = format_annotation (type_hints ["return" ], app .config )
655
+ insert_index : int | None = len (lines )
656
+ extra_newline = False
657
+ for at , line in enumerate (lines ):
658
+ if line .startswith (":rtype:" ):
659
+ insert_index = None
660
+ break
661
+ if line .startswith (":return:" ) or line .startswith (":returns:" ):
662
+ if " -- " in line and not app .config .typehints_use_rtype :
663
+ insert_index = None
664
+ break
665
+ insert_index = at
666
+ elif line .startswith (".." ):
667
+ # Make sure that rtype comes before any usage or examples section, with a blank line between.
668
+ insert_index = at
669
+ extra_newline = True
670
+ break
671
+
672
+ if insert_index is not None and app .config .typehints_document_rtype :
673
+ if insert_index == len (lines ): # ensure that :rtype: doesn't get joined with a paragraph of text
674
+ lines .append ("" )
675
+ insert_index += 1
676
+ if app .config .typehints_use_rtype or insert_index == len (lines ):
677
+ line = f":rtype: { formatted_annotation } "
678
+ if extra_newline :
679
+ lines [insert_index :insert_index ] = [line , "\n " ]
656
680
else :
657
- line = lines [insert_index ]
658
- lines [insert_index ] = f":return: { formatted_annotation } --{ line [line .find (' ' ):]} "
681
+ lines .insert (insert_index , line )
682
+ else :
683
+ line = lines [insert_index ]
684
+ lines [insert_index ] = f":return: { formatted_annotation } --{ line [line .find (' ' ):]} "
659
685
660
686
661
687
def validate_config (app : Sphinx , env : BuildEnvironment , docnames : list [str ]) -> None : # noqa: U100
0 commit comments