Seed bundled demos under top-level demos/ instead of code/

Move canonical sample scripts to a sibling folder of code/ and lib/ so
user projects stay separate from shipped examples. Backend seeding,
writable paths, and docs follow the new layout.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-14 22:34:12 +12:00
parent d355174f5a
commit e3400120d3
9 changed files with 63 additions and 53 deletions

View File

@@ -92,14 +92,16 @@ def test_new_user_workspace_has_default_main_py(tmp_path, monkeypatch):
assert reg.status_code == 200
assert reg.json()["username"] == "alice"
uid = reg.json()["id"]
code_root = tmp_path / "users" / f"alice-{uid}" / "code"
user_root = tmp_path / "users" / f"alice-{uid}"
code_root = user_root / "code"
demos_dir = user_root / "demos"
on_disk = code_root / "main.py"
assert on_disk.is_file()
assert on_disk.read_text(encoding="utf-8") == 'print("Hello, World!")\n'
canonical = ("pattern_rainbow_demo.py", "pattern_twinkle_demo.py", "pattern_chase_demo.py")
for fname in canonical:
cp = code_root / fname
assert cp.is_file(), f"missing bundled copy {fname} (workspace/code must ship with app)"
cp = demos_dir / fname
assert cp.is_file(), f"missing bundled copy demos/{fname} (workspace must ship with app)"
text = cp.read_text(encoding="utf-8")
assert len(text.strip()) > 20
assert "from led_patterns" not in text
@@ -110,7 +112,7 @@ def test_new_user_workspace_has_default_main_py(tmp_path, monkeypatch):
assert fetched.status_code == 200
assert fetched.json()["filename"] == "main.py"
assert 'Hello, World!' in fetched.json()["content"]
chase = client.get("/api/file/code/pattern_chase_demo.py")
chase = client.get("/api/file/demos/pattern_chase_demo.py")
assert chase.status_code == 200
assert "knight_rider_scanner_frame" in chase.json()["content"]
@@ -311,14 +313,6 @@ def test_lib_is_shared_read_only_across_users(tmp_path, monkeypatch):
shared_lib = tmp_path / "lib"
shared_lib.mkdir(parents=True, exist_ok=True)
(shared_lib / "shared.py").write_text("VALUE = 42\n", encoding="utf-8")
# Mirror canonical demo files so `_seed_canonical_demos_into_code` still works.
real_demos = config.PROJECT_ROOT / "workspace" / "code"
fake_demos = tmp_path / "workspace" / "code"
fake_demos.mkdir(parents=True, exist_ok=True)
for fname in ("pattern_rainbow_demo.py", "pattern_twinkle_demo.py", "pattern_chase_demo.py"):
src = real_demos / fname
if src.is_file():
(fake_demos / fname).write_text(src.read_text(encoding="utf-8"), encoding="utf-8")
monkeypatch.setattr(config, "PROJECT_ROOT", tmp_path)

View File

@@ -5,7 +5,7 @@ from pathlib import Path
def _load_patterns_module():
repo_root = Path(__file__).resolve().parents[1]
# Canonical home for shipped demos — `workspace/` is gitignored.
module_path = repo_root / "src" / "static" / "bundled-demos" / "led_patterns.py"
module_path = repo_root / "src" / "static" / "bundled-demos" / "demo" / "led_patterns.py"
spec = importlib.util.spec_from_file_location("led_patterns", module_path)
module = importlib.util.module_from_spec(spec)
assert spec is not None and spec.loader is not None