spec-case (Python)
In-code spec / case / why / ideal / tmp / link / rule markers + specgen, the static extractor
that compiles them into spec.json — the artifact ccr
consumes. Part of spec-case; see the repo
for concepts, the symbol-id contract, and the Go reference implementation.
Install
uv add spec-case # or: pip install spec-case
One dependency covers both ends: the markers are imported by your code at runtime,
and the same package ships the specgen console script for CI.
Use the markers
The markers are no-op decorators — at runtime each returns the function
unchanged, so importing and annotating costs nothing and never changes behavior.
They only mark functions for specgen's static (ast) extraction.
from spec_case import spec, case, why, ideal, tmp, link, rule
@spec("(tenant, name) unique; duplicate create -> ConflictError")
@case("happy_minimal", "only Name given should create", expect="201; body.id non-empty")
@case("duplicate_name", "duplicate Name", expect="409", forbid="a second row is written")
@why("database uniqueness is the cross-replica authority")
@ideal("one persistence owner replaces dual writes")
@tmp("dual-write during storage migration", until="all reads use the new store")
@link("component://docs/tenancy.md")
@rule("hot request path — watch new synchronous DB calls")
def create_notebook(req): ...
单个 spec 的 id 可省略。typing.overload 等同一 symbol 多声明场景可用
@spec("...", id="string_input") 区分;多个 spec 必须全部提供唯一 id。specgen 始终输出
统一的 {fqn?, specs[]} entry。
spec_case is zero-dependency (pure stdlib) and tiny, so taking it as a regular
runtime dependency is cheap. Because the decorators apply at import time, the
package must be importable anywhere the annotated module is imported (production
included) — it is a runtime dependency, not dev-only.
Run specgen (CI)
Compile markers into spec.json, and gate drift in CI:
uv run specgen <src-dir> -o spec.json # extract
uv run specgen <src-dir> -o spec.json --check # CI gate: exit 1 if spec.json drifted
--check compares the committed spec.json against the current markers and fails
if a symbol was renamed/removed or a marker changed. specgen parses with ast and
never imports or runs your code.
until is optional: @tmp("keep fallback") records the measure without an exit condition.
Metadata
Release files for spec-case 0.2.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| spec_case-0.2.3.tar.gz | 16.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| spec_case-0.2.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.8 kB
Release files / spec_case-0.2.3.tar.gz
| Download URL | spec_case-0.2.3.tar.gz |
|---|---|
| Size | 16.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b2fa1fba31e0032bd605bcc607ab36b42f7c498ba75560c650e273a5a21774f2
|
|
BLAKE2b-256 checksum How to use checksums |
080a3cf1c08f75f0d20ab2a9c7d0c865d376a5ed626c5e9b4b56c72c54f3e338
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / spec_case-0.2.3-py3-none-any.whl
| Download URL | spec_case-0.2.3-py3-none-any.whl |
|---|---|
| Size | 14.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
50be12c3b542581f528f61dc36191cd7e3b021b62954a7b421e0f5f7cbb6b802
|
|
BLAKE2b-256 checksum How to use checksums |
aa6425801b638ebd592b3f92ba2d9dd36e166b2169fa26c7e366d7d4aec65907
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|