From 41de7c113e7ab451cc9e9f8c6287f74e3cdd82a9 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Mon, 22 Jun 2026 15:42:02 +0200 Subject: [PATCH 01/27] Use mypy from pixi environment --- .pre-commit-config.yaml | 20 ++- esmvalcore/cmor/_fixes/cordex/cordex_fixes.py | 2 +- esmvalcore/io/intake_esgf.py | 6 +- esmvalcore/preprocessor/_io.py | 6 +- pixi.lock | 142 ++++++++++++++++++ pyproject.toml | 6 + 6 files changed, 169 insertions(+), 13 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 983593ddbf..6f3fe99dcb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,14 +31,20 @@ repos: - id: ruff-check args: [--fix] - id: ruff-format - - repo: https://github.com/pre-commit/mirrors-mypy - rev: "v2.1.0" + - repo: local hooks: - - id: mypy - additional_dependencies: - - "types-PyYAML" - - "types-requests" - - "numpy" + - id: type-check + name: type-check + entry: "pixi run --locked type-check" + # This uses local pixi installation + language: system + types: + - python + pass_filenames: false + # use require_serial so that script is only called once per commit + require_serial: true + verbose: false + always_run: false - repo: https://github.com/adrienverge/yamllint rev: "v1.38.0" hooks: diff --git a/esmvalcore/cmor/_fixes/cordex/cordex_fixes.py b/esmvalcore/cmor/_fixes/cordex/cordex_fixes.py index c3e5556687..e297feee80 100644 --- a/esmvalcore/cmor/_fixes/cordex/cordex_fixes.py +++ b/esmvalcore/cmor/_fixes/cordex/cordex_fixes.py @@ -311,7 +311,7 @@ def _use_standard_lambert_conformal_grid( lon_coord.units = "degrees_east" lat_coord.units = "degrees_north" lon_coord.points, lat_coord.points = transformer.transform( - *np.meshgrid(x_coord.points, y_coord.points), + *np.meshgrid(x_coord.points, y_coord.points), # type: ignore[call-overload] errcheck=True, ) diff --git a/esmvalcore/io/intake_esgf.py b/esmvalcore/io/intake_esgf.py index 2375958517..9142b883bf 100644 --- a/esmvalcore/io/intake_esgf.py +++ b/esmvalcore/io/intake_esgf.py @@ -38,6 +38,8 @@ from esmvalcore.iris_helpers import dataset_to_iris if TYPE_CHECKING: + from collections.abc import Mapping + import iris.cube from esmvalcore.typing import Facets, FacetValue @@ -85,7 +87,7 @@ def to_path_dict( quiet: bool = False, ) -> dict[str, list[str | Path]]: """Return the current search as a dictionary of paths to files.""" - kwargs = { + kwargs: Mapping[str, Any] = { "prefer_streaming": prefer_streaming, "globus_endpoint": globus_endpoint, "globus_path": globus_path, @@ -250,7 +252,7 @@ def find_data(self, **facets: FacetValue) -> list[IntakeESGFDataset]: if not any(_isglob(v) for v in values) } # Translate "our" facets to ESGF facets and "our" values to ESGF values. - query = { + query: dict[str, Any] = { their_facet: [ self.values.get(our_facet, {}).get(v, v) for v in non_glob_facets[our_facet] diff --git a/esmvalcore/preprocessor/_io.py b/esmvalcore/preprocessor/_io.py index 34b3838120..2b78838f79 100644 --- a/esmvalcore/preprocessor/_io.py +++ b/esmvalcore/preprocessor/_io.py @@ -25,7 +25,7 @@ from esmvalcore.iris_helpers import dataset_to_iris if TYPE_CHECKING: - from collections.abc import Sequence + from collections.abc import Mapping, MutableMapping, Sequence from dask.delayed import Delayed @@ -163,7 +163,7 @@ def load( def _load_zarr( file: str | Path, ignore_warnings: list[dict[str, Any]] | None = None, - backend_kwargs: dict[str, Any] | None = None, + backend_kwargs: Mapping[str, Any] | None = None, ) -> CubeList: # note on ``chunks`` kwarg to ``xr.open_dataset()`` # docs.xarray.dev/en/stable/generated/xarray.open_dataset.html @@ -177,7 +177,7 @@ def _load_zarr( # https://github.com/pp-mo/ncdata/issues/139 time_coder = xr.coders.CFDatetimeCoder(use_cftime=True) - open_kwargs = { + open_kwargs: MutableMapping[str, Any] = { "consolidated": False, "decode_times": time_coder, "engine": "zarr", diff --git a/pixi.lock b/pixi.lock index 6210e42121..a1507a02c1 100644 --- a/pixi.lock +++ b/pixi.lock @@ -13,6 +13,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/apsw-3.53.1.0-py314h5bd0f2a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py314h5bd0f2a_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ast-serialize-0.5.0-py310hd8a072f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-atk-2.38.0-h0630a04_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-core-2.40.3-h0630a04_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda @@ -184,6 +185,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/mmh3-5.2.1-py314ha160325_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py314h9891dd4_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/muparser-2.3.5-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-2.1.0-py314h518bba1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf-fortran-4.6.2-nompi_h4a60669_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.7.4-nompi_py311h498b1eb_107.conda @@ -211,6 +213,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/pyproj-3.7.2-py314h7ce3bca_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.5-habeac84_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-eccodes-2.47.0-np2py314h56abb78_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-librt-0.11.0-py314h0f05182_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-stratify-0.4.0-py314h5bd0f2a_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-xxhash-3.7.0-py314he82b845_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda @@ -392,6 +395,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/multidict-6.7.1-pyh62beb40_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/myproxyclient-2.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/myst-nb-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/myst-parser-5.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda @@ -411,6 +415,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.1.2-pyh145f28c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.10.0-pyhcf101f3_0.conda @@ -650,6 +655,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/multidict-6.7.1-pyh62beb40_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/myproxyclient-2.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/myst-nb-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/myst-parser-5.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda @@ -669,6 +675,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.1.2-pyh145f28c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.10.0-pyhcf101f3_0.conda @@ -775,6 +782,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/apsw-3.53.1.0-py314h6c2aa35_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ast-serialize-0.5.0-py310h3b8a9b8_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/atk-1.0-2.38.0-hd03087b_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.10.1-ha7d4cc1_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.9.13-h6ee9776_1.conda @@ -923,6 +931,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mmh3-5.2.1-py314h4ed92d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgpack-python-1.1.2-py314h784bc60_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/muparser-2.3.5-h11e0b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-2.1.0-py314h2fbedac_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/netcdf-fortran-4.6.2-nompi_h7d4a3b5_105.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/netcdf4-1.7.4-nompi_py311hfd37af6_107.conda @@ -952,6 +961,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyproj-3.7.2-py314h986c384_4.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.5-h4c637c5_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-eccodes-2.47.0-np2py314h4e57505_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-librt-0.11.0-py314ha14b1ff_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-stratify-0.4.0-py314h0612a62_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-xxhash-3.7.0-py314hd7fbd5c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda @@ -5112,6 +5122,25 @@ packages: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping size: 35598 timestamp: 1762509505285 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ast-serialize-0.5.0-py310hd8a072f_1.conda + noarch: python + sha256: cf1cf3d0fa59fe0ab6bc3af722d820c1a85a9233c786f614f377c651fec6a7f9 + md5: 6adea4814147f458d6278d053850b0ac + depends: + - python >=3.10 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - _python_abi3_support 1.* + - cpython >=3.10 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ast-serialize?source=hash-mapping + run_exports: {} + size: 1125371 + timestamp: 1780396651124 - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-atk-2.38.0-h0630a04_3.tar.bz2 sha256: 26ab9386e80bf196e51ebe005da77d57decf6d989b4f34d96130560bc133479c md5: 6b889f174df1e0f816276ae69281af4d @@ -8619,6 +8648,27 @@ packages: purls: [] size: 203174 timestamp: 1747116762269 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-2.1.0-py314h518bba1_0.conda + sha256: 9fcf9e7343c30fdeab75e8440caa2814798eeff22a6dc5f7a556df8372e1b0ca + md5: 5625fce7423d7579e60f9cbcc5738d2b + depends: + - ast-serialize >=0.3.0,<1.0.0 + - mypy_extensions >=1.0.0 + - pathspec >=1.0.0 + - python + - python-librt >=0.11.0 + - typing_extensions >=4.6.0 + - psutil >=4.0 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mypy?source=hash-mapping + run_exports: {} + size: 22860519 + timestamp: 1780315602311 - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda sha256: fc89f74bbe362fb29fa3c037697a89bec140b346a2469a90f7936d1d7ea4d8a3 md5: fc21868a1a5aacc937e7a18747acb8a5 @@ -9661,6 +9711,21 @@ packages: - pkg:pypi/eccodes?source=hash-mapping size: 241426 timestamp: 1777545172589 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-librt-0.11.0-py314h0f05182_0.conda + sha256: 4529fdc71dcaa13ad25c4708751029c56f507f7d26f1748f20875cea85a158fa + md5: 1c6a332e01cd8f81f350434fbf7bcaad + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/librt?source=hash-mapping + run_exports: {} + size: 156252 + timestamp: 1778511622812 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-stratify-0.4.0-py312h4c3975b_3.conda sha256: 89ad22ddc2be4a0faacfc1209c8053fbff94fb1ac6ecf5b9d53767c46bf9b4f4 md5: b0610b4174af97290f5f466a72583071 @@ -12681,6 +12746,18 @@ packages: - pkg:pypi/myproxyclient?source=hash-mapping size: 45567 timestamp: 1759838155628 +- conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda + sha256: 6ed158e4e5dd8f6a10ad9e525631e35cee8557718f83de7a4e3966b1f772c4b1 + md5: e9c622e0d00fa24a6292279af3ab6d06 + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mypy-extensions?source=hash-mapping + run_exports: {} + size: 11766 + timestamp: 1745776666688 - conda: https://conda.anaconda.org/conda-forge/noarch/myst-nb-1.4.0-pyhcf101f3_0.conda sha256: c81d0c8c74c3da66808f8da09d8e48f2af2d173d357d45239defaf466838edba md5: da07c7b1588ad0a44118d28aeb31b6a6 @@ -12958,6 +13035,18 @@ packages: - pkg:pypi/partd?source=hash-mapping size: 20884 timestamp: 1715026639309 +- conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.1.1-pyhd8ed1ab_0.conda + sha256: 6eaee417d33f298db79bc7185ab1208604c0e6cf51dade34cd513c6f9db9c6f3 + md5: 11adc78451c998c0fd162584abfa3559 + depends: + - python >=3.10 + license: MPL-2.0 + license_family: MOZILLA + purls: + - pkg:pypi/pathspec?source=hash-mapping + run_exports: {} + size: 56559 + timestamp: 1777271601895 - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda sha256: 202af1de83b585d36445dc1fda94266697341994d1a3328fabde4989e1b3d07a md5: d0d408b1f18883a944376da5cf8101ea @@ -14552,6 +14641,24 @@ packages: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping size: 34218 timestamp: 1762509977830 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ast-serialize-0.5.0-py310h3b8a9b8_1.conda + noarch: python + sha256: 6c6e47ef2a85e7ade5c94d2388f43bd8197129e6b6305f9e8a49380b7dfbc427 + md5: 480f5277fd3ed13ea6ea8b5d74563815 + depends: + - python >=3.10 + - __osx >=11.0 + - _python_abi3_support 1.* + - cpython >=3.10 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ast-serialize?source=hash-mapping + run_exports: {} + size: 1086020 + timestamp: 1780396657560 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/atk-1.0-2.38.0-hd03087b_2.conda sha256: b0747f9b1bc03d1932b4d8c586f39a35ac97e7e72fe6e63f2b2a2472d466f3c1 md5: 57301986d02d30d6805fdce6c99074ee @@ -17955,6 +18062,26 @@ packages: purls: [] size: 154087 timestamp: 1747117056226 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-2.1.0-py314h2fbedac_0.conda + sha256: d205dc89fa338ca312ed54864ca377e9a52e4273509370c3678503115c95eb05 + md5: 54f38ddefd5fbd675bc9ff69d7a31fd7 + depends: + - ast-serialize >=0.3.0,<1.0.0 + - mypy_extensions >=1.0.0 + - pathspec >=1.0.0 + - python + - python-librt >=0.11.0 + - typing_extensions >=4.6.0 + - psutil >=4.0 + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mypy?source=hash-mapping + run_exports: {} + size: 13520137 + timestamp: 1780315680928 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda sha256: 4ea6c620b87bd1d42bb2ccc2c87cd2483fa2d7f9e905b14c223f11ff3f4c455d md5: 343d10ed5b44030a2f67193905aea159 @@ -18997,6 +19124,21 @@ packages: - pkg:pypi/eccodes?source=hash-mapping size: 250582 timestamp: 1777545231051 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-librt-0.11.0-py314ha14b1ff_0.conda + sha256: 483c34d3224b1d8209206d5eba7b0f36f33a891908eec46d12a7a621d0a39001 + md5: 68be11fb4ea06efd0e13db21921afe56 + depends: + - python + - __osx >=11.0 + - python 3.14.* *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/librt?source=hash-mapping + run_exports: {} + size: 129714 + timestamp: 1778511905677 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-stratify-0.4.0-py312h4409184_3.conda sha256: 1ff8e204e8ba4c965da0a3d95ca177149f338d50a258a3f5cfdcacc95698dab6 md5: 6bca21dd95ce7b36d983fa6a3b831b4a diff --git a/pyproject.toml b/pyproject.toml index d8bc48dc15..1d06747cad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -141,6 +141,10 @@ ignore_missing_imports = true enable_error_code = [ "truthy-bool", ] +exclude = [ + "^doc/conf.py$", + "esmvalcore/cmor/tables/", +] # Configure linters @@ -296,6 +300,7 @@ test-r = { features = ["test-r"], solve-group = "test-r" } # Other development tools. [tool.pixi.feature.dev.dependencies] "jupyterlab" = "*" +"mypy" = "*" "pre-commit" = "*" "py-spy" = "*" @@ -314,4 +319,5 @@ test-r = { features = ["test-r"], solve-group = "test-r" } # Tasks for use with `pixi run `. [tool.pixi.tasks] test = {cmd = "pytest", description = "Run the tests"} +type-check = {cmd = "mypy esmvalcore", description = "Run the type checks"} doc = {cmd = "sphinx-build doc html", description = "Build the documentation"} From 3cef218111a526ed6d5e2063d732875208b8c021 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 16 Jul 2026 15:27:26 +0200 Subject: [PATCH 02/27] Also use ruff from pixi env and configure dependabot for pre-commit --- .github/dependabot.yml | 18 ++++++ .pre-commit-config.yaml | 28 ++++++--- pixi.lock | 135 ++++++++++++++++++++++++++-------------- pyproject.toml | 3 +- 4 files changed, 126 insertions(+), 58 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b8a7c258bc..446682c200 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,6 +14,24 @@ updates: interval: "weekly" cooldown: default-days: 7 + groups: + gha: + patterns: + - "*" + labels: + - dependencies + - github_actions + - automatedPR + - package-ecosystem: "pre-commit" + directory: "/" + schedule: + interval: "weekly" + cooldown: + default-days: 7 + groups: + pre-commit: + patterns: + - "*" labels: - dependencies - github_actions diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6f3fe99dcb..58bd2e3c2d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,23 +25,31 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace args: [--markdown-linebreak-ext=md] - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.15.17" + - repo: local hooks: - id: ruff-check - args: [--fix] + name: ruff check + entry: "pixi run --locked ruff check --force-exclude --fix" + language: system + require_serial: true + types_or: + - python + - jupyter - id: ruff-format - - repo: local - hooks: - - id: type-check - name: type-check - entry: "pixi run --locked type-check" - # This uses local pixi installation + name: ruff format + entry: "pixi run --locked ruff format --force-exclude" + language: system + require_serial: true + types_or: + - python + - jupyter + - id: mypy + name: mypy + entry: "pixi run --locked mypy" language: system types: - python pass_filenames: false - # use require_serial so that script is only called once per commit require_serial: true verbose: false always_run: false diff --git a/pixi.lock b/pixi.lock index a1507a02c1..48b7ce46eb 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1,7 +1,16 @@ version: 7 platforms: - name: linux-64 + virtual-packages: + - __unix=0=0 + - __linux=4.18 + - __glibc=2.28 + - __archspec=0=x86_64 - name: osx-arm64 + virtual-packages: + - __unix=0=0 + - __osx=13.0 + - __archspec=0=m1 environments: default: channels: @@ -222,6 +231,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2025.11.05-h5301d42_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-2026.5.1-py314h1bee95f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.15.21-h462bb3b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.7.3-hc5a330e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.17.1-py314hf07bd8e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/shapely-2.1.2-py314hbe3edd8_2.conda @@ -519,7 +529,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/zarr-3.2.1-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - - pypi: . + - pypi: ./ osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.5-pyhd8ed1ab_1.conda @@ -970,6 +980,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2025.11.05-ha480c28_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-2026.5.1-py314he1d1ac0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.15.21-h828de30_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.17.1-py314h18e1515_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/shapely-2.1.2-py314h277790e_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda @@ -992,7 +1003,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: . + - pypi: ./ esmvalcore: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -1405,7 +1416,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/zarr-3.2.1-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - - pypi: . + - pypi: ./ osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda @@ -1772,7 +1783,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: . + - pypi: ./ test-py312: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -2194,7 +2205,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/zarr-3.2.1-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - - pypi: . + - pypi: ./ osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda @@ -2569,7 +2580,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: . + - pypi: ./ test-py313: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -2989,7 +3000,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/zarr-3.2.1-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - - pypi: . + - pypi: ./ osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda @@ -3363,7 +3374,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: . + - pypi: ./ test-py314: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -3785,7 +3796,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/zarr-3.2.1-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - - pypi: . + - pypi: ./ osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-49.0-unix_0.conda @@ -4161,7 +4172,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: . + - pypi: ./ test-r: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -4594,7 +4605,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/zarr-3.2.1-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - - pypi: . + - pypi: ./ osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_r-mutex-1.0.1-anacondar_1.tar.bz2 @@ -5004,7 +5015,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - - pypi: . + - pypi: ./ packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda build_number: 20 @@ -6646,7 +6657,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/greenlet?source=compressed-mapping + - pkg:pypi/greenlet?source=hash-mapping size: 264973 timestamp: 1779292370689 - conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.7-he838d99_0.tar.bz2 @@ -8277,7 +8288,7 @@ packages: - python_abi 3.14.* *_cp314 license: BSD-3-Clause and MIT-CMU purls: - - pkg:pypi/lxml?source=compressed-mapping + - pkg:pypi/lxml?source=hash-mapping size: 1583195 timestamp: 1779194870520 - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-4.4.5-py312h3d67a73_1.conda @@ -8849,7 +8860,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/numpy?source=compressed-mapping + - pkg:pypi/numpy?source=hash-mapping size: 8928909 timestamp: 1779169198391 - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda @@ -9067,7 +9078,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/pandas?source=compressed-mapping + - pkg:pypi/pandas?source=hash-mapping size: 15303815 timestamp: 1778602611222 - conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.56.4-hda50119_1.conda @@ -9999,9 +10010,25 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/rpds-py?source=compressed-mapping + - pkg:pypi/rpds-py?source=hash-mapping size: 309696 timestamp: 1779976994059 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.15.21-h462bb3b_1.conda + noarch: python + sha256: e1c9458765584c20a11b400957b0d91889ead735a99f425323fbbf2fe26e7bb8 + md5: cd350880cf64a121362ed2e14ce7341f + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + constrains: + - __glibc >=2.17 + license: MIT + purls: + - pkg:pypi/ruff?source=compressed-mapping + run_exports: {} + size: 9347142 + timestamp: 1784124753497 - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.7.3-hc5a330e_0.conda sha256: 150a0a5254e8b15ad737549721c7d13406cd96432f3f446e07073dbd98bb2491 md5: f2bd09e21c5844a12e2f5eefcd075555 @@ -10080,7 +10107,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/scipy?source=compressed-mapping + - pkg:pypi/scipy?source=hash-mapping size: 16995364 timestamp: 1779874760991 - conda: https://conda.anaconda.org/conda-forge/linux-64/sed-4.10-h19d0853_0.conda @@ -10251,7 +10278,7 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/tornado?source=compressed-mapping + - pkg:pypi/tornado?source=hash-mapping size: 914451 timestamp: 1779915938568 - conda: https://conda.anaconda.org/conda-forge/linux-64/udunits2-2.2.28-h40f5838_3.conda @@ -10418,7 +10445,7 @@ packages: license: BSD-2-Clause license_family: BSD purls: - - pkg:pypi/wrapt?source=compressed-mapping + - pkg:pypi/wrapt?source=hash-mapping size: 117023 timestamp: 1779477450167 - conda: https://conda.anaconda.org/conda-forge/linux-64/xerces-c-3.3.0-hd9031aa_1.conda @@ -10830,7 +10857,7 @@ packages: license: PSF-2.0 license_family: PSF purls: - - pkg:pypi/aiohappyeyeballs?source=compressed-mapping + - pkg:pypi/aiohappyeyeballs?source=hash-mapping size: 20727 timestamp: 1779297825279 - conda: https://conda.anaconda.org/conda-forge/noarch/aiohttp-3.13.5-pyhf64b827_0.conda @@ -11046,8 +11073,7 @@ packages: depends: - python >=3.14 license: BSD-3-Clause AND MIT AND EPL-2.0 - purls: - - pkg:pypi/backports-zstd?source=compressed-mapping + purls: [] size: 7533 timestamp: 1778594057496 - conda: https://conda.anaconda.org/conda-forge/noarch/base58-2.1.1-pyhd8ed1ab_1.conda @@ -11194,7 +11220,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/cf-xarray?source=compressed-mapping + - pkg:pypi/cf-xarray?source=hash-mapping size: 71204 timestamp: 1778633103423 - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda @@ -11740,7 +11766,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/fonttools?source=compressed-mapping + - pkg:pypi/fonttools?source=hash-mapping size: 846038 timestamp: 1778770337113 - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda @@ -11765,7 +11791,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/frozenlist?source=compressed-mapping + - pkg:pypi/frozenlist?source=hash-mapping size: 19878 timestamp: 1779999782801 - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2026.4.0-pyhd8ed1ab_0.conda @@ -11931,7 +11957,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/idna?source=compressed-mapping + - pkg:pypi/idna?source=hash-mapping size: 56858 timestamp: 1779999227630 - conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda @@ -12109,7 +12135,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/ipython?source=compressed-mapping + - pkg:pypi/ipython?source=hash-mapping size: 651516 timestamp: 1780068620454 - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda @@ -12433,7 +12459,7 @@ packages: - python license: BSD-3-Clause purls: - - pkg:pypi/jupyter-server?source=compressed-mapping + - pkg:pypi/jupyter-server?source=hash-mapping size: 361523 timestamp: 1780151480958 - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda @@ -12667,7 +12693,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/mdit-py-plugins?source=compressed-mapping + - pkg:pypi/mdit-py-plugins?source=hash-mapping size: 50460 timestamp: 1778692223625 - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda @@ -12794,7 +12820,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/myst-parser?source=compressed-mapping + - pkg:pypi/myst-parser?source=hash-mapping size: 74888 timestamp: 1778696564508 - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda @@ -12806,7 +12832,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/narwhals?source=compressed-mapping + - pkg:pypi/narwhals?source=hash-mapping size: 284323 timestamp: 1778929680962 - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda @@ -13171,7 +13197,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/propcache?source=compressed-mapping + - pkg:pypi/propcache?source=hash-mapping size: 19936 timestamp: 1780037707071 - conda: https://conda.anaconda.org/conda-forge/noarch/prov-2.0.0-pyhd3deb0d_0.tar.bz2 @@ -13379,7 +13405,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/pyopenssl?source=compressed-mapping + - pkg:pypi/pyopenssl?source=hash-mapping size: 130658 timestamp: 1779003427956 - conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda @@ -13402,7 +13428,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/pyshp?source=compressed-mapping + - pkg:pypi/pyshp?source=hash-mapping size: 495946 timestamp: 1779928009778 - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda @@ -13570,7 +13596,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/python-discovery?source=compressed-mapping + - pkg:pypi/python-discovery?source=hash-mapping size: 34924 timestamp: 1779967197357 - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda @@ -13668,7 +13694,7 @@ packages: - python license: Apache-2.0 purls: - - pkg:pypi/python-multipart?source=compressed-mapping + - pkg:pypi/python-multipart?source=hash-mapping size: 37879 timestamp: 1780296101590 - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda @@ -14308,7 +14334,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/uvicorn?source=compressed-mapping + - pkg:pypi/uvicorn?source=hash-mapping size: 56276 timestamp: 1779633410850 - conda: https://conda.anaconda.org/conda-forge/noarch/varint-1.0.2-pyhd8ed1ab_1.conda @@ -14336,7 +14362,7 @@ packages: - python license: MIT purls: - - pkg:pypi/virtualenv?source=compressed-mapping + - pkg:pypi/virtualenv?source=hash-mapping size: 5151645 timestamp: 1780253977667 - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.7.0-pyhd8ed1ab_0.conda @@ -14481,7 +14507,7 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/yarl?source=compressed-mapping + - pkg:pypi/yarl?source=hash-mapping size: 81559 timestamp: 1779246114561 - conda: https://conda.anaconda.org/conda-forge/noarch/zarr-3.2.1-pyhc364b38_0.conda @@ -17675,7 +17701,7 @@ packages: - python_abi 3.14.* *_cp314 license: BSD-3-Clause and MIT-CMU purls: - - pkg:pypi/lxml?source=compressed-mapping + - pkg:pypi/lxml?source=hash-mapping size: 1376491 timestamp: 1779195548681 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-4.4.5-py312h2b25a0d_1.conda @@ -18256,7 +18282,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/numpy?source=compressed-mapping + - pkg:pypi/numpy?source=hash-mapping size: 6995531 timestamp: 1779169217034 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda @@ -18471,7 +18497,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/pandas?source=compressed-mapping + - pkg:pypi/pandas?source=hash-mapping size: 14368928 timestamp: 1778602917992 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pango-1.56.4-hf80efc4_1.conda @@ -19297,7 +19323,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/pyzmq?source=compressed-mapping + - pkg:pypi/pyzmq?source=hash-mapping size: 191432 timestamp: 1779484184540 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/qhull-2020.2-h420ef59_5.conda @@ -19402,9 +19428,24 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/rpds-py?source=compressed-mapping + - pkg:pypi/rpds-py?source=hash-mapping size: 292087 timestamp: 1779977082395 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.15.21-h828de30_1.conda + noarch: python + sha256: 2ebfbffb6b31462a75880772ad96021d4fbb35bd00e93d656d8a36d11c4c08aa + md5: 1020f02c620bee30481275fa159b78be + depends: + - python + - __osx >=11.0 + constrains: + - __osx >=11.0 + license: MIT + purls: + - pkg:pypi/ruff?source=compressed-mapping + run_exports: {} + size: 8639697 + timestamp: 1784124877114 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.17.1-py312h4519d97_1.conda sha256: c0ed2cbfa3485bac8570e52b577475778c603ee92d078a8b164d1ddec992e577 md5: 173d5eeba324363d9171946e86a81687 @@ -19468,7 +19509,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/scipy?source=compressed-mapping + - pkg:pypi/scipy?source=hash-mapping size: 13975038 timestamp: 1779874613589 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/shapely-2.1.2-py312h35cd81b_2.conda @@ -19930,7 +19971,7 @@ packages: purls: [] size: 433413 timestamp: 1764777166076 -- pypi: . +- pypi: ./ name: esmvalcore requires_dist: - aiohttp diff --git a/pyproject.toml b/pyproject.toml index 1d06747cad..3b0c67cad9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -137,6 +137,7 @@ exclude_lines = [ [tool.mypy] # See https://mypy.readthedocs.io/en/stable/config_file.html +packages = "esmvalcore" ignore_missing_imports = true enable_error_code = [ "truthy-bool", @@ -303,6 +304,7 @@ test-r = { features = ["test-r"], solve-group = "test-r" } "mypy" = "*" "pre-commit" = "*" "py-spy" = "*" +"ruff" = "*" # Feature for running tests with Python 3.12. [tool.pixi.feature.py312.dependencies] @@ -319,5 +321,4 @@ test-r = { features = ["test-r"], solve-group = "test-r" } # Tasks for use with `pixi run `. [tool.pixi.tasks] test = {cmd = "pytest", description = "Run the tests"} -type-check = {cmd = "mypy esmvalcore", description = "Run the type checks"} doc = {cmd = "sphinx-build doc html", description = "Build the documentation"} From f5a47e34ac2b364129eeb67c874b2d307c56cab0 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 16 Jul 2026 15:36:13 +0200 Subject: [PATCH 03/27] Remove some arguments that are not in the default pre-commit hook either --- .pre-commit-config.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3237fea2f2..03746f5788 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,8 +51,6 @@ repos: - python pass_filenames: false require_serial: true - verbose: false - always_run: false - repo: https://github.com/adrienverge/yamllint rev: "v1.38.0" hooks: From 33de918157213e820823a8ab2349e6d8c3674dbd Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 16 Jul 2026 15:39:19 +0200 Subject: [PATCH 04/27] Run pre-commit on CircleCI --- .circleci/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5fc6d40897..adcbf37815 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,6 +17,9 @@ jobs: - run: name: Check dependencies are compatible command: pixi run --as-is pip check + - run: + name: Check code quality + command: pixi run --as-is pre-commit run -a - run: name: Run tests command: | From 6ea1edf58e28bb35180ff767a4c0a419202d02d9 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 16 Jul 2026 15:47:12 +0200 Subject: [PATCH 05/27] Update docs --- doc/contributing.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/contributing.rst b/doc/contributing.rst index a6b1701fa6..8cba49cd2c 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -39,8 +39,8 @@ whenever you read it. It is recommended that you open a `draft pull request `__ -early, as this will cause :ref:`CircleCI to run the unit tests `, -:ref:`pre-commit.ci to analyse your code `, and +early, as this will cause CircleCI to :ref:`run the tests ` and +:ref:`analyse the code `, and :ref:`readthedocs to build the documentation `. It's also easier to get help from other developers if your code is visible in a pull request. @@ -249,7 +249,7 @@ should be correct. Both `ruff`_ and `mypy`_ are automatically run by pre-commit. When you make a pull request, adherence to the Python development best practices -is checked by `pre-commit.ci `_. +is checked by running the pre-commit hooks on CircleCI. YAML ~~~~ From 639434b13c693a66d05ff8f4488391deee203be5 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 16 Jul 2026 15:56:21 +0200 Subject: [PATCH 06/27] Cache mypy stuff --- .circleci/config.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index adcbf37815..f653a294b3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,9 +14,18 @@ jobs: steps: - checkout - pixi/pixi_setup + - run: + name: Generate mypy cache key + command: date '+%Y-%W' | tee mypy_cache_key.txt + - restore_cache: + key: type-check-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} - run: name: Check dependencies are compatible command: pixi run --as-is pip check + - save_cache: + key: type-check-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} + paths: + - ./.mypy_cache - run: name: Check code quality command: pixi run --as-is pre-commit run -a From 470424445e91356425633ce69d0d61f099f3a3c0 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 16 Jul 2026 16:07:16 +0200 Subject: [PATCH 07/27] Cache mypy results in the right place --- .circleci/config.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f653a294b3..4ab17466ec 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,21 +14,21 @@ jobs: steps: - checkout - pixi/pixi_setup + - run: + name: Check dependencies are compatible + command: pixi run --as-is pip check - run: name: Generate mypy cache key command: date '+%Y-%W' | tee mypy_cache_key.txt - restore_cache: - key: type-check-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} + key: types-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} - run: - name: Check dependencies are compatible - command: pixi run --as-is pip check + name: Check code quality + command: pixi run --as-is pre-commit run -a - save_cache: - key: type-check-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} + key: types-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} paths: - ./.mypy_cache - - run: - name: Check code quality - command: pixi run --as-is pre-commit run -a - run: name: Run tests command: | From 1d418954ef1b359c8406a82e14d69477256cb46a Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 16 Jul 2026 16:10:59 +0200 Subject: [PATCH 08/27] Also cache pre-commit installs --- .circleci/config.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4ab17466ec..ca65df2214 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,13 +21,14 @@ jobs: name: Generate mypy cache key command: date '+%Y-%W' | tee mypy_cache_key.txt - restore_cache: - key: types-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} + key: pre-commit-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} - run: name: Check code quality command: pixi run --as-is pre-commit run -a - save_cache: - key: types-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} + key: pre-commit-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} paths: + - ~/.cache/pre-commit - ./.mypy_cache - run: name: Run tests From 31aa0d26813b26a5ad052168431b9a73acaba602 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 16 Jul 2026 16:16:33 +0200 Subject: [PATCH 09/27] rerun tests From 0d6d7e2245aa0b6d1ca4bbd84a79d53d8b1b63e1 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 16 Jul 2026 16:31:43 +0200 Subject: [PATCH 10/27] Rename to pre-commit --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ca65df2214..72855ad334 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -18,15 +18,15 @@ jobs: name: Check dependencies are compatible command: pixi run --as-is pip check - run: - name: Generate mypy cache key - command: date '+%Y-%W' | tee mypy_cache_key.txt + name: Generate pre-commit cache key + command: date '+%Y-%W' | tee pre_commit_cache_key.txt - restore_cache: - key: pre-commit-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} + key: pre-commit-{{ .Branch }}-{{ checksum "pre_commit_cache_key.txt" }} - run: name: Check code quality command: pixi run --as-is pre-commit run -a - save_cache: - key: pre-commit-{{ .Branch }}-{{ checksum "mypy_cache_key.txt" }} + key: pre-commit-{{ .Branch }}-{{ checksum "pre_commit_cache_key.txt" }} paths: - ~/.cache/pre-commit - ./.mypy_cache From 7ddaa85a24e0987bf8d0144a91d73b5e4ade416a Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 16 Jul 2026 16:36:11 +0200 Subject: [PATCH 11/27] Use github action instead of pre-commit hook for Zizmor checks --- .github/workflows/zizmor.yml | 23 +++++++++++++++++++++++ .pre-commit-config.yaml | 5 ----- 2 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/zizmor.yml diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 0000000000..021560f489 --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,23 @@ +name: GitHub Actions Security Analysis with zizmor 🌈 + +on: + push: + branches: ["main"] + pull_request: + branches: ["**"] + +permissions: {} + +jobs: + zizmor: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Run zizmor 🌈 + uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7 + with: + advanced-security: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 03746f5788..e06eb31987 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -65,8 +65,3 @@ repos: - id: check-citation-file-format - id: check-github-workflows - id: check-circle-ci - - repo: https://github.com/zizmorcore/zizmor-pre-commit - rev: v1.26.1 - hooks: - - id: zizmor - args: [--fix=safe] From c5f6c859ddfc1d908da8c689489538b86b68e7a6 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Fri, 17 Jul 2026 09:18:47 +0200 Subject: [PATCH 12/27] Add mypy type stubs --- pyproject.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 6119e39fd2..bdd047dd41 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -305,6 +305,12 @@ test-r = { features = ["test-r"], solve-group = "test-r" } "pre-commit" = "*" "py-spy" = "*" "ruff" = "*" +# Mypy type stubs +"pandas-stubs" = "*" +"scipy-stubs" = "*" +"types-PyYAML" = "*" +"types-psutil" = "*" +"types-shapely" = "*" # Feature for running tests with Python 3.12. [tool.pixi.feature.py312.dependencies] From 7ce214c2dc961907f8ed6382ae247225747a86fd Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Fri, 17 Jul 2026 09:24:45 +0200 Subject: [PATCH 13/27] Add ruff cache to cache --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 72855ad334..887bee554a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,6 +30,7 @@ jobs: paths: - ~/.cache/pre-commit - ./.mypy_cache + - ./.ruff_cache - run: name: Run tests command: | From b4b7e939788049c34f98a97467d03b7b86e7b197 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Fri, 17 Jul 2026 09:26:05 +0200 Subject: [PATCH 14/27] Update lock file --- pixi.lock | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/pixi.lock b/pixi.lock index b50160bef8..947a15538f 100644 --- a/pixi.lock +++ b/pixi.lock @@ -425,9 +425,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/numpy-typing-compat-20260602.2.5-pyhb860519_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/oauthlib-3.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/optype-0.18.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/optype-numpy-0.18.0-pyh5504437_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandas-stubs-3.0.3.260530-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda @@ -487,6 +491,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-py-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scipy-stubs-1.18.0.1-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -512,6 +517,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/types-psutil-7.2.2.20260518-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/types-pytz-2026.2.0.20260518-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/types-pyyaml-6.0.12.20260518-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/types-shapely-2.1.0.20260402-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda @@ -688,9 +697,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/numpy-typing-compat-20260602.2.5-pyhb860519_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/oauthlib-3.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/optype-0.18.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/optype-numpy-0.18.0-pyh5504437_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandas-stubs-3.0.3.260530-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda @@ -750,6 +763,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-py-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scipy-stubs-1.18.0.1-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -775,6 +789,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.15.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/types-psutil-7.2.2.20260518-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/types-pytz-2026.2.0.20260518-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/types-pyyaml-6.0.12.20260518-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/types-shapely-2.1.0.20260402-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda @@ -13937,6 +13955,20 @@ packages: run_exports: {} size: 16817 timestamp: 1733408419340 +- conda: https://conda.anaconda.org/conda-forge/noarch/numpy-typing-compat-20260602.2.5-pyhb860519_1.conda + sha256: 510cf01dd2b3934078f8fda5360a645649e0652a4edd94fcaace58e0d53bde56 + md5: f337e1f9bbae5c509a95f77dc3a47a14 + depends: + - python >=3.12 + - numpy <2.6,>=2.5 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy-typing-compat?source=hash-mapping + run_exports: {} + size: 13203 + timestamp: 1782221065995 - conda: https://conda.anaconda.org/conda-forge/noarch/oauthlib-3.3.1-pyhd8ed1ab_0.conda sha256: dfa8222df90736fa13f8896f5a573a50273af8347542d412c3bd1230058e56a5 md5: d4f3f31ee39db3efecb96c0728d4bdbf @@ -13952,6 +13984,35 @@ packages: run_exports: {} size: 102059 timestamp: 1750415349440 +- conda: https://conda.anaconda.org/conda-forge/noarch/optype-0.18.0-pyhc364b38_0.conda + sha256: d88ea70bdbe44ea7e06d5305c363b4624609ed2712f2742e6fb25f05c536fdc0 + md5: c3b24fd5393b5c674dd9607424201e18 + depends: + - python >=3.12 + - typing-extensions >=4.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/optype?source=hash-mapping + run_exports: {} + size: 64931 + timestamp: 1780922251176 +- conda: https://conda.anaconda.org/conda-forge/noarch/optype-numpy-0.18.0-pyh5504437_0.conda + sha256: aa5238f44c1563606f0a448b480e67793422a125321f2039bd519915c21d547d + md5: 1871ee7210705711aec48e32842b3ca8 + depends: + - python >=3.12 + - numpy >=2.0,<2.8 + - numpy-typing-compat >=20260602.2.0,<20260603.2.0 + - optype ==0.18.0 pyhc364b38_0 + - python + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 10913 + timestamp: 1780922251176 - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda sha256: 1840bd90d25d4930d60f57b4f38d4e0ae3f5b8db2819638709c36098c6ba770c md5: e51f1e4089cad105b6cac64bd8166587 @@ -13978,6 +14039,20 @@ packages: run_exports: {} size: 91574 timestamp: 1777103621679 +- conda: https://conda.anaconda.org/conda-forge/noarch/pandas-stubs-3.0.3.260530-pyhd8ed1ab_0.conda + sha256: e411d70a35f09f4439d3e8c60ec1a9263b1ee8e7746b610f79087244e1c06a3a + md5: 86cc2a42dc6d7ae2236cfc3a81d4ecc0 + depends: + - numpy >=1.26.0 + - python >=3.11 + - types-pytz >=2022.1.1 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pandas-stubs?source=hash-mapping + run_exports: {} + size: 110817 + timestamp: 1780233848320 - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 sha256: 2bb9ba9857f4774b85900c2562f7e711d08dd48e2add9bee4e1612fbee27e16f md5: 457c2c8c08e54905d6954e79cb5b5db9 @@ -14898,6 +14973,22 @@ packages: run_exports: {} size: 11074 timestamp: 1766025162370 +- conda: https://conda.anaconda.org/conda-forge/noarch/scipy-stubs-1.18.0.1-pyhc364b38_0.conda + sha256: 5fcdd4d08f120fa991dd0057b16cc8e33eedb29e19f7c29752feb33d76567c8a + md5: 762dcb2958a9b7cda6e38d0c04378715 + depends: + - python >=3.12 + - optype-numpy >=0.15.0,<0.20.0 + - python + constrains: + - scipy >=1.18.0,<1.19.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/scipy-stubs?source=hash-mapping + run_exports: {} + size: 381529 + timestamp: 1783898380185 - conda: https://conda.anaconda.org/conda-forge/noarch/sdkroot_env_osx-arm64-26.0-ha3f98da_7.conda sha256: fabfe031ede99898cb2b0b805f6c0d64fcc24ecdb444de3a83002d8135bf4804 md5: 5f0ebbfea12d8e5bddff157e271fdb2f @@ -15278,6 +15369,55 @@ packages: run_exports: {} size: 24279 timestamp: 1766494826559 +- conda: https://conda.anaconda.org/conda-forge/noarch/types-psutil-7.2.2.20260518-pyhd8ed1ab_0.conda + sha256: 4a42fa75861f41e8f1a694fc6e673c0877cbe02aa54ccbaec13cd33bead83713 + md5: 63874239ef27c5b5a8e3409a07382292 + depends: + - python >=3.10 + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/types-psutil?source=hash-mapping + run_exports: {} + size: 32892 + timestamp: 1779102286490 +- conda: https://conda.anaconda.org/conda-forge/noarch/types-pytz-2026.2.0.20260518-pyhcf101f3_0.conda + sha256: b96a77604fbe7cf4df9d48a1679247c5877aad00d00e663ce2e06f13b3e72dcb + md5: ee605d821d094cfb7d0eecdecaccdeee + depends: + - python >=3.10 + - python + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/types-pytz?source=hash-mapping + run_exports: {} + size: 20398 + timestamp: 1779096753335 +- conda: https://conda.anaconda.org/conda-forge/noarch/types-pyyaml-6.0.12.20260518-pyhcf101f3_0.conda + sha256: 58eb35e905356d7105db51e1cd7eb5a9f2029e0d0bb345215c0eb525babaffb4 + md5: 8c9d908beae2f052bf188c41c85f0b80 + depends: + - python >=3.10 + - python + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/types-pyyaml?source=hash-mapping + run_exports: {} + size: 26875 + timestamp: 1779101988372 +- conda: https://conda.anaconda.org/conda-forge/noarch/types-shapely-2.1.0.20260402-pyhcf101f3_0.conda + sha256: 77814d0eb90f9686de6929ab1301adb721afdf221dd12bca2f3a28054d50b87a + md5: 881262e1e2db2323071c4964c5028c7f + depends: + - python >=3.10 + - numpy >=1.20 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/types-shapely?source=hash-mapping + run_exports: {} + size: 37614 + timestamp: 1775123303475 - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c md5: edd329d7d3a4ab45dcf905899a7a6115 From 905b583eb203cb53e3ee351474031773582f25e4 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Fri, 17 Jul 2026 09:46:29 +0200 Subject: [PATCH 15/27] Fix type hints --- esmvalcore/preprocessor/_area.py | 9 ++++++--- esmvalcore/preprocessor/_compare_with_refs.py | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/esmvalcore/preprocessor/_area.py b/esmvalcore/preprocessor/_area.py index 34ceacad0c..801de835b7 100644 --- a/esmvalcore/preprocessor/_area.py +++ b/esmvalcore/preprocessor/_area.py @@ -16,6 +16,7 @@ import numpy as np import shapely import shapely.ops +import shapely.vectorized from dask import array as da from iris.coords import AuxCoord from iris.cube import CubeList @@ -47,6 +48,8 @@ logger = logging.getLogger(__name__) +type ExtractShapeMethod = Literal["contains", "representative"] + SHAPE_ID_KEYS: tuple[str, ...] = ("name", "NAME", "Name", "id", "ID") @@ -597,7 +600,7 @@ def _get_masks_from_geometries( geometries: dict[str, dict], lon: np.ndarray, lat: np.ndarray, - method: str = "contains", + method: ExtractShapeMethod = "contains", decomposed: bool = False, ) -> dict[str, np.ndarray]: """Get cube masks from requested regions.""" @@ -643,7 +646,7 @@ def _get_bounds( def _get_single_mask( lon: np.ndarray, lat: np.ndarray, - method: str, + method: ExtractShapeMethod, geometry: dict, ) -> np.ndarray: """Get single mask from one region.""" @@ -750,7 +753,7 @@ def _update_shapefile_path( def extract_shape( cube: Cube, shapefile: str | Path, - method: str = "contains", + method: ExtractShapeMethod = "contains", crop: bool = True, decomposed: bool = False, ids: list | dict | None = None, diff --git a/esmvalcore/preprocessor/_compare_with_refs.py b/esmvalcore/preprocessor/_compare_with_refs.py index 4e6fc6c180..a77c3b9ce5 100644 --- a/esmvalcore/preprocessor/_compare_with_refs.py +++ b/esmvalcore/preprocessor/_compare_with_refs.py @@ -592,7 +592,7 @@ def _get_emd( arr: np.ndarray, ref_arr: np.ndarray, bin_centers: np.ndarray, -) -> np.ndarray: +) -> float | np.ma.core.MaskedConstant: """Calculate Earth mover's distance (non-lazy).""" if np.ma.is_masked(arr) or np.ma.is_masked(ref_arr): return np.ma.masked # this is safe because PMFs will be masked arrays From 4ddf8663fd2c36f7d740b84396e2e419351bbef8 Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 14:10:08 +0100 Subject: [PATCH 16/27] add pixi as dev dependency --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index bdd047dd41..e10b8a3641 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -302,6 +302,7 @@ test-r = { features = ["test-r"], solve-group = "test-r" } [tool.pixi.feature.dev.dependencies] "jupyterlab" = "*" "mypy" = "*" +"pixi" = "*" "pre-commit" = "*" "py-spy" = "*" "ruff" = "*" From c89433c77a036e3a8275526528f7a89afffeae59 Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 14:26:54 +0100 Subject: [PATCH 17/27] remove install of pixi since it do diddly --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e10b8a3641..bdd047dd41 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -302,7 +302,6 @@ test-r = { features = ["test-r"], solve-group = "test-r" } [tool.pixi.feature.dev.dependencies] "jupyterlab" = "*" "mypy" = "*" -"pixi" = "*" "pre-commit" = "*" "py-spy" = "*" "ruff" = "*" From f619f2587b095626c894f96245cb98d45d3ab56b Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 14:49:20 +0100 Subject: [PATCH 18/27] attempt to install pixi in pre-commit hook --- .pre-commit-config.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 157af6e7af..c7017f66ed 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,9 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks --- +env: + PRE_COMMIT_USE_MAMBA: 1 + ci: autofix_prs: false @@ -29,7 +32,7 @@ repos: hooks: - id: ruff-check name: ruff check - entry: "pixi run --locked ruff check --force-exclude --fix" + entry: "mamba install -c conda-forge pixi && pixi run --locked ruff check --force-exclude --fix" language: system require_serial: true types_or: From f77faf9c6701bcb1949caba934f29e4f80d29133 Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 14:50:26 +0100 Subject: [PATCH 19/27] attempt to install pixi in pre-commit hook --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c7017f66ed..3c689e680b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: - jupyter - id: ruff-format name: ruff format - entry: "pixi run --locked ruff format --force-exclude" + entry: "mamba install -c conda-forge pixi && pixi run --locked ruff format --force-exclude" language: system require_serial: true types_or: @@ -48,7 +48,7 @@ repos: - jupyter - id: mypy name: mypy - entry: "pixi run --locked mypy" + entry: "mamba install -c conda-forge pixi && pixi run --locked mypy" language: system types: - python From 4f0b0e9f51bd8e743c94408f6429c3dbfaa31953 Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 14:54:18 +0100 Subject: [PATCH 20/27] attempt to install pixi in pre-commit hook part deux --- .pre-commit-config.yaml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3c689e680b..4c4313af16 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,9 +1,6 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks --- -env: - PRE_COMMIT_USE_MAMBA: 1 - ci: autofix_prs: false @@ -32,7 +29,7 @@ repos: hooks: - id: ruff-check name: ruff check - entry: "mamba install -c conda-forge pixi && pixi run --locked ruff check --force-exclude --fix" + entry: "export PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked ruff check --force-exclude --fix" language: system require_serial: true types_or: @@ -40,7 +37,7 @@ repos: - jupyter - id: ruff-format name: ruff format - entry: "mamba install -c conda-forge pixi && pixi run --locked ruff format --force-exclude" + entry: "export PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked ruff format --force-exclude" language: system require_serial: true types_or: @@ -48,7 +45,7 @@ repos: - jupyter - id: mypy name: mypy - entry: "mamba install -c conda-forge pixi && pixi run --locked mypy" + entry: "export PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked mypy" language: system types: - python From 578f758a364019f68c590714e22b8e8ebfa975d6 Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 15:01:15 +0100 Subject: [PATCH 21/27] try env instead of export --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4c4313af16..a16a9e5cdc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,7 @@ repos: hooks: - id: ruff-check name: ruff check - entry: "export PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked ruff check --force-exclude --fix" + entry: "env PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked ruff check --force-exclude --fix" language: system require_serial: true types_or: @@ -37,7 +37,7 @@ repos: - jupyter - id: ruff-format name: ruff format - entry: "export PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked ruff format --force-exclude" + entry: "env PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked ruff format --force-exclude" language: system require_serial: true types_or: @@ -45,7 +45,7 @@ repos: - jupyter - id: mypy name: mypy - entry: "export PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked mypy" + entry: "env PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked mypy" language: system types: - python From 43805a074234525d79a52104aeaed71770e5d360 Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 15:09:25 +0100 Subject: [PATCH 22/27] try via plain old bash -c --- .pre-commit-config.yaml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a16a9e5cdc..4dc4c38858 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,12 @@ repos: hooks: - id: ruff-check name: ruff check - entry: "env PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked ruff check --force-exclude --fix" + entry: > + bash -c ' + export PRE_COMMIT_USE_MAMBA=1 + mamba install -y -c conda-forge pixi + pixi run --locked ruff check --force-exclude --fix "$@" + ' -- language: system require_serial: true types_or: @@ -37,7 +42,12 @@ repos: - jupyter - id: ruff-format name: ruff format - entry: "env PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked ruff format --force-exclude" + entry: > + bash -c ' + export PRE_COMMIT_USE_MAMBA=1 + mamba install -y -c conda-forge pixi + pixi run --locked ruff format --force-exclude "$@" + '-- language: system require_serial: true types_or: @@ -45,7 +55,12 @@ repos: - jupyter - id: mypy name: mypy - entry: "env PRE_COMMIT_USE_MAMBA=1 && mamba install -c conda-forge pixi && pixi run --locked mypy" + entry: > + bash -c ' + export PRE_COMMIT_USE_MAMBA=1 + mamba install -y -c conda-forge pixi + pixi run --locked mypy "$@" + '-- language: system types: - python From e0ad7671a171754890339877265de94ef7b10373 Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 15:12:14 +0100 Subject: [PATCH 23/27] agh forgot language --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4dc4c38858..8d501fe943 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: mamba install -y -c conda-forge pixi pixi run --locked ruff check --force-exclude --fix "$@" ' -- - language: system + language: conda # system require_serial: true types_or: - python @@ -48,7 +48,7 @@ repos: mamba install -y -c conda-forge pixi pixi run --locked ruff format --force-exclude "$@" '-- - language: system + language: conda # system require_serial: true types_or: - python @@ -61,7 +61,7 @@ repos: mamba install -y -c conda-forge pixi pixi run --locked mypy "$@" '-- - language: system + language: conda # system types: - python pass_filenames: false From 18a2a467791efac6f5b86aa339323abac219a6e6 Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 15:35:55 +0100 Subject: [PATCH 24/27] use the env file --- .pre-commit-config.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8d501fe943..b0ac3905d9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,6 @@ repos: entry: > bash -c ' export PRE_COMMIT_USE_MAMBA=1 - mamba install -y -c conda-forge pixi pixi run --locked ruff check --force-exclude --fix "$@" ' -- language: conda # system @@ -45,7 +44,6 @@ repos: entry: > bash -c ' export PRE_COMMIT_USE_MAMBA=1 - mamba install -y -c conda-forge pixi pixi run --locked ruff format --force-exclude "$@" '-- language: conda # system @@ -58,7 +56,6 @@ repos: entry: > bash -c ' export PRE_COMMIT_USE_MAMBA=1 - mamba install -y -c conda-forge pixi pixi run --locked mypy "$@" '-- language: conda # system From dff5f4d4bf4bfe636600ace719606e5ea2034acc Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 15:36:06 +0100 Subject: [PATCH 25/27] use an env file --- environment.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 environment.yml diff --git a/environment.yml b/environment.yml new file mode 100644 index 0000000000..0cc6fa412f --- /dev/null +++ b/environment.yml @@ -0,0 +1,8 @@ +--- +name: pre-commit +channels: + - conda-forge + - nodefaults + +dependencies: + - pixi From 852045e90dfae9ff9244cc7b1216b0f840a01700 Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 15:41:18 +0100 Subject: [PATCH 26/27] remove unneeded env file --- environment.yml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 environment.yml diff --git a/environment.yml b/environment.yml deleted file mode 100644 index 0cc6fa412f..0000000000 --- a/environment.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: pre-commit -channels: - - conda-forge - - nodefaults - -dependencies: - - pixi From 6b2f6b33d1bf9a39431f626cefb4ed672f6d44ee Mon Sep 17 00:00:00 2001 From: Valeriu Predoi Date: Mon, 27 Jul 2026 15:43:58 +0100 Subject: [PATCH 27/27] try language python with additional deps --- .pre-commit-config.yaml | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b0ac3905d9..02dfd4946d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,36 +29,27 @@ repos: hooks: - id: ruff-check name: ruff check - entry: > - bash -c ' - export PRE_COMMIT_USE_MAMBA=1 - pixi run --locked ruff check --force-exclude --fix "$@" - ' -- - language: conda # system + entry: "pixi run --locked ruff check --force-exclude --fix" + additional_dependencies: ['pixi'] + language: python # system require_serial: true types_or: - python - jupyter - id: ruff-format name: ruff format - entry: > - bash -c ' - export PRE_COMMIT_USE_MAMBA=1 - pixi run --locked ruff format --force-exclude "$@" - '-- - language: conda # system + entry: "pixi run --locked ruff format --force-exclude" + additional_dependencies: ['pixi'] + language: python # system require_serial: true types_or: - python - jupyter - id: mypy name: mypy - entry: > - bash -c ' - export PRE_COMMIT_USE_MAMBA=1 - pixi run --locked mypy "$@" - '-- - language: conda # system + entry: "pixi run --locked mypy" + additional_dependencies: ['pixi'] + language: python # system types: - python pass_filenames: false