sphinx-autodoc-typehints icon indicating copy to clipboard operation
sphinx-autodoc-typehints copied to clipboard

WARNING: Cannot resolve forward reference in type annotations of "<MyMethod>": name '<NamedTuple>' is not defined

Open 1kastner opened this issue 4 years ago • 10 comments

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.

1kastner avatar Nov 09 '21 10:11 1kastner

How would sphinx-autodoc-typehints know that its a member of the A class? This information cannot be derived from MyTuple itself.

agronholm avatar Nov 09 '21 10:11 agronholm

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.

1kastner avatar Nov 09 '21 13:11 1kastner

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.

agronholm avatar Nov 11 '21 15:11 agronholm

Thank you very much. I will have a look whether I come across some solution.

1kastner avatar Nov 11 '21 16:11 1kastner

A PR for this would we welcome.

gaborbernat avatar Jan 08 '22 11:01 gaborbernat

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?

Zeitsperre avatar Mar 01 '23 19:03 Zeitsperre

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).

agronholm avatar Mar 01 '23 19:03 agronholm

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).

Zeitsperre avatar Mar 01 '23 21:03 Zeitsperre

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.
    """

pseusys avatar Aug 17 '23 00:08 pseusys