Skip to main content
Yanked

This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Reason given by maintainers: moved to tgzr index

tgzr.contextual_settigs

Manage settings values in layers of operations.

Install

pip install tgzr.contextual_settigs

If you want to use the demo GUI: pip install tgzr.contextual_settigs[demo] See Running the Demo

Usage

There will be more store types in the future (FileStore, RESTStore, SqlStore, ...) But there's only MemoryStore for now.

Also, you'll be able to provide your own store implementations.

MemoryStore

The MemoryStore stores the config in memory. You need to populate it yourself.

from tgzr.contextual_settigs.stores.memory_store import MemoryStore

# Create the store
store = MemoryStore()

# Populate values to some contexts
store.set("BASE", "app.name", "my_app")
store.set("BASE", "app.title", "My App")
store.set("BASE", "app.version", "1.0")
store.set("BASE", "team", ["Alice", "Bob"])

store.set("DEV", "app.title", "My App (Dev)")
store.set("DEV", "app.version", "1.0+dev1")
store.append("DEV", "team", "Carol")

store.set("RC", "app.title", "My App (Release Candidat)")
store.set("RC", "app.version", "2.0rc1")
store.remove("RC", "team", "Bob")
store.append("RC", "team", "Dee")

Resolving Config

As Nested Dicts

Once the store is populated, you can retrieve the config for a given context:

base = store.get_context_dict(["BASE"])
assert base["app"]["name"] == "my_app"
assert base["app"]["title"] == "My App"
assert base["team"] == ["Alice", "Bob"]

dev = store.get_context_dict(["DEV"])
try:
    base["app"]["name"]
except KeyError as err:
    assert str(err) == "name"
assert dev["app"]["title"] == "My App (Dev)"
assert dev["team"] == ["Carol"]

Or for a list of stacked contexts:

conf_dev = store.get_context_dict(["BASE", "DEV"])
assert conf_dev["app"]["name"] == "my_app"
assert conf_dev["app"]["title"] == "My App (Dev)"
assert conf_dev["team"] == ["Alice", "Bob", "Carol"]

conf_rc = store.get_context_dict(["BASE", "RC"])
assert conf_rc["app"]["name"] == "my_app"
assert conf_rc["app"]["title"] == "My App (Release Candidat)"
assert conf_rc["team"] == ["Alice", "Dee"]

With History

if you want to inspect how the value was built, you can set the with_history arg to True. The returned dict will contain a __history__ key containing a dict with the same keys as previously, but each value for these key is a list of dict depicting the operation affecting the value:

config = store.get_context_dict(["BASE", "DEV"], with_history=True)
assert config["app"]["name"] == "my_app"
assert config["app"]["title"] == "My App (Dev)"
assert config["team"] == ["Alice", "Bob", "Carol"]
assert config["__history__"]["app"].get("name") is None
assert config["__history__"]["app"]["title"][0]["context_name"] == "DEV"
assert config["__history__"]["app"]["title"][0]["op_name"] == "Set"

The history list contain dicts with these keys:

  • context_name: the name of the context affecting the value
  • op_name: the name of the operation affecting the value
  • op: a string representation of the operation affecting the value

As Flat Dict

If you prefer to access your value without nested dict, you can use get_context_flat() (with or without history):

config = store.get_context_flat(["BASE", "DEV"])
assert config["app.name"] == "my_app"
assert config["app.title"] == "My App (Dev)"
assert config["team"] == ["Alice", "Bob", "Carol"]
assert config["__history__"].get("app.name") is None
assert config["__history__"]["app.title"][0]["context_name"] == "DEV"
assert config["__history__"]["app.title"][0]["op_name"] == "Set"

As Pydantic Models

You can get a config as an instance of a pydantic.BaseModel. This is usefull to coerce / validate the schema of the generated config, and also provide you with ✨code completion✨:

import pydantic

class AppSettings(pydantic.BaseModel):
    name: str | None = None
    title: str | None = None
    version: str | None = None

class Config(pydantic.BaseModel):
    app: AppSettings = AppSettings()
    team: list[str] = []

config = store.get_context(["BASE", "DEV"], Config)
assert config.app.name == "my_app"
assert config.app.title == "My App (Dev)"
assert config.team == ["Alice", "Bob", "Carol"]
Note: 
You cannot request the history when getting the context as a pydandic model.

Context name expansion

Environment Variables

You can use environment variable in the context names:

import os

os.environ['STAGE'] = 'PROD'

config_1 = store.get_context_dict(['defaults', '$STAGE'])
config_2 = store.get_context_dict(['defaults', 'PROD'])
assert config_1 == config_2

You can even nest environment variables:

import os

os.environ['FirstName'] = 'Guido'
os.environ['LastName'] = 'van Rossum'
os.environ['FullName'] = '$FirstName $LastName'

config_1 = store.get_context_dict(['$FullName'])
config_2 = store.get_context_dict(['Guido van Rossum'])
assert config_1 == config_2

Expand Path

When you manage context for a hierarchy of things, you often need to specify a context per level of that hierarchy. For example, with a hierarchy like:

'$project_name/teams/$team_name'

You'll probably want to use context names like:

['@project_name', '$project_name/teams', '$project_name/teams/$team_name']

to cumulate all the value set at each level of the hierarchy.

To generate this list, you can use the Expand Path notation. When a context name is enclosed with square brackets, the name will be treated as the path you want to expand:

config_1 = store.get_context_dict(['Base', '[$PROJ/Teams/$Team]', 'Last'])
config_2 = store.get_context_dict(
    ['Base', '$PROJ', '$PROJ/Teams', '$PROJ/Teams/$Team', 'Last']
)
assert config_1 == config_2

(Of course, environement variable will be reduced too)

Running the Demo

To run the Demo GUI, you must install with the demo extra:

pip install tgzr.contextual_settigs[demo]

And then, you can launch the demo with:

uv run tgzr_contextual_settings_demo

or, if you want to pass arguments to faspapi:

uv run -p 3.13 --extra demo fastapi dev ./src/tgzr/contextual_settigs/demo/app.py

This will open a browser window with the Demo GUI.

With docker

If you fancy it, you can build a docker image and run it.

From the root of the repository:

docker build -t tgzr-contextual_settigs-demo .
docker run -d --name contextual_settigs_demo -p 8083:8080 tgzr-contextual_settigs-demo

Implementation Checklist

  • MemoryStore
  • Basic set of operators
  • Get context as dict
  • Get context as flat dict
  • Get context as pydantic model
  • Support env var in context names
  • Support path expansion in context names
  • Get context with history
  • Rename *store -> *Conf ?
  • Support context info (color, type, ...)
  • [~] web UI
  • Update context with dict
  • Update context with flat dict
  • Update context with pydantic model
  • [~] Base models for collection of items
  • Validate context with pydantic model, report all error (for gui/inspection)
  • Refactor tests wiht pytest
  • test store.get_context* with path
  • Rest Service
  • desktop UI
  • Fancy operators
  • FileStore
  • SqlStore
  • RestStore
  • Support string templating in context name
  • Support env var in values
  • Support string templating in values

Metadata

Release files for tgzr.contextual_settings 0.100

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tgzr.contextual_settings 0.100
File Size Uploaded
tgzr_contextual_settings-0.100.tar.gz 662.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tgzr.contextual_settings 0.100
File Interpreter ABI Platform
tgzr_contextual_settings-0.100-py3-none-any.whl Python 3 none any Details

Total release size: 1.3 MB

Release files / tgzr_contextual_settings-0.100.tar.gz

Download URL tgzr_contextual_settings-0.100.tar.gz
Size 662.4 kB
Tags Source
SHA-256 checksum
How to use checksums
6126c975dcd3bed5c98045aca07e1d66137be0b9fe896497d8e16216906289e7
BLAKE2b-256 checksum
How to use checksums
db5e10aa78ad134b6373e2c3f2a9cb90fd0028c920cf6b7ed75eeb149f14f71b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"KDE neon","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / tgzr_contextual_settings-0.100-py3-none-any.whl

Download URL tgzr_contextual_settings-0.100-py3-none-any.whl
Size 675.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ef89c4ff49babe1405598d6b8cfd9fec7c491a0144b6030a42e92fc6f9f39946
BLAKE2b-256 checksum
How to use checksums
a3a4b28fb30d04e30cb40bea4f5063c6b171743ffd2cc471625804b639bf0213
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"KDE neon","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.100 This release

2 release files

0.0.12

2 release files

0.0.11

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page