Spatial Runtime
A zero-dependency semantic drawing runtime for Python.
Spatial Runtime combines a persistent scene graph, geometric constraints, atomic editing, versioned documents, reactive rendering, and a local interactive Studio. Drawings are ordinary Python programs, while every object remains addressable through a stable semantic ID.
Use it to build diagrams, illustrations, generated graphics, and machine-editable scenes that retain their structure after rendering.
Why Spatial Runtime?
- Semantic scenes — address objects by IDs such as
hero.head, not by fragile array positions. - Structured geometry — preserve hierarchy, styles, anchors, relations, constraints, metadata, dependencies, roles, guides, and z-order.
- Safe editing transactions — solve and validate before committing, with automatic rollback when an edit is invalid.
- Multiple outputs — generate deterministic SVG, PNG, PDF, canvas, inspection, and feedback documents.
- Reactive workflow — watch drawing files and their local imports, retain the last good render after an error, and avoid unchanged artifact writes.
- Local Studio — inspect, select, drag, edit, preview, undo, and export a scene in the browser.
- Zero runtime dependencies — install the package without pulling in a third-party runtime stack.
Spatial Runtime requires Python 3.11 or newer.
Installation
Install the package from PyPI:
python -m pip install spatial-runtime
Confirm that the command-line interface is available:
spatial --help
Quick start
Create drawing.py:
from spatial import Circle, Rect, Scene
scene = Scene(600, 400, id="portrait")
scene.group("hero")
scene.add(
Circle(
(300, 130),
55,
id="head",
role="structural",
style={"fill": "#ffd8ad", "stroke": "#17131f", "stroke_width": 4},
),
parent="hero",
)
scene.add(
Rect(
245,
190,
110,
150,
id="body",
role="structural",
style={"fill": "#ffb454", "stroke": "#17131f", "stroke_width": 4},
),
parent="hero",
)
scene.relate("attached", "hero.head", "hero.body", at="neck")
scene.constrain("hero.head", horizontally_aligned_with="hero.body")
scene.solve_constraints()
Run the complete construct, render, inspect, and feedback cycle:
spatial cycle drawing.py --out-dir out
Or open the scene in Studio:
spatial studio drawing.py --open
Semantic scenes
A scene is more than a list of drawing commands. Nodes keep their meaning and relationships throughout the drawing workflow:
head = scene["hero.head"]
head.anchor("neck", (300, 180))
head.set_lod(summary="circular face attached to the body")
scene.relate("attached", "hero.head", "hero.body", at="neck")
scene.constrain("hero.head", horizontally_aligned_with="hero.body")
Stable hierarchical IDs make scenes straightforward to inspect, patch, and modify from Python or an automated tool.
Atomic edits and validation
Scene.edit() treats a group of changes as one transaction. Spatial Runtime
solves constraints and validates the scene before committing. Solver
non-convergence or an error-level validation issue rejects the transaction,
restores the previous state, and raises EditRejectedError.
from spatial import EditRejectedError
try:
with scene.edit("move the head upward") as edit:
scene["hero.head"].move(dy=-8)
except EditRejectedError as error:
print(error.result.reason)
print(error.result.solve_report)
print(error.result.issues)
else:
print(edit.result.diff)
Warnings, including out-of-canvas geometry, remain visible without rejecting a
valid edit. Use allow_invalid=True when you deliberately need to commit an
invalid state while retaining its complete diagnostics.
Undo, redo, and named snapshots are available during the active Python or Studio session.
Rendering and inspection
Render the same semantic scene to several targets:
scene.render_svg("render.svg")
scene.render_blueprint("blueprint.svg")
scene.render_raster("render.png", scale=2)
scene.render_pdf("render.pdf")
scene.save("scene.json")
print(scene.inspect("hero", detail="full"))
print(scene.inspect("hero", detail="full", structured=True))
print(scene.occupancy("hero"))
print(scene.validate())
Portable outputs use explicit, versioned document envelopes:
| Document | Schema |
|---|---|
| Scene snapshot | spatial.scene |
| Declarative patch | spatial.patch |
| Canvas commands | spatial.canvas |
| Structured inspection | spatial.inspection |
| Reactive feedback | spatial.feedback |
For example, Scene.save() writes a lossless snapshot of the current scene:
{
"schema": "spatial.scene",
"schema_version": 1,
"scene": {
"id": "portrait",
"width": 600,
"height": 400,
"styles": {}
},
"nodes": [],
"constraints": [],
"relations": []
}
All built-in node types have exact codecs. Materialized custom Component
subclasses load as FrozenComponent snapshots that retain their class
provenance, layer metadata, hierarchy, and children. Custom Node subclasses
can register their own codecs.
Packaged JSON Schemas are available through load_schema("scene"); use
"patch", "canvas", "inspection", or "feedback" for the other document
types.
Declarative patches
[!NOTE] The patch protocol is experimental and may evolve between releases.
Scene.apply_patch() applies a JSON-compatible set of operations atomically:
result = scene.apply_patch(
{
"schema": "spatial.patch",
"schema_version": 1,
"label": "Move the head upward",
"operations": [
{"op": "move", "target": "hero.head", "dx": 0, "dy": -8}
],
}
)
Patches support:
- adding, removing, and reparenting nodes;
- moving, positioning, scaling, rotating, and editing handles;
- changing styles, metadata, visibility, roles, z-order, and anchors; and
- adding or removing relations and constraints.
Operations run in order inside one transaction. An unknown operation, malformed
payload, missing target, or rejected edit rolls back the entire patch.
dry_run=True evaluates the patch on a clone and returns its projected diff,
diagnostics, and canvas without changing the live scene.
Reactive rendering
Watch a drawing and rebuild when its source or local Python imports change:
spatial watch drawing.py --out-dir out --debounce 0.15
The reactive runner:
- waits for file changes to settle before rebuilding;
- reloads changed local modules;
- retains the last valid scene and artifacts after execution errors;
- reports failures as structured feedback and continues watching;
- writes artifacts atomically; and
- skips filesystem writes when the generated bytes are unchanged.
SVG fragments and canvas commands are cached by normalized node state. Reloading canonical Python source starts a fresh session and clears undo/redo.
Local Studio
[!NOTE] Studio is experimental and intended for trusted local use.
spatial studio drawing.py --host 127.0.0.1 --port 8765 --open
Studio includes:
- a searchable semantic hierarchy with role and layer filters;
- a zoomable SVG viewport with click selection and drag-to-move;
- geometry, style, anchor, relation, constraint, metadata, and dependency controls;
- guide, blueprint, bounds, anchor, and role overlays;
- editable semantic handles and dry-run previews;
- undo, redo, reload, and JSON snapshot export; and
- structural diffs, changed-node highlighting, pixel-diff overlays, warnings, and solver status.
Studio edits only the in-memory scene and never rewrites the Python drawing. Reloading the source discards session edits and starts a new undo/redo history.
Studio has no authentication or security boundary. Drawing files execute as
fully trusted Python, so run only code you trust and keep Studio bound to
127.0.0.1 unless you intentionally choose otherwise.
Source and history model
Python source is authoritative. Scene JSON captures the complete current scene state for interchange, inspection, and export, but it does not contain snapshots or undo/redo history.
Use Git for durable source history. Spatial Runtime intentionally does not add a sandbox, permission system, authentication layer, or revision-control layer around drawing files.
Documentation
The examples directory contains complete scenes demonstrating
primitives, components, constraints, patterns, fields, surfaces, skeletons,
perspective, rendering, and inspection.
Development
Clone the repository, then install the development tools:
python -m pip install -e ".[dev]"
Run the main checks:
python -m compileall -q src
ruff check src tests
mypy
coverage run -m unittest discover -s tests -v
coverage report
node --test tests/js/studio.test.mjs
The release suite covers persistence round trips, transaction rollback, patch atomicity, deterministic renderer documents, reactive recovery, Studio endpoints, browser behavior, and performance at 100-, 1,000-, and 10,000-node scene sizes.
Project status
Spatial Runtime 2.0.0 is beta software. The core scene, persistence, transaction, validation, rendering, inspection, and reactive APIs are stable. The patch protocol and Studio are experimental.
Released under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spatial_runtime-2.0.0.tar.gz.
File metadata
- Download URL: spatial_runtime-2.0.0.tar.gz
- Upload date:
- Size: 94.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25d69b3b592e086ddf53c21981c87d781f08811d490e0d3d7833e7923b4649fc
|
|
| MD5 |
d4580a39d627d99fed1e8bdb27b12365
|
|
| BLAKE2b-256 |
e8c9393d07c2d628af9d4542d0226f19f11261b25ff002bff9a676ffb57c0940
|
File details
Details for the file spatial_runtime-2.0.0-py3-none-any.whl.
File metadata
- Download URL: spatial_runtime-2.0.0-py3-none-any.whl
- Upload date:
- Size: 91.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f8640d2d66258cf97fcab91dd794c939ae0272dab6feee4713c252e9fe4c6a29
|
|
| MD5 |
c6589e81ad8b9a17abf1f4cb38cb5074
|
|
| BLAKE2b-256 |
b43b5115f34a053ebf9674109bf7692291513dbad7d1bc00bf2c13dc37bb6f92
|