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 9SSC_CONFIG_PATH = os.path.expanduser("~/.local/share/wuenlp-tools/ssc_config.json") 10PROJECT_SSC_CONFIG_CANDIDATES = ( 11 ".wuenlp_ssc_config.json", 12 "wuenlp_ssc_config.json", 13) 14 15# JSON keys in ssc_config.json / project config (values are absolute paths). 16SSC_REPO_ROOT_KEY = "ssc_repo_root" 17SSC_SCENE_MODEL_PATH_KEY = "scene_model_path" 18SSC_SUSPENSE_MODEL_ROOT_KEY = "suspense_model_root" 19 20_ENV_BY_KEY = { 21 SSC_REPO_ROOT_KEY: "SSC_REPO_ROOT", 22 SSC_SCENE_MODEL_PATH_KEY: "SSC_SCENE_MODEL_PATH", 23 SSC_SUSPENSE_MODEL_ROOT_KEY: "SSC_SUSPENSE_MODEL_ROOT", 24} 25 26__all__ = [ 27 "SSC_CONFIG_PATH", 28 "PROJECT_SSC_CONFIG_CANDIDATES", 29 "read_ssc_config", 30 "write_ssc_config", 31 "get_ssc_repo_root", 32 "get_ssc_scene_model_path", 33 "get_ssc_suspense_model_root", 34] 35 36 37def read_ssc_config() -> dict[str, Any]: 38 """Read merged SSC config: user file, then project file in cwd (project wins).""" 39 merged: dict[str, Any] = {} 40 if os.path.isfile(SSC_CONFIG_PATH): 41 try: 42 with open(SSC_CONFIG_PATH, encoding="utf-8") as f: 43 merged.update(json.load(f)) 44 except json.JSONDecodeError: 45 pass 46 for filename in PROJECT_SSC_CONFIG_CANDIDATES: 47 candidate = os.path.join(os.getcwd(), filename) 48 if os.path.isfile(candidate): 49 try: 50 with open(candidate, encoding="utf-8") as f: 51 merged.update(json.load(f)) 52 except json.JSONDecodeError: 53 pass 54 break 55 return merged 56 57 58def write_ssc_config(config: dict[str, Any]) -> None: 59 os.makedirs(os.path.dirname(SSC_CONFIG_PATH), exist_ok=True) 60 with open(SSC_CONFIG_PATH, "w", encoding="utf-8") as f: 61 json.dump(config, f, indent=2) 62 63 64def _require_ssc_path(key: str) -> str: 65 env_name = _ENV_BY_KEY[key] 66 if env_name in os.environ and os.environ[env_name].strip(): 67 return os.environ[env_name].strip() 68 value = read_ssc_config().get(key) 69 if value and str(value).strip(): 70 return str(value).strip() 71 raise RuntimeError( 72 f"SSC path {key!r} is not configured. " 73 f"Set environment variable {env_name} or add {key!r} to " 74 f"{SSC_CONFIG_PATH} (or a project {PROJECT_SSC_CONFIG_CANDIDATES[0]} file)." 75 ) 76 77 78def get_ssc_repo_root() -> str: 79 return _require_ssc_path(SSC_REPO_ROOT_KEY) 80 81 82def get_ssc_scene_model_path() -> str: 83 return _require_ssc_path(SSC_SCENE_MODEL_PATH_KEY) 84 85 86def get_ssc_suspense_model_root() -> str: 87 return _require_ssc_path(SSC_SUSPENSE_MODEL_ROOT_KEY)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
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.
38def read_ssc_config() -> dict[str, Any]: 39 """Read merged SSC config: user file, then project file in cwd (project wins).""" 40 merged: dict[str, Any] = {} 41 if os.path.isfile(SSC_CONFIG_PATH): 42 try: 43 with open(SSC_CONFIG_PATH, encoding="utf-8") as f: 44 merged.update(json.load(f)) 45 except json.JSONDecodeError: 46 pass 47 for filename in PROJECT_SSC_CONFIG_CANDIDATES: 48 candidate = os.path.join(os.getcwd(), filename) 49 if os.path.isfile(candidate): 50 try: 51 with open(candidate, encoding="utf-8") as f: 52 merged.update(json.load(f)) 53 except json.JSONDecodeError: 54 pass 55 break 56 return merged
Read merged SSC config: user file, then project file in cwd (project wins).