pybind11-stubgen icon indicating copy to clipboard operation
pybind11-stubgen copied to clipboard

Include import on submodules

Open marcoffee opened this issue 3 years ago • 2 comments

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.

marcoffee avatar Jan 08 '22 04:01 marcoffee

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.

sizmailov avatar Jan 08 '22 06:01 sizmailov

@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

marcoffee avatar Jan 10 '22 12:01 marcoffee

The issue with all imports should be resolved with #112

sizmailov avatar Aug 29 '23 13:08 sizmailov