varve 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. varve-0.1.0/.github/workflows/ci.yml +53 -0
  2. varve-0.1.0/.github/workflows/release.yml +96 -0
  3. varve-0.1.0/.gitignore +6 -0
  4. varve-0.1.0/.pre-commit-config.yaml +9 -0
  5. varve-0.1.0/.release-please-manifest.json +3 -0
  6. varve-0.1.0/AGENTS.md +21 -0
  7. varve-0.1.0/ARCHITECTURE.md +107 -0
  8. varve-0.1.0/CHANGELOG.md +62 -0
  9. varve-0.1.0/CONTRIBUTING.md +37 -0
  10. varve-0.1.0/LICENSE +21 -0
  11. varve-0.1.0/PKG-INFO +193 -0
  12. varve-0.1.0/README.md +161 -0
  13. varve-0.1.0/pyproject.toml +67 -0
  14. varve-0.1.0/release-please-config.json +10 -0
  15. varve-0.1.0/src/varve/__init__.py +16 -0
  16. varve-0.1.0/src/varve/branch.py +92 -0
  17. varve-0.1.0/src/varve/branch_config.py +172 -0
  18. varve-0.1.0/src/varve/cli/app.py +297 -0
  19. varve-0.1.0/src/varve/cli/argmap.py +226 -0
  20. varve-0.1.0/src/varve/cli/clean.py +118 -0
  21. varve-0.1.0/src/varve/context.py +164 -0
  22. varve-0.1.0/src/varve/dashboard/cli.py +139 -0
  23. varve-0.1.0/src/varve/dashboard/discovery.py +89 -0
  24. varve-0.1.0/src/varve/dashboard/models.py +50 -0
  25. varve-0.1.0/src/varve/dashboard/render.py +136 -0
  26. varve-0.1.0/src/varve/dashboard/state.py +162 -0
  27. varve-0.1.0/src/varve/decorators.py +102 -0
  28. varve-0.1.0/src/varve/engine/runner.py +549 -0
  29. varve-0.1.0/src/varve/engine/state.py +114 -0
  30. varve-0.1.0/src/varve/keying/astkey.py +76 -0
  31. varve-0.1.0/src/varve/keying/fingerprint.py +106 -0
  32. varve-0.1.0/src/varve/keying/keys.py +258 -0
  33. varve-0.1.0/src/varve/keyspec.py +23 -0
  34. varve-0.1.0/src/varve/log.py +15 -0
  35. varve-0.1.0/src/varve/models.py +86 -0
  36. varve-0.1.0/src/varve/pipeline.py +127 -0
  37. varve-0.1.0/src/varve/py.typed +1 -0
  38. varve-0.1.0/src/varve/store/lock.py +79 -0
  39. varve-0.1.0/src/varve/store/store.py +143 -0
  40. varve-0.1.0/tests/test_argmap.py +194 -0
  41. varve-0.1.0/tests/test_astkey.py +56 -0
  42. varve-0.1.0/tests/test_branch.py +16 -0
  43. varve-0.1.0/tests/test_branch_config.py +55 -0
  44. varve-0.1.0/tests/test_clean.py +221 -0
  45. varve-0.1.0/tests/test_cli.py +640 -0
  46. varve-0.1.0/tests/test_collection.py +79 -0
  47. varve-0.1.0/tests/test_context.py +191 -0
  48. varve-0.1.0/tests/test_dashboard_cli.py +500 -0
  49. varve-0.1.0/tests/test_dashboard_discovery.py +145 -0
  50. varve-0.1.0/tests/test_dashboard_state.py +204 -0
  51. varve-0.1.0/tests/test_experiment.py +63 -0
  52. varve-0.1.0/tests/test_fingerprint.py +53 -0
  53. varve-0.1.0/tests/test_keys.py +411 -0
  54. varve-0.1.0/tests/test_lock.py +33 -0
  55. varve-0.1.0/tests/test_runner.py +451 -0
  56. varve-0.1.0/tests/test_runner_branch.py +70 -0
  57. varve-0.1.0/tests/test_runner_log.py +35 -0
  58. varve-0.1.0/tests/test_state.py +236 -0
  59. varve-0.1.0/tests/test_store.py +86 -0
  60. varve-0.1.0/uv.lock +508 -0
@@ -0,0 +1,53 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ${{ github.workflow }}-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ test:
18
+ name: Python ${{ matrix.python-version }}
19
+ runs-on: ubuntu-latest
20
+ strategy:
21
+ fail-fast: false
22
+ matrix:
23
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
24
+
25
+ steps:
26
+ - name: Check out repository
27
+ uses: actions/checkout@v6
28
+ with:
29
+ persist-credentials: false
30
+
31
+ - name: Set up Python
32
+ uses: actions/setup-python@v6
33
+ with:
34
+ python-version: ${{ matrix.python-version }}
35
+
36
+ - name: Set up uv
37
+ uses: astral-sh/setup-uv@v7
38
+
39
+ - name: Install dependencies
40
+ run: uv sync --extra dev
41
+
42
+ - name: Ruff lint
43
+ run: uv run ruff check .
44
+
45
+ - name: Ruff format
46
+ run: uv run ruff format --check .
47
+
48
+ - name: Tests
49
+ run: uv run pytest
50
+
51
+ - name: Pyright pre-flight
52
+ continue-on-error: true
53
+ run: uv run pyright
@@ -0,0 +1,96 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ${{ github.workflow }}-${{ github.ref }}
14
+ cancel-in-progress: false
15
+
16
+ jobs:
17
+ release-please:
18
+ name: Release PR
19
+ runs-on: ubuntu-latest
20
+ if: github.event_name == 'push'
21
+ permissions:
22
+ contents: write
23
+ issues: write
24
+ pull-requests: write
25
+ outputs:
26
+ release_created: ${{ steps.release.outputs.release_created }}
27
+ tag_name: ${{ steps.release.outputs.tag_name }}
28
+ version: ${{ steps.release.outputs.version }}
29
+
30
+ steps:
31
+ - name: Create or finalize release PR
32
+ id: release
33
+ uses: googleapis/release-please-action@v4
34
+ with:
35
+ token: ${{ secrets.RELEASE_PLEASE_TOKEN || github.token }}
36
+ config-file: release-please-config.json
37
+ manifest-file: .release-please-manifest.json
38
+
39
+ build:
40
+ name: Build distribution
41
+ needs: release-please
42
+ if: ${{ always() && (github.event_name == 'workflow_dispatch' || needs.release-please.outputs.release_created == 'true') }}
43
+ runs-on: ubuntu-latest
44
+
45
+ steps:
46
+ - name: Check out repository
47
+ uses: actions/checkout@v6
48
+ with:
49
+ persist-credentials: false
50
+
51
+ - name: Set up Python
52
+ uses: actions/setup-python@v6
53
+ with:
54
+ python-version: "3.x"
55
+
56
+ - name: Set up uv
57
+ uses: astral-sh/setup-uv@v7
58
+
59
+ - name: Build source and wheel distributions
60
+ run: uv build --no-sources
61
+
62
+ - name: Smoke install from sdist
63
+ run: |
64
+ python -m venv /tmp/varve-smoke
65
+ /tmp/varve-smoke/bin/python -m pip install dist/*.tar.gz
66
+ /tmp/varve-smoke/bin/python -c "import varve; varve.Pipeline"
67
+
68
+ - name: Store distribution packages
69
+ uses: actions/upload-artifact@v5
70
+ with:
71
+ name: python-package-distributions
72
+ path: dist/
73
+
74
+ publish-to-pypi:
75
+ name: Publish to PyPI
76
+ needs:
77
+ - release-please
78
+ - build
79
+ runs-on: ubuntu-latest
80
+ if: needs.release-please.outputs.release_created == 'true'
81
+ environment:
82
+ name: pypi
83
+ url: https://pypi.org/p/varve
84
+ permissions:
85
+ contents: read
86
+ id-token: write
87
+
88
+ steps:
89
+ - name: Download distribution packages
90
+ uses: actions/download-artifact@v6
91
+ with:
92
+ name: python-package-distributions
93
+ path: dist/
94
+
95
+ - name: Publish distribution to PyPI
96
+ uses: pypa/gh-action-pypi-publish@release/v1
varve-0.1.0/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .venv/
2
+ .pytest_cache/
3
+ .ruff_cache/
4
+ __pycache__/
5
+ *.py[cod]
6
+
@@ -0,0 +1,9 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.14.5
4
+ hooks:
5
+ - id: ruff-check
6
+ types_or: [python, pyi]
7
+ args: [--fix]
8
+ - id: ruff-format
9
+ types_or: [python, pyi]
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.1.0"
3
+ }
varve-0.1.0/AGENTS.md ADDED
@@ -0,0 +1,21 @@
1
+ # AGENTS.md
2
+
3
+ ## Read First
4
+
5
+ - User-facing positioning and examples: `README.md`.
6
+ - Package layout, dependency direction, cache/store, CLI/config, clean, and dashboard boundaries: `ARCHITECTURE.md`.
7
+ - Contributor setup, public API policy, style, and Conventional Commits: `CONTRIBUTING.md`.
8
+
9
+ ## Agent Rules
10
+
11
+ `varve` is an independent Python infrastructure submodule. Documentation, comments, examples, and user-facing messages in this submodule must be English.
12
+
13
+ Keep the public import surface small:
14
+
15
+ ```python
16
+ from varve import Ctx, Pipeline, JSON, KeySpec, StageSpec, batch_stage, stage
17
+ ```
18
+
19
+ Prefer compact pre-1.0 APIs over compatibility shims. If an old public name is awkward and there are no external users, update current callers and docs instead of keeping deprecated aliases.
20
+
21
+ When changing author-facing behavior, update `README.md` and `ARCHITECTURE.md` in the same change. Release/version/changelog design lives in the workspace spec, not in this submodule.
@@ -0,0 +1,107 @@
1
+ # varve Architecture
2
+
3
+ `varve` is a small single-machine runner for Python-defined experiment pipelines with a materialized, content-addressed cache. Users define `Pipeline` classes and stages; varve owns branch-aware output roots, cache keys, store records, generated CLI commands, and clean/status behavior.
4
+
5
+ ## Package Layout
6
+
7
+ ```text
8
+ src/varve/
9
+ ├── __init__.py # public re-export surface
10
+ ├── pipeline.py # Pipeline base class, stage collection, CLI hook
11
+ ├── decorators.py # @stage, @batch_stage, StageSpec
12
+ ├── context.py # Ctx passed to stage methods
13
+ ├── branch.py # varve.yaml and override branch helpers
14
+ ├── branch_config.py # Config construction and output-root selection
15
+ ├── keyspec.py # JSON and KeySpec declarations
16
+ ├── models.py # persisted pydantic store models
17
+ ├── keying/ # source/file/config/upstream key components
18
+ ├── store/ # file lock and latest-wins Store
19
+ ├── engine/ # cache-state decisions and runner
20
+ ├── cli/ # generated Pipeline.cli() commands
21
+ └── dashboard/ # varve ls/show/refresh over existing stores
22
+ ```
23
+
24
+ ## Public Surface
25
+
26
+ Only these names are exported from `varve.__all__`:
27
+
28
+ ```python
29
+ from varve import Ctx, Pipeline, JSON, KeySpec, StageSpec, batch_stage, stage
30
+ ```
31
+
32
+ Everything else is internal unless this document or `README.md` says otherwise. `Store`, persisted models, keying helpers, runner helpers, and dashboard models may be used by internal code and tests through full module paths, but they are not public API.
33
+
34
+ ## Dependency Direction
35
+
36
+ - Low-level packages: `keying`, `store`, and `engine.state`. They depend only on leaf modules such as `models`, `log`, and `keyspec`.
37
+ - Middle layer: `branch_config` and `engine.runner`.
38
+ - Top layers: `cli` and `dashboard`.
39
+ - Public-facing modules such as `pipeline`, `decorators`, and `context` may use internals to keep the user API small.
40
+ - The only intentional reverse edge is the lazy import inside `Pipeline.cli()`: `from varve.cli.app import main`.
41
+
42
+ There is no import-direction tool. Keep the graph boring by review.
43
+
44
+ ## Cache And Store
45
+
46
+ The store lives under `<output_root>/.varve/` and is latest-wins, not append-only:
47
+
48
+ ```text
49
+ .varve/
50
+ ├── manifest.json
51
+ ├── lock
52
+ ├── stages/<stage>.json
53
+ ├── attempts/<stage>.json
54
+ └── partial/<stage>/<run_key>/
55
+ ```
56
+
57
+ `content_key` includes stage source, discovered project callables, full `Config`, declared `KeySpec.files`, declared `KeySpec.values`, and upstream content keys. `run_key` adds batch partition values.
58
+
59
+ Recorded artifact paths are output-root-relative. Stage bodies should write through `ctx.out`.
60
+
61
+ Stage bodies read upstream outputs through `ctx.input(stage)` for exactly one path or `ctx.inputs(stage)` for a list of paths. Both helpers require `stage` to be declared in the current stage's `needs=` list, because only declared upstreams are folded into the content key.
62
+
63
+ Known cache states are `dirty`, `hit`, `artifact-missing`, `stale`, `no-cache`, `resume`, and `unrecoverable`.
64
+
65
+ ## Output Roots And Branches
66
+
67
+ `Pipeline.default_output_root(config)` returns the base output root. The CLI can override that with `--out`. Varve then appends the selected branch:
68
+
69
+ ```text
70
+ base/<branch> # persistent branches
71
+ base/.tmp/<branch> # temporary override branches
72
+ ```
73
+
74
+ `varve.yaml` is discovered next to the pipeline module. Missing `varve.yaml` is allowed for `main`.
75
+
76
+ ## CLI And Config
77
+
78
+ `Pipeline.cli(argv)` delegates to `varve.cli.app.main` and provides `run`, `status`, `plan`, `list`, and `clean`.
79
+
80
+ `argparse` parses commands and generated `Args` flags. `pydantic-settings` builds semantic `Config` values from branch/override values, environment variables, `.env`, and model defaults.
81
+
82
+ Config priority:
83
+
84
+ ```text
85
+ branch or override value > env > dotenv (.env) > field default
86
+ ```
87
+
88
+ Do not add Click or Typer. The strict `argparse` behavior is intentional.
89
+
90
+ ## Clean Safety
91
+
92
+ All clean operations require a valid `.varve/manifest.json` anchor under the selected output root.
93
+
94
+ Full clean removes the whole output root after rejecting dangerous roots such as empty paths, `/`, the home directory, and the current working directory. Pipelines can narrow allowed full-clean roots by overriding `Pipeline.clean_roots(config)`.
95
+
96
+ Per-stage clean only deletes recorded artifacts and store records for the selected downstream closure. It does not use `allowed_roots`; its boundary is the manifest anchor plus recorded artifact paths.
97
+
98
+ ## Dashboard
99
+
100
+ The top-level `varve` console script reads existing stores.
101
+
102
+ Temporary branches under `out/.tmp` are filtered by default and included only with `--include-temp`. Discovery is zero-import; state rendering imports stored manifest modules only after discovery. `refresh` runs branches whose evaluated status is executable: `artifact-missing`, `dirty`, `no-cache`, `resume`, or `stale`.
103
+
104
+ ## Known Limitations
105
+
106
+ - Source fingerprints use `ast.dump`; a CPython minor-version upgrade may invalidate caches.
107
+ - Windows is not supported yet because locking uses `fcntl`.
@@ -0,0 +1,62 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-07-05)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * ctx.input now requires exactly one output; use ctx.inputs for upstream stages with zero or multiple outputs.
9
+ * rename Experiment to Pipeline
10
+ * removes file_set, __version__, the Ctx ledger alias, the corrupt-store status, KeySpec.coerce, and the top-level dashboard --include-temp compatibility path.
11
+ * **keying:** enable automatic source uses
12
+ * **dashboard:** evaluate status through engine
13
+ * **cli:** redesign generated commands
14
+ * **core:** rename branches.yaml to varve.yaml
15
+ * **core:** KeySpec.config is removed and the full Config now enters the content key; Experiment.output_root gained branch/is_temporary and resolve_output_root is gone; `--config` now points to branches.yaml and semantic flags are replaced by --branch/--override/--name.
16
+ * **cli:** own output root resolution
17
+
18
+ ### Features
19
+
20
+ * add file set key helper ([ab1046a](https://github.com/moeakwak/varve/commit/ab1046a069a354e5553717ce732272948d77235f))
21
+ * **cli:** own output root resolution ([04b93ff](https://github.com/moeakwak/varve/commit/04b93fff8a97f1315dc82dc6bad9924bc1ef2ea3))
22
+ * **cli:** redesign generated commands ([cf5b729](https://github.com/moeakwak/varve/commit/cf5b72941550defd09806e9d2e70d1fc9c1c6bb9))
23
+ * **cli:** support `refresh --prefix` ([adb2a06](https://github.com/moeakwak/varve/commit/adb2a06664ca44cf990f136d8feb3292018afa85))
24
+ * **cli:** support Literal/Enum choices, null, help, and lighter clean ([53879bf](https://github.com/moeakwak/varve/commit/53879bffda1daadeca809b63a85e02b22c2f6f9f))
25
+ * **context:** default tqdm progress bar for resumed batch stages ([62b33f2](https://github.com/moeakwak/varve/commit/62b33f21a8991befb604401e6833e4486a87148e))
26
+ * **core:** branch-scoped runs with Args/Config split and full-config keying ([13dfb0f](https://github.com/moeakwak/varve/commit/13dfb0f54a377bd5f11f468af8670fe33c6854ee))
27
+ * **dashboard:** add `refresh` command ([eebf01e](https://github.com/moeakwak/varve/commit/eebf01ebced024db197531f2bcdd33695c8b91c3))
28
+ * **dashboard:** add read-only store dashboard ([1f32834](https://github.com/moeakwak/varve/commit/1f32834b8f256c055135d9cc8e7230c17f4bd981))
29
+ * **dashboard:** evaluate status through engine ([c0df1b9](https://github.com/moeakwak/varve/commit/c0df1b9269c159e51e434254e1a5a67d87c329c3))
30
+ * **dashboard:** include temporary branches ([733673a](https://github.com/moeakwak/varve/commit/733673a30631c944479364ce312e8f3fbef0d7b5))
31
+ * **dashboard:** show persisted stage duration ([6ce520f](https://github.com/moeakwak/varve/commit/6ce520f45614c260a6ca2ed8360c601489d6f301))
32
+ * **keying:** enable automatic source uses ([2d05a8f](https://github.com/moeakwak/varve/commit/2d05a8f8d37fb0bf04cdeb3c86bc6f3f0cedc1e4))
33
+ * split upstream output helpers ([805cd7d](https://github.com/moeakwak/varve/commit/805cd7d8ab557e8031f4588c6655f3751909a605))
34
+
35
+
36
+ ### Bug Fixes
37
+
38
+ * **cli:** refresh executable dashboard stores ([024ce71](https://github.com/moeakwak/varve/commit/024ce719dcd3e243d62a27c5c0ae40485f4e8a07))
39
+ * **engine:** harden output-root path and lock handling ([d4c481d](https://github.com/moeakwak/varve/commit/d4c481d292bd70333d6753637cda44712c1b1ff4))
40
+ * **keying:** stabilize `__main__` helper labels ([96916ea](https://github.com/moeakwak/varve/commit/96916eab1af66c05841fd05a7a978f8d00f5250b))
41
+
42
+
43
+ ### Documentation
44
+
45
+ * sync docs with current behavior ([c9dcfb0](https://github.com/moeakwak/varve/commit/c9dcfb0df9fc1da777768ec5ddc02d4c0e11321c))
46
+
47
+
48
+ ### Code Refactoring
49
+
50
+ * **core:** rename branches.yaml to varve.yaml ([4b1a369](https://github.com/moeakwak/varve/commit/4b1a3692b3631a5120bd32f9e1584820f8637390))
51
+ * rename Experiment to Pipeline ([e994f79](https://github.com/moeakwak/varve/commit/e994f7955b011d39216fde5b5402891164a8e710))
52
+ * simplify varve surface and tests ([07649ba](https://github.com/moeakwak/varve/commit/07649ba03a6f5ec218e1a144a7e481ec0440d27e))
53
+
54
+ ## Changelog
55
+
56
+ All notable changes to this project will be documented in this file.
57
+
58
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
59
+
60
+ Varve is in the 0.x phase. Minor releases may include breaking API or store schema changes; read this changelog before upgrading.
61
+
62
+ Release entries are generated by release-please from Conventional Commits.
@@ -0,0 +1,37 @@
1
+ # Contributing
2
+
3
+ Varve is still alpha-stage. Keep changes small, tested, and easy to review.
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ uv sync --extra dev
9
+ uv run ruff check .
10
+ uv run ruff format --check .
11
+ uv run pytest
12
+ uv run pyright
13
+ ```
14
+
15
+ `pyright` is currently a pre-flight signal, not a blocking quality bar.
16
+
17
+ ## Public API
18
+
19
+ The public import surface is intentionally small:
20
+
21
+ ```python
22
+ from varve import Ctx, JSON, KeySpec, Pipeline, StageSpec, batch_stage, stage
23
+ ```
24
+
25
+ Do not re-export internal store, keying, runner, or dashboard types from `varve.__all__`. Treat public API and `.varve/` store schema changes as breaking.
26
+
27
+ ## Style
28
+
29
+ - User-facing docs, examples, comments, and messages are English.
30
+ - Follow the package boundaries in `ARCHITECTURE.md`.
31
+ - Do not add Click, Typer, import-linter, or release tooling beyond what is already documented.
32
+ - Use Conventional Commits: `<type>(<scope>)<!>: <subject>`.
33
+ - Append `!` for public API or store schema breaks.
34
+
35
+ ## Releases
36
+
37
+ Do not hand-edit versions or release changelog entries; release-please owns them.
varve-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bob Wang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
varve-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,193 @@
1
+ Metadata-Version: 2.4
2
+ Name: varve
3
+ Version: 0.1.0
4
+ Summary: A small Python library for experiment pipelines with code-aware materialized caching.
5
+ Project-URL: Repository, https://github.com/moeakwak/varve
6
+ Project-URL: Issues, https://github.com/moeakwak/varve/issues
7
+ Project-URL: Changelog, https://github.com/moeakwak/varve/blob/main/CHANGELOG.md
8
+ Author: Bob Wang
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: POSIX
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: pydantic-settings[yaml]>=2.0.0
24
+ Requires-Dist: pydantic>=2.0.0
25
+ Requires-Dist: rich>=13.0.0
26
+ Requires-Dist: tqdm>=4.66.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: pyright>=1.1.0; extra == 'dev'
29
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
30
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # varve
34
+
35
+ [![PyPI](https://img.shields.io/pypi/v/varve.svg)](https://pypi.org/project/varve/) [![License](https://img.shields.io/pypi/l/varve.svg)](LICENSE)
36
+
37
+ 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.
38
+
39
+ 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.
40
+
41
+ For the package layout, cache model, and edge-case behavior, see [ARCHITECTURE.md](ARCHITECTURE.md). For contribution guidance, see [CONTRIBUTING.md](CONTRIBUTING.md).
42
+
43
+ ## Quick start
44
+
45
+ ```python
46
+ from pydantic import BaseModel
47
+ from varve import Pipeline, stage
48
+
49
+
50
+ class Config(BaseModel):
51
+ seed: int = 1
52
+
53
+
54
+ class Demo(Pipeline):
55
+ Config = Config
56
+
57
+ @stage(produces="sample.txt")
58
+ def sample(self, ctx):
59
+ (ctx.out / "sample.txt").write_text(str(ctx.config.seed))
60
+
61
+
62
+ if __name__ == "__main__":
63
+ raise SystemExit(Demo.cli())
64
+ ```
65
+
66
+ Run the pipeline:
67
+
68
+ ```bash
69
+ python demo.py run
70
+ python demo.py status
71
+ python demo.py plan
72
+ python demo.py list
73
+ python demo.py clean --yes
74
+ ```
75
+
76
+ By default, outputs are written next to the pipeline module under `out/main/`. Use `--out PATH` to choose a different output base.
77
+
78
+ ## Batch stages
79
+
80
+ 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.
81
+
82
+ ```python
83
+ from pathlib import Path
84
+
85
+ from pydantic import BaseModel
86
+ from varve import Ctx, Pipeline, batch_stage, stage
87
+
88
+
89
+ class Config(BaseModel):
90
+ batch_size: int = 100
91
+
92
+
93
+ class Args(BaseModel):
94
+ progress: bool = True
95
+
96
+
97
+ class Demo(Pipeline):
98
+ Config = Config
99
+ Args = Args
100
+
101
+ @stage(produces="items.txt")
102
+ def prepare(self, ctx: Ctx[Config, Args]) -> None:
103
+ (ctx.out / "items.txt").write_text("alpha\nbeta\ngamma\n")
104
+
105
+ @batch_stage(needs="prepare", partition_key=("batch_size",))
106
+ async def process(self, ctx: Ctx[Config, Args]):
107
+ items = ctx.input("prepare").read_text().splitlines()
108
+ async for index, item in ctx.resume(items, progress=ctx.args.progress):
109
+ path = ctx.out / "parts" / f"{index:04d}.txt"
110
+ path.parent.mkdir(parents=True, exist_ok=True)
111
+ path.write_text(item.upper())
112
+ yield path
113
+
114
+ @stage(needs="process", produces="summary.txt")
115
+ def summarize(self, ctx: Ctx[Config, Args]) -> None:
116
+ parts = [path.read_text() for path in ctx.inputs("process")]
117
+ (ctx.out / "summary.txt").write_text("\n".join(parts))
118
+ ```
119
+
120
+ `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.
121
+
122
+ ## Why varve
123
+
124
+ 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.
125
+
126
+ 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.
127
+
128
+ The core design choices are:
129
+
130
+ - **Pipelines are Python code.** Stages are instance methods, dependencies are declared with `needs=`, and semantic configuration is a pydantic model.
131
+ - **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.
132
+ - **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.
133
+ - **Single machine, no service.** Varve uses an in-process runner and a file-system store. There is no daemon, database, or remote backend.
134
+
135
+ ## Features
136
+
137
+ - Public API: `Pipeline`, `@stage`, `@batch_stage`, `KeySpec`, `Ctx`, `JSON`, and `StageSpec`.
138
+ - Generated pipeline commands:
139
+ - `run [--branch NAME] [--override JSON] [--upto STAGE | --downstream STAGE] [--force] [--out PATH]`
140
+ - `status [--branch NAME] [--upto STAGE | --downstream STAGE] [--out PATH]`
141
+ - `plan [--upto STAGE | --downstream STAGE]`
142
+ - `list`
143
+ - `clean [--branch NAME] [--downstream STAGE] [--out PATH] [--yes]`
144
+ - `run`, `status`, and `clean` also accept generated flags from the pipeline's `Args` model.
145
+ - Cache states for hits, stale records, missing artifacts, dirty attempts, resumable batches, and unrecoverable partition changes.
146
+ - `ctx.input(...)`, `ctx.inputs(...)`, and `ctx.resume(...)` for stage bodies.
147
+ - `KeySpec.files` for pinning input file contents into the content key.
148
+
149
+ ## Branches
150
+
151
+ `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.
152
+
153
+ Varve resolves the output root from `--out` or `Pipeline.default_output_root(config)`, then appends the selected branch:
154
+
155
+ ```text
156
+ out/<branch> # persistent branches
157
+ out/.tmp/<branch> # temporary override branches
158
+ ```
159
+
160
+ 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`.
161
+
162
+ ## Dashboard
163
+
164
+ The top-level `varve` command discovers existing stores without requiring a custom dashboard entrypoint:
165
+
166
+ ```bash
167
+ varve ls [--root DIR] [--include-temp]
168
+ varve show <pipeline_id> [--root DIR] [--branch NAME] [--include-temp]
169
+ varve refresh [--root DIR] [--prefix MODULE_PREFIX] [--include-temp]
170
+ ```
171
+
172
+ Dashboard commands are secondary tooling. The primary interface remains each pipeline's generated CLI.
173
+
174
+ ## Platform support
175
+
176
+ Varve is currently Unix-only. The output-root lock uses `fcntl`, so Windows support requires a future lock implementation.
177
+
178
+ Source fingerprints use `ast.dump`. A CPython minor-version upgrade may invalidate stage source hashes and rebuild caches.
179
+
180
+ ## API stability
181
+
182
+ 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.
183
+
184
+ ## Non-goals
185
+
186
+ - Remote storage or data version control.
187
+ - Distributed scheduling or cluster execution.
188
+ - Workflow platform, server, or DAG visualization service.
189
+ - Cross-pipeline lineage or observability platform.
190
+
191
+ ## License
192
+
193
+ MIT. See [LICENSE](LICENSE).