diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index abcb32e9..a89e9bf0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -255,6 +255,48 @@ jobs: - name: Check wheel availability across supported platforms run: python scripts/check_wheel_availability.py + package-distribution: + # Build the exact artifacts that will eventually be uploaded under + # the `veralang` distribution name (#737). This stays separate from + # release automation (#481): PR CI validates artifacts but publishes + # nothing. + permissions: + contents: read + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + + - name: Install packaging tools + run: pip install build twine + + - name: Build and inspect distribution archives + run: | + python -m build + python -m twine check dist/* + python scripts/check_distribution.py dist + + - name: Install and smoke-test the wheel outside the checkout + run: | + python -m venv "$RUNNER_TEMP/veralang-wheel-smoke" + "$RUNNER_TEMP/veralang-wheel-smoke/bin/python" -m pip install dist/*.whl + cp examples/hello_world.vera "$RUNNER_TEMP/hello_world.vera" + cd "$RUNNER_TEMP" + "$RUNNER_TEMP/veralang-wheel-smoke/bin/vera" version + "$RUNNER_TEMP/veralang-wheel-smoke/bin/vera" check hello_world.vera + run_out="$("$RUNNER_TEMP/veralang-wheel-smoke/bin/vera" run hello_world.vera)" + printf '%s\n' "$run_out" + case "$run_out" in + *"Hello, World!"*) ;; + *) echo "::error::wheel smoke: unexpected 'vera run' output"; exit 1 ;; + esac + sbom: permissions: contents: read diff --git a/CHANGELOG.md b/CHANGELOG.md index 31a9ecc3..bb126c74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Added +- **PyPI publication readiness** ([#737](https://github.com/aallan/vera/issues/737)) renames the Python distribution to `veralang` while preserving the `vera` command and import package, adds a dedicated registry README, and gates the built sdist/wheel contents plus an installed-wheel CLI smoke test in CI. The existing GitHub-source installation path remains supported; automated publication is still gated on [#481](https://github.com/aallan/vera/issues/481). - **Inference + JSON composition example** ([#379](https://github.com/aallan/vera/issues/379)) demonstrates an effectful model call flowing through pure JSON parsing, typed integer extraction, and a statically proved 0–100 normalization contract. Raw JSON and tagged or untagged fenced responses are accepted, with the original completion retained in malformed-response diagnostics. ### Fixed diff --git a/LSP_SERVER.md b/LSP_SERVER.md index ce082dd1..7b25dd2d 100644 --- a/LSP_SERVER.md +++ b/LSP_SERVER.md @@ -27,11 +27,18 @@ the introspection commands), see the CLI cookbook, The server lives behind the optional `[lsp]` extra (pure-Python dependencies: `pygls`, `lsprotocol`): +```bash +python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install "veralang[lsp]" +``` + +To install the current GitHub source instead: + ```bash git clone https://github.com/aallan/vera.git cd vera -python -m venv .venv && source .venv/bin/activate -pip install -e ".[lsp]" # or ".[dev]", which includes it +python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install -e ".[lsp]" # or ".[dev]", which includes it ``` Then: diff --git a/PYPI_README.md b/PYPI_README.md new file mode 100644 index 00000000..987073ad --- /dev/null +++ b/PYPI_README.md @@ -0,0 +1,71 @@ +# Vera + +Vera is a programming language designed for large language models to write. It +has mandatory contracts, algebraic effects, typed slot references instead of +variable names, and a compiler that emits WebAssembly. + +Full documentation, examples, and the language specification are available at +[veralang.dev](https://veralang.dev) and in the +[GitHub repository](https://github.com/aallan/vera). + +## Install a released version + +Vera requires Python 3.11 or later. Create a virtual environment and install +the `veralang` distribution: + +```bash +python -m venv .venv +source .venv/bin/activate +python -m pip install veralang +``` + +On Windows, activate the environment with `.venv\Scripts\activate` instead. +For editor and agent integration through the language server, install the LSP +extra: + +```bash +python -m pip install "veralang[lsp]" +``` + +The distribution is named `veralang`, but the installed command remains +`vera`, and Python code still imports it as `import vera`. **Do not run `pip install vera`**: that name belongs to an unrelated +ERAV citizen-science project on PyPI. + +## Install from GitHub source + +The source route remains supported for compiler development, unreleased +changes, and testing the current `main` branch: + +```bash +git clone https://github.com/aallan/vera.git +cd vera +python -m venv .venv +source .venv/bin/activate +python -m pip install -e . +``` + +Use `python -m pip install -e ".[lsp]"` for the language server or +`python -m pip install -e ".[dev]"` when working on the compiler. + +## Try it + +```vera +public fn safe_divide(@Int, @Int -> @Int) + requires(@Int.1 != 0) + ensures(@Int.result == @Int.0 / @Int.1) + effects(pure) +{ + @Int.0 / @Int.1 +} +``` + +```bash +vera check program.vera +vera verify program.vera +vera run program.vera +``` + +See the [CLI cookbook](https://github.com/aallan/vera/blob/main/TOOLCHAIN.md), +[language reference](https://veralang.dev/SKILL.md), +[supported-platform policy](https://github.com/aallan/vera#supported-platforms), +and [issue tracker](https://github.com/aallan/vera/issues) for more. diff --git a/README.md b/README.md index 8b440c92..b218c193 100644 --- a/README.md +++ b/README.md @@ -115,15 +115,33 @@ Every diagnostic has a stable error code (`E001`–`E702`) and is available as s ### Installation +Install the released `veralang` distribution from PyPI: + +```bash +python -m venv .venv +source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install veralang +``` + +The distribution is named `veralang`, but the installed command remains +`vera`, and Python code still imports it as `import vera`. For editor and agent integration through the language server, install +`python -m pip install "veralang[lsp]"`. Do not run `pip install vera`: that +name belongs to an unrelated project on PyPI. + +The GitHub source route remains supported for compiler development, unreleased +changes, and testing the current `main` branch: + ```bash git clone https://github.com/aallan/vera.git cd vera python -m venv .venv -source .venv/bin/activate -pip install -e ".[dev]" +source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install -e ".[dev]" ``` -`[dev]` includes everything (tests, linters, the language server). For a lighter install that only adds editor/agent support to the base toolchain, use `pip install -e ".[lsp]"` — see [LSP_SERVER.md](LSP_SERVER.md). +`[dev]` includes everything (tests, linters, the language server). For a lighter +source install that only adds editor/agent support to the base toolchain, use +`python -m pip install -e ".[lsp]"` — see [LSP_SERVER.md](LSP_SERVER.md). #### Supported platforms diff --git a/SKILL.md b/SKILL.md index df357465..b689ba3f 100644 --- a/SKILL.md +++ b/SKILL.md @@ -9,15 +9,30 @@ Vera is a programming language designed for LLMs to write. It uses typed slot re ## Installation -Vera requires Python 3.11 or later. Node.js 22+ is optional (only needed for `vera compile --target browser` and browser parity tests). Install from the repository: +Vera requires Python 3.11 or later. Node.js 22+ is optional (only needed for `vera compile --target browser` and browser parity tests). Install the released `veralang` distribution from PyPI: + +```bash +python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install veralang +``` + +This installs the `vera` command and all runtime dependencies (Lark parser, Z3 solver, wasmtime). For editor/agent integration via the Language Server Protocol, install `python -m pip install "veralang[lsp]"` — see [LSP_SERVER.md](LSP_SERVER.md). + +The GitHub source route remains supported for unreleased changes and compiler development: ```bash git clone https://github.com/aallan/vera.git && cd vera -python -m venv .venv && source .venv/bin/activate -pip install -e . +python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install -e . +``` + +For an editable source install with the language server, use `python -m pip install -e ".[lsp]"`. Verify the installed CLI — works for either route, with no checkout required: + +```bash +vera version ``` -This installs the `vera` command and all runtime dependencies (Lark parser, Z3 solver, wasmtime). For editor/agent integration via the Language Server Protocol, install the optional extra instead: `pip install -e ".[lsp]"` — see [LSP_SERVER.md](LSP_SERVER.md). After installation, verify it works: +From a source checkout you can also run the bundled example end to end: ```bash vera check examples/hello_world.vera # should print "OK: examples/hello_world.vera" @@ -27,14 +42,14 @@ vera run examples/hello_world.vera # should print "Hello, World!" If you are working on the compiler itself, install development dependencies too: ```bash -pip install -e ".[dev]" +python -m pip install -e ".[dev]" ``` > **Platform support**: Vera is tested in CI on macOS 15+ (Apple Silicon), Ubuntu 24.04 LTS (x86_64), and Windows Server 2022, against Python 3.11–3.13. macOS 14 (Sonoma) and earlier, and Ubuntu 22.04 LTS aarch64, are out of scope — install will fail at dependency resolution. See [README §Supported platforms](README.md#supported-platforms) for the full matrix, workarounds, and the data behind the baseline. > > **For agents running in a sandbox** (Claude.ai, Code Interpreter, container-based execution environments, etc.): the steps above work. Sandboxes typically have Python, `git`, `pip`, and outbound network access — that's all Vera needs. **Run the install commands and verify with `vera run examples/hello_world.vera` before concluding that Vera "isn't available." Don't assume the sandbox lacks the toolchain — try it.** > -> One caveat: `pip install vera` (no source) installs a *different* package from PyPI (an ERAV citizen-science library — unrelated to this Vera). Always install from the GitHub source clone shown above. +> One caveat: `pip install vera` installs a *different* package from PyPI (an ERAV citizen-science library — unrelated to this Vera). Use the `veralang` distribution or the GitHub source clone shown above; both install the `vera` command. ## Toolchain diff --git a/docs/SKILL.md b/docs/SKILL.md index 1e6c1830..c596c689 100644 --- a/docs/SKILL.md +++ b/docs/SKILL.md @@ -9,15 +9,30 @@ Vera is a programming language designed for LLMs to write. It uses typed slot re ## Installation -Vera requires Python 3.11 or later. Node.js 22+ is optional (only needed for `vera compile --target browser` and browser parity tests). Install from the repository: +Vera requires Python 3.11 or later. Node.js 22+ is optional (only needed for `vera compile --target browser` and browser parity tests). Install the released `veralang` distribution from PyPI: + +```bash +python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install veralang +``` + +This installs the `vera` command and all runtime dependencies (Lark parser, Z3 solver, wasmtime). For editor/agent integration via the Language Server Protocol, install `python -m pip install "veralang[lsp]"` — see [LSP_SERVER.md](https://github.com/aallan/vera/blob/main/LSP_SERVER.md). + +The GitHub source route remains supported for unreleased changes and compiler development: ```bash git clone https://github.com/aallan/vera.git && cd vera -python -m venv .venv && source .venv/bin/activate -pip install -e . +python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install -e . +``` + +For an editable source install with the language server, use `python -m pip install -e ".[lsp]"`. Verify the installed CLI — works for either route, with no checkout required: + +```bash +vera version ``` -This installs the `vera` command and all runtime dependencies (Lark parser, Z3 solver, wasmtime). For editor/agent integration via the Language Server Protocol, install the optional extra instead: `pip install -e ".[lsp]"` — see [LSP_SERVER.md](https://github.com/aallan/vera/blob/main/LSP_SERVER.md). After installation, verify it works: +From a source checkout you can also run the bundled example end to end: ```bash vera check examples/hello_world.vera # should print "OK: examples/hello_world.vera" @@ -27,14 +42,14 @@ vera run examples/hello_world.vera # should print "Hello, World!" If you are working on the compiler itself, install development dependencies too: ```bash -pip install -e ".[dev]" +python -m pip install -e ".[dev]" ``` > **Platform support**: Vera is tested in CI on macOS 15+ (Apple Silicon), Ubuntu 24.04 LTS (x86_64), and Windows Server 2022, against Python 3.11–3.13. macOS 14 (Sonoma) and earlier, and Ubuntu 22.04 LTS aarch64, are out of scope — install will fail at dependency resolution. See [README §Supported platforms](https://github.com/aallan/vera/blob/main/README.md#supported-platforms) for the full matrix, workarounds, and the data behind the baseline. > > **For agents running in a sandbox** (Claude.ai, Code Interpreter, container-based execution environments, etc.): the steps above work. Sandboxes typically have Python, `git`, `pip`, and outbound network access — that's all Vera needs. **Run the install commands and verify with `vera run examples/hello_world.vera` before concluding that Vera "isn't available." Don't assume the sandbox lacks the toolchain — try it.** > -> One caveat: `pip install vera` (no source) installs a *different* package from PyPI (an ERAV citizen-science library — unrelated to this Vera). Always install from the GitHub source clone shown above. +> One caveat: `pip install vera` installs a *different* package from PyPI (an ERAV citizen-science library — unrelated to this Vera). Use the `veralang` distribution or the GitHub source clone shown above; both install the `vera` command. ## Toolchain diff --git a/docs/index.md b/docs/index.md index 58d8e062..aa30613b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -208,17 +208,25 @@ Serving HTTP on http://0.0.0.0:8080/ ## Get Started -Python 3.11+ and Git. Everything else installs into a virtual environment. +Python 3.11+. Everything else installs into a virtual environment. + +```bash +python -m venv .venv +source .venv/bin/activate +python -m pip install veralang +``` + +Or install the current GitHub source for development: ```bash -# Clone and install git clone https://github.com/aallan/vera.git cd vera python -m venv .venv source .venv/bin/activate -pip install -e ".[dev]" +python -m pip install -e ".[dev]" +``` -# Check, verify, run, compile +```bash vera check examples/absolute_value.vera vera verify examples/safe_divide.vera vera run examples/hello_world.vera diff --git a/docs/llms-full.txt b/docs/llms-full.txt index 2e2483c2..554e9e6f 100644 --- a/docs/llms-full.txt +++ b/docs/llms-full.txt @@ -15,15 +15,30 @@ Vera is a programming language designed for LLMs to write. It uses typed slot re ## Installation -Vera requires Python 3.11 or later. Node.js 22+ is optional (only needed for `vera compile --target browser` and browser parity tests). Install from the repository: +Vera requires Python 3.11 or later. Node.js 22+ is optional (only needed for `vera compile --target browser` and browser parity tests). Install the released `veralang` distribution from PyPI: + +```bash +python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install veralang +``` + +This installs the `vera` command and all runtime dependencies (Lark parser, Z3 solver, wasmtime). For editor/agent integration via the Language Server Protocol, install `python -m pip install "veralang[lsp]"` — see [LSP_SERVER.md](https://github.com/aallan/vera/blob/main/LSP_SERVER.md). + +The GitHub source route remains supported for unreleased changes and compiler development: ```bash git clone https://github.com/aallan/vera.git && cd vera -python -m venv .venv && source .venv/bin/activate -pip install -e . +python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install -e . +``` + +For an editable source install with the language server, use `python -m pip install -e ".[lsp]"`. Verify the installed CLI — works for either route, with no checkout required: + +```bash +vera version ``` -This installs the `vera` command and all runtime dependencies (Lark parser, Z3 solver, wasmtime). For editor/agent integration via the Language Server Protocol, install the optional extra instead: `pip install -e ".[lsp]"` — see [LSP_SERVER.md](https://github.com/aallan/vera/blob/main/LSP_SERVER.md). After installation, verify it works: +From a source checkout you can also run the bundled example end to end: ```bash vera check examples/hello_world.vera # should print "OK: examples/hello_world.vera" @@ -33,14 +48,14 @@ vera run examples/hello_world.vera # should print "Hello, World!" If you are working on the compiler itself, install development dependencies too: ```bash -pip install -e ".[dev]" +python -m pip install -e ".[dev]" ``` > **Platform support**: Vera is tested in CI on macOS 15+ (Apple Silicon), Ubuntu 24.04 LTS (x86_64), and Windows Server 2022, against Python 3.11–3.13. macOS 14 (Sonoma) and earlier, and Ubuntu 22.04 LTS aarch64, are out of scope — install will fail at dependency resolution. See [README §Supported platforms](https://github.com/aallan/vera/blob/main/README.md#supported-platforms) for the full matrix, workarounds, and the data behind the baseline. > > **For agents running in a sandbox** (Claude.ai, Code Interpreter, container-based execution environments, etc.): the steps above work. Sandboxes typically have Python, `git`, `pip`, and outbound network access — that's all Vera needs. **Run the install commands and verify with `vera run examples/hello_world.vera` before concluding that Vera "isn't available." Don't assume the sandbox lacks the toolchain — try it.** > -> One caveat: `pip install vera` (no source) installs a *different* package from PyPI (an ERAV citizen-science library — unrelated to this Vera). Always install from the GitHub source clone shown above. +> One caveat: `pip install vera` installs a *different* package from PyPI (an ERAV citizen-science library — unrelated to this Vera). Use the `veralang` distribution or the GitHub source clone shown above; both install the `vera` command. ## Toolchain @@ -2641,11 +2656,18 @@ the introspection commands), see the CLI cookbook, The server lives behind the optional `[lsp]` extra (pure-Python dependencies: `pygls`, `lsprotocol`): +```bash +python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install "veralang[lsp]" +``` + +To install the current GitHub source instead: + ```bash git clone https://github.com/aallan/vera.git cd vera -python -m venv .venv && source .venv/bin/activate -pip install -e ".[lsp]" # or ".[dev]", which includes it +python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate +python -m pip install -e ".[lsp]" # or ".[dev]", which includes it ``` Then: diff --git a/docs/llms.txt b/docs/llms.txt index 08e66f5a..fa8d0502 100644 --- a/docs/llms.txt +++ b/docs/llms.txt @@ -4,7 +4,7 @@ Vera uses De Bruijn indexing for bindings: `@Int.0` is the most recent `Int` binding, `@Int.1` the one before. There are no variable names. Contracts are mandatory — every function must declare `requires(...)`, `ensures(...)`, and `effects(...)`. The Z3 SMT solver verifies contracts statically where possible; remaining contracts become runtime assertions. All side effects (IO, Http, HttpServer, State, Exceptions, Async, Inference, Random) are tracked in the type system via algebraic effects. -Current version: 0.1.4. The reference compiler is written in Python. Install with `pip install -e .` from the repository. +Current version: 0.1.4. The reference compiler is written in Python. Install the `veralang` distribution from PyPI or use `pip install -e ".[dev]"` from the repository. ## Homepage diff --git a/pyproject.toml b/pyproject.toml index c989cddb..cd9ca7d8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ [project] -name = "vera" +name = "veralang" version = "0.1.4" description = "Vera: a programming language designed for LLMs, with full contracts, algebraic effects, and typed slot references" -readme = "README.md" +readme = "PYPI_README.md" license = "MIT" requires-python = ">=3.11" authors = [ @@ -14,6 +14,7 @@ classifiers = [ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Compilers", ] dependencies = [ @@ -73,7 +74,7 @@ dev = [ # `pip install -e ".[dev]"` can run tests/test_lsp.py without a # second pin list to keep in sync (PEP 508 extras self-reference; # supported by pip >= 21.2 and uv). - "vera[lsp]", + "veralang[lsp]", ] mutation = [ # Mutation testing (#387). Kept separate from [dev] so the @@ -82,7 +83,7 @@ mutation = [ # was chosen over cosmic-ray: its coverage-guided test selection # is ~90x faster on this Z3/WASM suite, and its copy-based model # never mutates the working tree in place. See MUTATION.md. - "vera[dev]", + "veralang[dev]", "mutmut>=3.6", "pytest-timeout>=2.4", # scripts/mutation_report.py renders the per-module chart with matplotlib; diff --git a/scripts/build_site.py b/scripts/build_site.py index 3888adf9..30416fc7 100644 --- a/scripts/build_site.py +++ b/scripts/build_site.py @@ -86,7 +86,8 @@ def build_llms_txt(version: str) -> str: Random) are tracked in the type system via algebraic effects. Current version: {version}. The reference compiler is written in Python. \ -Install with `pip install -e .` from the repository. +Install the `veralang` distribution from PyPI or use `pip install -e ".[dev]"` from \ +the repository. ## Homepage @@ -605,17 +606,25 @@ def build_index_md(version: str) -> str: ## Get Started -Python 3.11+ and Git. Everything else installs into a virtual environment. +Python 3.11+. Everything else installs into a virtual environment. + +```bash +python -m venv .venv +source .venv/bin/activate +python -m pip install veralang +``` + +Or install the current GitHub source for development: ```bash -# Clone and install git clone {REPO}.git cd vera python -m venv .venv source .venv/bin/activate -pip install -e ".[dev]" +python -m pip install -e ".[dev]" +``` -# Check, verify, run, compile +```bash vera check examples/absolute_value.vera vera verify examples/safe_divide.vera vera run examples/hello_world.vera diff --git a/scripts/check_distribution.py b/scripts/check_distribution.py new file mode 100644 index 00000000..c4d81463 --- /dev/null +++ b/scripts/check_distribution.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +"""Validate Vera's built wheel and source distribution contents.""" + +from __future__ import annotations + +import configparser +from email.parser import Parser +from pathlib import Path +import sys +import tarfile +import tomllib +import zipfile + + +ROOT = Path(__file__).resolve().parent.parent + + +def _project_identity() -> tuple[str, str]: + data = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8")) + project = data["project"] + return str(project["name"]), str(project["version"]) + + +def _check_metadata(raw: bytes, name: str, version: str, source: str) -> None: + metadata = Parser().parsestr(raw.decode("utf-8")) + if metadata["Name"] != name: + raise ValueError(f"{source}: Name is {metadata['Name']!r}, expected {name!r}") + if metadata["Version"] != version: + raise ValueError( + f"{source}: Version is {metadata['Version']!r}, expected {version!r}" + ) + + +def _check_no_generated_files(names: set[str], source: str) -> None: + bad = sorted( + path + for path in names + if "/__pycache__/" in f"/{path}" or path.endswith((".pyc", ".pyo")) + ) + if bad: + raise ValueError(f"{source}: generated Python files included: {bad}") + + +def _check_wheel(path: Path, name: str, version: str) -> None: + dist_info = f"{name}-{version}.dist-info" + with zipfile.ZipFile(path) as archive: + names = set(archive.namelist()) + required = { + "vera/__init__.py", + "vera/cli.py", + "vera/grammar.lark", + "vera/browser/harness.mjs", + "vera/browser/runtime.mjs", + f"{dist_info}/METADATA", + f"{dist_info}/entry_points.txt", + f"{dist_info}/RECORD", + } + missing = sorted(required - names) + if missing: + raise ValueError(f"{path.name}: required files missing: {missing}") + if any(item.startswith("tests/") for item in names): + raise ValueError(f"{path.name}: wheel must not include tests/") + if not any(item == f"{dist_info}/licenses/LICENSE" for item in names): + raise ValueError(f"{path.name}: packaged LICENSE is missing") + _check_no_generated_files(names, path.name) + _check_metadata( + archive.read(f"{dist_info}/METADATA"), name, version, path.name + ) + + entry_points = configparser.ConfigParser() + entry_points.read_string( + archive.read(f"{dist_info}/entry_points.txt").decode("utf-8") + ) + command = entry_points.get("console_scripts", "vera", fallback="") + if command != "vera.cli:main": + raise ValueError( + f"{path.name}: vera console script is {command!r}, " + "expected 'vera.cli:main'" + ) + + +def _check_sdist(path: Path, name: str, version: str) -> None: + top = f"{name}-{version}" + with tarfile.open(path, "r:gz") as archive: + names = {member.name for member in archive.getmembers()} + required = { + f"{top}/LICENSE", + f"{top}/PKG-INFO", + f"{top}/PYPI_README.md", + f"{top}/pyproject.toml", + f"{top}/vera/grammar.lark", + f"{top}/vera/browser/harness.mjs", + f"{top}/vera/browser/runtime.mjs", + } + missing = sorted(required - names) + if missing: + raise ValueError(f"{path.name}: required files missing: {missing}") + _check_no_generated_files(names, path.name) + metadata_file = archive.extractfile(f"{top}/PKG-INFO") + if metadata_file is None: + raise ValueError(f"{path.name}: could not read PKG-INFO") + _check_metadata(metadata_file.read(), name, version, path.name) + + +def main(argv: list[str] | None = None) -> int: + args = sys.argv[1:] if argv is None else argv + dist_dir = Path(args[0]) if args else ROOT / "dist" + name, version = _project_identity() + wheel = dist_dir / f"{name}-{version}-py3-none-any.whl" + sdist = dist_dir / f"{name}-{version}.tar.gz" + + missing = [str(path) for path in (wheel, sdist) if not path.is_file()] + if missing: + print(f"ERROR: expected distribution files are missing: {missing}", file=sys.stderr) + return 1 + + try: + _check_wheel(wheel, name, version) + _check_sdist(sdist, name, version) + except (ValueError, OSError, tarfile.TarError, zipfile.BadZipFile) as exc: + print(f"ERROR: {exc}", file=sys.stderr) + return 1 + + print(f"Distribution archives for {name} {version} are complete.") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/check_licenses.py b/scripts/check_licenses.py index 8cce8d51..d04b3e4f 100644 --- a/scripts/check_licenses.py +++ b/scripts/check_licenses.py @@ -41,7 +41,7 @@ ] # Packages to exclude from checking (this project itself). -_SELF_PACKAGES: set[str] = {"vera"} +_SELF_PACKAGES: set[str] = {"veralang"} def _is_compatible(license_str: str) -> bool: diff --git a/scripts/check_version_sync.py b/scripts/check_version_sync.py index dac7057d..89a92fac 100644 --- a/scripts/check_version_sync.py +++ b/scripts/check_version_sync.py @@ -94,7 +94,7 @@ def main() -> int: print("ERROR: Could not find version string in README.md", file=sys.stderr) return 1 - # uv.lock — the editable ``[[package]] name = "vera"`` entry holds + # uv.lock — the editable ``[[package]] name = "veralang"`` entry holds # the same version as ``pyproject.toml``. CI runs ``uv lock --check`` # in the lint job (`.github/workflows/ci.yml`); a stale lockfile # fails CI with a generic "lockfile needs to be updated" message @@ -106,7 +106,7 @@ def main() -> int: if not lock.is_file(): print("ERROR: uv.lock not found", file=sys.stderr) return 1 - # Match ``name = "vera"`` followed by ``version = "X.Y.Z"`` on the + # Match ``name = "veralang"`` followed by ``version = "X.Y.Z"`` on the # next non-blank line. Anchored on the package boundary # (``[[package]]``) so we don't accidentally pick up a transitive # dependency that happens to be named ``vera`` in some far-future @@ -114,13 +114,13 @@ def main() -> int: # with ``source = { editable = "." }``. lock_match = re.search( r'\[\[package\]\]\s*\n' - r'name\s*=\s*"vera"\s*\n' + r'name\s*=\s*"veralang"\s*\n' r'version\s*=\s*"([0-9]+\.[0-9]+\.[0-9]+)"', lock.read_text(encoding="utf-8"), ) if not lock_match: print( - 'ERROR: Could not find ``[[package]] name = "vera"`` block ' + 'ERROR: Could not find ``[[package]] name = "veralang"`` block ' "with a version field in uv.lock — has the lockfile shape " "changed?", file=sys.stderr, diff --git a/uv.lock b/uv.lock index 45dbf7b0..a41d7c5c 100644 --- a/uv.lock +++ b/uv.lock @@ -1545,7 +1545,7 @@ wheels = [ ] [[package]] -name = "vera" +name = "veralang" version = "0.1.4" source = { editable = "." } dependencies = [ @@ -1600,8 +1600,8 @@ requires-dist = [ { name = "pytest-timeout", marker = "extra == 'mutation'", specifier = ">=2.4" }, { name = "pytest-xdist", marker = "extra == 'dev'", specifier = ">=3.6" }, { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.15.21" }, - { name = "vera", extras = ["dev"], marker = "extra == 'mutation'" }, - { name = "vera", extras = ["lsp"], marker = "extra == 'dev'" }, + { name = "veralang", extras = ["dev"], marker = "extra == 'mutation'" }, + { name = "veralang", extras = ["lsp"], marker = "extra == 'dev'" }, { name = "wasmtime", specifier = ">=46.0.1" }, { name = "z3-solver", specifier = ">=4.15.5" }, ]