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

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: Enum

Category of a stub symbol.

CLASS = 'class'
FUNCTION = 'function'
VARIABLE = 'variable'
ALIAS = 'alias'
OVERLOAD = 'overload'
class StubSymbol(name: str, kind: SymbolKind, lineno: int)[source]

Bases: object

Base dataclass for all stub symbols.

Parameters:
  • name (str)

  • kind (SymbolKind)

  • lineno (int) – Source line of the definition (used for sort-order in the stub).

name: str
kind: SymbolKind
lineno: int
__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: StubSymbol

A class definition, combining runtime type with AST metadata.

Parameters:

Examples

>>> sym = ClassSymbol(name="Widget", lineno=5)
>>> sym.kind
<SymbolKind.CLASS: 'class'>
__init__(name: str, lineno: int, live_type: type | None = None, ast_info: ClassInfo | None = None) None[source]
live_type: type | None = None
ast_info: ClassInfo | None = None
class FunctionSymbol(name: str, lineno: int, live_func: Any | None = None, ast_info: FunctionInfo | None = None, is_async: bool = False)[source]

Bases: StubSymbol

A top-level function definition, combining runtime callable + AST info.

Parameters:
  • live_func (callable or None) – The runtime function object. None in 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]
live_func: Any | None = None
ast_info: FunctionInfo | None = None
is_async: bool = False
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: StubSymbol

A module-level variable or constant.

Parameters:
  • live_value (Any) – The runtime value of the variable. None in AST-only mode or when the variable evaluates to None.

  • 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]
live_value: Any = None
annotation_str: str | None = None
inferred_type_str: str | None = None
ast_info: VariableInfo | None = None
property effective_type_str: str | None

Return annotation_str if available, else inferred_type_str.

class AliasSymbol(name: str, lineno: int, ast_info: TypeVarInfo | None = None, live_obj: Any = None)[source]

Bases: StubSymbol

A TypeAlias, TypeVar, ParamSpec, TypeVarTuple, or NewType declaration.

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
live_obj: Any = None
class OverloadGroup(name: str, lineno: int, variants: list[FunctionSymbol] | None = None, live_func: Any | None = None)[source]

Bases: StubSymbol

Multiple @overload variants 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-@overload one).

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]
live_func: Any | None = None
class SymbolTable[source]

Bases: object

Ordered collection of StubSymbol entries 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
__init__() None[source]
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 None if not present.

get_class(name: str) ClassSymbol | None[source]

Return the ClassSymbol for name, or None.

get_function(name: str) FunctionSymbol | None[source]

Return the FunctionSymbol for name, or None.

by_kind(kind: SymbolKind) Iterator[StubSymbol][source]

Yield all symbols of kind in definition order.

classes() Iterator[ClassSymbol][source]

Yield all ClassSymbol entries in source order.

functions() Iterator[FunctionSymbol][source]

Yield all top-level FunctionSymbol entries in source order.

variables() Iterator[VariableSymbol][source]

Yield all VariableSymbol entries in source order.

aliases() Iterator[AliasSymbol][source]

Yield all AliasSymbol entries in source order.

overload_groups() Iterator[OverloadGroup][source]

Yield all OverloadGroup entries in source order.

all_names() list[str][source]

Return all symbol names in definition 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 SymbolTable by merging runtime and AST information.

Live objects from module are matched against the ASTSymbols by name and combined into typed StubSymbol entries. When module is None (AST-only mode), all live_* fields are None.

The symbol table is populated in this order:

  1. TypeAlias / TypeVar declarations (from AST).

  2. Classes — merged with inspect.getmembers when module is available; filtered to symbols whose __module__ matches module_name.

  3. Module-level functions — from AST; live_func set from module.

  4. Overload groups — grouped @overload functions from AST.

  5. Module-level variables — from AST; live_value set from module.

Parameters:
  • module (types.ModuleType or None) – Loaded module from load_module(), or None for 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. None means include all public (non-underscore-prefixed) names unless include_private is True.

  • include_private (bool) – When True, names starting with _ are not filtered out. Defaults to False.

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.