pybind / pybind/pybind11-stubgen
Parent-package-qualified Enum defaults trigger circular imports
@ax3l is already working on this.
Since Apr 20, 2026.
- Dominant language
- Python
- Stars
- 361
- Forks
- 75
- PR merge metrics
- No merged PRs in 30d
Description
Summary
pybind11-stubgen can emit argument default values like:
strategy: GrowthStrategy = amrex.space3d.GrowthStrategy.Poisson
This is problematic when the generated stubs are imported as Python code (e.g. in Spinx for autodoc), because evaluating that default at import time may traverse the parent package while it is still initializing.
In practice this can fail with:
AttributeError: cannot access submodule 'space3d' of module 'amrex' (most likely due to a
circular import)
I hit this in pyAMReX, which currently works around the issue by post-processing the
generated stubs.
Real-world example
- https://github.com/AMReX-Codes/pyamrex/blob/26.04/src/Base/PODVector.cpp#L184-L190
- https://github.com/AMReX-Codes/pyamrex/blob/26.04/src/Base/PODVector.cpp#L93-L107
Importing the generated package fails with:
File ".../amrex/space3d/__init__.py", line 51, in <module>
from amrex.space3d.amrex_3d_pybind import (
File ".../amrex/space3d/amrex_3d_pybind/__init__.py", line 13821, in <module>
class PODVector_real_pinned:
File ".../amrex/space3d/amrex_3d_pybind/__init__.py", line 13851, in
PODVector_real_pinned
strategy: GrowthStrategy = amrex.space3d.GrowthStrategy.Poisson,
^^^^^^^^^^^^^
AttributeError: cannot access submodule 'space3d' of module 'amrex' (most likely due to a
circular import)
Why this seems to happen
The generated default value is import-time executable Python.
When it is parent-package-qualified (amrex.space3d.GrowthStrategy.Poisson), importing the
generated submodule can force access back through the parent package while that package
is still in the middle of from .amrex_3d_pybind import *, which creates the circular
import failure.
Expected behavior
Generated stubs should avoid emitting parent-package-qualified default expressions that
require traversing the partially initialized parent package during import.
A non-evaluated or otherwise safe representation would avoid this problem, for example:
strategy: GrowthStrategy = "GrowthStrategy.Poisson"
or another representation that preserves useful information without executing a parent-
package lookup during import.
Possible fix directions
- Rewrite defaults that refer to enum members in the current generated module/package to
avoid parent-package-qualified access. - Prefer a non-evaluated representation for such defaults when generating importable stub code.
- Add a regression test covering package importability for this case.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.