Skip to content

Commit deb5108

Browse files
ConradMearnsclaude
andauthored
Add trunk-based CI/release pipeline + tag-driven versioning (#23)
* seeds: sync 2026-06-23 * Add Context environment + telemetry to the DIZZY generator Two optional top-level feat sections supply extra inputs to a function's context, declared once and referenced by name from procedures, policies, projections, and queriers: - environment: injected constants/variables (in place of os env), surfaced as context.env.<name>; shapes authored in def/environment.yaml. - telemetry: host-injected observation sinks (the emitters pattern, but for transport-only observation, never recorded as events), surfaced as context.telemetry.<name>(payload); shapes in def/telemetry.yaml. Folded into the existing pipeline: generate definitions scaffolds the two def files; generate static compiles them to gen_def/pydantic/{environment, telemetry}.py and threads optional env/telemetry fields into each function context via the shared generators/context_extras helper. No-op (byte- identical) when a function declares neither. Includes a new agent.feat.yaml fixture exercising all four function kinds, scaffold + context snapshots, loader normalization/validation, and CLI e2e. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Fix scaffold generators emitting invalid YAML for multi-line descriptions commands/events/models/queries rendered `description: {text}` inline, so a multi-line `|` block from the feat file produced unindented continuation lines — invalid YAML that broke `generate static`. Route them all through generators/yaml_util.description_lines, which emits a literal block scalar when the description spans multiple lines (single-line output unchanged). Closes dizzy-bb64. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * seeds: sync 2026-06-23 * working agent demo * examples/agent: streaming agent demo + slim to reactivity loop Build out the agent example as a runnable demo of the environment + telemetry context inputs, then slim it to a focused single-turn shape: - environment `llm` (model / api_key / base_url) injected in place of os.environ - two telemetry sinks: `stream_chunk` (per-token text delta, live) and `usage` (turn-level token counts, reported once) — kept separate because usage is a completion-time aggregate, not available per chunk - run_agent_turn implementation streams via the injected client, forwarding deltas to stream_chunk and reporting usage, then emits the durable events - demo.py is the host: in-memory event log, emit closures, injected llm config, and the two telemetry sinks; streams the reply to the CLI Removes the read side (get_conversation query, conversations model, and both projections) — unused by this single-turn demo, leaving a clean reactivity loop: send_message -> run_agent_turn -> user_message_sent / agent_replied. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add trunk-based CI/release pipeline, tag-driven versioning, docs - CI (`ci.yml`): pytest gates on PRs/main across py3.11-3.13; ruff lint/format and `ty` run as an advisory (non-required) `quality` job. - Release (`release.yml`): a `v*` tag builds sdist+wheel and cuts a GitHub Release with the artifacts attached. No package-index publishing for now. - Version is derived from git tags via hatch-vcs; `__init__` reads the build-time `_version.py` (gitignored) with an importlib fallback. - pyproject: release metadata (license/authors/classifiers/urls), ruff config (generated files excluded, B008 ignored for the Typer idiom), ruff + ty dev deps. - justfile: `lint`, `fmt`, `fmt-check`, `ci`, `build`, `examples-check` recipes. - CHANGELOG.md (Keep a Changelog) + CONTRIBUTING.md (trunk-based flow, gates, release). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Apply ruff lint + format cleanup Mechanical `ruff check --fix` + `ruff format` across hand-authored source and tests (generated schema files excluded), plus the few manual fixes ruff could not auto-apply: wrap over-long error strings, add `stacklevel` to the adapter warning, drop an unused test variable, and narrow a blind `Exception` to `ValidationError`. ruff now passes clean; the remaining advisory signal is ~30 `ty` diagnostics, tracked separately. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * changelog: document core DIZZY capabilities for 0.1.0 The Unreleased section described only the CI/release infra. Add the actual product surface (feature-file format, the generate pipeline, runtime targets, simulate/onboard/docs/config, worked examples) ahead of the tooling items, so the inaugural 0.1.0 changelog reflects what DIZZY does. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * seeds: sync 2026-06-25 --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent a4e540d commit deb5108

88 files changed

Lines changed: 2875 additions & 404 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main]
7+
8+
concurrency:
9+
group: ci-${{ github.ref }}
10+
cancel-in-progress: true
11+
12+
jobs:
13+
# The gate: tests must pass before merge. Mark this job (each matrix entry)
14+
# as a required status check in branch protection.
15+
test:
16+
name: test (py${{ matrix.python-version }})
17+
runs-on: ubuntu-latest
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
python-version: ["3.11", "3.12", "3.13"]
22+
steps:
23+
- uses: actions/checkout@v4
24+
with:
25+
# hatch-vcs needs full history + tags to compute the version.
26+
fetch-depth: 0
27+
- uses: astral-sh/setup-uv@v5
28+
with:
29+
enable-cache: true
30+
- run: uv sync --python ${{ matrix.python-version }}
31+
- run: uv run pytest
32+
33+
# Advisory: lint / format / type signal. NOT a required check, so it never
34+
# blocks a merge while these are being adopted across the codebase.
35+
quality:
36+
name: quality (advisory)
37+
runs-on: ubuntu-latest
38+
steps:
39+
- uses: actions/checkout@v4
40+
with:
41+
fetch-depth: 0
42+
- uses: astral-sh/setup-uv@v5
43+
with:
44+
enable-cache: true
45+
- run: uv sync
46+
- name: ruff lint
47+
run: uv run ruff check dizzy/src/dizzy dizzy/tests
48+
- name: ruff format check
49+
run: uv run ruff format --check dizzy/src/dizzy dizzy/tests
50+
- name: ty type check
51+
run: uv run ty check dizzy/src/dizzy dizzy/tests

.github/workflows/release.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Release
2+
3+
# Trunk-based: a release is just a version tag pushed to main.
4+
# git tag v0.2.0 && git push origin v0.2.0
5+
#
6+
# This builds the sdist + wheel and attaches them to a GitHub Release.
7+
# (Publishing to a package index is intentionally out of scope for now.)
8+
on:
9+
push:
10+
tags:
11+
- "v*"
12+
13+
jobs:
14+
release:
15+
name: build + GitHub Release
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: write
19+
steps:
20+
- uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 0
23+
- uses: astral-sh/setup-uv@v5
24+
- name: Verify tag matches package version
25+
run: |
26+
uv sync
27+
PKG="$(uv run python -c 'import dizzy; print(dizzy.__version__)')"
28+
TAG="${GITHUB_REF_NAME#v}"
29+
echo "tag=$TAG package=$PKG"
30+
test "$PKG" = "$TAG" || { echo "::error::tag $TAG != package version $PKG"; exit 1; }
31+
- run: rm -rf dist && uv build
32+
- name: Create release
33+
env:
34+
GH_TOKEN: ${{ github.token }}
35+
run: |
36+
gh release create "$GITHUB_REF_NAME" dist/* \
37+
--title "$GITHUB_REF_NAME" \
38+
--notes "See [CHANGELOG.md](https://github.com/PNNL/dizzy/blob/main/CHANGELOG.md)."

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ __pycache__/
33
.env
44
.vscode
55

6+
# Build / publish artifacts
7+
dist/
8+
build/
9+
*.egg-info/
10+
11+
# Generated at build time by hatch-vcs from the git tag
12+
dizzy/src/dizzy/_version.py
13+
614
# Generated lib/ workspace artifacts (regenerated by `uv sync`)
715
.venv/
816
examples/guestbook/lib/python-uv/uv.lock

.seeds/issues.jsonl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,13 @@
6868
{"id":"dizzy-ddb3","title":"dizzy drift: compare runtime traces to the feature-file; flag undeclared emissions/access/components","status":"open","type":"feature","priority":3,"createdAt":"2026-06-18T00:12:50.601Z","updatedAt":"2026-06-18T00:13:03.089Z","description":"v4. Requirements: docs/cli.md § dizzy drift. Compare runtime traces against the feature-file: undeclared event emissions, undeclared model access, components present in one but not the other. The feature-file as enforced contract, not documentation. Built in THIS repo.","labels":["roadmap"],"blockedBy":["dizzy-cb2f"]}
6969
{"id":"dizzy-bf28","title":"Align onboard/prime verbs with Seeds: rename dizzy onboard→prime, add onboard installer","status":"open","type":"task","priority":2,"createdAt":"2026-06-18T14:00:27.325Z","updatedAt":"2026-06-18T14:00:42.157Z","description":"## Problem\n`dizzy onboard` is misnamed. Comparing the three verbs:\n\n| Verb | Behavior | Mutates files? | Cadence |\n|------|----------|----------------|---------|\n| `sd onboard` | Writes/updates a Seeds section into CLAUDE.md/AGENTS.md (`--check`, `--stdout`) | YES — installer | Once per repo |\n| `sd prime` | Prints agent context (rules, command ref, workflow) to stdout | No | Every session / after compaction |\n| `dizzy onboard` | Prints an agent overview to stdout (components, feature-file role, change taxonomy, exemplars) | No | Read-first per session |\n\n`dizzy onboard` is read-only and per-session — its own doc (docs/onboard.md, docs/cli.md:94-101) even says \"Modeled on the seeds tool's `prime` verb.\" So it semantically IS `dizzy prime` wearing the wrong name. DIZZY currently has NO equivalent of `sd onboard` (the installer that injects a section into CLAUDE.md).\n\n## Recommendation — adopt the Seeds two-verb split\n1. Rename `dizzy onboard` → `dizzy prime` — the per-session context printer (it already is this).\n2. Reclaim `dizzy onboard` for the installer role it's missing: write a DIZZY section into CLAUDE.md/AGENTS.md (with `--check`/`--stdout`), like `sd onboard`.\n\nResult: same mental model agents already learn from Seeds — `onboard` = install once, `prime` = load each session.\n\n## Implementation notes / order (per CLAUDE.md conventions)\n- `onboard` is a SHIPPED command (docs/cli.md:25). Change scope in docs/cli.md FIRST, then seeds, then code.\n- Rename canonical doc dizzy/src/dizzy/docs/onboard.md → prime.md and update the `_print_doc(\"onboard.md\")` call (cli.py:398-401).\n- Keep a deprecation alias `onboard` → `prime` for a release for anything referencing the old name.\n- New `dizzy onboard` installer: write DIZZY section to CLAUDE.md/AGENTS.md, support `--check` and `--stdout`.\n\n## Minimal fallback\nIf renaming a shipped verb is too much churn now: just ADD `dizzy onboard` (installer) alongside the existing printer, and rename the printer to `prime` later. Downside: leaves the confusing semantics in place."}
7070
{"id":"dizzy-7609","title":"examples/recipes: chained PROV recipe workflow","status":"closed","type":"task","priority":2,"createdAt":"2026-06-18T14:38:47.244Z","updatedAt":"2026-06-18T14:51:24.894Z","closedAt":"2026-06-18T14:51:24.894Z"}
71+
{"id":"dizzy-d4b7","title":"Context Environment & Telemetry: inject constants and observation sinks into DIZZY function contexts","status":"open","type":"epic","priority":2,"createdAt":"2026-06-23T16:45:31.674Z","updatedAt":"2026-06-23T16:45:53.873Z","blocks":["dizzy-a701","dizzy-9745","dizzy-aa1d","dizzy-0983","dizzy-262a","dizzy-2686","dizzy-7e4e"]}
72+
{"id":"dizzy-a701","title":"feat schema + loader: environment/telemetry sections and per-function reference lists","status":"closed","type":"task","priority":2,"createdAt":"2026-06-23T16:45:52.821Z","updatedAt":"2026-06-23T16:47:36.103Z","description":"Add top-level environment/telemetry sections (EnvironmentDef/TelemetryDef, {name,description}) to def/feat.yaml; add environment/telemetry multivalued-string lists to Procedure/Policy/Projection/Querier(QueryDef). Regenerate feat_schema.py via just gen-feat-pydantic. Wire _SECTIONS normalization + cross-ref validation in feat_loader.py.","blockedBy":["dizzy-d4b7"],"blocks":["dizzy-9745","dizzy-aa1d"],"closedAt":"2026-06-23T16:47:36.103Z"}
73+
{"id":"dizzy-9745","title":"scaffold generators: def/environment.yaml + def/telemetry.yaml","status":"closed","type":"task","priority":2,"createdAt":"2026-06-23T16:45:52.895Z","updatedAt":"2026-06-23T16:48:49.927Z","description":"New generators/environment.py + generators/telemetry.py mirroring events.py: one LinkML class per entry, skip-if-exists. environment classes = injected constant shapes; telemetry classes = sink payload shapes.","blockedBy":["dizzy-d4b7"],"blocks":["dizzy-aa1d","dizzy-0983"],"closedAt":"2026-06-23T16:48:49.927Z"}
74+
{"id":"dizzy-aa1d","title":"context threading: env + telemetry fields into procedure/policy/projection/querier contexts","status":"closed","type":"task","priority":2,"createdAt":"2026-06-23T16:45:52.976Z","updatedAt":"2026-06-23T16:50:44.671Z","description":"Shared helper rendering <name>_env dataclass (fields typed by gen_def.pydantic.environment.<entry>) and <name>_telemetry dataclass (Callable[[Payload],None], emitters pattern, from gen_def.pydantic.telemetry.<entry>). Add optional env/telemetry fields to each context. Build+validate procedures first, then replicate to policies, projections, querier. No-op when lists empty.","blockedBy":["dizzy-d4b7"],"blocks":["dizzy-0983"],"closedAt":"2026-06-23T16:50:44.671Z"}
75+
{"id":"dizzy-0983","title":"CLI pipeline: fold env/telemetry scaffold + linkml compile into generate definitions/static","status":"closed","type":"task","priority":2,"createdAt":"2026-06-23T16:45:53.071Z","updatedAt":"2026-06-23T16:52:50.624Z","description":"def_cmd: write_scaffold_environment/telemetry when declared. gen(static): extend missing-stub guard, run_linkml_pydantic per entry into gen_def/pydantic/{environment,telemetry}/<name>.py.","blockedBy":["dizzy-d4b7"],"blocks":["dizzy-262a"],"closedAt":"2026-06-23T16:52:50.624Z"}
76+
{"id":"dizzy-262a","title":"tests: scaffold + context snapshots, loader validation, CLI e2e for env/telemetry","status":"closed","type":"task","priority":2,"createdAt":"2026-06-23T16:45:53.156Z","updatedAt":"2026-06-23T16:57:19.856Z","description":"Add env/telemetry to fixtures; new test_environment/test_telemetry; extend procedure/policy/projection/querier generator tests (with + without); loader normalization + negative cross-ref; CLI e2e asserts def/environment.yaml + def/telemetry.yaml written. just test + just check green.","blockedBy":["dizzy-d4b7"],"closedAt":"2026-06-23T16:57:19.856Z"}
77+
{"id":"dizzy-2686","title":"docs: authoring.md + SPECIFICATION.md for environment/telemetry (whitepaper deferred)","status":"closed","type":"task","priority":3,"createdAt":"2026-06-23T16:45:53.243Z","updatedAt":"2026-06-23T17:00:30.371Z","description":"Document the two top-level sections and per-function reference lists in authoring.md and SPECIFICATION.md. Whitepaper.typ prose deferred to a separate maintainer pass.","blockedBy":["dizzy-d4b7"],"closedAt":"2026-06-23T17:00:30.371Z"}
78+
{"id":"dizzy-7e4e","title":"follow-up: env/telemetry cross-runtime (rust-cargo, typescript-npm) in generate libraries","status":"open","type":"task","priority":3,"createdAt":"2026-06-23T16:45:53.314Z","updatedAt":"2026-06-23T16:45:53.873Z","description":"lib command currently only threads commands/events/models/queries to rust/ts linkml gen. Extend to environment/telemetry schema dirs + non-Python context emission.","blockedBy":["dizzy-d4b7"]}
79+
{"id":"dizzy-bb64","title":"scaffold generators emit invalid YAML for multi-line descriptions","status":"closed","type":"bug","priority":2,"createdAt":"2026-06-23T16:52:50.546Z","updatedAt":"2026-06-23T17:36:31.113Z","description":"commands.py, events.py, queries.py, models.py render 'description: {text}' inline; a multi-line | block from the feat file produces unindented continuation lines = invalid YAML (breaks generate static). Fixed in environment.py/telemetry.py via generators/yaml_util.description_lines; route the other scaffold generators through the same helper (will update their snapshots).","closedAt":"2026-06-23T17:36:31.113Z"}
80+
{"id":"dizzy-bb86","title":"Resolve ~30 ty type-check diagnostics (advisory CI)","status":"open","type":"task","priority":3,"createdAt":"2026-06-25T14:49:38.724Z","updatedAt":"2026-06-25T14:49:38.724Z","description":"The quality job in ci.yml runs ty as advisory. ~30 diagnostics remain across dizzy/src/dizzy and dizzy/tests (mostly Optional/None-sized access like config.policies[0] where the field is list|None). Fix these so the advisory quality job goes green; consider then promoting ty to a required check. Introduced alongside the CI/release pipeline (PR pnnl/dizzy#23)."}

CHANGELOG.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Changelog
2+
3+
All notable changes to this project are documented here.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
### Added
11+
- **Feature-file format** (`.feat.yaml`): a single artifact declaring a domain
12+
as commands, events, procedures, policies, projections, models, and queries —
13+
the reactivity loop (commands → procedures → events → policies) and the data
14+
loop (events → projections → models → queries).
15+
- **`dizzy generate`** — the three-stage pipeline from a feature-file:
16+
`definitions` (LinkML `def/` schema stubs), `static` (the `gen_def/` and
17+
`gen_int/` typed-contract packages), and `libraries` (per-runtime
18+
implementation-stub packages driven by `libconfig.yaml`).
19+
- **Runtime targets**: `python-uv` (most complete), plus experimental
20+
`rust-cargo` and `typescript-npm` generators; model adapters (e.g. `sqla`).
21+
- **`dizzy simulate`** — LLM-driven execution of a feature-file against a
22+
scenario (level 0).
23+
- **`dizzy onboard` / `docs` / `config`** — agent-facing project overview, the
24+
CLI + authoring documentation, and a config template.
25+
- **Worked examples**: a fully implemented, runnable `guestbook`, plus
26+
`recipes`, `library`, and `agent` feature-files.
27+
- Trunk-based CI (`ci.yml`): tests gate every PR; ruff lint/format and `ty`
28+
type checks run as advisory signal.
29+
- Tag-driven release pipeline (`release.yml`): a `v*` tag builds the sdist +
30+
wheel and cuts a GitHub Release with those artifacts attached.
31+
- `CONTRIBUTING.md` documenting the dev setup, quality gates, and release flow.
32+
- `ruff` (lint + format) and `ty` added to the dev dependency group, with
33+
`just lint`, `just fmt`, `just fmt-check`, `just ci`, and `just build`
34+
recipes.
35+
36+
### Changed
37+
- Package version is now derived from git tags via `hatch-vcs` instead of being
38+
hardcoded in `pyproject.toml` and `__init__.py`.
39+
- `pyproject.toml` gained release metadata (license, authors, classifiers, URLs).
40+
41+
[Unreleased]: https://github.com/PNNL/dizzy/compare/HEAD

CONTRIBUTING.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Contributing to DIZZY
2+
3+
Thanks for helping! This project is **trunk-based**: `main` is always
4+
releasable, and all work lands through short-lived branches and pull requests.
5+
6+
## Development setup
7+
8+
DIZZY uses [`uv`](https://docs.astral.sh/uv/) and [`just`](https://just.systems/).
9+
10+
```sh
11+
git clone https://github.com/PNNL/dizzy
12+
cd dizzy
13+
uv sync # install deps + dev tools into .venv
14+
just install # optional: install the `dizzy` CLI as an editable tool
15+
dizzy onboard # read this before touching generators
16+
```
17+
18+
## The workflow
19+
20+
1. **Branch off `main`** — keep branches short-lived and focused:
21+
`git switch -c my-change`.
22+
2. **Make the change.** Match the surrounding code style.
23+
3. **Run the gates locally** (see below).
24+
4. **Open a PR into `main`.** CI runs automatically.
25+
5. **Squash-merge once green.** Keep `main` linear and releasable.
26+
27+
We track issues with [Seeds](https://github.com/jayminwest/seeds). Run
28+
`sd prime` at the start of a session and `sd ready` to find unblocked work.
29+
30+
## Quality gates
31+
32+
`just ci` runs everything CI runs, in the same order:
33+
34+
| Command | Tool | Blocks merge? |
35+
| ---------------- | ------ | ------------- |
36+
| `just test` | pytest + syrupy snapshots | **Yes** |
37+
| `just lint` | ruff (lint) | No — advisory |
38+
| `just fmt-check` | ruff (format) | No — advisory |
39+
| `just check` | `ty` (type check) | No — advisory |
40+
41+
- **Tests are the gate.** A PR must pass `pytest` on Python 3.11–3.13 to merge.
42+
In branch protection, mark the `test (py3.x)` checks as required.
43+
- **Lint / format / type checks are advisory.** They run in the `quality` job
44+
and report status, but are *not* required checks, so they won't block a merge
45+
while we adopt them across the codebase. Please still fix what you can —
46+
`just fmt` auto-formats, and `just lint` shows lint findings.
47+
- If you intentionally re-snapshot, use `just test-update` and review the diff.
48+
- Touching generators? Regenerate examples and confirm no drift:
49+
`just examples-check`.
50+
51+
## Documentation
52+
53+
- `docs/cli.md` and `docs/authoring.md` are the authoritative docs (symlinked
54+
into the package so they ship in the wheel — **edit the `docs/` copies**).
55+
When scope changes, change `docs/cli.md` first, then the seeds.
56+
- The whitepaper/architecture Typst files are maintainer-authored; you may
57+
fact-check them, but don't author them.
58+
59+
## Releasing (maintainers)
60+
61+
Versions come from git tags via `hatch-vcs` — there is **no** version number to
62+
edit in source. To cut a release:
63+
64+
1. **Update the changelog.** In `CHANGELOG.md`, rename the `[Unreleased]`
65+
section to the new version with today's date, and start a fresh
66+
`[Unreleased]` block above it. Keep entries grouped under
67+
Added / Changed / Fixed / Removed.
68+
2. **Land it on `main`** via PR, as usual.
69+
3. **Tag and push** from `main`:
70+
```sh
71+
git switch main && git pull
72+
git tag v0.2.0
73+
git push origin v0.2.0
74+
```
75+
4. The **Release** workflow takes over: it verifies the tag matches the built
76+
version, builds the sdist + wheel, and creates a GitHub Release with those
77+
artifacts attached.
78+
79+
Tags are `vMAJOR.MINOR.PATCH` following [SemVer](https://semver.org/). To test a
80+
build without releasing, run `just build` — artifacts land in `dist/`.

dizzy/src/dizzy/__init__.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
11
"""Dizzy core library."""
22

3-
__version__ = "0.1.0"
3+
try:
4+
# Written at build time by hatch-vcs from the git tag.
5+
from ._version import __version__
6+
except ImportError: # pragma: no cover - source checkout without a build
7+
from importlib.metadata import PackageNotFoundError
8+
from importlib.metadata import version as _version
9+
10+
try:
11+
__version__ = _version("dizzy")
12+
except PackageNotFoundError:
13+
__version__ = "0.0.0+unknown"

0 commit comments

Comments
 (0)