feat: add TTLCache for get_cache_version and TEMPLATE_AUTO_RELOAD config with Makefile worker count variables

This commit is contained in:
2026-06-14 14:46:36 +00:00
parent c151325916
commit d75d5dc6a8
149 changed files with 9811 additions and 262 deletions
+77
View File
@@ -0,0 +1,77 @@
# retoor <retoor@molodetz.nl>
from devplacepy.services.bot.monitor import BotMonitor, BotFrame
def test_update_meta_creates_and_merges():
monitor = BotMonitor()
monitor.update_meta(0, username="bytewren", persona="grumpy_senior")
monitor.update_meta(0, action="POST: rant [1]")
frame = monitor.frames[0]
assert frame.username == "bytewren"
assert frame.persona == "grumpy_senior"
assert frame.action == "POST: rant [1]"
assert frame.label() == "bytewren"
def test_store_and_read_image(tmp_path, monkeypatch):
import devplacepy.services.bot.monitor as mod
monkeypatch.setattr(mod, "MONITOR_DIR", tmp_path)
monitor = BotMonitor()
monitor.update_meta(2, username="anon")
monitor.store_image(2, b"jpegbytes")
assert monitor.frames[2].has_image is True
assert monitor.read_image(2) == b"jpegbytes"
assert monitor.frame_path(2) == tmp_path / "slot2.jpg"
def test_store_image_overwrites(tmp_path, monkeypatch):
import devplacepy.services.bot.monitor as mod
monkeypatch.setattr(mod, "MONITOR_DIR", tmp_path)
monitor = BotMonitor()
monitor.store_image(4, b"first")
captured_first = monitor.frames[4].captured_at
monitor.store_image(4, b"second")
assert monitor.read_image(4) == b"second"
assert monitor.frames[4].captured_at >= captured_first
assert len(list(tmp_path.glob("slot4.jpg"))) == 1
def test_store_empty_image_is_noop(tmp_path, monkeypatch):
import devplacepy.services.bot.monitor as mod
monkeypatch.setattr(mod, "MONITOR_DIR", tmp_path)
monitor = BotMonitor()
monitor.store_image(1, b"")
assert 1 not in monitor.frames
assert monitor.read_image(1) is None
def test_drop_evicts_row_and_file(tmp_path, monkeypatch):
import devplacepy.services.bot.monitor as mod
monkeypatch.setattr(mod, "MONITOR_DIR", tmp_path)
monitor = BotMonitor()
monitor.update_meta(0, username="x")
monitor.store_image(0, b"data")
monitor.drop(0)
assert 0 not in monitor.frames
assert monitor.read_image(0) is None
def test_snapshot_sorted_and_serializable():
monitor = BotMonitor()
monitor.update_meta(3, username="c")
monitor.update_meta(1, username="a")
snap = monitor.snapshot()
assert [row["slot"] for row in snap] == [1, 3]
assert "frame_url" not in snap[0]
assert snap[0]["active"] is False
def test_frame_inactive_without_image():
frame = BotFrame(slot=0, username="z")
assert frame.is_active() is False
assert frame.label() == "z"
+116
View File
@@ -5,6 +5,7 @@ import pytest
import requests
from tests.conftest import BASE_URL, run_async
from devplacepy.database import db, get_table, init_db, refresh_snapshot
from devplacepy.utils import generate_uid
from devplacepy import config, project_files
from devplacepy.services.containers import api, store, runtime
from devplacepy.services.containers.backend.base import Mount, PortMapping, RunSpec
@@ -31,9 +32,27 @@ def env(tmp_path, monkeypatch):
pid = "ctest-p1"
project = {"uid": pid, "slug": "ctest", "title": "C", "user_uid": "ctest-u1"}
user = {"uid": "ctest-u1", "username": "ctestadmin"}
get_table("users").insert(
{
"uid": user["uid"],
"username": user["username"],
"email": "ctestadmin@example.com",
"api_key": generate_uid(),
"password_hash": "",
"role": "Member",
"is_active": True,
"level": 1,
"xp": 0,
"stars": 0,
"deleted_at": None,
"deleted_by": None,
}
)
refresh_snapshot()
project_files.write_text_file(pid, user, "app.py", "print(1)\n")
yield {"fake": fake, "project": project, "user": user}
runtime.set_backend(None)
get_table("users").delete(uid=user["uid"])
for table in _CONTAINER_TABLES:
if table in db.tables:
for row in [r for r in get_table(table).find()]:
@@ -188,3 +207,100 @@ def test_ingress_validation(env):
)
with pytest.raises(api.ContainerError):
api.validate_ingress("taken", None, [PortMapping(80, 80)])
def test_validate_boot_languages():
assert api.validate_boot("none", "ignored") == ("none", "")
assert api.validate_boot("python", "print(1)") == ("python", "print(1)")
with pytest.raises(api.ContainerError):
api.validate_boot("ruby", "puts 1")
with pytest.raises(api.ContainerError):
api.validate_boot("bash", " ")
def test_boot_script_precedence_in_run_spec(env):
inst = _ready_instance(
env,
boot_language="python",
boot_script="print('boot')\n",
boot_command="python other.py",
autostart=False,
)
spec = api.run_spec_for(inst, config.CONTAINER_IMAGE)
assert spec.command == ["python", "/app/.devplace_boot.py"]
inst2 = _ready_instance(
env, name="i2", boot_command="python serve.py", autostart=False
)
spec2 = api.run_spec_for(inst2, config.CONTAINER_IMAGE)
assert spec2.command == ["/bin/sh", "-c", "python serve.py"]
def test_materialize_boot_script_writes_file(env, tmp_path):
workspace = tmp_path / "boot-ws"
inst = _ready_instance(
env, name="boot", boot_language="bash", boot_script="echo hi\n", autostart=False
)
store.update_instance(inst["uid"], {"workspace_dir": str(workspace)})
inst = store.get_instance(inst["uid"])
api.materialize_boot_script(inst)
written = workspace / ".devplace_boot.sh"
assert written.is_file()
assert written.read_text() == "echo hi\n"
def test_run_as_uid_drives_pravda_env(env):
_promote_admin(env["user"]["username"])
key = _api_key(env["user"]["username"])
inst = _ready_instance(
env, name="runas", run_as_uid=env["user"]["uid"], autostart=False
)
pravda = api.pravda_env(inst)
assert pravda["PRAVDA_API_KEY"] == key
assert pravda["PRAVDA_USER_UID"] == env["user"]["uid"]
def test_run_as_uid_rejects_unknown_user(env):
with pytest.raises(api.ContainerError):
run_async(
api.create_instance(
env["project"], name="bad", run_as_uid="nope-uid", autostart=False
)
)
def test_start_on_boot_pass_forces_running(env):
inst = _ready_instance(env, name="boot", start_on_boot=True, autostart=False)
assert inst["desired_state"] == store.DESIRED_STOPPED
service = ContainerService()
service._boot_pass(store.all_instances())
refresh_snapshot()
assert store.get_instance(inst["uid"])["desired_state"] == store.DESIRED_RUNNING
def test_status_change_records_event(env):
inst = _ready_instance(env, name="hist", restart_policy="never", autostart=True)
service = ContainerService()
run_async(service.run_once())
refresh_snapshot()
inst = store.get_instance(inst["uid"])
api.set_desired_state(inst, store.DESIRED_STOPPED)
run_async(service.run_once())
refresh_snapshot()
events = [e["event"] for e in store.list_events(inst["uid"])]
assert "status_change" in events
def test_bidirectional_sync_newer_wins(env, tmp_path):
workspace = tmp_path / "sync-ws"
workspace.mkdir()
pid = env["project"]["uid"]
user = env["user"]
project_files.write_text_file(pid, user, "shared.txt", "from project\n")
fs_only = workspace / "fromfs.txt"
fs_only.write_text("from fs\n")
counts = project_files.sync_dir_bidirectional(pid, str(workspace), user)
assert counts["exported"] >= 1
assert counts["imported"] >= 1
assert (workspace / "shared.txt").read_text() == "from project\n"
imported = project_files.read_file(pid, "fromfs.txt")
assert imported["content"] == "from fs\n"
+3 -4
View File
@@ -1,7 +1,6 @@
# retoor <retoor@molodetz.nl>
import asyncio
from tests.conftest import run_async
from devplacepy.services.deepsearch import chat as chat_module
from devplacepy.services.deepsearch.chat import DeepsearchChat
from devplacepy.services.deepsearch.embeddings import local_embed
@@ -32,7 +31,7 @@ def test_answer_is_grounded_and_cited(monkeypatch):
monkeypatch.setattr(chat_module, "complete_chat", fake_complete)
chat = DeepsearchChat(collection, "k")
answer = asyncio.run(chat.answer("where was the transistor invented"))
answer = run_async(chat.answer("where was the transistor invented"))
assert "Bell Labs" in answer.text
assert answer.citations
assert answer.citations[0]["url"].startswith("https://")
@@ -48,7 +47,7 @@ def test_answer_when_no_chunks(monkeypatch):
monkeypatch.setattr(chat_module, "embed_texts", fake_embed)
chat = DeepsearchChat(collection, "k")
answer = asyncio.run(chat.answer("anything"))
answer = run_async(chat.answer("anything"))
assert answer.citations == []
assert "did not capture" in answer.text
finally:
@@ -1,10 +1,11 @@
# retoor <retoor@molodetz.nl>
import asyncio
import json
import tempfile
from pathlib import Path
from tests.conftest import run_async
from devplacepy.services.jobs.deepsearch import crawl as crawl_module
from devplacepy.services.jobs.deepsearch import worker as worker_module
from devplacepy.services.jobs.deepsearch.crawl import CrawledPage, CrawlOutcome
@@ -79,7 +80,7 @@ def test_worker_run_produces_report(monkeypatch):
"collection": "ds_worker_test_one",
"cached_hashes": [],
}
report = asyncio.run(worker_module._run(payload, output_dir))
report = run_async(worker_module._run(payload, output_dir))
assert report["query"] == "history of the transistor"
assert report["page_count"] == 2
assert report["chunk_count"] > 0
@@ -100,4 +101,4 @@ def test_worker_control_cancel_stops(monkeypatch):
output_dir = Path(tmp)
(output_dir / "control.json").write_text(json.dumps({"state": "cancelled"}))
should_stop = worker_module._make_stop(output_dir)
assert asyncio.run(should_stop()) is True
assert run_async(should_stop()) is True
+2
View File
@@ -52,6 +52,8 @@ def _make_source_project(*, is_private=False, binary=False):
)
get_table("projects").insert(
{
"deleted_at": None,
"deleted_by": None,
"uid": pid,
"user_uid": owner_uid,
"slug": f"{pid}-source",
+4
View File
@@ -240,6 +240,8 @@ def test_export_blocks_malicious_db_path(zip_env, tmp_path):
pid = "ziptest-evil"
get_table("project_files").insert(
{
"deleted_at": None,
"deleted_by": None,
"uid": "evil-node",
"project_uid": pid,
"user_uid": "u",
@@ -267,6 +269,8 @@ def test_traversal_payload_marks_job_failed(zip_env):
pid = "ziptest-evil2"
get_table("project_files").insert(
{
"deleted_at": None,
"deleted_by": None,
"uid": "evil-node2",
"project_uid": pid,
"user_uid": "u",
+2
View File
@@ -146,6 +146,8 @@ def test_run_once_updates_existing_news_row(local_db, monkeypatch):
existing_uid = generate_uid()
get_table("news").insert(
{
"deleted_at": None,
"deleted_by": None,
"uid": existing_uid,
"external_id": external_id,
"slug": "",