fix: normalize unicode escape sequences and reformat multi-line expressions across codebase

This commit is contained in:
2026-06-09 16:48:08 +00:00
parent 66dfda88bc
commit c4f2937415
175 changed files with 12660 additions and 4175 deletions
+23 -5
View File
@@ -5,8 +5,16 @@ from __future__ import annotations
from ..actions.spec import Action, Param
def field(name: str, description: str, required: bool = False, kind: str = "string") -> Param:
return Param(name=name, location="body", description=description, required=required, type=kind)
def field(
name: str, description: str, required: bool = False, kind: str = "string"
) -> Param:
return Param(
name=name,
location="body",
description=description,
required=required,
type=kind,
)
SCHEDULE_FIELDS: tuple[Param, ...] = (
@@ -20,8 +28,16 @@ SCHEDULE_FIELDS: tuple[Param, ...] = (
"run_at",
"For kind=once: absolute UTC time in ISO 8601, e.g. 2026-06-09T14:30:00.",
),
field("delay_seconds", "For kind=once: run this many seconds from now.", kind="integer"),
field("every_seconds", "For kind=interval: number of seconds between runs.", kind="integer"),
field(
"delay_seconds",
"For kind=once: run this many seconds from now.",
kind="integer",
),
field(
"every_seconds",
"For kind=interval: number of seconds between runs.",
kind="integer",
),
field(
"start_at",
"For kind=interval: optional ISO 8601 UTC time of the first run. "
@@ -73,7 +89,9 @@ TASK_ACTIONS: tuple[Action, ...] = (
requires_auth=False,
params=(
field("enabled_only", "Only return enabled tasks.", kind="boolean"),
field("status", "Filter by status: pending, running, done, error, disabled."),
field(
"status", "Filter by status: pending, running, done, error, disabled."
),
),
),
Action(
+42 -10
View File
@@ -15,7 +15,15 @@ from .store import TaskStore
logger = logging.getLogger("devii.tasks.controller")
SCHEDULE_KEYS = ("kind", "run_at", "delay_seconds", "every_seconds", "start_at", "cron", "max_runs")
SCHEDULE_KEYS = (
"kind",
"run_at",
"delay_seconds",
"every_seconds",
"start_at",
"cron",
"max_runs",
)
RESULT_PREVIEW_CHARS = 500
TRUTHY = {"1", "true", "yes", "on"}
@@ -105,7 +113,10 @@ class TaskController:
)
rows.sort(key=lambda row: row.get("next_run_at") or "")
return json.dumps(
{"count": len(rows), "tasks": [_serialize(row, preview=True) for row in rows]},
{
"count": len(rows),
"tasks": [_serialize(row, preview=True) for row in rows],
},
ensure_ascii=False,
)
@@ -127,7 +138,9 @@ class TaskController:
if "enabled" in arguments:
changes["enabled"] = _as_bool(arguments.get("enabled"))
if any(key in arguments and arguments[key] is not None for key in SCHEDULE_KEYS):
if any(
key in arguments and arguments[key] is not None for key in SCHEDULE_KEYS
):
merged = {key: row.get(key) for key in SCHEDULE_KEYS}
for key in SCHEDULE_KEYS:
if key in arguments and arguments[key] is not None:
@@ -137,10 +150,16 @@ class TaskController:
changes["next_run_at"] = to_iso(schedule.first_run(now_utc()))
changes["status"] = "pending"
if changes.get("enabled") and row.get("status") in ("done", "disabled", "error"):
if changes.get("enabled") and row.get("status") in (
"done",
"disabled",
"error",
):
changes.setdefault("status", "pending")
if not changes.get("next_run_at") and not row.get("next_run_at"):
schedule = self._build_schedule({key: row.get(key) for key in SCHEDULE_KEYS})
schedule = self._build_schedule(
{key: row.get(key) for key in SCHEDULE_KEYS}
)
changes["next_run_at"] = to_iso(schedule.first_run(now_utc()))
if changes.get("enabled") is False:
changes["status"] = "disabled"
@@ -150,7 +169,10 @@ class TaskController:
self._store.update(row["uid"], changes)
return json.dumps(
{"status": "updated", "task": _serialize(self._store.get(row["uid"]), preview=True)},
{
"status": "updated",
"task": _serialize(self._store.get(row["uid"]), preview=True),
},
ensure_ascii=False,
)
@@ -168,12 +190,18 @@ class TaskController:
{"enabled": True, "status": "pending", "next_run_at": to_iso(now_utc())},
)
return json.dumps(
{"status": "queued", "uid": row["uid"], "note": "Will execute on the next scheduler tick."},
{
"status": "queued",
"uid": row["uid"],
"note": "Will execute on the next scheduler tick.",
},
ensure_ascii=False,
)
def _build_schedule(self, source: dict[str, Any]) -> Schedule:
payload = {key: source.get(key) for key in SCHEDULE_KEYS if source.get(key) is not None}
payload = {
key: source.get(key) for key in SCHEDULE_KEYS if source.get(key) is not None
}
try:
return Schedule(**payload)
except ValidationError as exc:
@@ -195,10 +223,14 @@ class TaskController:
return row
def compute_followup(row: dict[str, Any], reference: Any) -> tuple[dict[str, Any], bool]:
def compute_followup(
row: dict[str, Any], reference: Any
) -> tuple[dict[str, Any], bool]:
run_count = int(row.get("run_count") or 0) + 1
max_runs = row.get("max_runs")
upcoming = next_run(row.get("kind"), row.get("every_seconds"), row.get("cron"), reference)
upcoming = next_run(
row.get("kind"), row.get("every_seconds"), row.get("cron"), reference
)
changes: dict[str, Any] = {"run_count": run_count, "last_run_at": to_iso(reference)}
if upcoming is None or (max_runs is not None and run_count >= int(max_runs)):
+6 -2
View File
@@ -50,7 +50,9 @@ def _parse_field(field: str, low: int, high: int) -> set[int]:
def cron_next(expr: str, after: datetime) -> datetime:
fields = expr.split()
if len(fields) != 5:
raise ValueError("Cron expression must have 5 fields: minute hour dom month dow")
raise ValueError(
"Cron expression must have 5 fields: minute hour dom month dow"
)
minutes = _parse_field(fields[0], 0, 59)
hours = _parse_field(fields[1], 0, 23)
days = _parse_field(fields[2], 1, 31)
@@ -139,7 +141,9 @@ class Schedule(BaseModel):
}
def next_run(kind: str, every_seconds: Optional[int], cron: Optional[str], reference: datetime) -> Optional[datetime]:
def next_run(
kind: str, every_seconds: Optional[int], cron: Optional[str], reference: datetime
) -> Optional[datetime]:
if kind == "interval" and every_seconds:
return reference + timedelta(seconds=int(every_seconds))
if kind == "cron" and cron:
+5 -1
View File
@@ -77,7 +77,11 @@ class Scheduler:
logger.exception("Task uid=%s crashed", uid)
self._store.update(
uid,
{"status": "error", "last_error": str(exc), "last_run_at": to_iso(now_utc())},
{
"status": "error",
"last_error": str(exc),
"last_run_at": to_iso(now_utc()),
},
)
self._on_event("error", row, str(exc))
return
+25 -6
View File
@@ -10,7 +10,13 @@ import dataset
logger = logging.getLogger("devii.tasks.store")
TABLE = "devii_tasks"
INDEXED_COLUMNS = (["owner_kind", "owner_id"], ["uid"], ["enabled"], ["next_run_at"], ["status"])
INDEXED_COLUMNS = (
["owner_kind", "owner_id"],
["uid"],
["enabled"],
["next_run_at"],
["status"],
)
def memory_db() -> Any:
@@ -41,12 +47,19 @@ class TaskStore:
def create(self, record: dict[str, Any]) -> None:
self._table.insert({**record, **self._scope})
logger.info("Task created uid=%s owner=%s/%s", record.get("uid"), self._owner_kind, self._owner_id)
logger.info(
"Task created uid=%s owner=%s/%s",
record.get("uid"),
self._owner_kind,
self._owner_id,
)
def get(self, uid: str) -> dict[str, Any] | None:
return self._table.find_one(uid=uid, **self._scope)
def list(self, enabled_only: bool = False, status: str | None = None) -> list[dict[str, Any]]:
def list(
self, enabled_only: bool = False, status: str | None = None
) -> list[dict[str, Any]]:
criteria: dict[str, Any] = dict(self._scope)
if enabled_only:
criteria["enabled"] = True
@@ -69,12 +82,18 @@ class TaskStore:
return 0
stuck = list(self._table.find(status="running", **self._scope))
for row in stuck:
self._table.update({"uid": row["uid"], "status": "pending", **self._scope},
["uid", "owner_kind", "owner_id"])
self._table.update(
{"uid": row["uid"], "status": "pending", **self._scope},
["uid", "owner_kind", "owner_id"],
)
if stuck:
logger.info("Recovered %d task(s) stuck in running", len(stuck))
return len(stuck)
def due(self, now_iso: str) -> list[dict[str, Any]]:
rows = self._table.find(enabled=True, status="pending", **self._scope)
return [row for row in rows if row.get("next_run_at") and row["next_run_at"] <= now_iso]
return [
row
for row in rows
if row.get("next_run_at") and row["next_run_at"] <= now_iso
]