Examples

The programs below are complete and runnable from a checkout with the project installed in .venv. Except for migration, they write to a distinct platform-specific per-user configuration directory, not to the source tree.

Run an example on Windows with:

.\.venv\Scripts\python.exe examples\basic_store.py

Basic storage

This example saves a mapping, loads a fresh copy, and prints the exact path. Running it again replaces the same example configuration.

 1"""Save and reload a small per-user configuration."""
 2
 3from upref import ConfigStore
 4
 5
 6store = ConfigStore("upref-basic-example")
 7
 8store.save(
 9    {
10        "theme": "dark",
11        "notifications": True,
12    }
13)
14
15config = store.load()
16print(config)
17print(f"Configuration saved to: {store.path}")

Defaults, update, and delete

Defaults are merged recursively in memory. The resolved mapping is then saved, selected changes are merged and persisted, and the example removes its file.

 1"""Combine defaults, persist selected changes, then clean up the example."""
 2
 3from upref import Config, ConfigStore
 4
 5
 6store = ConfigStore("upref-update-example")
 7
 8defaults: Config = {
 9    "network": {
10        "host": "localhost",
11        "port": 8080,
12    },
13    "notifications": True,
14}
15
16config = store.load(defaults=defaults)
17print("With defaults:", config)
18
19# Loading defaults does not write them. Save the resolved configuration when
20# the application wants those values to become persistent.
21store.save(config)
22
23updated = store.update(
24    {
25        "network": {"port": 9000},
26        "notifications": False,
27    }
28)
29print("Saved changes:", updated)
30
31print("Configuration removed:", store.delete())

Terminal collection

On the first run, missing values are requested in the terminal. Later runs reuse saved values. Cancelling before save leaves the existing file unchanged.

 1"""Ask only for missing values in a terminal, then save them explicitly."""
 2
 3from upref import ConfigStore, Field, PromptCancelled, collect
 4
 5
 6store = ConfigStore("upref-tty-example")
 7schema = {
 8    "service_url": Field(
 9        "Service URL",
10        description="For example: https://api.example.org",
11    ),
12    "timeout": Field(
13        "Timeout in seconds",
14        parser=int,
15        validator=lambda value: isinstance(value, int) and value > 0,
16    ),
17}
18
19try:
20    values = collect(
21        schema,
22        initial=store.load(),
23        interface="tty",
24        mode="missing",
25    )
26except PromptCancelled:
27    print("Input cancelled; the configuration was not changed.")
28else:
29    store.save(values)
30    print(f"Configuration saved to: {store.path}")

Migrating from v1

This program imports an existing historical file. Change LEGACY_NAME to the old configuration name. Migration leaves its source untouched and checks for an existing v2 target before saving. Concurrent migrations require an external lock.

 1"""Import values from an existing Upref v1 configuration."""
 2
 3from upref import ConfigStore, UprefError
 4
 5
 6LEGACY_NAME = "my_personnal_data"
 7store = ConfigStore("upref-migration-example")
 8
 9try:
10    migrated = store.import_legacy(LEGACY_NAME)
11except UprefError as error:
12    print(f"Migration was not performed: {error}")
13else:
14    print("Migrated keys:", ", ".join(sorted(migrated)))
15    print(f"New configuration: {store.path}")

Warning

Upref configuration files contain plain YAML. Masked interactive input is not encrypted storage; use a system keyring or secrets manager for passwords and tokens.