93 lines
3.3 KiB
Python
93 lines
3.3 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import os
|
|
from pathlib import Path
|
|
from types import ModuleType
|
|
|
|
|
|
def _user_config_path() -> Path | None:
|
|
explicit = os.environ.get("COPIENATOR_CONFIG", "").strip()
|
|
if explicit:
|
|
return Path(explicit).expanduser().resolve()
|
|
local = Path.cwd() / "config.py"
|
|
return local.resolve() if local.is_file() else None
|
|
|
|
|
|
def _load_user_config(path: Path) -> ModuleType:
|
|
if not path.is_file():
|
|
raise FileNotFoundError(f"Copienator configuration not found: {path}")
|
|
spec = importlib.util.spec_from_file_location("_copienator_user_config", path)
|
|
if spec is None or spec.loader is None:
|
|
raise ImportError(f"Could not load Copienator configuration: {path}")
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def _settings(path: Path | None) -> dict[str, object]:
|
|
import default_config
|
|
|
|
values = {
|
|
name: getattr(default_config, name)
|
|
for name in dir(default_config)
|
|
if not name.startswith("_")
|
|
}
|
|
if path is not None:
|
|
# Preserve compatibility defaults for older personal configurations.
|
|
values.update(THINKING_LEVEL_FOR_LABEL="medium", THINKING_LEVEL_PRO="high")
|
|
module = _load_user_config(path)
|
|
values.update({
|
|
name: getattr(module, name)
|
|
for name in dir(module)
|
|
if not name.startswith("_")
|
|
})
|
|
# Historically the name recognizer inherited the label model when omitted.
|
|
if not hasattr(module, "MODEL_FOR_NAME_ID"):
|
|
values["MODEL_FOR_NAME_ID"] = values["MODEL_FOR_LABEL_ID"]
|
|
values["PAGE_SPLITTER_KB"] = {
|
|
"reverse_pages": "i",
|
|
"add_secondary_splitter": "<Insert>",
|
|
"delete_secondary_splitter": "<Delete>",
|
|
**values["PAGE_SPLITTER_KB"],
|
|
}
|
|
return values
|
|
|
|
|
|
CONFIG_PATH = _user_config_path()
|
|
_global_settings = _settings(CONFIG_PATH)
|
|
globals().update(_global_settings)
|
|
LOCAL_CONFIG_PATH: Path | None = None
|
|
_evaluation_overrides: set[str] = set()
|
|
|
|
|
|
def use_evaluation(root: str | Path | None) -> None:
|
|
"""Apply selected evaluation settings, resetting any previous overrides."""
|
|
global LOCAL_CONFIG_PATH, _evaluation_overrides
|
|
path = Path(root).expanduser().resolve() / "config.py" if root is not None else None
|
|
values = dict(_global_settings)
|
|
overrides = {}
|
|
if path is not None and path.is_file() and path != CONFIG_PATH:
|
|
module = _load_user_config(path)
|
|
overrides = {
|
|
name: getattr(module, name)
|
|
for name in dir(module)
|
|
if name.isupper() and name in _global_settings
|
|
}
|
|
values.update(overrides)
|
|
else:
|
|
path = None
|
|
for name in ("ANNOTATION_MAX_HEIGHT_PX", "ANNOTATION_MAX_PIXELS"):
|
|
if type(values[name]) is not int or values[name] <= 0:
|
|
raise ValueError(f"{name} must be a positive integer (pixels)")
|
|
values["PAGE_SPLITTER_KB"] = {
|
|
"reverse_pages": "i",
|
|
"add_secondary_splitter": "<Insert>",
|
|
"delete_secondary_splitter": "<Delete>",
|
|
**values["PAGE_SPLITTER_KB"],
|
|
}
|
|
for name in _evaluation_overrides | overrides.keys():
|
|
globals()[name] = values[name]
|
|
_evaluation_overrides = set(overrides)
|
|
LOCAL_CONFIG_PATH = path
|