wuenlp_tools.ssc_config

SSC checkpoint and repo paths (user / project config, or environment variables).

 1"""SSC checkpoint and repo paths (user / project config, or environment variables)."""
 2
 3from __future__ import annotations
 4
 5import json
 6import os
 7from typing import Any
 8
 9from wuenlp_tools.utils import _UserPath
10
11SSC_CONFIG_PATH = _UserPath.home() / ".local/share/wuenlp-tools" / "ssc_config.json"
12PROJECT_SSC_CONFIG_CANDIDATES = (
13    ".wuenlp_ssc_config.json",
14    "wuenlp_ssc_config.json",
15)
16
17# JSON keys in ssc_config.json / project config (values are absolute paths).
18SSC_REPO_ROOT_KEY = "ssc_repo_root"
19SSC_SCENE_MODEL_PATH_KEY = "scene_model_path"
20SSC_SUSPENSE_MODEL_ROOT_KEY = "suspense_model_root"
21
22_ENV_BY_KEY = {
23    SSC_REPO_ROOT_KEY: "SSC_REPO_ROOT",
24    SSC_SCENE_MODEL_PATH_KEY: "SSC_SCENE_MODEL_PATH",
25    SSC_SUSPENSE_MODEL_ROOT_KEY: "SSC_SUSPENSE_MODEL_ROOT",
26}
27
28__all__ = [
29    "SSC_CONFIG_PATH",
30    "PROJECT_SSC_CONFIG_CANDIDATES",
31    "read_ssc_config",
32    "write_ssc_config",
33    "get_ssc_repo_root",
34    "get_ssc_scene_model_path",
35    "get_ssc_suspense_model_root",
36]
37
38
39def read_ssc_config() -> dict[str, Any]:
40    """Read merged SSC config: user file, then project file in cwd (project wins)."""
41    merged: dict[str, Any] = {}
42    if os.path.isfile(SSC_CONFIG_PATH):
43        try:
44            with open(SSC_CONFIG_PATH, encoding="utf-8") as f:
45                merged.update(json.load(f))
46        except json.JSONDecodeError:
47            pass
48    for filename in PROJECT_SSC_CONFIG_CANDIDATES:
49        candidate = os.path.join(os.getcwd(), filename)
50        if os.path.isfile(candidate):
51            try:
52                with open(candidate, encoding="utf-8") as f:
53                    merged.update(json.load(f))
54            except json.JSONDecodeError:
55                pass
56            break
57    return merged
58
59
60def write_ssc_config(config: dict[str, Any]) -> None:
61    os.makedirs(os.path.dirname(SSC_CONFIG_PATH), exist_ok=True)
62    with open(SSC_CONFIG_PATH, "w", encoding="utf-8") as f:
63        json.dump(config, f, indent=2)
64
65
66def _require_ssc_path(key: str) -> str:
67    env_name = _ENV_BY_KEY[key]
68    if env_name in os.environ and os.environ[env_name].strip():
69        return os.environ[env_name].strip()
70    value = read_ssc_config().get(key)
71    if value and str(value).strip():
72        return str(value).strip()
73    raise RuntimeError(
74        f"SSC path {key!r} is not configured. "
75        f"Set environment variable {env_name} or add {key!r} to "
76        f"{SSC_CONFIG_PATH} (or a project {PROJECT_SSC_CONFIG_CANDIDATES[0]} file)."
77    )
78
79
80def get_ssc_repo_root() -> str:
81    return _require_ssc_path(SSC_REPO_ROOT_KEY)
82
83
84def get_ssc_scene_model_path() -> str:
85    return _require_ssc_path(SSC_SCENE_MODEL_PATH_KEY)
86
87
88def get_ssc_suspense_model_root() -> str:
89    return _require_ssc_path(SSC_SUSPENSE_MODEL_ROOT_KEY)
SSC_CONFIG_PATH = PosixPath('~/.local/share/wuenlp-tools/ssc_config.json')

Path whose repr uses ~ instead of the expanded home directory.

PROJECT_SSC_CONFIG_CANDIDATES = ('.wuenlp_ssc_config.json', 'wuenlp_ssc_config.json')

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

def read_ssc_config() -> dict[str, typing.Any]:
40def read_ssc_config() -> dict[str, Any]:
41    """Read merged SSC config: user file, then project file in cwd (project wins)."""
42    merged: dict[str, Any] = {}
43    if os.path.isfile(SSC_CONFIG_PATH):
44        try:
45            with open(SSC_CONFIG_PATH, encoding="utf-8") as f:
46                merged.update(json.load(f))
47        except json.JSONDecodeError:
48            pass
49    for filename in PROJECT_SSC_CONFIG_CANDIDATES:
50        candidate = os.path.join(os.getcwd(), filename)
51        if os.path.isfile(candidate):
52            try:
53                with open(candidate, encoding="utf-8") as f:
54                    merged.update(json.load(f))
55            except json.JSONDecodeError:
56                pass
57            break
58    return merged

Read merged SSC config: user file, then project file in cwd (project wins).

def write_ssc_config(config: dict[str, typing.Any]) -> None:
61def write_ssc_config(config: dict[str, Any]) -> None:
62    os.makedirs(os.path.dirname(SSC_CONFIG_PATH), exist_ok=True)
63    with open(SSC_CONFIG_PATH, "w", encoding="utf-8") as f:
64        json.dump(config, f, indent=2)
def get_ssc_repo_root() -> str:
81def get_ssc_repo_root() -> str:
82    return _require_ssc_path(SSC_REPO_ROOT_KEY)
def get_ssc_scene_model_path() -> str:
85def get_ssc_scene_model_path() -> str:
86    return _require_ssc_path(SSC_SCENE_MODEL_PATH_KEY)
def get_ssc_suspense_model_root() -> str:
89def get_ssc_suspense_model_root() -> str:
90    return _require_ssc_path(SSC_SUSPENSE_MODEL_ROOT_KEY)