simvx.core.scene_io.symbols¶
Where a class is defined, where it is used, and how to rename it.
This module is the foundation for cross-file class rename. It is stateless and does no I/O: every function takes the source text of one module and either answers a question about it or returns the rewritten text. Nothing here holds a parse tree, so a caller can hand it text straight off disk and compare what it gets back byte for byte.
Discovery is a walk of the standard library’s own parse tree, so the constructs it understands are the ones the running Python understands. Rewriting never regenerates source: the spans of the identifiers that move are spliced and every other byte of the file is the author’s, which is what makes an idempotent rename byte-identical rather than merely equivalent.
Use-site classification is purely syntactic, with no name resolution: an aliased import does not propagate to its alias, and a plain rebinding of the name in a block suppresses the uses below it in that block.
Module Contents¶
Classes¶
A top-level class definition discovered in a module’s source. |
|
A site where a class name is referenced. |
Functions¶
Top-level class definitions of |
|
Every site in |
|
Rename a class throughout |
|
Rewrite |
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 module’s source.
A caller moving the class to another file wants :attr:
leading_triviaand- Attr:
texttogether: the comment an author wrote above a class describes that class and has to travel with it, and it is held separately only so that a caller listing classes is not handed text that is not the class.
- name: str¶
None
- bases: tuple[str, ...]¶
None
- line: int¶
None
- text: str¶
None
- leading_trivia: str = <Multiline-String>¶
- class simvx.core.scene_io.symbols.UseSiteRef[source]¶
A site where a class name is referenced.
- Attr:
lineand :attr:columnlocate the identifier itself, in the editor’s convention: the line is 1-indexed and the column counts characters from 0. For an aliased import (from x import Foo as Bar) they locate the source nameFoorather than the alias.
- kind: simvx.core.scene_io.symbols.UseKind¶
None
- line: int¶
None
- column: int¶
None
- import_module: str | None¶
None
- import_alias: str | None¶
None
- simvx.core.scene_io.symbols.find_class_definitions(source: str) list[simvx.core.scene_io.symbols.ClassDefRef][source]¶
Top-level class definitions of
source, in source order.Classes nested inside functions (or other classes) are not returned: they are not project-rename candidates. Raises :class:
SceneSyntaxErrorwhensourcedoes not parse.
- simvx.core.scene_io.symbols.find_class_uses(source: str, class_name: str) list[simvx.core.scene_io.symbols.UseSiteRef][source]¶
Every site in
sourcereferencingclass_name, classified by kind.Ordered by position. Scope-aware: a plain
<class_name> = …rebinding shadows the uses written below it in the same block, and a function or class body starts again unshadowed because a name bound outside it is a different binding from one bound inside. Conservative everywhere else: a site whose meaning depends on what a name resolves to at runtime is included.Raises :class:
SceneSyntaxErrorwhensourcedoes not parse.
- simvx.core.scene_io.symbols.rename_class_in_source(source: str, old_name: str, new_name: str) str[source]¶
Rename a class throughout
source, returning the rewritten text.Rewrites the name of every top-level
class <old_name>definition and every site :func:find_class_usesreports, except that an aliased import keeps its alias:from x import Old as Pbecomesfrom x import New as Pand thePuses below it are left alone, because they were never references to this class.Only whole identifiers move. A class name written inside a string or a comment is text rather than a reference and is left as the author wrote it. Idempotent: renaming a class to the name it already has returns
sourceunchanged, byte for byte.
- simvx.core.scene_io.symbols.rename_module_in_imports(source: str, old_module: str, new_module: str) str[source]¶
Rewrite
from <old_module> import …lines to namenew_moduleinstead.Used when the user renames a class’s defining file (or folder) and every importer’s module path has to follow.
old_moduleandnew_moduleare dotted names, spelled as they would be in an absolute import ("src.player","src.hero").Matches both:
Exact matches:
from src.player import Xwhenold_moduleis"src.player".Trailing-segment matches:
from .player import Xandfrom foo.bar.player import Xwhen the import’s last component is the last component ofold_module. This is what makes a relative import follow (.playershares its leaf withsrc.playeralthough the prefix differs), and anchoring on the trailing segment is what keeps an unrelatedfrom os.path import Xout of it.
Idempotent, and returns
sourceunchanged when nothing matches. A plainimport xbinds the module itself rather than a name from it, and rewriting it would need the uses of that binding to follow; it is left alone here and would warrant a primitive of its own.