Skip to content

config

App-wide configuration: a single, frozen Config tree loaded once and injected wherever configuration is needed.

tiargus.config

App-wide configuration for tiargus.

A single, frozen Config tree is loaded once from a unified config.yaml and injected wherever configuration is needed (reports, save-path resolution, and the argus watcher). Consumers take an optional config= parameter and fall back to the cached singleton via get_config, so default callers pass nothing while tests and the REPL pass an explicit object.

DEFAULT_WEIGHTS = {'Water': 1.0, 'Vols': 1.0, 'Metal': 1.0, 'Nobles': 5.0, 'Fissiles': 10.0} module-attribute

Default resource weights used to score hab sites in the site report.

Noble gases and fissiles are weighted higher to reflect their relative scarcity. Override any value via the site_report.weights mapping in config.yaml.

ArgusConfig dataclass

Runtime settings for the argus watcher (fleshed out in a later part).

Source code in src/tiargus/config.py
 92
 93
 94
 95
 96
 97
 98
 99
100
@dataclass(frozen=True)
class ArgusConfig:
    """Runtime settings for the argus watcher (fleshed out in a later part)."""

    interval: int = 30
    """Save-file polling interval, in seconds."""

    routines: dict = field(default_factory=dict)
    """Per-routine state; an opaque passthrough until routines are typed."""

interval = 30 class-attribute instance-attribute

Save-file polling interval, in seconds.

routines = field(default_factory=dict) class-attribute instance-attribute

Per-routine state; an opaque passthrough until routines are typed.

Config dataclass

The unified, app-wide configuration tree.

Source code in src/tiargus/config.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
@dataclass(frozen=True)
class Config:
    """The unified, app-wide configuration tree."""

    general: GeneralConfig = field(default_factory=GeneralConfig)
    site_report: SiteReportConfig = field(default_factory=SiteReportConfig)
    argus: ArgusConfig = field(default_factory=ArgusConfig)

    @classmethod
    def load(cls, path: str | Path | None = None) -> "Config":
        """Load configuration from a YAML file, falling back to defaults.

        A missing file yields an all-defaults ``Config``; no error is raised.

        Args:
            path: YAML file to read.  Defaults to
                [config_path][tiargus.config.config_path] when ``None``.
        """
        resolved = Path(path) if path is not None else config_path()
        if not resolved.is_file():
            return cls()
        try:
            with resolved.open() as f:
                data = yaml.safe_load(f)
        except (OSError, yaml.YAMLError):
            return cls()
        if not isinstance(data, dict):
            return cls()
        return cls._from_dict(data)

    @classmethod
    def _from_dict(cls, data: dict) -> "Config":
        data = _migrate_legacy(data)

        general = data.get("general") or {}
        site_report = data.get("site_report") or {}
        argus = data.get("argus") or {}

        weights = dict(DEFAULT_WEIGHTS)
        weights.update(_validate_weights(site_report.get("weights")))

        defaults = cls()
        return cls(
            general=GeneralConfig(save_path=general.get("save_path")),
            site_report=SiteReportConfig(
                weights=weights,
                monthly=site_report.get("monthly", defaults.site_report.monthly),
            ),
            argus=ArgusConfig(
                interval=argus.get("interval", defaults.argus.interval),
                routines=argus.get("routines") or {},
            ),
        )

    def save(self, path: str | Path | None = None) -> None:
        """Serialize this config to a YAML file in the unified layout.

        Args:
            path: Destination file.  Defaults to
                [config_path][tiargus.config.config_path] when ``None``.  The
                parent directory is created if it does not exist.
        """
        resolved = Path(path) if path is not None else config_path()
        resolved.parent.mkdir(parents=True, exist_ok=True)
        data = {
            "general": {"save_path": self.general.save_path},
            "site_report": {
                "weights": dict(self.site_report.weights),
                "monthly": self.site_report.monthly,
            },
            "argus": {
                "interval": self.argus.interval,
                "routines": dict(self.argus.routines),
            },
        }
        with resolved.open("w") as f:
            yaml.safe_dump(data, f, sort_keys=False)

load(path=None) classmethod

Load configuration from a YAML file, falling back to defaults.

A missing file yields an all-defaults Config; no error is raised.

Parameters:

Name Type Description Default
path str | Path | None

YAML file to read. Defaults to config_path when None.

None
Source code in src/tiargus/config.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
@classmethod
def load(cls, path: str | Path | None = None) -> "Config":
    """Load configuration from a YAML file, falling back to defaults.

    A missing file yields an all-defaults ``Config``; no error is raised.

    Args:
        path: YAML file to read.  Defaults to
            [config_path][tiargus.config.config_path] when ``None``.
    """
    resolved = Path(path) if path is not None else config_path()
    if not resolved.is_file():
        return cls()
    try:
        with resolved.open() as f:
            data = yaml.safe_load(f)
    except (OSError, yaml.YAMLError):
        return cls()
    if not isinstance(data, dict):
        return cls()
    return cls._from_dict(data)

save(path=None)

Serialize this config to a YAML file in the unified layout.

Parameters:

Name Type Description Default
path str | Path | None

Destination file. Defaults to config_path when None. The parent directory is created if it does not exist.

None
Source code in src/tiargus/config.py
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
def save(self, path: str | Path | None = None) -> None:
    """Serialize this config to a YAML file in the unified layout.

    Args:
        path: Destination file.  Defaults to
            [config_path][tiargus.config.config_path] when ``None``.  The
            parent directory is created if it does not exist.
    """
    resolved = Path(path) if path is not None else config_path()
    resolved.parent.mkdir(parents=True, exist_ok=True)
    data = {
        "general": {"save_path": self.general.save_path},
        "site_report": {
            "weights": dict(self.site_report.weights),
            "monthly": self.site_report.monthly,
        },
        "argus": {
            "interval": self.argus.interval,
            "routines": dict(self.argus.routines),
        },
    }
    with resolved.open("w") as f:
        yaml.safe_dump(data, f, sort_keys=False)

GeneralConfig dataclass

Top-level settings shared across tools.

Source code in src/tiargus/config.py
73
74
75
76
77
78
@dataclass(frozen=True)
class GeneralConfig:
    """Top-level settings shared across tools."""

    save_path: str | None = None
    """Explicit save-file path, or ``None`` to auto-detect the latest autosave."""

save_path = None class-attribute instance-attribute

Explicit save-file path, or None to auto-detect the latest autosave.

SiteReportConfig dataclass

Settings for the hab-site report.

Source code in src/tiargus/config.py
81
82
83
84
85
86
87
88
89
@dataclass(frozen=True)
class SiteReportConfig:
    """Settings for the hab-site report."""

    weights: dict[str, float] = field(default_factory=lambda: dict(DEFAULT_WEIGHTS))
    """Resource weights driving the score formula."""

    monthly: bool = True
    """When ``True``, resource income is shown monthly; ``False`` for daily."""

monthly = True class-attribute instance-attribute

When True, resource income is shown monthly; False for daily.

weights = field(default_factory=(lambda: dict(DEFAULT_WEIGHTS))) class-attribute instance-attribute

Resource weights driving the score formula.

config_dir()

Return the OS-appropriate user config directory for tiargus.

Source code in src/tiargus/config.py
182
183
184
def config_dir() -> Path:
    """Return the OS-appropriate user config directory for tiargus."""
    return Path(platformdirs.user_config_dir("tiargus"))

config_path()

Return the path to the user's config.yaml.

The TIARGUS_CONFIG environment variable, when set, overrides the default location (config_dir/config.yaml).

Source code in src/tiargus/config.py
187
188
189
190
191
192
193
194
195
196
def config_path() -> Path:
    """Return the path to the user's ``config.yaml``.

    The ``TIARGUS_CONFIG`` environment variable, when set, overrides the
    default location ([config_dir][tiargus.config.config_dir]``/config.yaml``).
    """
    env = os.environ.get("TIARGUS_CONFIG")
    if env:
        return Path(env)
    return config_dir() / "config.yaml"

get_config()

Return the cached app-wide config, loading it once on first call.

Source code in src/tiargus/config.py
202
203
204
205
206
207
def get_config() -> Config:
    """Return the cached app-wide config, loading it once on first call."""
    global _config
    if _config is None:
        _config = Config.load()
    return _config

reset_config()

Clear the cached config so the next get_config reloads from disk (a test seam).

Source code in src/tiargus/config.py
216
217
218
219
220
def reset_config() -> None:
    """Clear the cached config so the next [get_config][tiargus.config.get_config]
    reloads from disk (a test seam)."""
    global _config
    _config = None

set_config(cfg)

Replace the cached config (a test/REPL seam).

Source code in src/tiargus/config.py
210
211
212
213
def set_config(cfg: Config) -> None:
    """Replace the cached config (a test/REPL seam)."""
    global _config
    _config = cfg