Developer Notes =============== Installation Options -------------------- The package provides several optional dependency groups: .. code-block:: bash pip install -e . # Core only (requests + tqdm + tomlkit) pip install -e ".[test]" # Testing (pytest + pytest-cov) pip install -e ".[lint]" # Linting + type-checking (ruff, mypy) pip install -e ".[docs]" # Documentation (Sphinx + extensions) pip install -e ".[dev]" # All of the above + jupyter .. list-table:: :header-rows: 1 :widths: 15 35 50 * - Extra - Installs - Use case * - ``test`` - ``pytest>=7.0``, ``pytest-cov>=4.0`` - Running the test suite (with coverage). * - ``lint`` - ``ruff>=0.6``, ``mypy>=1.10``, ``types-requests`` - Linting, formatting, and type-checking. * - ``docs`` - ``sphinx>=7.0``, ``pydata-sphinx-theme>=0.15``, ``sphinx-design``, ``sphinx-copybutton``, ``myst-parser`` - Building the HTML documentation. * - ``dev`` - All of the above + ``jupyter`` - Full development environment including notebooks. Building the Documentation -------------------------- .. code-block:: bash sphinx-build -b html -w warnings_sphinx_build.txt docs docs/_build/html The ``-w`` flag writes warnings to ``warnings_sphinx_build.txt``. The CI build uses ``-W`` (warnings as errors) to enforce clean builds. To preview locally: .. code-block:: bash python3 -m http.server 8000 --directory docs/_build/html Then open http://localhost:8000. CI/CD ----- Four GitHub Actions workflows run the project: **Tests** (``.github/workflows/tests.yml``): - Push / pull request to ``main``. - Runs ``pytest --cov`` across Python 3.10, 3.11, 3.12, and 3.13. **Quality** (``.github/workflows/quality.yml``): - Push / pull request to ``main``. - Runs ``ruff check``, ``ruff format --check``, and ``mypy``. **Documentation** (``.github/workflows/docs.yml``): - Push to ``main``. - Builds the docs with warnings as errors (``-W``) and deploys to GitHub Pages. **Publish** (``.github/workflows/publish.yml``): - Runs when a GitHub Release is *published*. - Builds the sdist + wheel, runs ``twine check --strict``, and uploads to PyPI via OIDC Trusted Publishing (no API token is stored). Optionally enable the local ``pre-commit`` hooks (ruff lint + format plus basic hygiene) so commits are checked before they reach CI: .. code-block:: bash pip install -e ".[lint]" pre-commit pre-commit install One-time setup -------------- These configure the automation and are done **once** per repository, not per release: - **GitHub Pages** — repository **Settings → Pages → Source: GitHub Actions**. The docs then publish on every push to ``main`` at https://fschwar4.github.io/saia_python/. - **PyPI Trusted Publisher** — at https://pypi.org/manage/account/publishing/, add a publisher (a *pending publisher* before the project's first upload) with project ``saia-python``, owner ``fschwar4``, repository ``saia_python``, workflow ``publish.yml``, environment ``pypi``. This lets the Publish workflow upload without a stored token. - **Zenodo archiving** — at https://zenodo.org/account/settings/github/, log in with GitHub and toggle the ``saia_python`` repository **on** *before* the next release, so each Release is archived and assigned a DOI. Versioning ---------- The project follows `Semantic Versioning `_ (``MAJOR.MINOR.PATCH``). The version lives in ``pyproject.toml`` under ``[project] version`` and is read at runtime via ``importlib.metadata`` as ``saia_python.__version__``. Releasing --------- The established release flow (assumes the one-time setup above is done). Publishing to PyPI happens through the **Publish** workflow on a GitHub Release — no manual upload to PyPI and no stored token. 1. **Bump the version** in ``pyproject.toml`` and update ``docs/CHANGELOG.md`` — promote the ``[Unreleased]`` entries into a dated ``[X.Y.Z]`` section and update the compare links at the bottom. 2. **Check locally** (CI enforces the same): .. code-block:: bash ruff check saia_python tests ruff format --check saia_python tests mypy pytest --cov=saia_python sphinx-build -b html -W docs docs/_build/html python -m build && twine check --strict dist/* 3. *(Optional)* **TestPyPI dry-run** — preview the upload and rendered metadata before the real release. TestPyPI versions are immutable, so use a throwaway suffix (e.g. ``X.Y.Z.dev1``) if you need to re-test: .. code-block:: bash python -m build twine upload --repository testpypi dist/* # verify in a clean venv (dependencies resolve from real PyPI): pip install --index-url https://test.pypi.org/simple/ \ --extra-index-url https://pypi.org/simple/ saia-python 4. **Commit, tag, and push:** .. code-block:: bash git add -A git commit -m "Release X.Y.Z: " git push origin main git tag -a vX.Y.Z -m "saia-python X.Y.Z" git push origin vX.Y.Z 5. **Create the GitHub Release** for tag ``vX.Y.Z`` (for example ``gh release create vX.Y.Z --notes-file ``). Publishing the Release fires the **Publish** workflow, which uploads to PyPI via Trusted Publishing; Zenodo simultaneously archives the Release and mints a DOI. 6. **Wire the DOI** — add the Zenodo concept and version DOIs to ``CITATION.cff`` (``identifiers:``) and the DOI badge to ``README.md``, then commit.