Coverage for scanpath_studio/__init__.py: 93%
27 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-07 21:10 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-07 21:10 +0000
1"""Streamlit workbench + headless API for scanpath visualization."""
3from __future__ import annotations
5__all__ = [
6 "ScanpathData",
7 "__version__",
8 "animate_scanpath",
9 "build_authored_scanpath",
10 "cache_status",
11 "check_data_health",
12 "check_for_updates",
13 "clear_cache",
14 "compare_scanpaths",
15 "figure_code",
16 "figure_options",
17 "list_parts",
18 "list_trials",
19 "load_authored_scanpath",
20 "load_onestop",
21 "load_participant_metadata",
22 "load_potec",
23 "load_raw_gaze",
24 "load_sample_data",
25 "load_sample_raw_gaze",
26 "load_scanpath_data",
27 "load_text_metadata",
28 "load_trial_metadata",
29 "main",
30 "plot_corpus_figure",
31 "plot_scanpath",
32 "propose_schema",
33 "render_parent_trial",
34 "save_figure",
35 "save_figure_layers",
36 "version_info",
37]
38# The release this tree descends from: the number `/release` bumps (with
39# CITATION.cff), `pyproject.toml` builds with, and publish.yml checks a tag
40# against. `__version__` is the exact build, worked out from it lazily
41# (build_info.py, #139) — "0.35.0" at the release itself,
42# "0.35.0.post3+g8f18219" three commits after it.
43__release__ = "0.37.1"
45# Public headless API (see api.py / datasets.py / eyegenbench.py). Resolved lazily so
46# `import scanpath_studio` stays cheap and doesn't pull in pandas/plotly/
47# streamlit until first use.
48# The MultiplEYE and benchmark-corpus loaders stay importable but are left out
49# of `__all__`: those corpora are held back from this release
50# (`constants.multipleye_enabled` / `benchmark_corpora_enabled`).
51# The app's own computed measures are held back the same way
52# (`constants.computed_measures_enabled`): importable, but not advertised —
53# they raise without SCANPATH_EXPERIMENTAL=1 (#374).
54_HELD_BACK_EXPORTS = frozenset(
55 {
56 "alignment_sensitivity",
57 "analysis_tables",
58 "compute_word_metrics",
59 "preprocess_data",
60 "reader_summary",
61 "trial_summary",
62 }
63)
64_DATASET_EXPORTS = frozenset({"load_potec", "load_multipleye", "load_onestop"})
65_EYEGENBENCH_EXPORTS = frozenset({"load_eyegenbench", "eyegenbench_datasets"})
66_API_EXPORTS = (
67 (frozenset(__all__) | _HELD_BACK_EXPORTS)
68 - {"__version__", "main"}
69 - _DATASET_EXPORTS
70 - _EYEGENBENCH_EXPORTS
71)
74def __getattr__(name: str):
75 if name == "__version__":
76 from .build_info import build_info
78 # Worked out once (it may run `git describe`), then a plain attribute.
79 globals()["__version__"] = build_info().version
80 return globals()["__version__"]
81 if name in _API_EXPORTS:
82 from . import api
84 return getattr(api, name)
85 if name in _DATASET_EXPORTS:
86 from . import datasets
88 return getattr(datasets, name)
89 if name in _EYEGENBENCH_EXPORTS:
90 from . import eyegenbench
92 return getattr(eyegenbench, name)
93 raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
96def __dir__() -> list:
97 return sorted(set(globals()) | set(__all__))
100def main() -> None:
101 """The app's Streamlit script body. To open the app, run `scanpath-studio`;
102 from Python, use the headless API instead."""
103 from .app import main as _main
105 _main()