stubpy.generator¶
stubpy.generator¶
Top-level orchestrator for stub generation — single files and entire packages.
Public functions¶
generate_stub()— generate a.pyifile for one.pysource file.generate_package()— recursively generate stubs for a whole package directory.collect_classes()— helper that returns classes from a module in source order.
generate_stub pipeline¶
Load — import the source file as a live module (skipped in
AST_ONLYmode; graceful fallback inAUTOmode).AST pre-pass — harvest structural metadata without executing code.
Scan imports — build a
{name: stmt}map for the source file.Build alias registry — discover type-alias sub-modules.
Build symbol table — merge AST + runtime data into a
SymbolTable.Emit stubs — generate stubs for every public symbol in source order: aliases (TypeVar / TypeAlias), classes, overloaded functions, plain functions, and module-level variables.
__all__filtering is applied via the symbol table.Assemble header — collect
typingnames, type-module imports, special imports (abc,dataclasses), and cross-file imports.Write — write the complete
.pyito output_path.
generate_package calls generate_stub for every .py file found
under the package root, mirroring the directory tree under the output
directory.
Single-file generation
- generate_stub(filepath: str, output_path: str | None = None, ctx: StubContext | None = None) str[source]¶
Generate a
.pyistub file for the Python source at filepath.A fresh
StubContextis created when ctx isNone, making this function fully re-entrant. Pass an explicit ctx to supply customStubConfigoptions (e.g.include_private=True,execution_mode=ExecutionMode.AST_ONLY) or to inspect diagnostics after the call.Execution modes¶
RUNTIME(default)Execute the module; full introspection available.
AST_ONLYParse the AST only — no module execution. Safer for modules with import-time side effects; live types will be
None.AUTOExecute when possible; fall back to AST-only on load failure.
- param filepath:
Path to the
.pysource file.- type filepath:
str
- param output_path:
Where to write the
.pyifile. Defaults to the same directory and stem as filepath with a.pyiextension.- type output_path:
str, optional
- param ctx:
Pre-configured context. Created fresh when
None.- type ctx:
StubContext, optional
- returns:
str – Full stub content as a string, identical to what is written to disk.
- raises FileNotFoundError:
If filepath does not exist.
- raises ImportError:
If the source file cannot be loaded as a module (
RUNTIMEmode only;AUTOmode falls back to AST-only instead of raising).
See also
generate_packageBatch generation for a whole package directory.
stubpy.loader.load_moduleStage 1 — module loading.
stubpy.ast_pass.ast_harvestStage 2 — AST pre-pass.
stubpy.symbols.build_symbol_tableStage 5 — symbol table.
stubpy.emitter.generate_class_stubClass stub emission.
stubpy.emitter.generate_function_stubFunction stub emission.
stubpy.emitter.generate_variable_stubVariable stub emission.
stubpy.emitter.generate_alias_stubAlias/TypeVar stub emission.
stubpy.emitter.generate_overload_group_stubOverload group stub emission.
- collect_classes(module: ModuleType, module_name: str) list[type][source]¶
Return all classes defined in module, sorted by source-line order.
Uses
inspect.getmembers()filtered to classes whose__module__matches module_name, so only classes defined in the file itself are included — not classes imported into it.- Parameters:
module (types.ModuleType) – The loaded module returned by
load_module().module_name (str) – Synthetic name assigned to the module by
load_module()(e.g."_stubpy_target_graphics").
- Returns:
list of type – Classes sorted by their first source line, mirroring source order.
Package generation
- generate_package(package_dir: str | Path, output_dir: str | Path | None = None, ctx_factory: Callable[[Path, Path], StubContext] | Callable[[], StubContext] | None = None, config: StubConfig | None = None) PackageResult[source]¶
Generate
.pyistubs for every.pyfile in package_dir.Walks package_dir recursively and calls
generate_stub()for each.pysource file. For every sub-directory that contains an__init__.py, the corresponding__init__.pyiis created under output_dir (if it was not already produced bygenerate_stub).Files matching any pattern in
config.excludeare skipped. Files that fail with an exception or ERROR-level diagnostics are recorded inPackageResult.failedand processing continues.- Parameters:
package_dir (str or Path) – Root of the package to process.
output_dir (str or Path or None) – Directory where stubs are written. The subdirectory structure of package_dir is reproduced under output_dir. When
None(default), stubs are written alongside the source files.ctx_factory (callable or None) –
Called to produce a fresh
StubContextfor each file. Two signatures are accepted:ctx_factory()— called with no arguments (backward compatible).ctx_factory(source_path, output_path)— called with the absolutePathof the source.pyfile and the destination.pyipath, allowing per-file customisation (e.g. differentexecution_modefor slow modules, extra exclude patterns for generated files, custom annotation handlers).
When
None, a context derived from config (or a default config) is used.config (StubConfig or None) – Configuration applied when ctx_factory is
None. When both areNone,StubConfigdefaults are used.
- Returns:
PackageResult – Contains
stubs_written(success paths) andfailed((path, diagnostics)pairs for errored files).- Raises:
FileNotFoundError – If package_dir does not exist on disk.
Examples
>>> from stubpy import generate_package >>> result = generate_package("mypackage/", "stubs/") >>> print(result.summary()) Generated 8 stubs, 0 failed.
- class PackageResult(stubs_written: list[Path] = <factory>, failed: list[tuple[~pathlib.Path, list[~stubpy.diagnostics.Diagnostic]]]=<factory>)[source]¶
Bases:
objectOutcome of a
generate_package()run.- failed¶
One entry per source file that raised an exception or accumulated ERROR-level diagnostics. Each entry is
(source_path, diagnostics).- Type:
list of tuple[Path, list[Diagnostic]]
Examples
>>> r = PackageResult() >>> r.summary() 'Generated 0 stubs, 0 failed.'
Pipeline stages
Each call to generate_stub() runs eight stages in order:
generate_stub(filepath)
│
├─ 1. loader load_module() → module, path, name
│ └─ (skipped in AST_ONLY; warning+fallback in AUTO)
├─ 2. ast_pass ast_harvest() → ASTSymbols
├─ 3. imports scan_import_statements() → import_map
├─ 4. aliases build_alias_registry() → ctx populated
├─ 5. symbols build_symbol_table() → SymbolTable
├─ 6. emitter for each symbol (source order):
│ ├─ AliasSymbol → generate_alias_stub()
│ ├─ ClassSymbol → generate_class_stub()
│ │ └─ for each method:
│ │ resolver resolve_params()
│ │ emitter generate_method_stub()
│ ├─ OverloadGroup → generate_overload_group_stub()
│ ├─ FunctionSymbol → generate_function_stub()
│ └─ VariableSymbol → generate_variable_stub()
├─ 7. imports collect_typing_imports() → header
│ collect_special_imports()
│ collect_cross_imports()
└─ 8. write .pyi file written to disk
Execution modes
The pipeline respects ExecutionMode:
RUNTIME(default)Execute the module at stage 1. All introspection paths available.
AST_ONLYSkip stage 1 entirely. Live types will be
None; stubs are built from AST metadata only. Useful for modules with import-time side effects.AUTOAttempt stage 1; if the load raises any exception, record a
WARNINGdiagnostic and continue with AST-only data.
Package processing
generate_package() calls generate_stub() for every .py
file found by a recursive directory walk. It mirrors the source tree
under the output directory and ensures every sub-package has an
__init__.pyi. Files that fail are collected in
PackageResult.failed rather than aborting the run.