Ctrl K
ComunidadGuías…

pyproject.toml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# API stability (roadmap item 338, docs/gate-dependency-contract.md): the
# primary promised dependency surface for `pip install revl` is `revl.gate`
# (its `__all__`, pinned exactly by tests/test_gate_compat.py). The narrow
# `revl.fs_workspace` Python root-binding and committed-preimage host APIs have
# separate capability versions and contracts in docs/witnessed-fs.md. Every other
# `revl.*` module is importable — a wheel cannot hide its modules — but
# UNVERSIONED, and may change on any release including a patch. Within
# `revl.gate`, `gate_version().api` (see src/revl/gate.py) is the semver of
# that surface itself, independent of this package's own `version` below,
# which tracks the revl LANGUAGE. See docs/gate-dependency-contract.md for
# the full consumer-facing security contract this classifier implies: a
# refusal is authoritative and fail-closed; an admission is a compile-time
# judgment scoped to `gate_version().frontier`, never a runtime sandbox.
#
# `revl.fs` is a second such narrow, separately versioned host surface
# (`WRITE_RECEIPT_API_VERSION`): a guarded native write returning a receipt with
# an expected-before check (issue #523), documented in docs/witnessed-fs.md.
[project]
name = "revl"
version = "2.0.0"
description = "A research language for spatiotemporal composability (Cordis paradigm)"
readme = "README.md"
requires-python = ">=3.11"
license = { text = "AGPL-3.0-only AND MIT" }
license-files = ["LICENSE", "LICENSES/*", "LICENSING.md", "TRADEMARK.md"]
classifiers = [
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3 :: Only",
    "Topic :: Software Development :: Compilers",
]

[project.optional-dependencies]
# `coverage` is a TEST dependency, not a runtime one: tests/test_selfhost_coverage.py
# measures which statements of the mirrored reference emitters the self-host corpus
# never executes (roadmap item 429) and gates on it, which needs a real tracer.
# `pyyaml`: tests/test_env_gated_skips_run_somewhere.py reads .github/workflows/
# to pair each CI-gated test against the job that actually runs it. It used to
# reach for PyYAML through `importorskip`, so on an install without it the
# strongest anti-silent-skip checks in the repo silently skipped (issue #266).
# It is a test dependency now, so they cannot.
# `cryptography`: a TEST dependency for the same reason `pyyaml` is one.
# src/revl/tee_quote.py implements ECDSA over P-256 and P-384 in pure Python
# integers, and that code decides whether a TEE attestation quote is genuine.
# tests/test_ecdsa_differential.py checks it against OpenSSL's implementation on
# random keys and messages in both directions, which is the only check that does
# not rely on the module agreeing with itself. It imports `cryptography` HARD:
# behind an `importorskip` the one independent check on the quote verifier's
# crypto would report SKIPPED, which is the same colour as a pass, on every
# machine that happens not to have the library (issue #266). The one module in
# `src/revl` that imports it is the optional signing backend below, and
# tests/test_1460_signing_backend.py asserts that; the differentials pin that
# backend off so they still compare two implementations.
# The test extra pins the exact release the python backend's hashed lock pins
# (backends/python/requirements.txt, installed with `--require-hashes` by
# backends/python/setup.sh), so a repo-level `pip install -e ".[test]"` gets the
# same artifact version the backend verifies its signature vectors against.
# The consumer-facing `crypto` extra below stays a range: it is the optional
# signing surface, not a test toolchain.
# `llguidance`: a TEST dependency too, so the grammar-engine checks in
# tests/test_constrained_decoding_1462.py run in CI instead of skipping, and
# tests/test_source_grammar_1661.py runs the grammar `revl grammar --format
# lark` exports over every parseable `.rvl` in the tree with it (imported hard,
# so that check cannot skip). At run time it is the optional `constrain` extra
# below and never required; `src/revl` never imports it for the grammar export.
test = ["pytest>=8.0", "pytest-asyncio", "coverage>=7.0", "pyyaml", "cryptography==50.0.2",
        "llguidance>=1.0"]
# `crypto`: constant-time ECDSA SIGNING (issue #1460). The pure-Python signer in
# src/revl/tee_quote.py takes time that depends on the secret nonce, so with this
# extra installed `ecdsa_sign` goes through OpenSSL instead (src/revl/
# _ecdsa_backend.py), byte-for-byte the same RFC 6979 signatures. A signer that
# is exposed to a network refuses without it. Verification never needs it. 44 is
# the first release with deterministic ECDSA. revl still has no REQUIRED runtime
# dependency.
crypto = ["cryptography>=44.0"]
# Constrained decoding's local grammar engine (issue #1462). When installed,
# the provider adapters compile a derived GBNF grammar before claiming it and
# check a completion made under a `gbnf` claim byte for byte. Absent, both
# checks are skipped and nothing else changes (revl.providers.structured).
constrain = ["llguidance>=1.0"]
# OpenTelemetry export for causal lifecycle traces (revl.otel, item 120). Kept
# out of the base install so it stays dependency-light; absent, revl.otel
# degrades to a no-op / span-mapping dump rather than a hard import error.
otel = ["opentelemetry-sdk>=1.20", "opentelemetry-api>=1.20"]

[project.scripts]
revl = "revl.__main__:main"
truc = "revl.truc:main"

[build-system]
requires = ["hatchling==1.27.0"]
build-backend = "hatchling.build"

# WHAT THE DISTRIBUTIONS SHIP, and why it is computed rather than copied.
#
# The per-tier emitters, runtimes and their golden data live in `backends/`, a
# sibling of `src/revl` in a checkout. They must ride *inside* the wheel or every
# backend-touching command (`revl run`, cross-tier `revl test`, placement, fault
# tests) breaks once installed — the checkout path does not exist under
# site-packages. They ship as `revl/backends`; `revl._backends_root()` prefers
# the checkout location and falls back to that packaged copy. `stdlib/` ships
# the same way (roadmap 319), for `revl._paths.stdlib_root()`.
#
# Both used to arrive through a plain `force-include` of the two directories.
# hatchling applies `force-include` AFTER file selection and exempts it from
# every exclude rule and from the ignore files, so it copied the two trees
# VERBATIM off the builder's disk. The wheel therefore contained whatever
# happened to be lying around rather than what the commit says
# (GHSA-gj88-cx6q-38r2), which is the wrong property for a published artifact
# in two ways:
#
#   * size and correctness — a developer build shipped `node_modules`, cargo
#     `target/debug`, a cloned `.cordis-py`, compiled runner binaries and stray
#     `*.log` scratch files: 2933 members / 250 MB unpacked against the 523 the
#     commit actually describes;
#   * non-determinism — two builds of the SAME commit on two machines produced
#     different wheels, so nothing about the artifact could be derived from the
#     revision. Anything sitting under `backends/` at build time rode along,
#     `.gitignore`d or not, and `.gitignore` routes machine-generated secrets
#     there on purpose (`backends/typescript/test-secret-store/`).
#
# `hatch_build.py` replaces the directory-level force-include with a PER-FILE
# one it computes: from `git ls-files` in a checkout, and from the deny-list
# below when there is no git (a wheel built out of an unpacked sdist). The
# wheel target keeps `packages = ["src/revl"]` — remapping `backends` with a
# `sources` entry would have been the tidier spelling, but a `sources` rewrite
# that CHANGES a prefix rather than removing one makes editable installs
# impossible, and `pip install -e ".[test]"` is how eleven CI jobs and every
# contributor set up (README.md, CONTRIBUTING.md).
#
# `tools/check_wheel_manifest.py` is the gate: it asserts the built wheel's
# member list EQUALS `git ls-files` of those trees plus the `.dist-info`, and
# that the sdist carries no untracked file. It runs in `lint`, in the release
# dry run, and immediately before the PyPI upload.
[tool.hatch.build.targets.wheel]
packages = ["src/revl"]

[tool.hatch.build.targets.wheel.hooks.custom]
path = "hatch_build.py"

# The sdist has the same shape of problem, one step milder: hatchling reads the
# ROOT `.gitignore` and none of the sixteen nested ones, so a plain build swept
# in `backends/rust/*/target/` (909 files) and the compiled
# `backends/go/placement_runner/revl_placement_runner`. These excludes state the
# artifact classes in the packaging file itself, root-anchored, mirroring the
# nested ignore files. They also feed `hatch_build.py`'s no-git fallback.
#
# Redundancy with `.gitignore` is the point: this is packaging's own statement
# of what may never ship, and it does not move when an ignore rule is relaxed
# somewhere else for an unrelated reason.
[tool.hatch.build]
exclude = [
  # dependency, build and vendored-clone trees (npm, cargo, go, java, python)
  "**/node_modules",
  "**/target",
  "**/.cordis-py",
  "**/.cordis4j*",
  "**/.venv",
  "**/__pycache__",
  "**/*.py[cod]",
  "**/*.class",
  "**/Cargo.lock",
  # generated and scratch output written by the harnesses and by test runs
  "**/.pytest_cache",
  "**/.conformance-*",
  "**/*.log",
  "**/*-note.txt",
  "backends/typescript/_gen",
  "backends/go/placement_runner/emitted/*.go",
  "backends/go/placement_runner/revl_placement_runner",
  "backends/java/placement/out",
  "backends/java/placement/gen",
  "backends/java/placement/real_out",
  "backends/java/placement/real_gen",
  "backends/java/placement/adt_out",
  "backends/java/placement/adt_gen",
  "backends/java/placement/*spec.json",
  "backends/java/placement/adt_prov.json",
  "backends/java/placement/adt_cons.json",
  # machine-generated secrets: `.gitignore` routes them here on purpose, and a
  # distribution is the last place on earth they may appear
  "backends/typescript/test-secret-store",
  # credential-shaped files, by name. Nothing tracked matches any of these, so
  # they cost nothing; they exist for the one path that cannot consult git --
  # `hatch_build.py`'s fallback, building a wheel out of an unpacked sdist --
  # where the rule is necessarily a deny-list rather than an allow-list.
  "**/.env",
  "**/.env.*",
  "**/.npmrc",
  "**/.netrc",
  "**/credentials",
  "**/*.pem",
  "**/*.key",
  "**/*.p12",
  "**/*.pfx",
  "**/id_rsa*",
  "**/id_ed25519*",
]

# The one place tracked content sits UNDER an ignore rule. `.gitignore:36` is
# `backends/typescript/tests/generated/` — the TS harness writes throwaway
# modules there — but seventeen fixtures in that directory were force-added and
# ARE tracked. Without this, hatchling's ignore handling drops them from the
# sdist, and a wheel built out of that sdist (`pip install revl-2.0.0.tar.gz`)
# comes out seventeen files short of one built in a checkout.
#
# `artifacts` is hatchling's "include even though VCS ignores it" hook. It lists
# the seventeen by exact path ON PURPOSE rather than as `*.ts`: a glob would
# also sweep up whatever the harness last wrote there, which is the
# non-determinism this whole section exists to remove. Add a tracked fixture to
# that directory and `tools/check_wheel_manifest.py` reds until the path is
# added here too — loud rot beats a silently short distribution.
artifacts = [
  "backends/typescript/tests/generated/conformance.ts",
  "backends/typescript/tests/generated/dynamic_reserved_key.ts",
  "backends/typescript/tests/generated/empty_list_types.ts",
  "backends/typescript/tests/generated/fr1_loop.ts",
  "backends/typescript/tests/generated/fr3_json_int.ts",
  "backends/typescript/tests/generated/instance_get.ts",
  "backends/typescript/tests/generated/r3_migrator.ts",
  "backends/typescript/tests/generated/reserved_words.ts",
  "backends/typescript/tests/generated/spawn.ts",
  "backends/typescript/tests/generated/str_scan.ts",
  "backends/typescript/tests/generated/tenants.ts",
  "backends/typescript/tests/generated/unique_writes.ts",
  "backends/typescript/tests/generated/user_cache.ts",
  "backends/typescript/tests/generated/v3_map.ts",
  "backends/typescript/tests/generated/v3_stdlib.ts",
  "backends/typescript/tests/generated/v3_tests.test.ts",
  "backends/typescript/tests/generated/v3_types_functions.ts",
  "backends/typescript/tests/generated/witnessed_teardown.ts",
]

# Lint gate (roadmap 110d). The repo already carries a `# noqa` discipline whose
# codes are overwhelmingly Pyflakes (F): unused imports/locals, undefined names,
# placeholder-less f-strings. Pin ruff to that same F-level surface, not ruff's
# broader default set (E4/E7/E9 + F), so the gate enforces the discipline that
# exists without surfacing hundreds of pre-existing E/PL findings this sweep is
# not meant to litigate. Widen deliberately (its own change), never by drift.
[tool.ruff]
target-version = "py311"

[tool.ruff.lint]
select = ["F"]

# roadmap item 419a: `backends/python/pytest.ini` (asyncio_mode = auto) is
# only picked up when pytest's rootdir search lands INSIDE backends/python —
# e.g. `cd backends/python && pytest`, or `pytest backends/python/tests/`
# given alone. pytest resolves exactly one inifile per session from the
# common ancestor of the given args; combine backends/python/tests/ with a
# sibling like backends/wasm/ (`pytest backends/wasm/ backends/python/tests/`)
# and the common ancestor climbs to the repo root, where this file — until
# now with no [tool.pytest.ini_options] — won, silently discarding
# backends/python/pytest.ini's asyncio_mode and reddening every unmarked
# `async def` test with "async def functions are not natively supported".
# Mirror the same setting here so a combined run stays covered regardless of
# which inifile pytest happens to pick. This is a no-op for every OTHER
# pytest invocation in the repo (`pytest tests/ -q`,
# `pytest backends/wasm/... -q`, ...): none of those trees define any
# `async def test_*` for asyncio_mode to touch.
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
markers = [
    # Issue #2216: a test that is slow by NATURE rather than by repeating work
    # a session could share. The fast lanes (the pre-commit hook,
    # `pre-merge --affected`, CI's pull-request `root-suite-affected` job) set
    # REVL_SKIP_SLOW=1 and tests/conftest.py deselects these; the full gate and
    # the merge-queue matrix keep running them.
    "slow: slow-by-nature test the affected/fast lanes deselect (issue #2216)",
]