Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
1kastner opened this issue Nov 9, 2021 · 9 comments

Comments

@1kastner
Copy link

1kastner commented Nov 9, 2021

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.

@agronholm
Copy link
Collaborator

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

@1kastner
Copy link
Author

1kastner commented Nov 9, 2021

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.

@agronholm
Copy link
Collaborator

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.

@1kastner
Copy link
Author

1kastner commented Nov 11, 2021

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

@gaborbernat
Copy link
Member

A PR for this would we welcome.

@Zeitsperre
Copy link

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?

@agronholm
Copy link
Collaborator

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

@Zeitsperre
Copy link

Zeitsperre commented Mar 1, 2023

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

@pseusys
Copy link

pseusys commented Aug 17, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants