stubpy.symbols¶
stubpy.symbols¶
Symbol table — the unified data model for one stub-generation pass.
A SymbolTable holds an ordered collection of StubSymbol
entries, one per public name in the target module. Each entry carries
both the live runtime object (when available from
load_module()) and the AST metadata harvested by
stubpy.ast_pass.
Using a single symbol table as the shared data model eliminates the
implicit coupling that existed between collect_classes() and the rest
of the pipeline: every future pipeline stage reads and writes the same
table rather than maintaining parallel, ad-hoc data structures.
Symbol hierarchy¶
StubSymbol— base dataclassClassSymbol— aclassdefinitionFunctionSymbol— a top-leveldeforasync defVariableSymbol— a module-level annotated variableAliasSymbol—TypeAlias/TypeVar/NewTypeetc.OverloadGroup— multiple@overloadvariants of one name
Examples
>>> from stubpy.symbols import SymbolTable, ClassSymbol, SymbolKind
>>> tbl = SymbolTable()
>>> tbl.add(ClassSymbol(name="Foo", lineno=1))
>>> tbl.get("Foo").name
'Foo'
>>> tbl.get("Missing") is None
True
- class SymbolKind(value)[source]¶
Bases:
EnumCategory of a stub symbol.
- CLASS = 'class'¶
- FUNCTION = 'function'¶
- VARIABLE = 'variable'¶
- ALIAS = 'alias'¶
- OVERLOAD = 'overload'¶
- class StubSymbol(name: str, kind: SymbolKind, lineno: int)[source]¶
Bases:
objectBase dataclass for all stub symbols.
- Parameters:
name (str)
kind (SymbolKind)
lineno (int) – Source line of the definition (used for sort-order in the stub).
- kind: SymbolKind¶
- __init__(name: str, kind: SymbolKind, lineno: int) None¶
- class ClassSymbol(name: str, lineno: int, live_type: type | None = None, ast_info: ClassInfo | None = None)[source]¶
Bases:
StubSymbolA class definition, combining runtime type with AST metadata.
- Parameters:
live_type (type or None) – The runtime class object from
load_module().Nonein AST-only mode.ast_info (ClassInfo or None) – Metadata from
ASTHarvester.
Examples
>>> sym = ClassSymbol(name="Widget", lineno=5) >>> sym.kind <SymbolKind.CLASS: 'class'>
- class FunctionSymbol(name: str, lineno: int, live_func: Any | None = None, ast_info: FunctionInfo | None = None, is_async: bool = False)[source]¶
Bases:
StubSymbolA top-level function definition, combining runtime callable + AST info.
- Parameters:
live_func (callable or None) – The runtime function object.
Nonein AST-only mode.ast_info (FunctionInfo or None) – Metadata from
ASTHarvester.is_async (bool) – Derived from ast_info when available; defaults to
False.
Examples
>>> sym = FunctionSymbol(name="greet", lineno=3, is_async=True) >>> sym.kind <SymbolKind.FUNCTION: 'function'> >>> sym.is_async True
- __init__(name: str, lineno: int, live_func: Any | None = None, ast_info: FunctionInfo | None = None, is_async: bool = False) None[source]¶
- ast_info: FunctionInfo | None = None¶
- class VariableSymbol(name: str, lineno: int, live_value: Any = None, annotation_str: str | None = None, inferred_type_str: str | None = None, ast_info: VariableInfo | None = None)[source]¶
Bases:
StubSymbolA module-level variable or constant.
- Parameters:
live_value (Any) – The runtime value of the variable.
Nonein AST-only mode or when the variable evaluates toNone.annotation_str (str or None) – Type annotation as an unparsed string, from the AST.
inferred_type_str (str or None) –
type(live_value).__name__when no annotation is available.ast_info (VariableInfo or None)
Examples
>>> sym = VariableSymbol(name="MAX", lineno=1, annotation_str="int") >>> sym.kind <SymbolKind.VARIABLE: 'variable'>
- __init__(name: str, lineno: int, live_value: Any = None, annotation_str: str | None = None, inferred_type_str: str | None = None, ast_info: VariableInfo | None = None) None[source]¶
- ast_info: VariableInfo | None = None¶
- class AliasSymbol(name: str, lineno: int, ast_info: TypeVarInfo | None = None, live_obj: Any = None)[source]¶
Bases:
StubSymbolA
TypeAlias,TypeVar,ParamSpec,TypeVarTuple, orNewTypedeclaration.- Parameters:
ast_info (TypeVarInfo or None)
live_obj (Any) – The runtime object, if available.
Examples
>>> sym = AliasSymbol(name="T", lineno=1) >>> sym.kind <SymbolKind.ALIAS: 'alias'>
- __init__(name: str, lineno: int, ast_info: TypeVarInfo | None = None, live_obj: Any = None) None[source]¶
- ast_info: TypeVarInfo | None = None¶
- class OverloadGroup(name: str, lineno: int, variants: list[FunctionSymbol] | None = None, live_func: Any | None = None)[source]¶
Bases:
StubSymbolMultiple
@overloadvariants that share a single function name.- Parameters:
variants (list of FunctionSymbol) – One entry per
@overload-decorated definition, in source order.live_func (callable or None) – The concrete implementation callable (the non-
@overloadone).
Examples
>>> grp = OverloadGroup(name="parse", lineno=10) >>> len(grp.variants) 0
- __init__(name: str, lineno: int, variants: list[FunctionSymbol] | None = None, live_func: Any | None = None) None[source]¶
- variants: list[FunctionSymbol]¶
- class SymbolTable[source]¶
Bases:
objectOrdered collection of
StubSymbolentries for one module.Preserves source-definition order so that the emitted stub mirrors the original file layout. Provides lookup by name and iteration by kind.
Examples
>>> tbl = SymbolTable() >>> tbl.add(ClassSymbol(name="Foo", lineno=1)) >>> tbl.add(FunctionSymbol(name="bar", lineno=10)) >>> len(tbl) 2 >>> tbl.get("Foo").kind <SymbolKind.CLASS: 'class'> >>> "Foo" in tbl True >>> "Missing" in tbl False
- add(symbol: StubSymbol) None[source]¶
Append symbol to the table.
If a symbol with the same name already exists it is overwritten in the index (the old entry is retained in the ordered list for compatibility, but lookup returns the newer entry).
- get(name: str) StubSymbol | None[source]¶
Return the symbol for name, or
Noneif not present.
- get_class(name: str) ClassSymbol | None[source]¶
Return the
ClassSymbolfor name, orNone.
- get_function(name: str) FunctionSymbol | None[source]¶
Return the
FunctionSymbolfor name, orNone.
- by_kind(kind: SymbolKind) Iterator[StubSymbol][source]¶
Yield all symbols of kind in definition order.
- classes() Iterator[ClassSymbol][source]¶
Yield all
ClassSymbolentries in source order.
- functions() Iterator[FunctionSymbol][source]¶
Yield all top-level
FunctionSymbolentries in source order.
- variables() Iterator[VariableSymbol][source]¶
Yield all
VariableSymbolentries in source order.
- aliases() Iterator[AliasSymbol][source]¶
Yield all
AliasSymbolentries in source order.
- overload_groups() Iterator[OverloadGroup][source]¶
Yield all
OverloadGroupentries in source order.
- sorted_by_line() list[StubSymbol][source]¶
Return all symbols sorted by lineno ascending.
- build_symbol_table(module: ModuleType | None, module_name: str, ast_symbols: ASTSymbols, all_exports: set[str] | None = None, include_private: bool = False) SymbolTable[source]¶
Build a
SymbolTableby merging runtime and AST information.Live objects from module are matched against the
ASTSymbolsby name and combined into typedStubSymbolentries. When module isNone(AST-only mode), alllive_*fields areNone.The symbol table is populated in this order:
TypeAlias / TypeVar declarations (from AST).
Classes — merged with
inspect.getmemberswhen module is available; filtered to symbols whose__module__matches module_name.Module-level functions — from AST;
live_funcset from module.Overload groups — grouped
@overloadfunctions from AST.Module-level variables — from AST;
live_valueset from module.
- Parameters:
module (types.ModuleType or None) – Loaded module from
load_module(), orNonefor AST-only mode.module_name (str) – Synthetic
_stubpy_target_*module name used to filter local classes from imported ones.ast_symbols (ASTSymbols) – Output from
ast_harvest().all_exports (set of str or None) – When provided, only names in this set are included.
Nonemeans include all public (non-underscore-prefixed) names unless include_private isTrue.include_private (bool) – When
True, names starting with_are not filtered out. Defaults toFalse.
- Returns:
SymbolTable – Populated, source-order-preserving symbol table.
Examples
>>> import types as _t >>> from stubpy.ast_pass import ast_harvest >>> m = _t.ModuleType("_stubpy_target_ex") >>> class Foo: pass >>> Foo.__module__ = "_stubpy_target_ex" >>> m.Foo = Foo >>> syms = ast_harvest("class Foo: pass") >>> tbl = build_symbol_table(m, "_stubpy_target_ex", syms) >>> tbl.get("Foo").kind.value 'class'
Notes
build_symbol_table() merges the live module objects from
load_module() with the AST metadata from
ast_harvest(). When the module is None
(AST-only mode), all live_* fields on every symbol are None.
The table preserves source-definition order so that the emitted
.pyi mirrors the original file layout. Use
sorted_by_line() to retrieve symbols in ascending
lineno order regardless of insertion order.
When __all__ is present in the source, build_symbol_table()
accepts an all_exports set and filters out any symbol whose name is
not in that set. Private names (those starting with _) are always
excluded regardless of all_exports.