diff --git a/src/openadapt_viewer/recording_db.py b/src/openadapt_viewer/recording_db.py index 699c20f..d108322 100644 --- a/src/openadapt_viewer/recording_db.py +++ b/src/openadapt_viewer/recording_db.py @@ -55,7 +55,14 @@ class LegacyCaptureError(FileNotFoundError): A subclass of ``FileNotFoundError`` because that is what the absence of a readable ``recording.db`` is, and because callers that only want to report - "this directory is not loadable" need no new except clause. + "this directory is not loadable" need no new except clause. The CLI's + top-level handler and the scanner's per-directory handler both rely on + that. + + The cost of the inheritance is that a caller which catches + ``FileNotFoundError`` to mean "try a different format" swallows this too, + and the message it carries is the only place the conversion command + appears. Such a caller must re-raise this class ahead of the broad clause. """ diff --git a/src/openadapt_viewer/viewers/benchmark/generator.py b/src/openadapt_viewer/viewers/benchmark/generator.py index f164a27..d2fdf4f 100644 --- a/src/openadapt_viewer/viewers/benchmark/generator.py +++ b/src/openadapt_viewer/viewers/benchmark/generator.py @@ -8,6 +8,7 @@ from openadapt_viewer.core.html_builder import HTMLBuilder from openadapt_viewer.core.types import BenchmarkRun +from openadapt_viewer.recording_db import LegacyCaptureError from openadapt_viewer.viewers.benchmark.data import create_sample_data, load_benchmark_data from openadapt_viewer.viewers.benchmark.real_data_loader import load_real_capture_data @@ -31,6 +32,10 @@ def generate_benchmark_html( Returns: Path to the generated HTML file + Raises: + LegacyCaptureError: If data_path holds a pre-2026-07-17 ``capture.db``. + The message names the conversion command. + POLICY: ALWAYS defaults to real data, from $OPENADAPT_CAPTURE_RECORDING. Set use_real_data=False ONLY for unit tests with sample data. """ @@ -41,6 +46,14 @@ def generate_benchmark_html( # Try to load as capture directory first, fall back to benchmark data try: run = load_real_capture_data(data_path) + except LegacyCaptureError: + # Re-raised ahead of the fallback because it is a subclass of + # FileNotFoundError and the fallback would otherwise swallow it. + # This directory is a recording, not a benchmark result directory, + # and load_benchmark_data reads it as an empty one: the user got + # "Generated: ..." and a viewer holding zero tasks, while the + # conversion command sat unread in this exception. + raise except (FileNotFoundError, ValueError, KeyError): # Fall back to benchmark data format run = load_benchmark_data(data_path) diff --git a/src/openadapt_viewer/viewers/capture/generator.py b/src/openadapt_viewer/viewers/capture/generator.py index 6ffb0f8..6b5d28e 100644 --- a/src/openadapt_viewer/viewers/capture/generator.py +++ b/src/openadapt_viewer/viewers/capture/generator.py @@ -7,6 +7,7 @@ from __future__ import annotations import json +from importlib import resources from pathlib import Path from typing import Any @@ -89,12 +90,15 @@ def _generate_viewer_html( Capture Viewer - {capture_id} - - + + @@ -401,6 +405,50 @@ def _generate_viewer_html( """ +def _read_package_asset(package: str, name: str) -> str: + """Return the text of a file that ships inside the installed package. + + The generated page is one file the user can move anywhere, so its stylesheet + and its script are inlined rather than linked. A ```` or ``" not in html_content or "<script>" in html_content assert "