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

1"""Streamlit workbench + headless API for scanpath visualization.""" 

2 

3from __future__ import annotations 

4 

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" 

44 

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) 

72 

73 

74def __getattr__(name: str): 

75 if name == "__version__": 

76 from .build_info import build_info 

77 

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 

83 

84 return getattr(api, name) 

85 if name in _DATASET_EXPORTS: 

86 from . import datasets 

87 

88 return getattr(datasets, name) 

89 if name in _EYEGENBENCH_EXPORTS: 

90 from . import eyegenbench 

91 

92 return getattr(eyegenbench, name) 

93 raise AttributeError(f"module {__name__!r} has no attribute {name!r}") 

94 

95 

96def __dir__() -> list: 

97 return sorted(set(globals()) | set(__all__)) 

98 

99 

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 

104 

105 _main()