From 9c9c5b7daca94760f527f485c411a14fbad1aebe Mon Sep 17 00:00:00 2001 From: Timothy Allen Date: Fri, 2 Oct 2026 21:21:08 +0200 Subject: [PATCH] Load a job record that holds unknown fields A downgrade of Bindery no longer stops at the start. --- bindery/jobs.py | 6 ++++-- tests/test_jobs.py | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/bindery/jobs.py b/bindery/jobs.py index 970a28c..2575b03 100644 --- a/bindery/jobs.py +++ b/bindery/jobs.py @@ -4,7 +4,7 @@ import json import sqlite3 import uuid from collections import deque -from dataclasses import asdict, dataclass, field +from dataclasses import asdict, dataclass, field, fields from datetime import datetime, timedelta from enum import StrEnum from pathlib import Path @@ -104,7 +104,9 @@ class Job: @classmethod def from_record(cls, record: str) -> "Job": - d = json.loads(record) + # A record of a newer Bindery can hold fields that this one does not know. + known = {f.name for f in fields(cls)} + d = {k: v for k, v in json.loads(record).items() if k in known} d["mode"] = DownloadMode(d["mode"]) d["status"] = QueueStatus(d["status"]) d["created"] = datetime.fromisoformat(d["created"]) diff --git a/tests/test_jobs.py b/tests/test_jobs.py index c2d19aa..1fdcc9a 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -1,5 +1,6 @@ """The job queue: shared jobs, order, cancelling and the job history.""" +import json from datetime import datetime, timedelta from bindery import config @@ -167,3 +168,10 @@ def test_the_api_form_of_a_job_hides_the_path_of_an_upload(): job = Job(mode=DownloadMode.IMPORT_FILE, options={"path": "/config/uploads/x.epub", "name": "x.epub"}) assert job.to_dict()["options"] == {"name": "x.epub"} assert Job.from_record(job.to_record()).options == job.options + + +def test_a_record_of_a_newer_bindery_loads_without_its_unknown_fields(): + job = Job(mode=DownloadMode.NEW, story_id=3) + record = json.dumps({**json.loads(job.to_record()), "priority": 5}) + loaded = Job.from_record(record) + assert (loaded.id, loaded.story_id, loaded.mode) == (job.id, 3, DownloadMode.NEW)