A small Python library for experiment pipelines with code-aware materialized caching.
Project description
varve
Varve is a small Python library for running experiment pipelines as code. Each stage is a Python method, the run/status/plan/list/clean CLI is generated for you, and every output is cached under a key derived automatically from your code, config, and pinned inputs, so re-runs only re-execute what actually changed. Single machine, no daemon, no pipeline YAML.
A varve is an annual layer of lake sediment: thin, ordered, and datable. This library uses the same idea for pipeline outputs: materialized layers whose keys record the code, config, inputs, and upstream layers that produced them.
For the package layout, cache model, and edge-case behavior, see ARCHITECTURE.md. For contribution guidance, see CONTRIBUTING.md.
Quick start
from pydantic import BaseModel
from varve import Pipeline, stage
class Config(BaseModel):
seed: int = 1
class Demo(Pipeline):
Config = Config
@stage(produces="sample.txt")
def sample(self, ctx):
(ctx.out / "sample.txt").write_text(str(ctx.config.seed))
if __name__ == "__main__":
raise SystemExit(Demo.cli())
Run the pipeline:
python demo.py run
python demo.py status
python demo.py plan
python demo.py list
python demo.py clean --yes
By default, outputs are written next to the pipeline module under out/main/. Use --out PATH to choose a different output base.
Batch stages
Use @batch_stage for resumable batch work. The stage iterates through ctx.resume(...), writes one or more files per item, and yields the paths it produced. If a run fails halfway through, the next run skips completed batch indexes and continues from the remaining items.
from pathlib import Path
from pydantic import BaseModel
from varve import Ctx, Pipeline, batch_stage, stage
class Config(BaseModel):
batch_size: int = 100
class Args(BaseModel):
progress: bool = True
class Demo(Pipeline):
Config = Config
Args = Args
@stage(produces="items.txt")
def prepare(self, ctx: Ctx[Config, Args]) -> None:
(ctx.out / "items.txt").write_text("alpha\nbeta\ngamma\n")
@batch_stage(needs="prepare", partition_key=("batch_size",))
async def process(self, ctx: Ctx[Config, Args]):
items = ctx.input("prepare").read_text().splitlines()
async for index, item in ctx.resume(items, progress=ctx.args.progress):
path = ctx.out / "parts" / f"{index:04d}.txt"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(item.upper())
yield path
@stage(needs="process", produces="summary.txt")
def summarize(self, ctx: Ctx[Config, Args]) -> None:
parts = [path.read_text() for path in ctx.inputs("process")]
(ctx.out / "summary.txt").write_text("\n".join(parts))
ctx.input("stage") returns exactly one upstream output path and fails if the stage produced zero or many paths. ctx.inputs("stage") always returns list[Path]. Both require the upstream stage to be declared in needs=, so the upstream content key is part of the downstream cache key.
Why varve
Varve is for research and data-analysis pipelines where Python code is already the best source of truth. It is intentionally closer to a small library such as redun, Hamilton, or pydoit than to a workflow platform.
Unlike DVC, varve is not data version control. Unlike Snakemake, it does not introduce a separate DSL. Unlike Prefect, Dagster, or Airflow, it has no scheduler service, worker fleet, or deployment model.
The core design choices are:
- Pipelines are Python code. Stages are instance methods, dependencies are declared with
needs=, and semantic configuration is a pydantic model. - Cache keys are code-aware by default. Varve fingerprints stage source, automatically discovered project callables, full Config values, declared input files, declared JSON values, and upstream content keys.
- Outputs are materialized. Successful stage records point at durable files under the output root, so missing artifacts are detected instead of silently treated as cache hits.
- Single machine, no service. Varve uses an in-process runner and a file-system store. There is no daemon, database, or remote backend.
Features
- Public API:
Pipeline,@stage,@batch_stage,KeySpec,Ctx,JSON, andStageSpec. - Generated pipeline commands:
run [--branch NAME] [--override JSON] [--upto STAGE | --downstream STAGE] [--force] [--out PATH]status [--branch NAME] [--upto STAGE | --downstream STAGE] [--out PATH]plan [--upto STAGE | --downstream STAGE]listclean [--branch NAME] [--downstream STAGE] [--out PATH] [--yes]
run,status, andcleanalso accept generated flags from the pipeline'sArgsmodel.- Cache states for hits, stale records, missing artifacts, dirty attempts, resumable batches, and unrecoverable partition changes.
ctx.input(...),ctx.inputs(...), andctx.resume(...)for stage bodies.KeySpec.filesfor pinning input file contents into the content key.
Branches
varve.yaml lives next to the pipeline module. The main branch is the default and may rely entirely on Config defaults when the file is missing.
Varve resolves the output root from --out or Pipeline.default_output_root(config), then appends the selected branch:
out/<branch> # persistent branches
out/.tmp/<branch> # temporary override branches
Use run --override '{"field": "value"}' to deep-merge JSON over main and create a temporary branch. status and clean locate that branch later with --branch NAME.
Dashboard
The top-level varve command discovers existing stores without requiring a custom dashboard entrypoint:
varve ls [--root DIR] [--include-temp]
varve show <pipeline_id> [--root DIR] [--branch NAME] [--include-temp]
varve refresh [--root DIR] [--prefix MODULE_PREFIX] [--include-temp]
Dashboard commands are secondary tooling. The primary interface remains each pipeline's generated CLI.
Platform support
Varve is currently Unix-only. The output-root lock uses fcntl, so Windows support requires a future lock implementation.
Source fingerprints use ast.dump. A CPython minor-version upgrade may invalidate stage source hashes and rebuild caches.
API stability
Varve follows SemVer, but 0.x releases are alpha releases. Minor releases may include breaking changes to the public API or to the .varve/ store schema. Read CHANGELOG.md before upgrading.
Non-goals
- Remote storage or data version control.
- Distributed scheduling or cluster execution.
- Workflow platform, server, or DAG visualization service.
- Cross-pipeline lineage or observability platform.
License
MIT. See LICENSE.
Project details
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 varve-0.1.0.tar.gz.
File metadata
- Download URL: varve-0.1.0.tar.gz
- Upload date:
- Size: 86.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
761f47aa57a8bdb225e3d908cfc82891121f6802ccc9f24505d4ed579f7d2cb2
|
|
| MD5 |
2f3daeccf2340f687a7d7bbf890928c0
|
|
| BLAKE2b-256 |
cdceb191ce7d7c94e2d60523fd1415adcd9454c1352aebdb2617ccaff2f9d73f
|
Provenance
The following attestation bundles were made for varve-0.1.0.tar.gz:
Publisher:
release.yml on moeakwak/varve
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
varve-0.1.0.tar.gz -
Subject digest:
761f47aa57a8bdb225e3d908cfc82891121f6802ccc9f24505d4ed579f7d2cb2 - Sigstore transparency entry: 2076388113
- Sigstore integration time:
-
Permalink:
moeakwak/varve@e8d4360d0afc8d2d7a99d26987090bea667993fa -
Branch / Tag:
refs/heads/main - Owner: https://github.com/moeakwak
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e8d4360d0afc8d2d7a99d26987090bea667993fa -
Trigger Event:
push
-
Statement type:
File details
Details for the file varve-0.1.0-py3-none-any.whl.
File metadata
- Download URL: varve-0.1.0-py3-none-any.whl
- Upload date:
- Size: 41.8 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 |
0c5b9495eb554acfdb0062f9f2ec87ed7d382aa4300a844530a2bb6bcf0d7381
|
|
| MD5 |
9907a97af9f9a667327dabb3fa34d38d
|
|
| BLAKE2b-256 |
0973c19bfca86816fac7d7b64ade59ca6b7361f54475298b4699a407144b9351
|
Provenance
The following attestation bundles were made for varve-0.1.0-py3-none-any.whl:
Publisher:
release.yml on moeakwak/varve
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
varve-0.1.0-py3-none-any.whl -
Subject digest:
0c5b9495eb554acfdb0062f9f2ec87ed7d382aa4300a844530a2bb6bcf0d7381 - Sigstore transparency entry: 2076388661
- Sigstore integration time:
-
Permalink:
moeakwak/varve@e8d4360d0afc8d2d7a99d26987090bea667993fa -
Branch / Tag:
refs/heads/main - Owner: https://github.com/moeakwak
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e8d4360d0afc8d2d7a99d26987090bea667993fa -
Trigger Event:
push
-
Statement type: