# Development verbs for the zarr-metadata package. Recipes run with this
# directory as the working directory regardless of where `just` is invoked.

# List available recipes
# Quoted arguments must survive delegation from the root Justfile.
set positional-arguments

default:
    @just --list

# Run the test suite on the project interpreter; extra args are passed to pytest
test *args:
    uv run --group test pytest tests "$@"

# The oldest and newest interpreters the package is declared for: the floor is
# `requires-python`, the ceiling the newest classifier, both read from
# pyproject.toml. CI's matrix is written out in its workflow, so a change to
# the declared range is made there too.
# uv fetches an interpreter it does not have. A difference in how a version
# materialises annotations or resolves a stub shows up here, not only in CI.
# Run the test suite on the oldest and newest supported interpreters
test-versions *args:
    #!/usr/bin/env bash
    set -euo pipefail
    read -r floor ceiling < <(uv run python - <<'EOF'
    import re
    import tomllib

    project = tomllib.load(open("pyproject.toml", "rb"))["project"]
    floor = re.fullmatch(r">=\s*(\d+\.\d+)", project["requires-python"]).group(1)
    declared = [
        classifier.rsplit(" ", 1)[1]
        for classifier in project["classifiers"]
        if classifier.startswith("Programming Language :: Python :: 3.")
    ]
    print(floor, max(declared, key=lambda version: tuple(map(int, version.split(".")))))
    EOF
    )
    for version in "$floor" "$ceiling"; do
        echo "== python $version =="
        uv run --python "$version" --group test pytest tests "$@"
    done

# Lint with the same invocation CI uses
lint:
    uvx ruff check .

# Pinned so a pyright release cannot turn CI red on its own schedule. Bump it
# deliberately: run the new version, read what it found, then move the pin.
pyright_version := "1.1.414"

# Run under the interpreter CI runs pyright under, so a version-dependent
# stdlib or stub difference shows up here rather than only in CI.
# Type-check the package, sources and tests alike
typecheck:
    uv run --python 3.11 --group test --with 'pyright=={{ pyright_version }}' pyright

# Run everything CI runs for this package, on both ends of the version range
check: lint typecheck test-versions docs-check

# Preview the changelog that the next release would generate
changelog-draft:
    uvx towncrier build --draft --version Unreleased

# Build this package's documentation site, warnings as errors
docs-check:
    env DISABLE_MKDOCS_2_WARNING=true uv run --group docs mkdocs build --strict

# With no argument, uses port 8000 if free, otherwise an ephemeral free port;
# an explicitly requested port is used as-is so a conflict fails loudly.
# Serve this package's documentation site
docs-serve port="":
    #!/usr/bin/env bash
    set -euo pipefail
    port="{{ port }}"
    if [ -z "$port" ]; then
        port=$(uv run --group docs python -c '
    import socket
    s = socket.socket()
    try:
        s.bind(("127.0.0.1", 8000))
    except OSError:
        s.close()
        s = socket.socket()
        s.bind(("127.0.0.1", 0))
    print(s.getsockname()[1])
    s.close()
    ')
    fi
    exec env DISABLE_MKDOCS_2_WARNING=true uv run --group docs mkdocs serve -a "localhost:$port"
