simvx.editor.project_classes¶
Discovery + cache for user-defined Node subclasses in the active project.
Walks the project src/ directory (configurable via
simvx.toml [editor].class_files_dir) and parses each .py file with
- func:
simvx.core.scene_io.parse_sourceto find top-levelclass X(...)definitions whose base list references a knownNodesubclass name.
The result feeds the Add Node dialog’s class picker so users can instantiate their own classes alongside engine built-ins. We deliberately do not import the project files – the dialog only needs the class name, module path, and file location for display + lazy resolution at instantiation time.
Cache invalidation is mtime-based: each call to :meth:ProjectClassIndex.refresh
re-stats every .py file under the configured root and re-parses any whose
mtime changed since the last scan. Files with syntax errors are skipped
silently (the parser still returns a tree thanks to error recovery, but we
treat any reported error as “skip and try again next refresh”).
Module Contents¶
Classes¶
A user-defined Node subclass discovered by walking project source files. |
|
Mtime-cached index of user-defined Node subclasses under a project root. |
|
Outcome of a project-wide :func: |
Functions¶
Rename a class everywhere it appears in the project. |
Data¶
API¶
- simvx.editor.project_classes.log¶
‘getLogger(…)’
- class simvx.editor.project_classes.ProjectClass[source]¶
A user-defined Node subclass discovered by walking project source files.
module_pathis the dotted module name relative to the configured root (e.g.player.attack).file_pathis the absolute filesystem path, kept so the editor can open the source on demand.- name: str¶
None
- module_path: str¶
None
- file_path: pathlib.Path¶
None
- bases: tuple[str, ...]¶
None
- class simvx.editor.project_classes.ProjectClassIndex(project_path: pathlib.Path | None = None, *, src_subdir: str = 'src')[source]¶
Mtime-cached index of user-defined Node subclasses under a project root.
Construct once per project session; call :meth:
refreshwhenever the picker is about to be shown.refreshis cheap when nothing changed (onestatper.pyfile plus a dict lookup); a full re-scan only happens for files whose mtime advanced.Initialization
- set_project_path(project_path: pathlib.Path | None) None[source]¶
Switch the index to a new project; clears the cache.
- refresh() list[simvx.editor.project_classes.ProjectClass][source]¶
Rescan the project root, re-parsing only files with changed mtime.
Returns the full list of discovered classes (sorted by name).
- all() list[simvx.editor.project_classes.ProjectClass][source]¶
Return the cached list without rescanning.
- iter_use_sites(class_name: str) collections.abc.Iterator[tuple[pathlib.Path, simvx.core.scene_io.UseSiteRef]][source]¶
Yield
(file_path, use_site)pairs for every reference toclass_name.Walks every project file (re-scanning the cache first) and runs
- Func:
simvx.core.scene_io.find_class_usesagainst each parsed source. Files with parse errors are skipped silently — the next- Meth:
refreshwill re-attempt them.
- resolve(project_class: simvx.editor.project_classes.ProjectClass) type[simvx.core.Node] | None[source]¶
Import the project module and return the class object, or None.
The picker stores
ProjectClassrecords (name + module path) so the editor can display the list without executing user code. When the user actually picks an entry, the editor calls this to import the module and resolve the live class. Failures are logged and returnNone– callers should surface a user-visible error in that case.
- class simvx.editor.project_classes.RenameResult[source]¶
Outcome of a project-wide :func:
rename_classoperation.- files_modified: tuple[pathlib.Path, ...]¶
None
- file_renamed: tuple[pathlib.Path, pathlib.Path] | None¶
None
- simvx.editor.project_classes.rename_class(project_index: simvx.editor.project_classes.ProjectClassIndex, old_name: str, new_name: str, *, rename_file: bool = False) simvx.editor.project_classes.RenameResult[source]¶
Rename a class everywhere it appears in the project.
Updates the class definition + every importer + every instantiation site by parsing each affected file, running
- Func:
simvx.core.scene_io.rename_class_in_sourceagainst it, and writing the result back. Two-phase: collect every new-source mapping in memory first; only write to disk after every file successfully rewrites. If a write fails partway, restore each already-written file from its in-memory snapshot.
When
rename_file=Trueand the definition lives in a file whose stem matches the old class’s snake_case form (or in a folder whose name matches), also rename the file/folder to match the new class. Importers in other files are updated by virtue of the same cross-file rewrite.Returns the set of files modified and (optionally) the file rename. Raises :class:
ValueErrorifold_namehas no definition in the project, or ifnew_namealready names another project class.