simvx.editor.scene_diff¶
Reconcile a parsed scene class with a live runtime Node tree.
The editor mutates the runtime tree directly while the user works (drag a node, change a Property, add a child); on save we need to push those mutations back into the on-disk source without losing comments, blank lines, hand-written helper functions, or import ordering.
- func:
apply_runtime_diffis the integration point: given a- class:
~simvx.core.scene_io.SceneClass(a parso-backed view of the class in the user’s.pyfile) and the live runtime root, it issues the minimum set of structural edits via the SceneClass API so the next- meth:
SceneFile.savewrites a file whose__init__matches the runtime tree exactly.
Identity matching uses the same name-sanitisation rule the greenfield
emitter applies (:func:structural_type_name + _canonical_var_names
below): each runtime child gets its var name computed; if the parsed
source already has a child with that name, the two are treated as the
same node and reconciled in place. Otherwise it’s an add (for runtime-
only nodes) or a remove (for source-only nodes).
v1 limitations (locked down by tests):
Renaming a runtime child mid-session manifests as a remove + add at save time. Proper rename detection requires a stable identity beyond the user-visible
.name, which is a v2 concern.Procedural
__init__bodies (children built inside loops or conditionals) are not safe to diff-reconcile; callers should detect that case via :func:~simvx.core.scene_io.has_procedural_constructionand fall back to greenfield save.
Module Contents¶
Functions¶
Reconcile |
Data¶
API¶
- simvx.editor.scene_diff.__all__¶
[‘apply_runtime_diff’]
- simvx.editor.scene_diff.apply_runtime_diff(scene_class: simvx.core.scene_io.SceneClass, runtime_root: simvx.core.Node, *, identity_hints: dict[simvx.core.Node, str] | None = None) None[source]¶
Reconcile
scene_classso its__init__matchesruntime_root.Mutation strategy:
Update root
super().__init__kwargs to reflect non-default Property values on the runtime root (insert/update/remove).For each top-level runtime child whose canonical var name already exists in the source, update its constructor kwargs in place.
Append runtime children whose canonical name has no source counterpart via :meth:
SceneClass.add_child(auto-importing the type via the file’s :class:ImportSet).Remove source-only children via :meth:
SceneClass.remove_child, then drop now-unused imports for types no longer referenced by any remaining child constructor.If the surviving children are out of order relative to the runtime tree, call :meth:
SceneClass.reorder_children.
Only top-level children of the root are reconciled in v1 (matching the emitter’s depth: nested
add_childcalls aren’t expressed in the current scene-class shape). Deeper sub-tree reconciliation is a v2 concern.identity_hintsis an optional{runtime_node: source_var_name}mapping captured at scene load. When a runtime node has a hint and its current canonical var name differs from the hint, the diff treats this as a rename — the source var is renamed in place via- Meth:
SceneClass.rename_childand kwargs/type-swap are reconciled against the renamed source — rather than emitting a remove + add seam (which would lose the original source position and any kwargs the source had that the runtime no longer carries explicitly).