| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- """Regression test for the print-queue path of the #1397 force-timelapse fix.
- The first round of #1397 only wired the override into ``background_dispatch.py``,
- which covers Print Now / Reprint Now flows. The print *queue* uses a separate
- scheduler at ``print_scheduler.py:_start_print`` that calls
- ``printer_manager.start_print`` directly — and the first attempt skipped that
- call site, so queued prints' timelapse setting passed through unchanged and
- the finish-photo path had nothing to draw from. Field-test caught this when
- Martin queued two prints (H2D + X1C); neither got a forced timelapse and
- ``archive.bambuddy_forced_timelapse`` stayed False on both.
- This test pins the wiring at the source level: the helper is imported AND
- its return value is what ``start_print(timelapse=...)`` receives. We can't
- exercise the full ``_start_print`` method without standing up a real DB +
- printer_manager + ams_assignment fixture stack, but the structural assert
- is enough to catch regression at the dispatch hook.
- """
- import ast
- from pathlib import Path
- SCHEDULER_PATH = Path(__file__).resolve().parent.parent.parent / "app" / "services" / "print_scheduler.py"
- def _find_call_to_start_print(tree: ast.AST) -> ast.Call:
- """Walk the AST and return the printer_manager.start_print(...) Call node
- inside _start_print. Should be exactly one."""
- for node in ast.walk(tree):
- if not isinstance(node, ast.Call):
- continue
- func = node.func
- if not isinstance(func, ast.Attribute):
- continue
- if func.attr != "start_print":
- continue
- value = func.value
- if not isinstance(value, ast.Name) or value.id != "printer_manager":
- continue
- return node
- raise AssertionError("Could not find printer_manager.start_print(...) call in print_scheduler.py")
- def test_start_print_timelapse_kwarg_uses_resolved_value():
- """``timelapse=`` kwarg passed to start_print must reference
- ``effective_timelapse`` (the resolved value) — not ``item.timelapse``
- (the user's raw choice). If a refactor drops the resolver call and
- restores ``item.timelapse``, this test fails."""
- source = SCHEDULER_PATH.read_text()
- tree = ast.parse(source)
- call = _find_call_to_start_print(tree)
- timelapse_kw = next((kw for kw in call.keywords if kw.arg == "timelapse"), None)
- assert timelapse_kw is not None, "start_print(timelapse=...) kwarg is missing"
- # The value must be the resolved variable, not item.timelapse.
- value = timelapse_kw.value
- assert isinstance(value, ast.Name) and value.id == "effective_timelapse", (
- f"timelapse= must be the resolver's return value (effective_timelapse), "
- f"got {ast.dump(value)}. The queue path must apply the same #1397 "
- f"override as background_dispatch.py — otherwise queued prints' "
- f"finish-photo extractor has nothing to pull from."
- )
- def test_scheduler_imports_resolve_effective_timelapse():
- """The import must exist somewhere in print_scheduler.py — guards against
- a future refactor removing it and falling back to item.timelapse."""
- source = SCHEDULER_PATH.read_text()
- assert "from backend.app.services.background_dispatch import resolve_effective_timelapse" in source, (
- "print_scheduler.py must import resolve_effective_timelapse from background_dispatch"
- )
|