diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 51798679..217e6e6e 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -57,10 +57,11 @@ package is in a virtual environment. This is how you would set one up with Python's built-in venv: ```bash -python3 -m venv .env -source ./.env/bin/activate -pip install -U pip -pip install -ve .[all] +python3 -m venv .venv +source ./.venv/bin/activate +pip install dependency-groups +pip-install-dependency-groups dev +pip install -ve. ```
Optional: External Jupyter kernel (click to expand) @@ -109,7 +110,8 @@ Here is the recommendation for a CMake install: ```bash python3 -m venv env_cmake source ./env_cmake/bin/activate -pip install -r dev-requirements.txt +pip install dependency-groups +pip-install-dependency-groups dev cmake -S . -B build-debug \ -GNinja \ -DCMAKE_INSTALL_PREFIX=$(python -c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False))") @@ -285,7 +287,8 @@ This requires LLVM 9+, and is based on [this post](https://aras-p.info/blog/2019 brew install llvm # macOS way to get clang-9 python3 -m venv .env_core # general environment (no install will be made) . .env_core/bin/activate -pip install -r dev-requirements.txt +pip install dependency-groups +pip-install-dependency-groups dev CXX="/usr/local/opt/llvm/bin/clang++" cmake -S . -B build-llvm \ -DCMAKE_CXX_FLAGS="-ftime-trace" \ -DPYTHON_EXECUTABLE=$(which python) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 41161b85..4897da56 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -6,6 +6,7 @@ on: paths: - "examples/*.py" - "notebooks/*.ipynb" + - ".github/workflows/examples.yml" push: branches: - master @@ -21,13 +22,10 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.9" - - name: Pre-install NumPy - run: python -m pip install -r dev-requirements.txt nbconvert ipykernel - - name: Install kernel - run: python -m ipykernel install --user --name boost-hist - - name: Build - run: python -m pip install .[examples] + - uses: astral-sh/setup-uv@v4 + - name: Build and install kernel + run: uv run --group examples -m ipykernel install --user --name boost-hist - name: Examples - run: for f in examples/*.py; do python "$f"; done + run: for f in examples/*.py; do uv run "$f"; done - name: Notebooks - run: jupyter nbconvert --execute --ExecutePreprocessor.timeout=90 --inplace notebooks/*.ipynb + run: uv run jupyter nbconvert --execute --ExecutePreprocessor.timeout=90 --inplace notebooks/*.ipynb diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 535dff11..4592e9e1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -85,6 +85,11 @@ jobs: key: ${{ matrix.python-version }} create-symlink: true + - name: Make requirements.txt + run: | + uv pip install --system dependency-groups + dependency-groups dev > dev-requirements.txt + - name: Install python tools run: uv pip install --system -r dev-requirements.txt pytest-github-actions-annotate-failures env: diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml index f880ac74..ff317b42 100644 --- a/.github/workflows/weekly.yml +++ b/.github/workflows/weekly.yml @@ -21,10 +21,13 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - name: Build and install wheel - run: pip install -v .[test] + run: | + pip install dependency-groups + pip-install-dependency-groups test + pip install -v . - name: Test run: python -m pytest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0330c5d0..118c1dcd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,6 @@ repos: - id: debug-statements - id: end-of-file-fixer - id: mixed-line-ending - - id: requirements-txt-fixer - id: trailing-whitespace - repo: https://github.com/cheshirekow/cmake-format-precommit diff --git a/.readthedocs.yml b/.readthedocs.yml index 0351b0eb..16dfeaff 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -6,20 +6,14 @@ version: 2 build: - os: ubuntu-22.04 + os: "ubuntu-22.04" tools: - python: "3" - -# Build documentation in the docs/ directory with Sphinx -sphinx: - configuration: docs/conf.py - -# Include PDF and ePub -formats: all - -python: - install: - - requirements: docs/requirements.txt + python: "3.12" + commands: + - asdf plugin add uv + - asdf install uv latest + - asdf global uv latest + - uv run --only-group docs sphinx-build -T -b html -d docs/_build/doctrees -D language=en docs $READTHEDOCS_OUTPUT/html submodules: exclude: all diff --git a/dev-requirements.txt b/dev-requirements.txt deleted file mode 100644 index 824811b3..00000000 --- a/dev-requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -cloudpickle -hypothesis >=6.0 -numpy -pytest >=6,!=6.1.0,!=7.1.0 -pytest-benchmark -setuptools_scm[toml] >=3.4,!=4.0.0 -uproot diff --git a/docs/conf.py b/docs/conf.py index 550405df..f62f3423 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -8,6 +8,7 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. # import contextlib +import importlib.metadata import shutil import sys from pathlib import Path @@ -31,11 +32,8 @@ copyright = "2020, Henry Schreiner, Hans Dembinski" author = "Henry Schreiner, Hans Dembinski" -# It is better to use pkg_resources, but we can't build on RtD -from pkg_resources import DistributionNotFound, get_distribution - -with contextlib.suppress(DistributionNotFound): - version = get_distribution("boost_histogram").version +with contextlib.suppress(ModuleNotFoundError): + version = importlib.metadata.version("boost_histogram") # passed if no version (latest/git hash) diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 72c68fb6..00000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -ipython -myst_parser>=0.13 -nbsphinx -numpy -Sphinx>=3.0.0 -sphinx-book-theme>=0.0.33 -sphinx_copybutton diff --git a/noxfile.py b/noxfile.py index b3f5fdf5..e23f8eb2 100644 --- a/noxfile.py +++ b/noxfile.py @@ -2,44 +2,55 @@ import argparse from pathlib import Path +from typing import Any import nox -nox.needs_version = ">=2024.3.2" +nox.needs_version = ">=2024.4.15" nox.options.default_venv_backend = "uv|virtualenv" -nox.options.sessions = ["lint", "tests"] -@nox.session +def _get_group(name: str, groups: dict[str, Any]) -> list[str]: + group = groups[name] + return [d if isinstance(d, str) else _get_group(d, groups) for d in group] + + +def dependency_groups(pyproject: dict[str, Any], *names: str) -> list[str]: + groups = pyproject["dependency-groups"] + return [item for name in names for item in _get_group(name, groups)] + + def tests(session: nox.Session) -> None: """ Run the unit and regular tests. """ - - session.install(".[test]") + pyproject = nox.project.load_toml("pyproject.toml") + session.install(".", *dependency_groups(pyproject, "test")) session.run("pytest", *session.posargs) -@nox.session +@nox.session(default=False) def hist(session: nox.Session) -> None: """ Run Hist's test suite """ + pyproject = nox.project.load_toml("pyproject.toml") session.install(".") tmpdir = session.create_tmp() session.chdir(tmpdir) session.run("git", "clone", "https://github.com/scikit-hep/hist", external=True) session.chdir("hist") - session.install(".[test,plot]") + session.install(".", *dependency_groups(pyproject, "test", "plot")) session.run("pip", "list") session.run("pytest", *session.posargs) -@nox.session(reuse_venv=True) +@nox.session(reuse_venv=True, default=False) def docs(session: nox.Session) -> None: """ Build the docs. Pass --non-interactive to avoid serving. Pass "-b linkcheck" to check links. """ + pyproject = nox.project.load_toml("pyproject.toml") parser = argparse.ArgumentParser() parser.add_argument( @@ -49,7 +60,7 @@ def docs(session: nox.Session) -> None: serve = args.builder == "html" and session.interactive extra_installs = ["sphinx-autobuild"] if serve else [] - session.install("-r", "docs/requirements.txt", *extra_installs) + session.install(*dependency_groups(pyproject, "docs"), *extra_installs) shared_args = ( "-n", # nitpicky mode @@ -67,13 +78,14 @@ def docs(session: nox.Session) -> None: session.run("sphinx-build", "--keep-going", *shared_args) -@nox.session +@nox.session(default=False) def build_api_docs(session: nox.Session) -> None: """ Build (regenerate) API docs. """ + pyproject = nox.project.load_toml("pyproject.toml") - session.install(".", "-r", "docs/requirements.txt") + session.install(*dependency_groups(pyproject, "docs")) session.run( "sphinx-apidoc", "-o", @@ -121,10 +133,11 @@ def pylint(session: nox.Session) -> None: session.run("pylint", "boost_histogram", *session.posargs) -@nox.session +@nox.session(default=False) def make_pickle(session: nox.Session) -> None: """ Make a pickle file for this version """ - session.install(".[dev]") + pyproject = nox.project.load_toml("pyproject.toml") + session.install(".", *dependency_groups(pyproject, "dev")) session.run("python", "tests/pickles/make_pickle.py", *session.posargs) diff --git a/pyproject.toml b/pyproject.toml index 5187e67f..f426a3f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,20 +50,29 @@ dependencies = [ "numpy", ] -[project.optional-dependencies] +[project.urls] +"Bug Tracker" = "https://github.com/scikit-hep/boost-histogram/issues" +Changelog = "https://boost-histogram.readthedocs.io/en/latest/CHANGELOG.html" +Chat = " https://gitter.im/HSF/PyHEP-histogramming" +Discussions = "https://github.com/scikit-hep/boost-histogram/discussions" +Documentation = "https://boost-histogram.readthedocs.io/" +Homepage = "https://github.com/scikit-hep/boost-histogram" + +[dependency-groups] dev = [ - "cloudpickle", - "hypothesis>=6.0", + { include-group = "test" }, "ipykernel", - "pytest-benchmark", - "pytest>=6.0", + "nbconvert", + "setuptools_scm", "typer", ] docs = [ + "ipython", "myst_parser>=0.13", "nbsphinx", + "numpy", "sphinx-book-theme>=0.0.33", - "Sphinx>=4.0", + "sphinx>=4.0", "sphinx_copybutton", ] examples = [ @@ -81,14 +90,6 @@ test = [ "pytest>=6.0", ] -[project.urls] -"Bug Tracker" = "https://github.com/scikit-hep/boost-histogram/issues" -Changelog = "https://boost-histogram.readthedocs.io/en/latest/CHANGELOG.html" -Chat = " https://gitter.im/HSF/PyHEP-histogramming" -Discussions = "https://github.com/scikit-hep/boost-histogram/discussions" -Documentation = "https://boost-histogram.readthedocs.io/" -Homepage = "https://github.com/scikit-hep/boost-histogram" - [tool.scikit-build] minimum-version = "build-system.requires" @@ -159,7 +160,7 @@ ignore_missing_imports = true [tool.cibuildwheel] build-frontend = "build[uv]" -test-extras = "test" +test-groups = ["test"] test-command = "pytest --benchmark-disable {project}/tests" skip = [ "pp38-*",