simvx.core.scene_io.symbols

Pure CST queries over a parso tree for class definitions and use sites.

This module is the foundation for cross-file class rename. It is stateless and does no I/O — all functions take a :class:SourceTree and walk the parso CST. rename_class_in_source mutates the tree in place; callers

meth:

SourceTree.dump the result.

Use-site classification is purely syntactic (no name resolution): an aliased import does not propagate to its alias, and a local-variable shadow inside a function suppresses uses of the class name within that function.

Module Contents

Classes

ClassDefRef

A top-level class definition discovered in a source tree.

UseSiteRef

A site where a class name is referenced.

Functions

find_class_definitions

Top-level class definitions, in source order.

find_class_uses

Every site referencing class_name, classified by kind.

rename_class_in_source

Rename a class within source_tree in-place.

rename_module_in_imports

Rewrite from <old_module> import lines to point at new_module.

Data

API

simvx.core.scene_io.symbols.__all__

[‘ClassDefRef’, ‘UseSiteRef’, ‘find_class_definitions’, ‘find_class_uses’, ‘rename_class_in_source’,…

simvx.core.scene_io.symbols.UseKind

None

class simvx.core.scene_io.symbols.ClassDefRef[source]

A top-level class definition discovered in a source tree.

name: str

None

bases: tuple[str, ...]

None

line: int

None

classdef_node: parso.tree.NodeOrLeaf

None

class simvx.core.scene_io.symbols.UseSiteRef[source]

A site where a class name is referenced.

leaf is the bare-name leaf to potentially rewrite. For aliased imports (from x import Foo as Bar) leaf points at the source name Foo (not the alias).

kind: simvx.core.scene_io.symbols.UseKind

None

line: int

None

leaf: parso.tree.NodeOrLeaf

None

import_module: str | None

None

import_alias: str | None

None

simvx.core.scene_io.symbols.find_class_definitions(source_tree: simvx.core.scene_io.source_tree.SourceTree) list[simvx.core.scene_io.symbols.ClassDefRef][source]

Top-level class definitions, in source order.

Classes nested inside functions (or other classes) are not returned — they are not project-rename candidates.

simvx.core.scene_io.symbols.find_class_uses(source_tree: simvx.core.scene_io.source_tree.SourceTree, class_name: str) list[simvx.core.scene_io.symbols.UseSiteRef][source]

Every site referencing class_name, classified by kind.

Scope-aware: a local <class_name> = assignment inside a function (or at module level) shadows subsequent uses of the name in that scope. Conservative: when uncertain, include the site.

simvx.core.scene_io.symbols.rename_class_in_source(source_tree: simvx.core.scene_io.source_tree.SourceTree, old_name: str, new_name: str) None[source]

Rename a class within source_tree in-place.

Rewrites the leaf .value for:

  • top-level class <old_name> definitions (the class name leaf)

  • every use site returned by :func:find_class_uses, except import_alias where only the source-name leaf is rewritten (the alias is preserved)

Idempotent: when old_name == new_name this is a no-op. Sites inside string literals are not touched (parso’s string leaf type means they never appear as name leaves in the first place).

simvx.core.scene_io.symbols.rename_module_in_imports(source_tree: simvx.core.scene_io.source_tree.SourceTree, old_module: str, new_module: str) None[source]

Rewrite from <old_module> import lines to point at new_module.

Used when the user renames a class’s defining file (or folder) and we need every importer’s module path to follow. old_module and new_module are dotted names matching the form parso emits in the from clause (e.g., "src.player" and "src.hero").

Matches both:

  • Exact matches — from src.player import X when old_module == "src.player".

  • Trailing-segment matches — from .player import X and from foo.bar.player import X when old_module ends with the same trailing segment as the import’s last component. This handles relative imports cleanly (.player shares the leaf player with src.player even though the prefix differs).

The match is anchored on the trailing segment to avoid sweeping in unrelated modules: from os.path import X is left alone when the rename target is unrelated to path.

Idempotent: rename_module_in_imports(tree, "x", "x") is a no-op. Plain import x statements (no from) are not handled here — they are rare for class imports and would warrant a separate primitive.