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.