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

Include import on submodules #72

Closed
wants to merge 2 commits into from

Conversation

marcoffee
Copy link
Contributor

This pull request include an import for each submodule of a module.
One might need to use definitions from the submodule(s) on the top-level module, but as it is now, pybind11-stubgen does not import from them.

Example:

struct ClassC {};
struct ClassB {};
struct ClassA { ClassB attr_b; ClassC attr_c; };

PYBIND11_MODULE(mod_a, m_a) {
  auto m_b = m_a.def_submodule("mod_b");
  auto m_c = m_b.def_submodule("mod_c");

  pybind11::class_<ClassC>(m_c, "ClassC");
  pybind11::class_<ClassB>(m_b, "ClassB");

  pybind11::class_<ClassA>(m_a, "ClassA")
    .def_readonly("attr_b", &ClassA::attr_b)
    .def_readonly("attr_c", &ClassA::attr_c);
}

Would generate 3 files / folders:

mod_a/__init__.pyi:

from __future__ import annotations
import mod_a
import typing

__all__ = [
    "ClassA",
    "mod_b"
]


class ClassA():
    @property
    def attr_b(self) -> mod_b.ClassB:
        """
        :type: mod_b.ClassB
        """
    @property
    def attr_c(self) -> mod_b.mod_c.ClassC:
        """
        :type: mod_b.mod_c.ClassC
        """
    pass

mod_a/mod_b/__init__.pyi:

from __future__ import annotations
import mod_a.mod_b
import typing

__all__ = [
    "ClassB",
    "mod_c"
]


class ClassB():
    pass

mod_a/mod_b/mod_c/__init__.pyi:

from __future__ import annotations
import mod_a.mod_b.mod_c
import typing

__all__ = [
    "ClassC"
]


class ClassC():
    pass

Note that mod_b is not imported into mod_a (nor mod_c is imported into mod_b), which causes warnings regarding the usage of mod_b.ClassB and mod_b.mod_c.ClassC.

This pull request adds an import for each submodule (mod_a imports mod_b and mod_b imports mod_c), hence, solving that kind of problem.

@sizmailov
Copy link
Owner

Hi. I see the problem. Although the proposed solution seems wrong to me. If you change definition of ClassA to

struct ClassA { int attr_b; int attr_c; };

the submodules must not be imported. Which seems to be not the case with the patch. Right?

I know that generated stubs are imperfect in terms of correctness. At the moment it's a plain tool. It simply prints what it sees. Fixing it would require complete analysis of parsed structure of the modules. Of course something can be patched in a simple matter and such patches are always welcome. I think that stubgen from mypy looks like a better candidate for writing 100%-correct stub generation given already existing scaffolding.

@marcoffee
Copy link
Contributor Author

@sizmailov I will try to make a similar parsing to the one made to detect the other imports then and update this pull request. Thanks for the feedback

@sizmailov
Copy link
Owner

The issue with all imports should be resolved with #112

@sizmailov sizmailov closed this Aug 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants