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).
Metadata
Release files for mrjk.varstore 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mrjk_varstore-0.1.2.tar.gz | 26.5 kB | Without provenance | Details for mrjk_varstore-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mrjk_varstore-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for mrjk_varstore-0.1.2-py3-none-any.whl |
Total release size: 52.9 kB
Release files / mrjk_varstore-0.1.2.tar.gz
| Download URL | mrjk_varstore-0.1.2.tar.gz |
|---|---|
| Size | 26.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9c7783ee0612d625bfba3994ac20d7945cfd7c4cf4bf84a2e4b1f9281f583a3d
|
|
BLAKE2b-256 checksum How to use checksums |
8fca9184af2ffcfee93f173e2c54a66da563d96bf0dd06ce8d0eaded7dd7d7f6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|
Release files / mrjk_varstore-0.1.2-py3-none-any.whl
| Download URL | mrjk_varstore-0.1.2-py3-none-any.whl |
|---|---|
| Size | 26.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
713cb011c42a1bfb2d172559826fc7979954a7b2c23cfbed802cac425474d9fb
|
|
BLAKE2b-256 checksum How to use checksums |
be5014cdbc31d6ed8f33ea3726778cfd2f34f73689610fb3bb64a7436176a0b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|
Security for mrjk.varstore 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.