varstore
Hierarchical variable store with optional recursive shell-style template rendering.
Formerly varmgr. The expand engine from the mrjk/python-expandvars fork is included as batteries (varstore.expand) — no separate expandvars install is required.
Table of Contents
- Goal
- Install
- Core concepts
- Quickstart
- Template rendering
- String-only expand API
- Inspection
- Migration from varmgr
- Development
- Running tests
- Release
Goal
varstore manages configuration variables across sources, scopes, and layers:
- Sources with numeric priority (
level, lower = higher priority) - Scopes listing sources and nested scopes
- Layers of key/value data per source
- Raw lookup (
StoreManager) vs rendered lookup (RenderableStoreManager) - Default template engine = shell expandvars (
$VAR/${VAR}); alternatepy_stringtemplateavailable
Install
Python 3.10+. Zero hard runtime dependencies beyond the stdlib.
pip install mrjk.varstore
Import as varstore:
from varstore import StoreManager, RenderableStoreManager, Source
Editable / from source:
mise trust && mise install
uv sync --all-groups
Core concepts
Sources
Named origins with optional priority level (lower = higher priority):
Source("app_cli", level=300, help="Application main CLI")
Source("app_defaults", level=999, help="Application defaults")
Scopes
Scopes list sources (and other scopes) to resolve against:
store.set_scopes({
"scope_app": ["app_cli", "app_env", "app_defaults"],
"scope_project": ["project_cli", "project_env", "project_defaults", "scope_app"],
})
Layers
Key/value payloads attached to a registered source:
store.set_layer("app_cli", {"app_name": "myapp", "debug": True})
Resolution APIs
StoreManager— raw storage:get_value/get_valuesreturn stored values as-is (templates are not expanded).RenderableStoreManager— same raw API, plusget_renderer(scope).render_var(...)/render_values(...)for expansion.
Quickstart
from varstore import StoreManager, Source
store = StoreManager()
store.add_sources([
Source("app_cli", level=300, help="Application main CLI"),
Source("app_env", level=300, help="Application environment variables"),
Source("app_defaults", level=999, help="Application defaults"),
])
store.set_scopes({
"scope_app": ["app_cli", "app_env", "app_defaults"],
})
store.set_layer("app_cli", {
"app_name": "myapp",
"debug": True,
})
app_name = store.get_value("app_name") # "myapp"
Template rendering
get_value always returns the raw stored value. Use a Renderer to expand templates.
from varstore import RenderableStoreManager, Source
store = RenderableStoreManager()
# ... add_sources / set_scopes ...
store.set_layer("project_env", {
"project_name": "myproject",
"env": "prod",
"stack_name": "${project_name}-${env}",
})
assert store.get_value("stack_name") == "${project_name}-${env}"
renderer = store.get_renderer(scope_name="scope_project")
assert renderer.render_var("stack_name") == "myproject-prod"
values = renderer.render_values()
Default engine is expandvars (shell-style). Alternate Python string.Template:
renderer = store.get_renderer(scope_name="scope_project", engine="py_stringtemplate")
Circular references raise TemplateRenderingCircularValueError. Undefined vars raise UndefinedVarError (customizable via render settings).
String-only expand API
For expansion without a store:
from varstore.expand import expand, expandvars, ExpandParser
expandvars("$HOME/bin")
expand("${FOO:-default}", environ={"FOO": "bar"})
ExpandParser(environ={"PATH": "/usr/bin"}).expand("$PATH:/opt/bin")
Inspection
store.show_sources_help()
layers = store.inspect_var("log_level", scope="scope_project")
names = store.get_source_names(scope="scope_stack")
value, report = renderer.render_var("stack_name", debug=True)
Migration from varmgr
| Before (varmgr) | After (varstore) |
|---|---|
from lib.store import ... |
from varstore import ... |
VarMgrError / VarMgrAppError / VarMgrUserError |
VarStoreError / VarStoreAppError / VarStoreUserError |
pip install git+...python-expandvars@develop |
not needed — engine is vendored |
Behavior of sources, scopes, layers, priority, and expand syntax is unchanged.
Development
mise trust && mise install
uv sync --all-groups
With mise activated, task and uv are on your PATH. After uv sync, project tools live in .venv.
task # list root tasks
task test_core # unit + coverage + lint (no docs)
task test # full CI gate (core + docs)
task fix_lint # auto-fix formatters
task docs # serve docs (Zensical)
More targets: cd ci && task, cd docs && task.
Running tests
task test_core
# or
uv run pytest
Release
./scripts/release.sh patch # bump, commit, tag
git push && git push --tags
Tag push v* triggers PyPI publish (configure Trusted Publishing / pypi environment). Docs: Zensical under docs/ (task docs).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mrjk_varstore-0.1.2.tar.gz.
File metadata
- Download URL: mrjk_varstore-0.1.2.tar.gz
- Upload date:
- Size: 26.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c7783ee0612d625bfba3994ac20d7945cfd7c4cf4bf84a2e4b1f9281f583a3d
|
|
| MD5 |
7707bf8f8e0c42047ef8eb03777a5f34
|
|
| BLAKE2b-256 |
8fca9184af2ffcfee93f173e2c54a66da563d96bf0dd06ce8d0eaded7dd7d7f6
|
File details
Details for the file mrjk_varstore-0.1.2-py3-none-any.whl.
File metadata
- Download URL: mrjk_varstore-0.1.2-py3-none-any.whl
- Upload date:
- Size: 26.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
713cb011c42a1bfb2d172559826fc7979954a7b2c23cfbed802cac425474d9fb
|
|
| MD5 |
f6094bba5eefb5efa377c378cc529f41
|
|
| BLAKE2b-256 |
be5014cdbc31d6ed8f33ea3726778cfd2f34f73689610fb3bb64a7436176a0b6
|