From b6a2e7532c5cbc87b3766cdd2128305d05bd3f33 Mon Sep 17 00:00:00 2001 From: "Thomas S." Date: Mon, 3 Feb 2025 10:42:59 +0100 Subject: [PATCH] ci: Use lockfiles to control cached venv (#1238) Closes #1146 . This PR intends to fix all the dependencies used in the CI in multiple `test-requirements.txt` files, in a fully automated way. It ensures that between two runs, the CI can't break because of a dependency update. It bases the pipelines cache on these files. On the other hand, it makes it easier to update the versions of the dependencies used in the CI. Currently, the versions are updated only if someone updates the `pyproject.toml` file, or if the CI cache is purged by hand. It will be now automatically updated each week by `dependabot`, in a pull-request. This PR updates the `dependabot` configuration, but I can't be sure it works before the merge. If not, we can easily create a `cron` pipeline calling the new `pip-compile.sh` script. --- This PR adds a new backend test ensuring that `test-requirements.txt` files are regenerated when `requirements.in` or `test-requirements.in` is modified. ![image](https://github.com/user-attachments/assets/310444b3-12de-46a6-8031-ed2d1671850c) --- .github/dependabot.yml | 9 +- .github/workflows/backend.yml | 48 ++-- .gitignore | 1 + .../0004-cache-python-dependencies-in-ci.md | 48 ++++ .../design/0005-use-python-lockfiles-in-ci.md | 35 +++ skore/ci/pip-compile.sh | 71 ++++++ .../requirements/python-3.10/.python-version | 1 + .../scikit-learn-1.6/test-requirements.txt | 229 ++++++++++++++++++ .../requirements/python-3.11/.python-version | 1 + .../scikit-learn-1.6/test-requirements.txt | 229 ++++++++++++++++++ .../requirements/python-3.12/.python-version | 1 + .../scikit-learn-1.4/test-requirements.txt | 229 ++++++++++++++++++ .../scikit-learn-1.5/test-requirements.txt | 229 ++++++++++++++++++ .../scikit-learn-1.6/test-requirements.txt | 229 ++++++++++++++++++ .../requirements/python-3.9/.python-version | 1 + .../scikit-learn-1.6/test-requirements.txt | 229 ++++++++++++++++++ skore/hatch/metadata.py | 68 +++++- skore/pyproject.toml | 67 +---- skore/requirements.in | 15 ++ skore/sphinx-requirements.in | 14 ++ skore/test-requirements.in | 14 ++ 21 files changed, 1685 insertions(+), 83 deletions(-) create mode 100644 docs/design/0004-cache-python-dependencies-in-ci.md create mode 100644 docs/design/0005-use-python-lockfiles-in-ci.md create mode 100644 skore/ci/pip-compile.sh create mode 100644 skore/ci/requirements/python-3.10/.python-version create mode 100644 skore/ci/requirements/python-3.10/scikit-learn-1.6/test-requirements.txt create mode 100644 skore/ci/requirements/python-3.11/.python-version create mode 100644 skore/ci/requirements/python-3.11/scikit-learn-1.6/test-requirements.txt create mode 100644 skore/ci/requirements/python-3.12/.python-version create mode 100644 skore/ci/requirements/python-3.12/scikit-learn-1.4/test-requirements.txt create mode 100644 skore/ci/requirements/python-3.12/scikit-learn-1.5/test-requirements.txt create mode 100644 skore/ci/requirements/python-3.12/scikit-learn-1.6/test-requirements.txt create mode 100644 skore/ci/requirements/python-3.9/.python-version create mode 100644 skore/ci/requirements/python-3.9/scikit-learn-1.6/test-requirements.txt create mode 100644 skore/requirements.in create mode 100644 skore/sphinx-requirements.in create mode 100644 skore/test-requirements.in diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a12cb4c42..fed1b2c99 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -18,6 +18,13 @@ updates: - package-ecosystem: "pip" directory: "/" schedule: - interval: "monthly" + interval: "weekly" commit-message: prefix: "chore(dependencies): PIP" + groups: + test-dependencies: + patterns: + - "*" + + # It uses `skore/ci/requirements/python*/.python-version` to specify the python + # version used to update `skore/ci/requirements/**/test-requirements.txt` diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index a683a86ad..02bf3b717 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -43,6 +43,27 @@ jobs: working-directory: skore/ run: pre-commit run --all-files ruff + backend-lockfiles: + runs-on: "ubuntu-latest" + if: ${{ github.event_name == 'pull_request' }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Check lockfiles are not obsolete + run: | + changes=$(git diff --name-only HEAD^1 HEAD) + + if + (echo "${changes}" | grep -qE 'skore/(test-)?requirements.in') && + (echo "${changes}" | (! grep -qE "skore/ci/requirements/.*/test-requirements.txt")) + then + echo '::error title=backend-lockfiles:: Lockfiles obsolete, please execute `$ cd skore/ci; bash pip-compile.sh`' + exit 1 + fi + backend-test: strategy: fail-fast: false @@ -77,7 +98,11 @@ jobs: id: cache-python-venv with: path: 'skore/venv' - key: python-venv-${{ matrix.os }}-${{ matrix.python }}-${{ matrix.scikit-learn }}-${{ hashFiles('skore/pyproject.toml') }} + key: >- + python-venv + -${{ matrix.os }} + -${{ matrix.python }} + -${{ hashFiles(format('skore/ci/requirements/python-{0}/scikit-learn-{1}/test-requirements.txt', matrix.python, matrix.scikit-learn)) }} - name: Setup python-venv working-directory: "skore/" @@ -97,20 +122,11 @@ jobs: fi - name: Install dependencies in python-venv - working-directory: "skore/" + working-directory: ${{ format('skore/ci/requirements/python-{0}/scikit-learn-{1}', matrix.python, matrix.scikit-learn) }} if: steps.cache-python-venv.outputs.cache-hit != 'true' run: | - python -m pip install --upgrade "pip" - python -m pip install --upgrade "build" - # adding `.*` to the version ensures that we install the latest version of - # scikit-learn that is compatible with the specified version - python -m pip install --upgrade "scikit-learn ==${{ matrix.scikit-learn }}.*" - - # Install `skore` and its dependencies - python -m pip install --upgrade --upgrade-strategy=eager ".[test]" - - # Uninstall the `skore` package itself - python -m pip uninstall -y "skore" + python -m pip install --upgrade pip build + python -m pip install --requirement test-requirements.txt - name: Save python-venv uses: actions/cache/save@v4 @@ -124,10 +140,8 @@ jobs: run: python -m build - name: Install - working-directory: skore/ - run: | - # Install `skore` without its dependencies, which are present in the venv - wheel=(dist/*.whl); python -m pip install --force-reinstall --no-deps "${wheel}" + working-directory: skore/dist/ + run: wheel=(*.whl); python -m pip install --force-reinstall --no-deps "${wheel}" - name: Show dependencies versions working-directory: skore/ diff --git a/.gitignore b/.gitignore index f6b1ce625..f1ca3a0ed 100644 --- a/.gitignore +++ b/.gitignore @@ -191,6 +191,7 @@ examples/plot_*.png # Include excluded directories from github-actions !/.github/**/build/ +!/skore/ci/**/.python-version # Exclude hatch artifacts skore/LICENSE diff --git a/docs/design/0004-cache-python-dependencies-in-ci.md b/docs/design/0004-cache-python-dependencies-in-ci.md new file mode 100644 index 000000000..4033dcbc4 --- /dev/null +++ b/docs/design/0004-cache-python-dependencies-in-ci.md @@ -0,0 +1,48 @@ +--- +date: 2025-01-09 +decision-makers: ["@thomass-dev"] +--- + +# Cache python dependencies in CI + +## Context and Problem Statement + +The choice was made to support the 3 latests versions of `scikit-learn`, jointly with +the OS team. + +To date, we already have a CI running `skore` tests with 2 OS, and 4 python versions. +The CI therefore runs the same job 2*4=8 times. To limit the installation time each time +we run the test, we use a native GH mechanism to persist the pip cache. That way, python +packages can be installed without the need to be re-download from PyPI. It's better than +nothing, but installation time is incompressibly slow. + +Supporting 3 versions of `scikit-learn` means adding at least 2 additional test runs: +- the latest version is test on each OS/python versions (no additonal test run), +- the 2 older versions of scikit-learn are tested on ubuntu-latest python 3.12 (2 + additional test runs) + +The CI is becoming very long, we need to find a way to reduce its duration. + +## Decision Outcome + +Speed-up tests by installing python dependencies in virtual environments and caching it: + +* pros: reduction of one minute per job when the cache is already built, otherwise + equivalent. +* cons: cache must be purged manually to install a new version of a dependency. It's not + a big deal for now, since the gain is higher than the constraint. + +Dependencies no longer need to be installed at each step, as they are already present in +the cached venv. + +We base the construction of the cache on the n-tuple OS, python, scikit-learn, and the +hash of the `pyproject.toml` file. This way, if the dependencies list changes, a new +cache is automatically built. + +Each test run knows which cache to use, depending on its context. + +Unused cache is automatically purged by GH after 90 days. + +## More Information + +Implementation in pull-request [#916](https://github.com/probabl-ai/skore/pull/916). diff --git a/docs/design/0005-use-python-lockfiles-in-ci.md b/docs/design/0005-use-python-lockfiles-in-ci.md new file mode 100644 index 000000000..4394902ad --- /dev/null +++ b/docs/design/0005-use-python-lockfiles-in-ci.md @@ -0,0 +1,35 @@ +--- +date: 2025-01-31 +decision-makers: ["@thomass-dev"] +--- + +# Use python `test-requirements.txt` lockfiles in CI + +## Context and Problem Statement + +With the pull-request [#916](https://github.com/probabl-ai/skore/pull/916), we cache now +the python dependencies to speed-up CI. However, to update in the cache the version of a +dependency, for example, to take advantage of a bugfix, we have to manually purge the GH +cache from the GH cli. It's not scallable. + +Moreover, in state of the CI, we can't control what version of a dependency is used. It +can lead to inconsistent tests, in particular when between two runs, a new version of a +dependency is released. + +We therefore want to define the dependencies versions in the CI, while leaving the user +free to install what he wants. + +## Decision Outcome + +We can't fix dependencies version in the `pyproject.toml` file without impacting users. +Instead, we fix the versions in separate requirement files, intended to be used only by +the CI. These files must be rebuilt after each change in the dependencies list, to stay +in sync at all times with the `pyproject.toml` file. + +These files are now used to construct the python cache in the CI. +These files are automatically managed by `dependabot`, to take account of new weekly +bugfixes. It produces pull-requests that must be accepted by maintainers. + +## More Information + +Implementation in pull-request [#1238](https://github.com/probabl-ai/skore/pull/1238). diff --git a/skore/ci/pip-compile.sh b/skore/ci/pip-compile.sh new file mode 100644 index 000000000..b6d48e615 --- /dev/null +++ b/skore/ci/pip-compile.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# +# This script compiles all the `test-requirements.txt` files, based on combinations of +# `python` and `scikit-learn` versions. These combinations mirror those defined in the +# GitHub `backend` workflow. +# +# You can pass any piptools parameter: +# +# $ bash pip-compile.sh --upgrade +# + +CWD="$PWD" +TMPDIR=$(mktemp -d) + +# Make sure that `TMPDIR` is removed on exit, whatever the signal +trap 'rm -rf ${TMPDIR}' 0 + +# Declare the combinations of `python` and `scikit-learn` versions +declare -a COMBINATIONS + +COMBINATIONS[0]='3.9;1.6' +COMBINATIONS[1]='3.10;1.6' +COMBINATIONS[2]='3.11;1.6' +COMBINATIONS[3]='3.12;1.4' +COMBINATIONS[4]='3.12;1.5' +COMBINATIONS[5]='3.12;1.6' + +set -eu + +( + # Copy everything necessary to compile requirements in `TMPDIR` + cp -r .. "${TMPDIR}/skore" + cp ../../LICENSE "${TMPDIR}/LICENSE" + cp ../../README.md "${TMPDIR}/README.md" + + # Move to `TMPDIR` to avoid absolute paths in requirements file + cd "${TMPDIR}" + + for combination in "${COMBINATIONS[@]}" + do + IFS=";" read -r -a combination <<< "${combination}" + + python="${combination[0]}" + scikit_learn="${combination[1]}" + filepath="${CWD}/requirements/python-${python}/scikit-learn-${scikit_learn}/test-requirements.txt" + + echo "Generating requirements: python ==${python} | scikit-learn ==${scikit_learn}" + + # Force the `python` version by creating the appropriate virtual environment + pyenv local "${python}" + python -m venv "python-${python}" + source "python-${python}/bin/activate" + + # Force the `scikit-learn` version by overloading test requirements + sed -i "s/scikit-learn.*/scikit-learn==${scikit_learn}.*/g" skore/test-requirements.in + + # Create the requirements file tree + mkdir -p $(dirname "${filepath}") + + # Create the requirements file + python -m pip install --upgrade pip pip-tools --quiet + python -m piptools compile \ + --quiet \ + --no-strip-extras \ + --no-header \ + --extra=test \ + --output-file="${filepath}" \ + "${@:2}" \ + skore/pyproject.toml + done +) diff --git a/skore/ci/requirements/python-3.10/.python-version b/skore/ci/requirements/python-3.10/.python-version new file mode 100644 index 000000000..c8cfe3959 --- /dev/null +++ b/skore/ci/requirements/python-3.10/.python-version @@ -0,0 +1 @@ +3.10 diff --git a/skore/ci/requirements/python-3.10/scikit-learn-1.6/test-requirements.txt b/skore/ci/requirements/python-3.10/scikit-learn-1.6/test-requirements.txt new file mode 100644 index 000000000..fd89bac25 --- /dev/null +++ b/skore/ci/requirements/python-3.10/scikit-learn-1.6/test-requirements.txt @@ -0,0 +1,229 @@ +altair==5.5.0 + # via skore (skore/pyproject.toml) +annotated-types==0.7.0 + # via pydantic +anyio==4.8.0 + # via + # httpx + # starlette +attrs==25.1.0 + # via + # jsonschema + # referencing +certifi==2024.12.14 + # via + # httpcore + # httpx + # requests +cfgv==3.4.0 + # via pre-commit +charset-normalizer==3.4.1 + # via requests +click==8.1.8 + # via uvicorn +contourpy==1.3.0 + # via matplotlib +coverage[toml]==7.6.10 + # via pytest-cov +cycler==0.12.1 + # via matplotlib +diskcache==5.6.3 + # via skore (skore/pyproject.toml) +distlib==0.3.9 + # via virtualenv +execnet==2.1.1 + # via pytest-xdist +fastapi==0.115.8 + # via skore (skore/pyproject.toml) +filelock==3.17.0 + # via + # huggingface-hub + # virtualenv +fonttools==4.55.8 + # via matplotlib +fsspec==2024.12.0 + # via huggingface-hub +h11==0.14.0 + # via + # httpcore + # uvicorn +httpcore==1.0.7 + # via httpx +httpx==0.28.1 + # via skore (skore/pyproject.toml) +huggingface-hub==0.28.1 + # via skops +identify==2.6.6 + # via pre-commit +idna==3.10 + # via + # anyio + # httpx + # requests +iniconfig==2.0.0 + # via pytest +jinja2==3.1.5 + # via + # altair + # skrub +joblib==1.4.2 + # via + # scikit-learn + # skore (skore/pyproject.toml) +jsonschema==4.23.0 + # via altair +jsonschema-specifications==2024.10.1 + # via jsonschema +kiwisolver==1.4.7 + # via matplotlib +markdown-it-py==3.0.0 + # via rich +markupsafe==3.0.2 + # via jinja2 +matplotlib==3.9.4 + # via + # skore (skore/pyproject.toml) + # skrub +mdurl==0.1.2 + # via markdown-it-py +narwhals==1.24.1 + # via altair +nodeenv==1.9.1 + # via pre-commit +numpy==2.0.2 + # via + # contourpy + # matplotlib + # pandas + # scikit-learn + # scipy + # skore (skore/pyproject.toml) + # skrub +orjson==3.10.15 + # via skore (skore/pyproject.toml) +packaging==24.2 + # via + # altair + # huggingface-hub + # matplotlib + # plotly + # pytest + # skops + # skrub +pandas==2.2.3 + # via + # skore (skore/pyproject.toml) + # skrub +pillow==11.1.0 + # via + # matplotlib + # skore (skore/pyproject.toml) +platformdirs==4.3.6 + # via + # skore (skore/pyproject.toml) + # virtualenv +plotly==5.24.1 + # via skore (skore/pyproject.toml) +pluggy==1.5.0 + # via pytest +polars==1.21.0 + # via skore (skore/pyproject.toml) +pre-commit==4.1.0 + # via skore (skore/pyproject.toml) +psutil==6.1.1 + # via skore (skore/pyproject.toml) +pyarrow==19.0.0 + # via skore (skore/pyproject.toml) +pydantic==2.10.6 + # via fastapi +pydantic-core==2.27.2 + # via pydantic +pygments==2.19.1 + # via rich +pyparsing==3.2.1 + # via matplotlib +pytest==8.3.4 + # via + # pytest-cov + # pytest-order + # pytest-randomly + # pytest-xdist + # skore (skore/pyproject.toml) +pytest-cov==6.0.0 + # via skore (skore/pyproject.toml) +pytest-order==1.3.0 + # via skore (skore/pyproject.toml) +pytest-randomly==3.16.0 + # via skore (skore/pyproject.toml) +pytest-xdist==3.6.1 + # via skore (skore/pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2024.2 + # via pandas +pyyaml==6.0.2 + # via + # huggingface-hub + # pre-commit +referencing==0.36.2 + # via + # jsonschema + # jsonschema-specifications +requests==2.32.3 + # via + # huggingface-hub + # skrub +rich==13.9.4 + # via skore (skore/pyproject.toml) +rpds-py==0.22.3 + # via + # jsonschema + # referencing +ruff==0.9.3 + # via skore (skore/pyproject.toml) +scikit-learn==1.6.1 + # via + # skops + # skore (skore/pyproject.toml) + # skrub +scipy==1.13.1 + # via + # scikit-learn + # skrub +six==1.17.0 + # via python-dateutil +skops==0.11.0 + # via skore (skore/pyproject.toml) +skrub==0.5.1 + # via skore (skore/pyproject.toml) +sniffio==1.3.1 + # via anyio +starlette==0.45.3 + # via fastapi +tabulate==0.9.0 + # via skops +tenacity==9.0.0 + # via plotly +threadpoolctl==3.5.0 + # via scikit-learn +tqdm==4.67.1 + # via huggingface-hub +typing-extensions==4.12.2 + # via + # altair + # anyio + # fastapi + # huggingface-hub + # pydantic + # pydantic-core + # referencing +tzdata==2025.1 + # via pandas +urllib3==2.3.0 + # via requests +uvicorn==0.34.0 + # via skore (skore/pyproject.toml) +virtualenv==20.29.1 + # via pre-commit diff --git a/skore/ci/requirements/python-3.11/.python-version b/skore/ci/requirements/python-3.11/.python-version new file mode 100644 index 000000000..2c0733315 --- /dev/null +++ b/skore/ci/requirements/python-3.11/.python-version @@ -0,0 +1 @@ +3.11 diff --git a/skore/ci/requirements/python-3.11/scikit-learn-1.6/test-requirements.txt b/skore/ci/requirements/python-3.11/scikit-learn-1.6/test-requirements.txt new file mode 100644 index 000000000..fd89bac25 --- /dev/null +++ b/skore/ci/requirements/python-3.11/scikit-learn-1.6/test-requirements.txt @@ -0,0 +1,229 @@ +altair==5.5.0 + # via skore (skore/pyproject.toml) +annotated-types==0.7.0 + # via pydantic +anyio==4.8.0 + # via + # httpx + # starlette +attrs==25.1.0 + # via + # jsonschema + # referencing +certifi==2024.12.14 + # via + # httpcore + # httpx + # requests +cfgv==3.4.0 + # via pre-commit +charset-normalizer==3.4.1 + # via requests +click==8.1.8 + # via uvicorn +contourpy==1.3.0 + # via matplotlib +coverage[toml]==7.6.10 + # via pytest-cov +cycler==0.12.1 + # via matplotlib +diskcache==5.6.3 + # via skore (skore/pyproject.toml) +distlib==0.3.9 + # via virtualenv +execnet==2.1.1 + # via pytest-xdist +fastapi==0.115.8 + # via skore (skore/pyproject.toml) +filelock==3.17.0 + # via + # huggingface-hub + # virtualenv +fonttools==4.55.8 + # via matplotlib +fsspec==2024.12.0 + # via huggingface-hub +h11==0.14.0 + # via + # httpcore + # uvicorn +httpcore==1.0.7 + # via httpx +httpx==0.28.1 + # via skore (skore/pyproject.toml) +huggingface-hub==0.28.1 + # via skops +identify==2.6.6 + # via pre-commit +idna==3.10 + # via + # anyio + # httpx + # requests +iniconfig==2.0.0 + # via pytest +jinja2==3.1.5 + # via + # altair + # skrub +joblib==1.4.2 + # via + # scikit-learn + # skore (skore/pyproject.toml) +jsonschema==4.23.0 + # via altair +jsonschema-specifications==2024.10.1 + # via jsonschema +kiwisolver==1.4.7 + # via matplotlib +markdown-it-py==3.0.0 + # via rich +markupsafe==3.0.2 + # via jinja2 +matplotlib==3.9.4 + # via + # skore (skore/pyproject.toml) + # skrub +mdurl==0.1.2 + # via markdown-it-py +narwhals==1.24.1 + # via altair +nodeenv==1.9.1 + # via pre-commit +numpy==2.0.2 + # via + # contourpy + # matplotlib + # pandas + # scikit-learn + # scipy + # skore (skore/pyproject.toml) + # skrub +orjson==3.10.15 + # via skore (skore/pyproject.toml) +packaging==24.2 + # via + # altair + # huggingface-hub + # matplotlib + # plotly + # pytest + # skops + # skrub +pandas==2.2.3 + # via + # skore (skore/pyproject.toml) + # skrub +pillow==11.1.0 + # via + # matplotlib + # skore (skore/pyproject.toml) +platformdirs==4.3.6 + # via + # skore (skore/pyproject.toml) + # virtualenv +plotly==5.24.1 + # via skore (skore/pyproject.toml) +pluggy==1.5.0 + # via pytest +polars==1.21.0 + # via skore (skore/pyproject.toml) +pre-commit==4.1.0 + # via skore (skore/pyproject.toml) +psutil==6.1.1 + # via skore (skore/pyproject.toml) +pyarrow==19.0.0 + # via skore (skore/pyproject.toml) +pydantic==2.10.6 + # via fastapi +pydantic-core==2.27.2 + # via pydantic +pygments==2.19.1 + # via rich +pyparsing==3.2.1 + # via matplotlib +pytest==8.3.4 + # via + # pytest-cov + # pytest-order + # pytest-randomly + # pytest-xdist + # skore (skore/pyproject.toml) +pytest-cov==6.0.0 + # via skore (skore/pyproject.toml) +pytest-order==1.3.0 + # via skore (skore/pyproject.toml) +pytest-randomly==3.16.0 + # via skore (skore/pyproject.toml) +pytest-xdist==3.6.1 + # via skore (skore/pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2024.2 + # via pandas +pyyaml==6.0.2 + # via + # huggingface-hub + # pre-commit +referencing==0.36.2 + # via + # jsonschema + # jsonschema-specifications +requests==2.32.3 + # via + # huggingface-hub + # skrub +rich==13.9.4 + # via skore (skore/pyproject.toml) +rpds-py==0.22.3 + # via + # jsonschema + # referencing +ruff==0.9.3 + # via skore (skore/pyproject.toml) +scikit-learn==1.6.1 + # via + # skops + # skore (skore/pyproject.toml) + # skrub +scipy==1.13.1 + # via + # scikit-learn + # skrub +six==1.17.0 + # via python-dateutil +skops==0.11.0 + # via skore (skore/pyproject.toml) +skrub==0.5.1 + # via skore (skore/pyproject.toml) +sniffio==1.3.1 + # via anyio +starlette==0.45.3 + # via fastapi +tabulate==0.9.0 + # via skops +tenacity==9.0.0 + # via plotly +threadpoolctl==3.5.0 + # via scikit-learn +tqdm==4.67.1 + # via huggingface-hub +typing-extensions==4.12.2 + # via + # altair + # anyio + # fastapi + # huggingface-hub + # pydantic + # pydantic-core + # referencing +tzdata==2025.1 + # via pandas +urllib3==2.3.0 + # via requests +uvicorn==0.34.0 + # via skore (skore/pyproject.toml) +virtualenv==20.29.1 + # via pre-commit diff --git a/skore/ci/requirements/python-3.12/.python-version b/skore/ci/requirements/python-3.12/.python-version new file mode 100644 index 000000000..e4fba2183 --- /dev/null +++ b/skore/ci/requirements/python-3.12/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/skore/ci/requirements/python-3.12/scikit-learn-1.4/test-requirements.txt b/skore/ci/requirements/python-3.12/scikit-learn-1.4/test-requirements.txt new file mode 100644 index 000000000..28c3fdc4b --- /dev/null +++ b/skore/ci/requirements/python-3.12/scikit-learn-1.4/test-requirements.txt @@ -0,0 +1,229 @@ +altair==5.5.0 + # via skore (skore/pyproject.toml) +annotated-types==0.7.0 + # via pydantic +anyio==4.8.0 + # via + # httpx + # starlette +attrs==25.1.0 + # via + # jsonschema + # referencing +certifi==2024.12.14 + # via + # httpcore + # httpx + # requests +cfgv==3.4.0 + # via pre-commit +charset-normalizer==3.4.1 + # via requests +click==8.1.8 + # via uvicorn +contourpy==1.3.0 + # via matplotlib +coverage[toml]==7.6.10 + # via pytest-cov +cycler==0.12.1 + # via matplotlib +diskcache==5.6.3 + # via skore (skore/pyproject.toml) +distlib==0.3.9 + # via virtualenv +execnet==2.1.1 + # via pytest-xdist +fastapi==0.115.8 + # via skore (skore/pyproject.toml) +filelock==3.17.0 + # via + # huggingface-hub + # virtualenv +fonttools==4.55.8 + # via matplotlib +fsspec==2024.12.0 + # via huggingface-hub +h11==0.14.0 + # via + # httpcore + # uvicorn +httpcore==1.0.7 + # via httpx +httpx==0.28.1 + # via skore (skore/pyproject.toml) +huggingface-hub==0.28.1 + # via skops +identify==2.6.6 + # via pre-commit +idna==3.10 + # via + # anyio + # httpx + # requests +iniconfig==2.0.0 + # via pytest +jinja2==3.1.5 + # via + # altair + # skrub +joblib==1.4.2 + # via + # scikit-learn + # skore (skore/pyproject.toml) +jsonschema==4.23.0 + # via altair +jsonschema-specifications==2024.10.1 + # via jsonschema +kiwisolver==1.4.7 + # via matplotlib +markdown-it-py==3.0.0 + # via rich +markupsafe==3.0.2 + # via jinja2 +matplotlib==3.9.4 + # via + # skore (skore/pyproject.toml) + # skrub +mdurl==0.1.2 + # via markdown-it-py +narwhals==1.24.1 + # via altair +nodeenv==1.9.1 + # via pre-commit +numpy==2.0.2 + # via + # contourpy + # matplotlib + # pandas + # scikit-learn + # scipy + # skore (skore/pyproject.toml) + # skrub +orjson==3.10.15 + # via skore (skore/pyproject.toml) +packaging==24.2 + # via + # altair + # huggingface-hub + # matplotlib + # plotly + # pytest + # skops + # skrub +pandas==2.2.3 + # via + # skore (skore/pyproject.toml) + # skrub +pillow==11.1.0 + # via + # matplotlib + # skore (skore/pyproject.toml) +platformdirs==4.3.6 + # via + # skore (skore/pyproject.toml) + # virtualenv +plotly==5.24.1 + # via skore (skore/pyproject.toml) +pluggy==1.5.0 + # via pytest +polars==1.21.0 + # via skore (skore/pyproject.toml) +pre-commit==4.1.0 + # via skore (skore/pyproject.toml) +psutil==6.1.1 + # via skore (skore/pyproject.toml) +pyarrow==19.0.0 + # via skore (skore/pyproject.toml) +pydantic==2.10.6 + # via fastapi +pydantic-core==2.27.2 + # via pydantic +pygments==2.19.1 + # via rich +pyparsing==3.2.1 + # via matplotlib +pytest==8.3.4 + # via + # pytest-cov + # pytest-order + # pytest-randomly + # pytest-xdist + # skore (skore/pyproject.toml) +pytest-cov==6.0.0 + # via skore (skore/pyproject.toml) +pytest-order==1.3.0 + # via skore (skore/pyproject.toml) +pytest-randomly==3.16.0 + # via skore (skore/pyproject.toml) +pytest-xdist==3.6.1 + # via skore (skore/pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2024.2 + # via pandas +pyyaml==6.0.2 + # via + # huggingface-hub + # pre-commit +referencing==0.36.2 + # via + # jsonschema + # jsonschema-specifications +requests==2.32.3 + # via + # huggingface-hub + # skrub +rich==13.9.4 + # via skore (skore/pyproject.toml) +rpds-py==0.22.3 + # via + # jsonschema + # referencing +ruff==0.9.3 + # via skore (skore/pyproject.toml) +scikit-learn==1.4.2 + # via + # skops + # skore (skore/pyproject.toml) + # skrub +scipy==1.13.1 + # via + # scikit-learn + # skrub +six==1.17.0 + # via python-dateutil +skops==0.11.0 + # via skore (skore/pyproject.toml) +skrub==0.5.1 + # via skore (skore/pyproject.toml) +sniffio==1.3.1 + # via anyio +starlette==0.45.3 + # via fastapi +tabulate==0.9.0 + # via skops +tenacity==9.0.0 + # via plotly +threadpoolctl==3.5.0 + # via scikit-learn +tqdm==4.67.1 + # via huggingface-hub +typing-extensions==4.12.2 + # via + # altair + # anyio + # fastapi + # huggingface-hub + # pydantic + # pydantic-core + # referencing +tzdata==2025.1 + # via pandas +urllib3==2.3.0 + # via requests +uvicorn==0.34.0 + # via skore (skore/pyproject.toml) +virtualenv==20.29.1 + # via pre-commit diff --git a/skore/ci/requirements/python-3.12/scikit-learn-1.5/test-requirements.txt b/skore/ci/requirements/python-3.12/scikit-learn-1.5/test-requirements.txt new file mode 100644 index 000000000..43792f379 --- /dev/null +++ b/skore/ci/requirements/python-3.12/scikit-learn-1.5/test-requirements.txt @@ -0,0 +1,229 @@ +altair==5.5.0 + # via skore (skore/pyproject.toml) +annotated-types==0.7.0 + # via pydantic +anyio==4.8.0 + # via + # httpx + # starlette +attrs==25.1.0 + # via + # jsonschema + # referencing +certifi==2024.12.14 + # via + # httpcore + # httpx + # requests +cfgv==3.4.0 + # via pre-commit +charset-normalizer==3.4.1 + # via requests +click==8.1.8 + # via uvicorn +contourpy==1.3.0 + # via matplotlib +coverage[toml]==7.6.10 + # via pytest-cov +cycler==0.12.1 + # via matplotlib +diskcache==5.6.3 + # via skore (skore/pyproject.toml) +distlib==0.3.9 + # via virtualenv +execnet==2.1.1 + # via pytest-xdist +fastapi==0.115.8 + # via skore (skore/pyproject.toml) +filelock==3.17.0 + # via + # huggingface-hub + # virtualenv +fonttools==4.55.8 + # via matplotlib +fsspec==2024.12.0 + # via huggingface-hub +h11==0.14.0 + # via + # httpcore + # uvicorn +httpcore==1.0.7 + # via httpx +httpx==0.28.1 + # via skore (skore/pyproject.toml) +huggingface-hub==0.28.1 + # via skops +identify==2.6.6 + # via pre-commit +idna==3.10 + # via + # anyio + # httpx + # requests +iniconfig==2.0.0 + # via pytest +jinja2==3.1.5 + # via + # altair + # skrub +joblib==1.4.2 + # via + # scikit-learn + # skore (skore/pyproject.toml) +jsonschema==4.23.0 + # via altair +jsonschema-specifications==2024.10.1 + # via jsonschema +kiwisolver==1.4.7 + # via matplotlib +markdown-it-py==3.0.0 + # via rich +markupsafe==3.0.2 + # via jinja2 +matplotlib==3.9.4 + # via + # skore (skore/pyproject.toml) + # skrub +mdurl==0.1.2 + # via markdown-it-py +narwhals==1.24.1 + # via altair +nodeenv==1.9.1 + # via pre-commit +numpy==2.0.2 + # via + # contourpy + # matplotlib + # pandas + # scikit-learn + # scipy + # skore (skore/pyproject.toml) + # skrub +orjson==3.10.15 + # via skore (skore/pyproject.toml) +packaging==24.2 + # via + # altair + # huggingface-hub + # matplotlib + # plotly + # pytest + # skops + # skrub +pandas==2.2.3 + # via + # skore (skore/pyproject.toml) + # skrub +pillow==11.1.0 + # via + # matplotlib + # skore (skore/pyproject.toml) +platformdirs==4.3.6 + # via + # skore (skore/pyproject.toml) + # virtualenv +plotly==5.24.1 + # via skore (skore/pyproject.toml) +pluggy==1.5.0 + # via pytest +polars==1.21.0 + # via skore (skore/pyproject.toml) +pre-commit==4.1.0 + # via skore (skore/pyproject.toml) +psutil==6.1.1 + # via skore (skore/pyproject.toml) +pyarrow==19.0.0 + # via skore (skore/pyproject.toml) +pydantic==2.10.6 + # via fastapi +pydantic-core==2.27.2 + # via pydantic +pygments==2.19.1 + # via rich +pyparsing==3.2.1 + # via matplotlib +pytest==8.3.4 + # via + # pytest-cov + # pytest-order + # pytest-randomly + # pytest-xdist + # skore (skore/pyproject.toml) +pytest-cov==6.0.0 + # via skore (skore/pyproject.toml) +pytest-order==1.3.0 + # via skore (skore/pyproject.toml) +pytest-randomly==3.16.0 + # via skore (skore/pyproject.toml) +pytest-xdist==3.6.1 + # via skore (skore/pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2024.2 + # via pandas +pyyaml==6.0.2 + # via + # huggingface-hub + # pre-commit +referencing==0.36.2 + # via + # jsonschema + # jsonschema-specifications +requests==2.32.3 + # via + # huggingface-hub + # skrub +rich==13.9.4 + # via skore (skore/pyproject.toml) +rpds-py==0.22.3 + # via + # jsonschema + # referencing +ruff==0.9.3 + # via skore (skore/pyproject.toml) +scikit-learn==1.5.2 + # via + # skops + # skore (skore/pyproject.toml) + # skrub +scipy==1.13.1 + # via + # scikit-learn + # skrub +six==1.17.0 + # via python-dateutil +skops==0.11.0 + # via skore (skore/pyproject.toml) +skrub==0.5.1 + # via skore (skore/pyproject.toml) +sniffio==1.3.1 + # via anyio +starlette==0.45.3 + # via fastapi +tabulate==0.9.0 + # via skops +tenacity==9.0.0 + # via plotly +threadpoolctl==3.5.0 + # via scikit-learn +tqdm==4.67.1 + # via huggingface-hub +typing-extensions==4.12.2 + # via + # altair + # anyio + # fastapi + # huggingface-hub + # pydantic + # pydantic-core + # referencing +tzdata==2025.1 + # via pandas +urllib3==2.3.0 + # via requests +uvicorn==0.34.0 + # via skore (skore/pyproject.toml) +virtualenv==20.29.1 + # via pre-commit diff --git a/skore/ci/requirements/python-3.12/scikit-learn-1.6/test-requirements.txt b/skore/ci/requirements/python-3.12/scikit-learn-1.6/test-requirements.txt new file mode 100644 index 000000000..fd89bac25 --- /dev/null +++ b/skore/ci/requirements/python-3.12/scikit-learn-1.6/test-requirements.txt @@ -0,0 +1,229 @@ +altair==5.5.0 + # via skore (skore/pyproject.toml) +annotated-types==0.7.0 + # via pydantic +anyio==4.8.0 + # via + # httpx + # starlette +attrs==25.1.0 + # via + # jsonschema + # referencing +certifi==2024.12.14 + # via + # httpcore + # httpx + # requests +cfgv==3.4.0 + # via pre-commit +charset-normalizer==3.4.1 + # via requests +click==8.1.8 + # via uvicorn +contourpy==1.3.0 + # via matplotlib +coverage[toml]==7.6.10 + # via pytest-cov +cycler==0.12.1 + # via matplotlib +diskcache==5.6.3 + # via skore (skore/pyproject.toml) +distlib==0.3.9 + # via virtualenv +execnet==2.1.1 + # via pytest-xdist +fastapi==0.115.8 + # via skore (skore/pyproject.toml) +filelock==3.17.0 + # via + # huggingface-hub + # virtualenv +fonttools==4.55.8 + # via matplotlib +fsspec==2024.12.0 + # via huggingface-hub +h11==0.14.0 + # via + # httpcore + # uvicorn +httpcore==1.0.7 + # via httpx +httpx==0.28.1 + # via skore (skore/pyproject.toml) +huggingface-hub==0.28.1 + # via skops +identify==2.6.6 + # via pre-commit +idna==3.10 + # via + # anyio + # httpx + # requests +iniconfig==2.0.0 + # via pytest +jinja2==3.1.5 + # via + # altair + # skrub +joblib==1.4.2 + # via + # scikit-learn + # skore (skore/pyproject.toml) +jsonschema==4.23.0 + # via altair +jsonschema-specifications==2024.10.1 + # via jsonschema +kiwisolver==1.4.7 + # via matplotlib +markdown-it-py==3.0.0 + # via rich +markupsafe==3.0.2 + # via jinja2 +matplotlib==3.9.4 + # via + # skore (skore/pyproject.toml) + # skrub +mdurl==0.1.2 + # via markdown-it-py +narwhals==1.24.1 + # via altair +nodeenv==1.9.1 + # via pre-commit +numpy==2.0.2 + # via + # contourpy + # matplotlib + # pandas + # scikit-learn + # scipy + # skore (skore/pyproject.toml) + # skrub +orjson==3.10.15 + # via skore (skore/pyproject.toml) +packaging==24.2 + # via + # altair + # huggingface-hub + # matplotlib + # plotly + # pytest + # skops + # skrub +pandas==2.2.3 + # via + # skore (skore/pyproject.toml) + # skrub +pillow==11.1.0 + # via + # matplotlib + # skore (skore/pyproject.toml) +platformdirs==4.3.6 + # via + # skore (skore/pyproject.toml) + # virtualenv +plotly==5.24.1 + # via skore (skore/pyproject.toml) +pluggy==1.5.0 + # via pytest +polars==1.21.0 + # via skore (skore/pyproject.toml) +pre-commit==4.1.0 + # via skore (skore/pyproject.toml) +psutil==6.1.1 + # via skore (skore/pyproject.toml) +pyarrow==19.0.0 + # via skore (skore/pyproject.toml) +pydantic==2.10.6 + # via fastapi +pydantic-core==2.27.2 + # via pydantic +pygments==2.19.1 + # via rich +pyparsing==3.2.1 + # via matplotlib +pytest==8.3.4 + # via + # pytest-cov + # pytest-order + # pytest-randomly + # pytest-xdist + # skore (skore/pyproject.toml) +pytest-cov==6.0.0 + # via skore (skore/pyproject.toml) +pytest-order==1.3.0 + # via skore (skore/pyproject.toml) +pytest-randomly==3.16.0 + # via skore (skore/pyproject.toml) +pytest-xdist==3.6.1 + # via skore (skore/pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2024.2 + # via pandas +pyyaml==6.0.2 + # via + # huggingface-hub + # pre-commit +referencing==0.36.2 + # via + # jsonschema + # jsonschema-specifications +requests==2.32.3 + # via + # huggingface-hub + # skrub +rich==13.9.4 + # via skore (skore/pyproject.toml) +rpds-py==0.22.3 + # via + # jsonschema + # referencing +ruff==0.9.3 + # via skore (skore/pyproject.toml) +scikit-learn==1.6.1 + # via + # skops + # skore (skore/pyproject.toml) + # skrub +scipy==1.13.1 + # via + # scikit-learn + # skrub +six==1.17.0 + # via python-dateutil +skops==0.11.0 + # via skore (skore/pyproject.toml) +skrub==0.5.1 + # via skore (skore/pyproject.toml) +sniffio==1.3.1 + # via anyio +starlette==0.45.3 + # via fastapi +tabulate==0.9.0 + # via skops +tenacity==9.0.0 + # via plotly +threadpoolctl==3.5.0 + # via scikit-learn +tqdm==4.67.1 + # via huggingface-hub +typing-extensions==4.12.2 + # via + # altair + # anyio + # fastapi + # huggingface-hub + # pydantic + # pydantic-core + # referencing +tzdata==2025.1 + # via pandas +urllib3==2.3.0 + # via requests +uvicorn==0.34.0 + # via skore (skore/pyproject.toml) +virtualenv==20.29.1 + # via pre-commit diff --git a/skore/ci/requirements/python-3.9/.python-version b/skore/ci/requirements/python-3.9/.python-version new file mode 100644 index 000000000..bd28b9c5c --- /dev/null +++ b/skore/ci/requirements/python-3.9/.python-version @@ -0,0 +1 @@ +3.9 diff --git a/skore/ci/requirements/python-3.9/scikit-learn-1.6/test-requirements.txt b/skore/ci/requirements/python-3.9/scikit-learn-1.6/test-requirements.txt new file mode 100644 index 000000000..fd89bac25 --- /dev/null +++ b/skore/ci/requirements/python-3.9/scikit-learn-1.6/test-requirements.txt @@ -0,0 +1,229 @@ +altair==5.5.0 + # via skore (skore/pyproject.toml) +annotated-types==0.7.0 + # via pydantic +anyio==4.8.0 + # via + # httpx + # starlette +attrs==25.1.0 + # via + # jsonschema + # referencing +certifi==2024.12.14 + # via + # httpcore + # httpx + # requests +cfgv==3.4.0 + # via pre-commit +charset-normalizer==3.4.1 + # via requests +click==8.1.8 + # via uvicorn +contourpy==1.3.0 + # via matplotlib +coverage[toml]==7.6.10 + # via pytest-cov +cycler==0.12.1 + # via matplotlib +diskcache==5.6.3 + # via skore (skore/pyproject.toml) +distlib==0.3.9 + # via virtualenv +execnet==2.1.1 + # via pytest-xdist +fastapi==0.115.8 + # via skore (skore/pyproject.toml) +filelock==3.17.0 + # via + # huggingface-hub + # virtualenv +fonttools==4.55.8 + # via matplotlib +fsspec==2024.12.0 + # via huggingface-hub +h11==0.14.0 + # via + # httpcore + # uvicorn +httpcore==1.0.7 + # via httpx +httpx==0.28.1 + # via skore (skore/pyproject.toml) +huggingface-hub==0.28.1 + # via skops +identify==2.6.6 + # via pre-commit +idna==3.10 + # via + # anyio + # httpx + # requests +iniconfig==2.0.0 + # via pytest +jinja2==3.1.5 + # via + # altair + # skrub +joblib==1.4.2 + # via + # scikit-learn + # skore (skore/pyproject.toml) +jsonschema==4.23.0 + # via altair +jsonschema-specifications==2024.10.1 + # via jsonschema +kiwisolver==1.4.7 + # via matplotlib +markdown-it-py==3.0.0 + # via rich +markupsafe==3.0.2 + # via jinja2 +matplotlib==3.9.4 + # via + # skore (skore/pyproject.toml) + # skrub +mdurl==0.1.2 + # via markdown-it-py +narwhals==1.24.1 + # via altair +nodeenv==1.9.1 + # via pre-commit +numpy==2.0.2 + # via + # contourpy + # matplotlib + # pandas + # scikit-learn + # scipy + # skore (skore/pyproject.toml) + # skrub +orjson==3.10.15 + # via skore (skore/pyproject.toml) +packaging==24.2 + # via + # altair + # huggingface-hub + # matplotlib + # plotly + # pytest + # skops + # skrub +pandas==2.2.3 + # via + # skore (skore/pyproject.toml) + # skrub +pillow==11.1.0 + # via + # matplotlib + # skore (skore/pyproject.toml) +platformdirs==4.3.6 + # via + # skore (skore/pyproject.toml) + # virtualenv +plotly==5.24.1 + # via skore (skore/pyproject.toml) +pluggy==1.5.0 + # via pytest +polars==1.21.0 + # via skore (skore/pyproject.toml) +pre-commit==4.1.0 + # via skore (skore/pyproject.toml) +psutil==6.1.1 + # via skore (skore/pyproject.toml) +pyarrow==19.0.0 + # via skore (skore/pyproject.toml) +pydantic==2.10.6 + # via fastapi +pydantic-core==2.27.2 + # via pydantic +pygments==2.19.1 + # via rich +pyparsing==3.2.1 + # via matplotlib +pytest==8.3.4 + # via + # pytest-cov + # pytest-order + # pytest-randomly + # pytest-xdist + # skore (skore/pyproject.toml) +pytest-cov==6.0.0 + # via skore (skore/pyproject.toml) +pytest-order==1.3.0 + # via skore (skore/pyproject.toml) +pytest-randomly==3.16.0 + # via skore (skore/pyproject.toml) +pytest-xdist==3.6.1 + # via skore (skore/pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2024.2 + # via pandas +pyyaml==6.0.2 + # via + # huggingface-hub + # pre-commit +referencing==0.36.2 + # via + # jsonschema + # jsonschema-specifications +requests==2.32.3 + # via + # huggingface-hub + # skrub +rich==13.9.4 + # via skore (skore/pyproject.toml) +rpds-py==0.22.3 + # via + # jsonschema + # referencing +ruff==0.9.3 + # via skore (skore/pyproject.toml) +scikit-learn==1.6.1 + # via + # skops + # skore (skore/pyproject.toml) + # skrub +scipy==1.13.1 + # via + # scikit-learn + # skrub +six==1.17.0 + # via python-dateutil +skops==0.11.0 + # via skore (skore/pyproject.toml) +skrub==0.5.1 + # via skore (skore/pyproject.toml) +sniffio==1.3.1 + # via anyio +starlette==0.45.3 + # via fastapi +tabulate==0.9.0 + # via skops +tenacity==9.0.0 + # via plotly +threadpoolctl==3.5.0 + # via scikit-learn +tqdm==4.67.1 + # via huggingface-hub +typing-extensions==4.12.2 + # via + # altair + # anyio + # fastapi + # huggingface-hub + # pydantic + # pydantic-core + # referencing +tzdata==2025.1 + # via pandas +urllib3==2.3.0 + # via requests +uvicorn==0.34.0 + # via skore (skore/pyproject.toml) +virtualenv==20.29.1 + # via pre-commit diff --git a/skore/hatch/metadata.py b/skore/hatch/metadata.py index cf5ab0944..bc8da2ab2 100644 --- a/skore/hatch/metadata.py +++ b/skore/hatch/metadata.py @@ -1,23 +1,71 @@ -import shutil from pathlib import Path -from contextlib import suppress from hatchling.metadata.plugin.interface import MetadataHookInterface +def readlines(filepath): + with open(filepath) as file: + yield from file + + class MetadataHook(MetadataHookInterface): def update(self, metadata): - license_path = Path(self.root, self.config["license-file"]) - license = license_path.read_text(encoding="utf-8") - readme = Path(self.root, self.config["readme-file"]).read_text(encoding="utf-8") - version = self.config["version-default"] + """ + Notes + ----- + Example of configuration: + + { + 'path': 'hatch/metadata.py', + 'version-default': '0.0.0+unknown', + 'license': {'file': '../LICENSE'}, + 'readme': {'file': '../README.md'}, + 'dependencies': {'file': 'requirements.in'}, + 'optional-dependencies': { + 'test': {'file': 'test-requirements.in'}, + 'sphinx': {'file': 'sphinx-requirements.in'}, + } + } + """ + + # Retrieve LICENCE from root files + license_filepath = self.config["license"]["file"] + license = Path(self.root, license_filepath).read_text(encoding="utf-8") + + # Copy LICENCE file in `sdist` + with open(Path(self.root, "LICENSE"), "w") as f: + f.write(license) - with suppress(FileNotFoundError): + # Retrieve README from root files + readme_filepath = self.config["readme"]["file"] + readme = Path(self.root, readme_filepath).read_text(encoding="utf-8") + + # Retrieve VERSION from file created by the CI + try: version = Path(self.root, "VERSION.txt").read_text(encoding="utf-8") + except FileNotFoundError: + version = self.config["version-default"] + + # Retrieve dependencies from requirements.in + dependencies_filepath = self.config["dependencies"]["file"] + dependencies = list(map(str.strip, readlines(dependencies_filepath))) + + # Retrieve optional dependencies from *-requirements.in + optional_dependencies_label_to_filepath = self.config["optional-dependencies"] + optional_dependencies = {} + for label, filepath in optional_dependencies_label_to_filepath.items(): + optional_dependencies_filepath = filepath["file"] + optional_dependencies[label] = list( + map( + str.strip, + readlines(optional_dependencies_filepath), + ) + ) + + # Update metadata metadata["license"] = {"text": license, "content-type": "text/plain"} metadata["readme"] = {"text": readme, "content-type": "text/markdown"} metadata["version"] = version - - license_dest = Path(self.root, license_path.name) - shutil.copy2(license_path, license_dest) + metadata["dependencies"] = dependencies + metadata["optional-dependencies"] = optional_dependencies diff --git a/skore/pyproject.toml b/skore/pyproject.toml index 797694760..5a3b34b8f 100644 --- a/skore/pyproject.toml +++ b/skore/pyproject.toml @@ -1,26 +1,15 @@ [project] name = "skore" description = "the scikit-learn sidekick" -dynamic = ["license", "readme", "version"] +dynamic = [ + "license", + "readme", + "version", + "dependencies", + "optional-dependencies", +] requires-python = ">=3.9, <3.13" maintainers = [{ name = "skore developers", email = "skore@signal.probabl.ai" }] -dependencies = [ - "diskcache", - "fastapi", - "joblib", - "matplotlib", - "numpy", - "orjson", - "pandas", - "plotly>=5,<6", - "pyarrow", - "rich", - "scikit-learn", - "skops", - "uvicorn", - "platformdirs", - "psutil", -] classifiers = [ "Intended Audience :: Science/Research", "Intended Audience :: Developers", @@ -56,9 +45,12 @@ build-backend = "hatchling.build" [tool.hatch.metadata.hooks.custom] path = "hatch/metadata.py" -license-file = "../LICENSE" -readme-file = "../README.md" version-default = "0.0.0+unknown" +license = { "file" = "../LICENSE" } +readme = { "file" = "../README.md" } +dependencies = { "file" = "requirements.in" } +optional-dependencies.test = { "file" = "test-requirements.in" } +optional-dependencies.sphinx = { "file" = "sphinx-requirements.in" } [tool.hatch.build.targets.sdist] only-include = ["src/", "hatch/"] @@ -68,41 +60,6 @@ artifacts = ["src/skore/ui/static/"] package = ["src/skore/"] artifacts = ["src/skore/ui/static/"] -[project.optional-dependencies] -test = [ - "altair>=5,<6", - "httpx", - "pillow", - "plotly", - "polars", - "pre-commit", - "pytest", - "pytest-cov", - "pytest-order", - "pytest-randomly", - "pytest-xdist", - "ruff", - "scikit-learn<1.7", - "skrub", -] - -sphinx = [ - "IPython", - "altair", - "numpydoc", - "polars", - "kaleido", - "pydata-sphinx-theme", - "sentence-transformers", - "sphinx", - "sphinx_autosummary_accessors", - "sphinx-design", - "sphinx-gallery", - "sphinx-copybutton", - "sphinx-tabs", - "skrub", -] - [tool.pytest.ini_options] addopts = [ "--doctest-modules", diff --git a/skore/requirements.in b/skore/requirements.in new file mode 100644 index 000000000..56f2c0a1b --- /dev/null +++ b/skore/requirements.in @@ -0,0 +1,15 @@ +diskcache +fastapi +joblib +matplotlib +numpy +orjson +pandas +platformdirs +plotly>=5,<6 +psutil +pyarrow +rich +scikit-learn +skops +uvicorn diff --git a/skore/sphinx-requirements.in b/skore/sphinx-requirements.in new file mode 100644 index 000000000..ac11433f0 --- /dev/null +++ b/skore/sphinx-requirements.in @@ -0,0 +1,14 @@ +IPython +altair +numpydoc +polars +kaleido +pydata-sphinx-theme +sentence-transformers +sphinx +sphinx_autosummary_accessors +sphinx-design +sphinx-gallery +sphinx-copybutton +sphinx-tabs +skrub diff --git a/skore/test-requirements.in b/skore/test-requirements.in new file mode 100644 index 000000000..1dbcf182e --- /dev/null +++ b/skore/test-requirements.in @@ -0,0 +1,14 @@ +altair>=5,<6 +httpx +pillow +plotly +polars +pre-commit +pytest +pytest-cov +pytest-order +pytest-randomly +pytest-xdist +ruff +scikit-learn<1.7 +skrub