sphinx-autodoc-typehints
sphinx-autodoc-typehints copied to clipboard
WARNING: Cannot resolve forward reference in type annotations of "<MyMethod>": name '<NamedTuple>' is not defined
Describe the bug
I have some nested NamedTuple definitions and sphinx_autodoc_typehints cannot resolve them. Without sphinx_autodoc_typehints, Sphinx has no issues generating a suitable documentation. In addition, PyCharm with its code linter is happy with it as well.
To Reproduce
The Python file:
class A:
MyTuple = NamedTuple(
"MyTuple ",
(
("b", Union[int, float]),
("c", Union[int, float])
)
)
def x(self) -> MyTuple:
return self.MyTuple(b=2, c=3)
A default Sphinx configuration will just do the work . These are the loaded extensions:
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.todo',
'sphinx.ext.napoleon',
'sphinx_autodoc_typehints'
]
Expected behavior
sphinx_autodoc_typehints can resolve the typehint even though it is a nested NamedTuple and displays the NamedTuple as a member of the class A.
How would sphinx-autodoc-typehints know that its a member of the A class? This information cannot be derived from MyTuple itself.
Well, I would expect sphinx-autodoc-typehints to resolve names in a functionally equivalent way like the other up-to-date tools with type-hint support do. At least PyCharm can make perfect sense of that code and it does check the type hints.
So based on the behavior of the code, I would suggest that the class should be part of the namespace that is explored (i.e., nested classes are also added) while looking up what the type hint should refer to. I have less experience with sphinx so I could not point to an exact line in the implementation. But just try it out what happens if you comment out sphinx_autodoc_typehints and see how sphinx handles it! It is capable of displaying nested classes.
All these other tools use static analysis to get information. If you can point out how sphinx-autodoc-typehints could find this information, I could try and make a fix.
Thank you very much. I will have a look whether I come across some solution.
A PR for this would we welcome.
I'm running into this with a custom class as well in my documentation. Is there an easy way of silencing this particular warning until a proper fix is made?
I just did an experiment, and this works:
class A:
class MyTuple(NamedTuple):
b: float
c: float
Not only is this much neater than the alternative, it also makes MyTuple contain the proper path (i.e. __main__.A.MyTuple).
It seems my case is a bit different, as I was running into issues with classes that used typing types in addition to custom classes:
class MyClass:
_parameters : dict[str, ParametersClass] = {}
_attributes: list[dict[str, typing.Any]] = None
The errors I was getting were resolved by turning these instances into strings:
class MyClass:
_parameters : dict[str, "ParametersClass"] = {}
_attributes: list[dict[str, "typing.Any"]] = None
I guess this is more of a workaround than an actual fix. (Confirmed working).
Same issue happens during documentation generation for any pydantic model with PrivateAttribute:
from uuid import uuid4
from pydantic import BaseModel, PrivateAttr
class SampleModela(BaseModel):
_private: str = PrivateAttr(default_factory=lambda: str(uuid4()))
"""
Private field docstring.
"""