diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 2238259..9e1d305 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,7 +1,7 @@ { "name": "repo-review[dev]", "image": "mcr.microsoft.com/devcontainers/python:0-3.11", - "postCreateCommand": "pipx install nox && pip install -e.[cli,test] pylint", + "postCreateCommand": "pipx install hatch && pip install -e.[cli,test] pylint", "customizations": { "vscode": { "extensions": [ diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 4c50098..83e0bc6 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -5,28 +5,32 @@ detailed description of best practices for developing Scikit-HEP packages. ## Quick development -The fastest way to start with development is to use nox. If you don't have nox, -you can use `pipx run nox` to run it without installing, or `pipx install nox`. -If you don't have pipx (pip for applications), then you can install with with -`pip install pipx` (the only case were installing an application with regular -pip is reasonable). If you use macOS, then pipx and nox are both in brew, use -`brew install pipx nox`. +The fastest way to start with development is to use hatch. If you don't have +hatch, you can use `pipx run hatch` to run it without installing, or `pipx +install hatch`. If you don't have pipx (pip for applications), then you can +install with with `pip install pipx` (the only case were installing an +application with regular pip is reasonable). If you use macOS, then pipx and +hatch are both in brew, use `brew install pipx hatch`. Hatch 1.10+ is required. -To use, run `nox`. This will lint and test using every installed version of -Python on your system, skipping ones that are not installed. You can also run -specific jobs: +Here are some common tasks you might want to run: ```console -$ nox -s lint # Lint only -$ nox -s tests # Tests -$ nox -s docs -- --serve # Build and serve the docs -$ nox -s build # Make an SDist and wheel +$ hatch run lint:lint # all linters (pre-commit) +$ hatch run pylint:lint # pylint +$ hatch fmt # just format & basic lint +$ hatch tests # run the tests +$ hatch build # build SDist and wheel +$ hatch run docs:serve # build and serve the docs +$ hatch run docs:html # just build the docs +$ hatch run docs:man # build manpage +$ hatch run docs:linkcheck # check for broken links +$ hatch run api-docs:build # rebuild the API docs +$ hatch run webapp:serve # serve the webapp +$ hatch run example:repo-review # Run an example ``` -Nox handles everything for you, including setting up an temporary virtual -environment for each run. - -You can also use `nox -s run -- .` to run an example set of checks on a repo. +Hatch handles everything for you, including setting up an temporary virtual +environment. ## Setting up a development environment manually @@ -71,19 +75,25 @@ pytest You can build the docs using: ```bash -nox -s docs +hatch run docs:docs ``` You can see a preview with: ```bash -nox -s docs -- --serve +hatch run docs:serve +``` + +You can rebuild the API docs with: + +```bash +$ hatch run api-docs:build ``` ## Pre-commit This project uses pre-commit for all style checking. While you can run it with -nox, this is such an important tool that it deserves to be installed on its +hatch, this is such an important tool that it deserves to be installed on its own. Install pre-commit and run: ```bash @@ -94,5 +104,5 @@ to check all files. ## Running DevContainer -You can use DevContainer, such as in GitHub Codespaces or locally. Nox and a +You can use DevContainer, such as in GitHub Codespaces or locally. Hatch and a local install will be available. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14a32a0..f3212b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,16 +32,14 @@ jobs: - name: Run PyLint run: | echo "::add-matcher::$GITHUB_WORKSPACE/.github/matchers/pylint.json" - pipx run --python=python nox -s pylint + pipx run --python=python hatch run pylint:lint checks: - name: Check Python ${{ matrix.python-version }} on ${{ matrix.runs-on }} + name: Check Python on ${{ matrix.runs-on }} runs-on: ${{ matrix.runs-on }} - needs: [pre-commit] strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12"] runs-on: [ubuntu-latest, macos-latest, windows-latest] steps: @@ -51,18 +49,19 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} + python-version: | + 3.10 + 3.11 + 3.12 - name: Setup uv uses: yezz123/setup-uv@v4 - with: - uv-venv: ".venv" - - name: Install package - run: uv pip install .[test,cli] + - name: Install hatch + run: uv pip install --system hatch - - name: Test package - run: python -m pytest -ra + - name: Test package (all Pythons) + run: hatch test -a env: PYTHONUTF8: "1" @@ -88,19 +87,22 @@ jobs: - name: Setup uv uses: yezz123/setup-uv@v4 - - uses: wntrblm/nox@2024.04.15 + - uses: actions/setup-python@v5 with: - python-versions: "3.11" + python-version: "3.12" + + - name: Install hatch + run: uv pip install --system hatch - name: Linkcheck - run: nox -s docs -- -b linkcheck + run: hatch run docs:linkcheck - name: Build docs with warnings as errors - run: nox -s docs -- -W + run: hatch run docs:html -W - name: Verify no changes required to API docs run: | - nox -s build_api_docs + hatch run api-docs:build git diff --exit-code action: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a21c97c..72286e9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -75,3 +75,15 @@ repos: language: pygrep entry: PyBind|Numpy|Cmake|CCache|Github|PyTest exclude: .pre-commit-config.yaml + + - repo: https://github.com/henryiii/validate-pyproject-schema-store + rev: 2024.04.29 + hooks: + - id: validate-pyproject + + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.28.2 + hooks: + - id: check-dependabot + - id: check-github-workflows + - id: check-readthedocs diff --git a/noxfile.py b/noxfile.py deleted file mode 100644 index 21c2cce..0000000 --- a/noxfile.py +++ /dev/null @@ -1,138 +0,0 @@ -from __future__ import annotations - -import argparse -import shutil -from pathlib import Path - -import nox - -DIR = Path(__file__).parent.resolve() - -nox.needs_version = ">=2024.3.2" -nox.options.default_venv_backend = "uv|virtualenv" -nox.options.sessions = ["lint", "pylint", "tests"] - - -@nox.session(reuse_venv=True) -def run(session: nox.Session) -> None: - """ - Run the program with a few example checks. - """ - - session.install("-e", ".[cli]") - session.install("-e", "tests/test_utilities") - session.run("python", "-m", "repo_review", *session.posargs) - - -@nox.session -def lint(session: nox.Session) -> None: - """ - Run the linter. - """ - session.install("pre-commit") - session.run("pre-commit", "run", "--all-files", *session.posargs) - - -@nox.session -def pylint(session: nox.Session) -> None: - """ - Run PyLint. - """ - # This needs to be installed into the package environment, and is slower - # than a pre-commit check - session.install("-e.[cli]", "pylint") - session.run("pylint", "src", *session.posargs) - - -@nox.session -def tests(session: nox.Session) -> None: - """ - Run the unit and regular tests. - """ - session.install("-e.[test,cli]") - session.run("pytest", *session.posargs) - - -@nox.session(reuse_venv=True) -def build(session: nox.Session) -> None: - """ - Build an SDist and wheel. - """ - - build_p = DIR.joinpath("build") - if build_p.exists(): - shutil.rmtree(build_p) - - session.install("build") - session.run("python", "-m", "build") - - -@nox.session(venv_backend="none") -def serve(session: nox.Session) -> None: - """ - Serve the webapp. - """ - - session.cd("docs") - session.log("Serving on http://localhost:8080") - session.run("python3", "-m", "http.server", "8080") - - -@nox.session(reuse_venv=True) -def docs(session: nox.Session) -> None: - """ - Build the docs. Pass "--serve" to serve. - """ - - parser = argparse.ArgumentParser() - parser.add_argument("--serve", action="store_true", help="Serve after building") - parser.add_argument( - "-b", dest="builder", default="html", help="Build target (default: html)" - ) - args, posargs = parser.parse_known_args(session.posargs) - - if args.builder != "html" and args.serve: - session.error("Must not specify non-HTML builder with --serve") - - extra_installs = ["sphinx-autobuild"] if args.serve else [] - - session.install("-e.[docs]", *extra_installs) - session.chdir("docs") - - if args.builder == "linkcheck": - session.run( - "sphinx-build", "-b", "linkcheck", ".", "_build/linkcheck", *posargs - ) - return - - shared_args = ( - "-n", # nitpicky mode - "-T", # full tracebacks - f"-b={args.builder}", - ".", - f"_build/{args.builder}", - *posargs, - ) - - if args.serve: - session.run("sphinx-autobuild", *shared_args) - else: - session.run("sphinx-build", "--keep-going", *shared_args) - - -@nox.session -def build_api_docs(session: nox.Session) -> None: - """ - Build (regenerate) API docs. - """ - session.install("sphinx") - session.chdir("docs") - session.run( - "sphinx-apidoc", - "-o", - "api/", - "--module-first", - "--no-toc", - "--force", - "../src/repo_review", - ) diff --git a/pyproject.toml b/pyproject.toml index 2852733..3cd786a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,6 +84,46 @@ repo-review = "repo_review.schema:get_schema" version.source = "vcs" build.hooks.vcs.version-file = "src/repo_review/_version.py" +[tool.hatch.envs.default] +installer = "uv" + +[tool.hatch.envs.hatch-test] +features = ["test", "cli"] + +[tool.hatch.envs.lint] +dependencies = ["pre-commit"] +skip-install = true +scripts.lint = "pre-commit run --all-files --show-diff-on-failure {args}" + +[tool.hatch.envs.pylint] +features = ["cli"] +dependencies = ["pylint"] +scripts.lint = "pylint repo_review {args}" + +[tool.hatch.envs.docs] +features = ["docs"] +dependencies = ["sphinx-autobuild"] +scripts.linkcheck = "sphinx-build -b=linkcheck docs docs/_build/linkcheck {args}" +scripts.html = "sphinx-build --keep-going -n -T -b=html docs docs/_build/html {args}" +scripts.serve = "sphinx-autobuild -n -T -b=html docs docs/_build/html {args}" +scripts.man = "sphinx-build --keep-going -n -T -b=man docs docs/_build/man {args}" + +[tool.hatch.envs.api-docs] +skip-install = true +dependencies = ["sphinx"] +scripts.build = "sphinx-apidoc -o docs/api/ --module-first --no-toc --force src/repo_review" + +[tool.hatch.envs.example] +features = ["cli"] +post-install-commands = ["$HATCH_UV pip install -e tests/test_utilities"] + +[tool.hatch.envs.webapp] +skip-install = true +scripts.serve = "cd docs && echo 'Serving on http://localhost:8080' && python -m http.server 8080" + +[[tool.hatch.envs.hatch-test.matrix]] +python = ["3.12", "3.11", "3.10"] + [tool.pytest.ini_options] minversion = "7.0" @@ -164,7 +204,7 @@ extend-select = [ "YTT", # flake8-2020 ] ignore = [ - "ISC001", # May collide with formatter + "ISC001", # May collide with formatter "PT004", # Incorrect check, usefixtures is the correct way to do this "PLR09", # Too many X "PLR2004", # Magic value in comparison