ENH: Add support for type annotations #601
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Resolves #196
Hi! I ran into the issue that numpydoc does not support typehints before Christmas, so I decided to have a crack at it. I have tried multiple different approaches (not in this git history), especially trying to combine numpydoc with sphinx-autodoc-typehints, but what I finally settled on is to make use of numpydoc's powerful class system (I have found that the data representation of
numpydoc
andsphinx-autodoc-typehints
are largely incompatible).My implementation edits the
_parse_param_list
method - responsible for creating the docstrings forParameters
,Other Parameters
,Attributes
,Methods
,Returns
,Yields
,Raises
, andReceives
sections - so that a type can be obtained from the type hint if one is not specified in the docstring (btw, I believe it should be relatively simple to implement #356 following a similar method). This means that the type hints can be supported for all those sections with minimal code. The way this works is defined in a new method,_get_type_from_signature
, which by default onNumpyDocString
only returns an empty string (no type). The actual type inference is implemented on the subclasses:FunctionDoc
Getting type hints for functions is the easier task since we can rely fully on
inspect.signature
. Firstly, the signature is obtained in__init__
to avoid recomputing it at every iteration of_parse_param_list
. All that is then necessary in_get_type_from_signature
is to return the type hint associated with the argument name, provided that the function has a signature and that the type hint is set.ClassDoc
At the basic level, the type hints for classes are similar to
FunctionDoc
and the code is therefore repeated (there is potentially room for optimisation where the code could be pulled out toNumpyDocString
, should that be desirable). However, there is an additional complication in that the class documentation may contain the attributes (which may be@property
) and therefore are not part of the__init__
signature. This required an additional method,_find_type_hints
:arg_name
is an attribute with a type annotation (typing.get_type_hints
handles unwrapping etc.)try
except
block handles the case where the annotation is a normal class (by getting__name__
) or an annotation fromtypes
....
, the remaining options are that thearg_name
doesn't exist, handled via:inspect.signature
:Robustness
From my testing, this implementation is able to handle everything my other projects could throw at it, but I would not be surprised if there are edge cases where it breaks down. I have not yet written any unit tests since I wasn't sure what the best way to do that in this repository is, or whether this is the method for solving #196 that you want to implement. Regardless, though, I think it might be possible to increase the robustness of my implementation by using some of the type-extraction functions from
sphinx-autodoc-typehints
(whether by depending on it as a whole, or by copying the relevant functions, I am unsure), such asget_annotation_args
orformat_annotation
.Conclusion
Please let me know what you think! I am keen to get
numpydoc
working with type annotations, and I believe that this implementation is a straightforward way to do that, but I am curious what your plans are for this issue.