`experimental-inspect`: `__all__` is set at runtime by `#[pymodule]` but never emitted into the stubs
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 16.2k
- Forks
- 1k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 66
Description
Bug Description
PyModuleMethods::add appends every added name to the module's __all__
(src/types/module.rs:500), so
every #[pymodule] has an __all__ at runtime. pyo3-introspection never emits one, so the stub
and the runtime disagree and mypy.stubtest reports one error per module:
error: allrepro.__all__ is not present in stub
Stub: in file .../allrepro/__init__.pyi
MISSING
Runtime: in file .../allrepro/__init__.py
<module 'allrepro' ...>
This matters beyond stubtest: without __all__, type checkers apply the implicit re-export
rules to the stub, which is not what the runtime module actually exports.
On pyo3_pytests this accounts for 15 of the 43 stubtest errors that block #6240.
Steps to Reproduce
-
Build an extension with the
experimental-inspectfeature:use pyo3::prelude::*; #[pymodule] mod allrepro { use pyo3::prelude::*; #[pyclass] pub struct Thing; #[pyfunction] pub fn helper() -> usize { 1 } } -
maturin develop, then
cargo run -p pyo3-introspection -- <path to .so> allrepro stubs -
The runtime has
__all__, the generatedstubs/__init__.pyidoes not:>>> import allrepro; allrepro.__all__ ['Thing', 'helper']# stubs/__init__.pyi from typing import final @final class Thing: ... def helper() -> int: ... -
Copy the
.pyinext to the extension,touch py.typed, runpython -m mypy.stubtest allrepro.
Backtrace
Your operating system and version
Linux (CachyOS, kernel 7.1.3)
Your Python version (python --version)
Python 3.13.14
Your Rust version (rustc --version)
rustc 1.96.0 (ac68faa20 2026-05-25)
Your PyO3 version
0.29.0 (main)
How did you install python? Did you use a virtualenv?
uv (uv venv --python 3.13)
Additional Info
The contents are already available to the generator: Module in
pyo3-introspection/src/model.rs carries modules, classes, functions and attributes, and
those match the runtime __all__ exactly in the cases checked. So module_stubs
(stubs.rs:49)
should be able to emit __all__ = [...] without new introspection data.
Open question — incomplete modules. Modules with a #[pymodule_init] are tagged incomplete and
get a def __getattr__(name: str) -> Incomplete: ... marker instead of a full listing. Emitting
__all__ for those asserts a completeness the introspector cannot verify, since a
#[pymodule_init] may add further exports. Options: emit it regardless, omit it for incomplete
modules (leaving the stubtest error in place), or emit a bare __all__: list[str] declaration.
Tested with stubtest 2.3.0.
Contributor guide
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.
Research direction
Start in pyo3-introspection/src/stubs.rs at module_stubs and inspect the Module data in pyo3-introspection/src/model.rs, including how incomplete modules are represented. Reproduce the generated stubs from the issue and run mypy.stubtest against the extension. Done means the stubs' all behavior matches runtime modules, with an explicit resolution for incomplete modules.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 65/100