Manage assets and their versions.
stage is a lightweight asset validation and registration service built around a small Python API and a CLI.
- validates asset identifiers and version metadata
- stores records on disk
- supports loading assets from JSON while skipping invalid entries without halting the entire run
Stage models two core concepts:
- Asset: identified by
kindandname - Version: identified by
asset,department, andnumber
The service validates values using token rules and path templates defined in YAML configuration, then stores assets and versions in a filesystem-backed hierarchy.
Default examples:
- Asset path:
character/hero_01 - Version path:
character/hero_01/animation/1.json
uv pip install .uv pip install --editable ".[dev]"Stage uses two optional environment variables:
STAGE_STORE: root directory where assets and versions are storedSTAGE_CONFIG: directory containing customtemplates.yamlandtokens.yaml
If STAGE_STORE is not set, Stage defaults to a temporary directory under your system temp path.
export STAGE_STORE=/path/to/stage-storeAfter installation, the package exposes the stage command.
stage --helpYou can increase logging verbosity with:
stage --info ...
stage --debug ...
--infoand--debugare mutually exclusive.
stage add hero_01 characterExample output:
Created Asset character/hero_01
stage get hero_01 characterExample output:
Asset character/hero_01 found
If the asset does not exist:
Asset character/hero_01 missing
stage list
stage list --asset-type character
stage list --asset-name hero_01If matches are found, Stage prints each asset id. Otherwise:
No Assets found
stage versions add hero_01 character animation 1 activeExample output:
Created Version character/hero_01/animation/1.json
Valid status values are:
activeinactive
stage versions get hero_01 character animation 1Example output:
Version character/hero_01/animation/1.json found
If the version does not exist:
No Version found
stage versions list hero_01 character
stage versions list hero_01 character --department animation
stage versions list hero_01 character --status active
stage versions list hero_01 character --version 2If no versions match:
No Versions found
stage load /path/to/assets.jsonThe loader:
- parses a list of asset/version entries from JSON
- skips invalid entries while continuing the run
- stores contiguous version sequences
- warns when entries are malformed or versions are missing/skipped
If nothing valid is loaded:
No Assets loaded
[
{
"asset": {
"type": "character",
"name": "hero_01"
},
"department": "animation",
"version": 1,
"status": "active"
}
]The codebase is intentionally small and split into focused modules:
src/stage/resolver.py- loads YAML configuration
- validates token values
- resolves ids into filesystem paths
- iterates existing assets/versions from disk using template matching
src/stage/entities.py- base entity abstraction
- shared id/path/existence behavior
- generic discovery via
find(...)
src/stage/assets.py- asset domain object
- asset creation and version spawning
src/stage/versions.py- version domain object
- payload loading, active-state inspection, and filtered lookup
src/stage/_cli.py- Click-based user interface
- command orchestration and user-facing messaging
Stage currently uses a filesystem-backed persistence model:
- assets are directories
- versions are JSON files below their asset directory
This keeps the implementation lightweight while preserving a clean abstraction around ids, discovery, and validation.
Validation is driven by two config files in src/stage/_config/:
templates.yaml: maps logical object types to tokenized path templatestokens.yaml: defines accepted token values as lists or regex patterns
This makes the system easy to extend without rewriting path logic everywhere.
The service is designed to fail gracefully where appropriate:
- CLI commands surface user-facing failures via
click.ClickException - JSON bulk load skips malformed entries instead of aborting the entire import
- missing or invalid filter/status values produce explicit messages
The test suite covers:
- resolver config loading, token validation, and path iteration
- entity discovery and filesystem existence checks
- asset and version creation rules
- CLI success, empty-result, and error-message behavior
Run the tests with:
pytest -qThis package uses the following tooling:
- MyPy - static type checking
- PyTest - testing framework
- pytest-cov - coverage reporting
- Ruff - linting and formatting
- Semantic Versioning -
Major.Minor.Patch - UV - environment management
- Clone this repo and
cdinto it. - Create a virtual environment.
uv venv
- Activate the virtual environment.
# Windows .venv\Scripts\Activate.ps1 # Linux source .venv/bin/activate
- Install the package in editable mode with development dependencies.
uv pip install --editable ".[dev]" - Install pre-commit hooks.
pre-commit install
pytest -q
ruff check .
ruff format .
mypy srcPotential next steps include:
- a higher-level public Python API module for application consumers
- storage backend abstraction beyond filesystem persistence
- richer structured logging for load/validation events
- REST API support
- CI automation for linting, typing, and tests