Sparse, scoped, multi-level property store with pluggable key mapping
Project description
vcti-properties
Sparse, scoped, multi-level property store with pluggable key mapping.
Overview
vcti-properties stores sparse named properties attached to entities or
collections, with optional layered resolution — a per-entity value that
falls back to a shared default. It spans the whole range from fixed metadata
(units, components, a creator — authoritative, rarely overridden) to overridable
properties (a plot's color, opacity, visibility — set as chart-wide defaults
and overridden per series). Both are just values addressed by a structured key.
Rather than a tangle of nested dictionaries, every property lives in one sparse store keyed by a flat string, and three concerns are kept cleanly separated:
- Authority — application-defined (system) properties vs. user-supplied ones, held in separate namespaces so they never collide. System names are drawn from a controlled vocabulary; user names are free-form.
- Locus — what a property is bound to: a specific entity (one column, element, node), or the whole collection.
- Resolution — a per-entity lookup can fall back to a shared default, so one value stands in for every entity that has not set its own.
Nothing here is dataset-specific: any set of entities — form fields, scene
objects, config sections — each carrying its own properties over shared
defaults, with system settings kept apart from user settings, fits the same
shape. The levels you declare encode the (authority, locus, name) parts
into one flat string key, so the store stays sparse (unset combinations cost
nothing) and lookups stay O(1). Pure standard library, zero runtime
dependencies.
Why not nested dicts or ChainMap?
Nested dictionaries — one level per authority, per entity, per name — mean a lot
of structure for little data, plus hand-rolled lookup repeated at every call
site. ChainMap gives you fallthrough for free, but you would need one dict per
(authority × locus) combination and must reassemble the chain per entity — the
layer count explodes with the number of entities. This package keeps the
unbounded axis (locus) in a flat key over one sparse dict, and reserves layered
fallthrough for the small, bounded axis where it belongs (see
Design & Concepts).
Installation
pip install vcti-properties
In pyproject.toml dependencies
dependencies = [
"vcti-properties>=1.0.0",
]
Quick Start
A store is defined by an ordered list of levels passed straight to
PropertyStore (it builds the key encoder for you). Each level is one part of
the key; the last level is the property name, and the value is stored
separately against the assembled key.
Here's a chart whose series are styled with chart-wide defaults that any series can override — exactly the overridable kind of value that is a property (unlike fixed metadata such as units or a creator):
from enum import StrEnum
from vcti.properties import PropertyStore, Level
class Style(StrEnum): # the plot properties we recognise
COLOR = "color"
OPACITY = "opacity"
VISIBLE = "visible"
chart = PropertyStore(
Level("series", sentinel="@"), # a specific series, or chart-wide (@)
Level("style", vocabulary=Style), # the property name
)
# Chart-wide defaults — apply to every series unless overridden:
chart.set(style=Style.COLOR, value="steelblue") # -> "@.color"
chart.set(style=Style.OPACITY, value=1.0)
chart.set(style=Style.VISIBLE, value=True)
# Per-series overrides:
chart.set(series="revenue", style=Style.COLOR, value="crimson")
chart.set(series="forecast", style=Style.OPACITY, value=0.4)
# resolve() = the series' own value, else the chart-wide default:
chart.resolve(series="revenue", style=Style.COLOR) # "crimson" (overridden)
chart.resolve(series="forecast", style=Style.COLOR) # "steelblue" (chart-wide default)
chart.resolve(series="forecast", style=Style.OPACITY) # 0.4 (overridden)
chart.get(series="forecast", style=Style.COLOR) # None (exact read, no fallback)
Add a system/user scope as one more level when the application's own defaults
must stay separate from a user's edits — system.* and user.* are distinct
namespaces that never collide (each resolves within itself):
from vcti.properties import PropertyStore, KeyScope, Level
chart = PropertyStore(
Level("scope", vocabulary=KeyScope), # application theme (system) vs. user edits (user)
Level("series", sentinel="@"),
Level("name"),
)
chart.set(scope=KeyScope.SYSTEM, name="color", value="steelblue") # "system.@.color"
chart.set(scope=KeyScope.USER, series="revenue", name="color", value="crimson") # "user.revenue.color"
With no levels, the store uses dot-joined paths (DefaultKeyMapper):
from vcti.properties import PropertyStore
store = PropertyStore() # or PropertyStore(separator="/")
store.set("user", "profile", value={"name": "Alice"}) # key "user.profile"
store.get("user", "profile") # {"name": "Alice"}
Key mappers
Passing levels to PropertyStore builds a KeyMapper — the codec that encodes
the (authority, locus, name) parts into a flat key and back. It's pluggable, so
one store serves every layout:
| Mapper | What it does |
|---|---|
DefaultKeyMapper |
Unstructured positional parts joined by a separator (a.b.c) — the default when no levels are given |
LeveledKeyMapper |
Structured named levels — built from the Levels you pass to PropertyStore |
Scenario-specific layouts (a system/user scoped key, a single-level config key)
are configurations of levels, not separate classes. For a bespoke scheme, pass
key_mapper= any object implementing parts_to_key(...) and key_to_parts(key).
See Extending.
Dependencies
None. Standard library only.
Project details
Release history Release notifications | RSS feed
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 vcti_properties-1.0.0.tar.gz.
File metadata
- Download URL: vcti_properties-1.0.0.tar.gz
- Upload date:
- Size: 16.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4bc2f5bcd7fc7fa101605ba0964d30c8495dd86fe2611f7a254cf3cfbfcd613
|
|
| MD5 |
42b82da7b43c9c00cb531c7e29fb4e95
|
|
| BLAKE2b-256 |
a5b8eed6a526a9fe0da85f3b1a9f5023fd02cf674a6cbe749db50e3c4cb27593
|
Provenance
The following attestation bundles were made for vcti_properties-1.0.0.tar.gz:
Publisher:
release.yml on vcollab/vcti-python-properties
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vcti_properties-1.0.0.tar.gz -
Subject digest:
c4bc2f5bcd7fc7fa101605ba0964d30c8495dd86fe2611f7a254cf3cfbfcd613 - Sigstore transparency entry: 2069995030
- Sigstore integration time:
-
Permalink:
vcollab/vcti-python-properties@0b0a152ed7647c2db03d0e4f5f82cfd64cf9d5a7 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/vcollab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0b0a152ed7647c2db03d0e4f5f82cfd64cf9d5a7 -
Trigger Event:
push
-
Statement type:
File details
Details for the file vcti_properties-1.0.0-py3-none-any.whl.
File metadata
- Download URL: vcti_properties-1.0.0-py3-none-any.whl
- Upload date:
- Size: 12.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a60f394c56896a78bb5bf78d55069f8cc0b30752adcc3b4c4069bf4c3e45a0ab
|
|
| MD5 |
18231e2d81d9bfcbe11306c343f1b5bc
|
|
| BLAKE2b-256 |
46bcc153849464cfb570ef79cf194bd045619e58ef694a19a370f41ace6faa1f
|
Provenance
The following attestation bundles were made for vcti_properties-1.0.0-py3-none-any.whl:
Publisher:
release.yml on vcollab/vcti-python-properties
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vcti_properties-1.0.0-py3-none-any.whl -
Subject digest:
a60f394c56896a78bb5bf78d55069f8cc0b30752adcc3b4c4069bf4c3e45a0ab - Sigstore transparency entry: 2069995246
- Sigstore integration time:
-
Permalink:
vcollab/vcti-python-properties@0b0a152ed7647c2db03d0e4f5f82cfd64cf9d5a7 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/vcollab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0b0a152ed7647c2db03d0e4f5f82cfd64cf9d5a7 -
Trigger Event:
push
-
Statement type: