spec-case (Python)
In-code spec / case / why / ideal / 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, 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")
@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.
Metadata
Release files for spec-case 0.2.1
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.1.tar.gz | 16.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| spec_case-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.0 kB
Release files / spec_case-0.2.1.tar.gz
| Download URL | spec_case-0.2.1.tar.gz |
|---|---|
| Size | 16.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9e6b0287d575d586057d74a63e6a5474a27b1533ca1710c8679fb4bbeee1267e
|
|
BLAKE2b-256 checksum How to use checksums |
03668286a379a44b08896b663fdaf2c2f5d38ea5be06d6437a075b7ab6457ed8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","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.1-py3-none-any.whl
| Download URL | spec_case-0.2.1-py3-none-any.whl |
|---|---|
| Size | 14.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
439f00181780ed4900997816cf88470a538b417c2b5c403016633963edaeeae8
|
|
BLAKE2b-256 checksum How to use checksums |
7af27f9a46cf5b6f31d6131e248add9d03204f9f96463633c96f9c5ec96c4fff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","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}
|