diff --git a/.copier-answers.yml b/.copier-answers.yml index 950858d..db8c23b 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY -_commit: v0.11.0 +_commit: v0.14.2 _src_path: gl:znicholls/copier-core-python-repository conda_release: false email: zebedee.nicholls@climate-energy-college.org diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 533891a..4fd0ef1 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -20,7 +20,7 @@ runs: id: setup-uv uses: astral-sh/setup-uv@v4 with: - version: "0.5.21" + version: "0.8.8" python-version: ${{ inputs.python-version }} - name: Install dependencies shell: bash diff --git a/.github/workflows/bump.yaml b/.github/workflows/bump.yaml index 0159f38..8bcfa04 100644 --- a/.github/workflows/bump.yaml +++ b/.github/workflows/bump.yaml @@ -1,25 +1,21 @@ name: Bump version -# For the time being, we still do this with pdm. -# Honestly, it doesn't really matter, -# but one day uv will have a bump command too and we can switch to that. -# Relevant issue in uv: https://github.com/astral-sh/uv/issues/6298 on: workflow_dispatch: inputs: bump_rule: type: choice - description: How to bump the project's version (see https://github.com/carstencodes/pdm-bump#usage) + description: How to bump the project's version (see https://docs.astral.sh/uv/reference/cli/#uv-version) options: - - no-pre-release - # no micro because we always sit on a pre-release in main, - # so we would always use no-pre-release instead of micro - # - micro + - patch - minor - major - - "pre-release --pre alpha" - - "pre-release --pre beta" - - "pre-release --pre release-candidate" + - stable + - alpha + - beta + - rc + - post + - dev required: true jobs: @@ -29,7 +25,7 @@ jobs: strategy: matrix: os: [ "ubuntu-latest" ] - python-version: [ "3.9" ] + python-version: [ "3.11" ] runs-on: "${{ matrix.os }}" env: CI_COMMIT_EMAIL: "ci-runner@openscm-zenodo.invalid" @@ -40,15 +36,6 @@ jobs: fetch-depth: 0 token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}" - - name: Setup PDM - uses: pdm-project/setup-pdm@v4.1 - with: - python-version: ${{ matrix.python-version }} - - - name: Install pdm-bump - run: | - pdm self add pdm-bump - - uses: ./.github/actions/setup with: python-version: ${{ matrix.python-version }} @@ -59,13 +46,13 @@ jobs: git config --global user.name "$GITHUB_ACTOR" git config --global user.email "$CI_COMMIT_EMAIL" - BASE_VERSION=`sed -ne 's/^version = "\([0-9\.a]*\)"/\1/p' pyproject.toml` + BASE_VERSION=`sed -ne 's/^version = "\([0-9\.post]*\)"/\1/p' pyproject.toml` echo "Bumping from version $BASE_VERSION" # Bump - pdm bump ${{ github.event.inputs.bump_rule }} + uv version --bump ${{ github.event.inputs.bump_rule }} - NEW_VERSION=`sed -ne 's/^version = "\([0-9\.a]*\)"/\1/p' pyproject.toml` + NEW_VERSION=`sed -ne 's/^version = "\([0-9\.]*\)"/\1/p' pyproject.toml` echo "Bumping to version $NEW_VERSION" # Build CHANGELOG @@ -78,12 +65,12 @@ jobs: # Bump to alpha (so that future commits do not have the same # version as the tagged commit) - BASE_VERSION=`sed -ne 's/^version = "\([0-9\.a]*\)"/\1/p' pyproject.toml` + BASE_VERSION=`sed -ne 's/^version = "\([0-9\.]*\)"/\1/p' pyproject.toml` # Bump to pre-release of next version - pdm bump pre-release --pre alpha + uv version --bump post - NEW_VERSION=`sed -ne 's/^version = "\([0-9\.a]*\)"/\1/p' pyproject.toml` + NEW_VERSION=`sed -ne 's/^version = "\([0-9\.post]*\)"/\1/p' pyproject.toml` echo "Bumping version $BASE_VERSION > $NEW_VERSION" # Commit and push diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d78c71e..1af68e5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -143,7 +143,7 @@ jobs: id: setup-uv uses: astral-sh/setup-uv@v4 with: - version: "0.5.21" + version: "0.8.8" python-version: ${{ matrix.python-version }} - name: Create venv run: | @@ -187,8 +187,9 @@ jobs: - name: Install run: | pip install --upgrade pip wheel - pip install . - pip install -r requirements-only-tests-locked.txt + pip install --no-deps . + pip install -r requirements-locked.txt + pip install -r requirements-only-tests-min-locked.txt - name: Run tests run: | pytest tests -r a -vv tests @@ -204,12 +205,17 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v4 - - uses: ./.github/actions/setup + - name: Set up Python "${{ matrix.python-version }}" + id: setup-python + uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} - uv-dependency-install-flags: "--no-dev" # no extras is default + python-version: "${{ matrix.python-version }}" + - name: Install + run: | + pip install --upgrade pip wheel + pip install . - name: Check importable without extras - run: uv run python scripts/test-install.py + run: python scripts/test-install.py check-build: strategy: @@ -224,11 +230,15 @@ jobs: id: setup-uv uses: astral-sh/setup-uv@v4 with: - version: "0.5.21" + version: "0.8.8" python-version: ${{ matrix.python-version }} - name: Build package run: | + uv run python scripts/add-locked-targets-to-pyproject-toml.py + cat pyproject.toml uv build + # Just in case, undo the changes to `pyproject.toml` + git restore --staged . && git restore . - name: Check build run: | tar -tvf dist/openscm_zenodo-*.tar.gz --wildcards '*openscm_zenodo/py.typed' diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 61d70ee..e31361c 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -32,9 +32,12 @@ jobs: id: setup-uv uses: astral-sh/setup-uv@v4 with: - version: "0.5.21" + version: "0.8.8" python-version: ${{ matrix.python-version }} - name: Publish to PyPI run: | + uv run python scripts/add-locked-targets-to-pyproject-toml.py uv build uv publish + # Just in case, undo the changes to `pyproject.toml` + git restore --staged . && git restore . diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e5ffb4f..7a7fceb 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -14,7 +14,7 @@ jobs: strategy: matrix: os: [ "ubuntu-latest" ] - python-version: [ "3.9" ] + python-version: [ "3.11" ] runs-on: "${{ matrix.os }}" steps: - name: Check out repository @@ -25,15 +25,18 @@ jobs: id: setup-uv uses: astral-sh/setup-uv@v4 with: - version: "0.5.21" + version: "0.8.8" python-version: ${{ matrix.python-version }} - name: Add version to environment run: | - PROJECT_VERSION=`sed -ne 's/^version = "\([0-9\.a]*\)"/\1/p' pyproject.toml` + PROJECT_VERSION=`sed -ne 's/^version = "\([0-9\.]*\)"/\1/p' pyproject.toml` echo "PROJECT_VERSION=$PROJECT_VERSION" >> $GITHUB_ENV - name: Build package for PyPI run: | + uv run python scripts/add-locked-targets-to-pyproject-toml.py uv build + # Just in case, undo the changes to `pyproject.toml` + git restore --staged . && git restore . - name: Generate Release Notes run: | echo "" >> ".github/release_template.md" diff --git a/.github/workflows/test-upstream-latest.yaml b/.github/workflows/test-upstream-latest.yaml index 809a76a..0d51ee4 100644 --- a/.github/workflows/test-upstream-latest.yaml +++ b/.github/workflows/test-upstream-latest.yaml @@ -36,7 +36,7 @@ jobs: id: setup-uv uses: astral-sh/setup-uv@v4 with: - version: "0.5.21" + version: "0.8.8" python-version: ${{ matrix.python-version }} # Often you need a step like this for e.g. numpy, scipy, pandas - name: Setup compilation dependencies diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 97cf330..2c78fa4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ ci: autoupdate_schedule: quarterly autoupdate_branch: pre-commit-autoupdate # Currently network access isn't supported in the pre-commit CI product. - skip: [uv-sync, uv-lock, uv-export, pdm-lock-check] + skip: [uv-sync, uv-lock, uv-export] # See https://pre-commit.com/hooks.html for more hooks repos: @@ -60,19 +60,3 @@ repos: args: ["-o", "requirements-only-tests-locked.txt", "--no-hashes", "--no-dev", "--no-emit-project", "--only-group", "tests"] # # Not released yet # - id: uv-sync - - repo: https://github.com/pdm-project/pdm - rev: 2.22.1 - hooks: - # Update the `pdm.lock` file if needed. - # We need the pdm lock file too - # so that we can build the locked version of the package. - - name: pdm-lock - id: pdm-lock-check - # Overwrite the hook's standard entry point to get the behaviour we want - entry: pdm lock - args: ["--group", ":all", "--strategy", "inherit_metadata"] - files: ^pyproject.toml$ - pass_filenames: false - # Double check that the `pdm.lock` file is up to date. - - id: pdm-lock-check - args: ["--group", ":all", "--strategy", "inherit_metadata"] diff --git a/Makefile b/Makefile index db9a8a3..155bd01 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ ruff-fixes: ## fix the code using ruff .PHONY: test test: ## run the tests - uv run pytest src tests -r a -v --doctest-modules --cov=src + uv run pytest src tests -r a -v --doctest-modules --doctest-report ndiff --cov=src # Note on code coverage and testing: # You must specify cov=src. @@ -80,12 +80,6 @@ licence-check: ## Check that licences of the dependencies are suitable uv run liccheck -r $(TEMP_FILE) -R licence-check.txt rm -f $(TEMP_FILE) -.PHONY: pdm-lock -pdm-lock: pdm.lock ## create/update the `pdm.lock` file - -pdm.lock: pyproject.toml - pdm lock --group :all --strategy inherit_metadata - .PHONY: virtual-environment virtual-environment: ## update virtual environment, create a new one if it doesn't already exist uv sync --all-extras --group all-dev diff --git a/changelog/18.trivial.md b/changelog/18.trivial.md new file mode 100644 index 0000000..0663d7d --- /dev/null +++ b/changelog/18.trivial.md @@ -0,0 +1 @@ +Updated to the latest version of the copier template diff --git a/docs/development.md b/docs/development.md index 859b48d..a6dd5a7 100644 --- a/docs/development.md +++ b/docs/development.md @@ -48,8 +48,8 @@ should change depending on the updates to the code base. Releasing is semi-automated via a CI job. The CI job requires the type of version bump that will be performed to be manually specified. -See the pdm-bump docs for the -[list of available bump rules](https://github.com/carstencodes/pdm-bump#usage). +See the `uv version` docs (specifically the `--bump` flag) for the +[list of available bump rules](https://docs.astral.sh/uv/reference/cli/#uv-version). ### Standard process @@ -57,7 +57,7 @@ The steps required are the following: 1. Bump the version: manually trigger the "bump" workflow from the main branch (see here: [bump workflow](https://github.com/openscm/OpenSCM-zenodo/actions/workflows/bump.yaml)). - A valid "bump_rule" (see [pdm-bump's docs](https://github.com/carstencodes/pdm-bump#usage)) + A valid "bump_rule" (see [uv's docs](https://docs.astral.sh/uv/reference/cli/#uv-version)) will need to be specified. This will then trigger a draft release. @@ -74,16 +74,15 @@ The steps required are the following: else 1. Enjoy the newly available version +[TODO: add in conda release instructions] #### Further details -We use [pdm](https://pdm-project.org/en/latest/) for building our project, -while [uv figures out how it wants to support building](https://github.com/astral-sh/uv/issues/3957). -This gives us the added benefit that we can use -[pdm-build-locked](https://pdm-build-locked.readthedocs.io/en/stable/) -to build locked versions of our package. -It is for these reasons that we have a pdm pre-commit hook -and a `pdm.lock` file in our repository. +We use [uv's build backend](https://docs.astral.sh/uv/concepts/build-backend) for building our project +and `scripts/add-locked-targets-to-pyproject-toml.py` +to provide locked extra groups for our package. +Including locked extra groups is why we run `scripts/add-locked-targets-to-pyproject-toml.py` +before any step related to building the package in the CI. ## Read the Docs diff --git a/docs/further-background/dependency-pinning-and-testing.md b/docs/further-background/dependency-pinning-and-testing.md index 252dc59..518fb95 100644 --- a/docs/further-background/dependency-pinning-and-testing.md +++ b/docs/further-background/dependency-pinning-and-testing.md @@ -24,8 +24,7 @@ In the majority of cases, new releases do not cause issues so pinning simply forces users to workaround overly strict pins[^1] (which can be done, see [working around incorrectly set pins][working-around-incorrectly-set-pins]). -The tradeoff with this approach is -This does run the risk that, +The tradeoff with this approach is that you run the risk that, if a dependency releases a breaking change, the function provided by our package may break too. @@ -128,7 +127,7 @@ Finally, we also check the installation of the locked versions of the package, i.e. installation with `pip install 'openscm-zenodo[locked]'`. These tests give us the greatest coverage of Python versions and operating systems and help alert us to places where users may face issues. -Having said that, these tests do require 30 separate CI runs, +Having said that, these tests do require 30 separate jobs, which is why we don't run them in CI. Through this combination of CI testing and installation testing, @@ -136,4 +135,4 @@ we get a pretty good coverage of the different ways in which our package can be It is not perfect, largely because the combinatorics don't allow for testing everything. If we find a particular, key, use case failing often, then we would happily discuss whether this should be included in the CI too, -to catch issues earlier than at user time. +to catch issues in advance of use. diff --git a/mkdocs.yml b/mkdocs.yml index 05508ca..e90b0fb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -70,7 +70,7 @@ plugins: handlers: python_xref: paths: [src] - import: + inventories: # Cross-ref helpers (lots included here, remove what you don't want) - https://www.attrs.org/en/stable/objects.inv - https://unidata.github.io/cftime/objects.inv @@ -87,11 +87,25 @@ plugins: - https://docs.scipy.org/doc/scipy/objects.inv - https://scitools-iris.readthedocs.io/en/stable/objects.inv - https://scmdata.readthedocs.io/en/stable/objects.inv + # # Not available for tqdm + # # https://github.com/tqdm/tqdm/issues/705 + # - https://tqdm.github.io/objects.inv - https://validators.readthedocs.io/en/stable/objects.inv - http://xarray.pydata.org/en/stable/objects.inv options: + # It turns out that xref does this check without considering config. + # As a result, every docstring is parsed as a google-style docstring. + # As docstrings are only parsed once, this results in rendering failures. + # Hence, turn off the checks here. + # mkdocs_autorefs catches anything which doesn't end up being a correct reference. + # The fix might be as simple as changing + # `self.collect(ref, PythonOptions())` + # to `self.collect(ref, self.get_options({}))` + # in the python-xref source, but it's hard to predict the side effects + # so we haven't bothered with that route. + check_crossrefs: false docstring_style: numpy - relative_crossrefs: yes + relative_crossrefs: true separate_signature: true show_root_heading: false show_signature_annotations: true @@ -111,6 +125,7 @@ plugins: markdown_extensions: # https://squidfunk.github.io/mkdocs-material/setup/extensions/python-markdown/#attribute-lists - attr_list + - footnotes # https://squidfunk.github.io/mkdocs-material/reference/math/#katex-mkdocsyml - pymdownx.arithmatex: generic: true diff --git a/pyproject.toml b/pyproject.toml index 5e36e67..9394f7e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,35 +60,54 @@ dev = [ "towncrier==24.8.0", "types-tqdm>=4.66.0.20240417", "types-requests>=2.32.0.20240712", + "tomli-w>=1.2.0", ] docs = [ # Key dependencies # ---------------- - "attrs==24.3.0", - "mkdocs-autorefs==1.2.0", + "attrs==25.3.0", + "mkdocs-autorefs==1.4.2", "mkdocs-gen-files==0.5.0", - "mkdocs-literate-nav==0.6.1", - "mkdocs-material==9.5.49", - "mkdocs-section-index==0.3.9", + "mkdocs-literate-nav==0.6.2", + "mkdocs-material==9.6.16", + "mkdocs-section-index==0.3.10", "mkdocs==1.6.1", - "mkdocstrings-python-xref==1.6.2", - "mkdocstrings-python==1.13.0", - "pymdown-extensions==10.13", - "ruff==0.8.6", + "mkdocstrings-python-xref==1.16.3", + "mkdocstrings-python==1.16.12", + "pymdown-extensions==10.16.1", + "ruff==0.12.8", # Key dependencies for notebook_based_docs # ---------------------------------------- - "jupyterlab==4.3.4", - "jupytext==1.16.6", + "jupyterlab==4.4.5", + "jupytext==1.17.2", "mkdocs-jupyter==0.25.1", ] # For minimum test dependencies. # These are used when running our minimum PyPI install tests. tests-min = [ - "pytest-cov==6.0.0", + # Key dependencies + # ---------------- "pytest==8.3.4", + # Implied by the key dependencies above + # ------------------------------------- + "colorama==0.4.6 ; sys_platform == 'win32'", + "iniconfig==2.0.0", + "packaging==24.2", + "pluggy==1.5.0", ] # Full test dependencies. tests-full = [ + # Key dependencies + # ---------------- + "pytest-cov==6.0.0", + # Implied by the key dependencies above + # ------------------------------------- + "colorama==0.4.6 ; sys_platform == 'win32'", + "coverage==7.6.10", + "iniconfig==2.0.0", + "packaging==24.2", + "pluggy==1.5.0", + "pytest==8.3.4", ] # Test dependencies # (partly split because liccheck uses toml, @@ -104,16 +123,11 @@ all-dev = [ ] [build-system] -requires = [ - "pdm-backend", - "pdm-build-locked", -] -build-backend = "pdm.backend" +requires = ["uv_build>=0.8.7,<0.9.0"] +build-backend = "uv_build" -[tool.pdm] -[tool.pdm.build] -locked = true -includes = [ +[tool.uv.build-backend] +source-include = [ "src/openscm_zenodo", "LICENCE", ] diff --git a/requirements-docs-locked.txt b/requirements-docs-locked.txt index 708d072..201f01e 100644 --- a/requirements-docs-locked.txt +++ b/requirements-docs-locked.txt @@ -7,8 +7,9 @@ argon2-cffi-bindings==21.2.0 arrow==1.3.0 asttokens==3.0.0 async-lru==2.0.4 -attrs==24.3.0 +attrs==25.3.0 babel==2.17.0 +backrefs==5.9 beautifulsoup4==4.13.3 bleach==6.2.0 certifi==2025.1.31 @@ -25,7 +26,7 @@ executing==2.2.0 fastjsonschema==2.21.1 fqdn==1.5.1 ghp-import==2.1.0 -griffe==1.5.7 +griffe==1.11.0 h11==0.14.0 httpcore==1.0.7 httpx==0.28.1 @@ -47,10 +48,10 @@ jupyter-events==0.12.0 jupyter-lsp==2.2.5 jupyter-server==2.15.0 jupyter-server-terminals==0.5.3 -jupyterlab==4.3.4 +jupyterlab==4.4.5 jupyterlab-pygments==0.3.0 jupyterlab-server==2.27.3 -jupytext==1.16.6 +jupytext==1.17.2 loguru==0.7.3 markdown==3.7 markdown-it-py==3.0.0 @@ -61,17 +62,17 @@ mdurl==0.1.2 mergedeep==1.3.4 mistune==3.1.1 mkdocs==1.6.1 -mkdocs-autorefs==1.2.0 +mkdocs-autorefs==1.4.2 mkdocs-gen-files==0.5.0 mkdocs-get-deps==0.2.0 mkdocs-jupyter==0.25.1 -mkdocs-literate-nav==0.6.1 -mkdocs-material==9.5.49 +mkdocs-literate-nav==0.6.2 +mkdocs-material==9.6.16 mkdocs-material-extensions==1.3.1 -mkdocs-section-index==0.3.9 -mkdocstrings==0.27.0 -mkdocstrings-python==1.13.0 -mkdocstrings-python-xref==1.6.2 +mkdocs-section-index==0.3.10 +mkdocstrings==0.30.0 +mkdocstrings-python==1.16.12 +mkdocstrings-python-xref==1.16.3 nbclient==0.10.2 nbconvert==7.16.6 nbformat==5.10.4 @@ -92,7 +93,7 @@ ptyprocess==0.7.0 ; (python_full_version < '3.10' and sys_platform == 'emscripte pure-eval==0.2.3 pycparser==2.22 pygments==2.19.1 -pymdown-extensions==10.13 +pymdown-extensions==10.16.1 python-dateutil==2.9.0.post0 python-json-logger==3.2.1 pywin32==308 ; platform_python_implementation != 'PyPy' and sys_platform == 'win32' @@ -101,13 +102,12 @@ pyyaml==6.0.2 pyyaml-env-tag==0.1 pyzmq==26.2.1 referencing==0.36.2 -regex==2024.11.6 requests==2.32.3 rfc3339-validator==0.1.4 rfc3986-validator==0.1.1 rich==13.9.4 rpds-py==0.22.3 -ruff==0.8.6 +ruff==0.12.8 send2trash==1.8.3 setuptools==75.6.0 shellingham==1.5.4 diff --git a/requirements-locked.txt b/requirements-locked.txt index 881f204..72d7a23 100644 --- a/requirements-locked.txt +++ b/requirements-locked.txt @@ -1,6 +1,6 @@ # This file was autogenerated by uv via the following command: # uv export -o requirements-locked.txt --no-hashes --no-dev --no-emit-project -attrs==24.3.0 +attrs==25.3.0 certifi==2025.1.31 charset-normalizer==3.4.1 click==8.1.8 diff --git a/requirements-only-tests-locked.txt b/requirements-only-tests-locked.txt index c5338c3..5a44e6f 100644 --- a/requirements-only-tests-locked.txt +++ b/requirements-only-tests-locked.txt @@ -1,7 +1,7 @@ # This file was autogenerated by uv via the following command: # uv export -o requirements-only-tests-locked.txt --no-hashes --no-dev --no-emit-project --only-group tests colorama==0.4.6 ; sys_platform == 'win32' -coverage==7.6.12 +coverage==7.6.10 exceptiongroup==1.2.2 ; python_full_version < '3.11' iniconfig==2.0.0 packaging==24.2 diff --git a/requirements-only-tests-min-locked.txt b/requirements-only-tests-min-locked.txt index fe0de9a..4d58c46 100644 --- a/requirements-only-tests-min-locked.txt +++ b/requirements-only-tests-min-locked.txt @@ -1,11 +1,9 @@ # This file was autogenerated by uv via the following command: # uv export -o requirements-only-tests-min-locked.txt --no-hashes --no-dev --no-emit-project --only-group tests-min colorama==0.4.6 ; sys_platform == 'win32' -coverage==7.6.12 exceptiongroup==1.2.2 ; python_full_version < '3.11' iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 pytest==8.3.4 -pytest-cov==6.0.0 -tomli==2.2.1 ; python_full_version <= '3.11' +tomli==2.2.1 ; python_full_version < '3.11' diff --git a/scripts/add-locked-targets-to-pyproject-toml.py b/scripts/add-locked-targets-to-pyproject-toml.py new file mode 100644 index 0000000..96514ab --- /dev/null +++ b/scripts/add-locked-targets-to-pyproject-toml.py @@ -0,0 +1,85 @@ +""" +Add locked targets to `pyproject.toml` + +This adds a "locked" target +plus a "