valeriupredoi: but what in the world is going on with the install tests? Are we asking for too many threads?
bouweandela: Looks like the CircleCI docker containers actually report the number of cores available on their host machine.
bouweandela: @valeriupredoi I fixed the problem with too many test runners on CircleCI and changed the way we run tests in the process. Could you please have another look?
valeriupredoi: @bouweandela all good for me with the pinning done in https://github.com/ESMValGroup/ESMValTool/pull/1804 - do you want to set the pinning here too or I can do it :beer: 
valeriupredoi: awesome! roll out @bouweandela :medal_military: 
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 09e597e53..f0ea8afc7 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,19 +1,22 @@
 ---
-version: 2
+version: 2.1
 
-aliases:
-  check_changes: &check_changes
-    name: Check changes
-    command: |
-      if (test "$CIRCLE_BRANCH" = master ||
-          git --no-pager diff --name-only origin/master... |
-          grep -q -E -f .circleci/install_triggers)
-      then
-        echo Running installation tests
-      else
-        echo Skipping installation tests
-        circleci step halt
-      fi
+orbs:
+  coverage-reporter: codacy/coverage-reporter@11.1.1
+
+commands:
+  check_changes:
+    steps:
+      - run: |
+          if (test "$CIRCLE_BRANCH" = master ||
+            git --no-pager diff --name-only origin/master... |
+            grep -q -E -f .circleci/install_triggers)
+          then
+            echo Running installation tests
+          else
+            echo Skipping installation tests
+            circleci step halt
+          fi
 
 jobs:
   test:
@@ -25,7 +28,8 @@ jobs:
       - checkout
       - run:
           command: |
-            python setup.py test --addopts '-m "not installation"'
+            pip install .[test]
+            pytest -n 2 -m "not installation"
       - store_test_results:
           path: test-reports/
       - store_artifacts:
@@ -38,7 +42,7 @@ jobs:
       - image: continuumio/miniconda3
     steps:
       - checkout
-      - run: *check_changes
+      - check_changes
       - restore_cache:
           key: python3-install-{{ .Branch }}
       - run:
@@ -51,13 +55,13 @@ jobs:
             conda env update >> /logs/conda.txt 2>&1
             set +x; conda activate esmvaltool; set -x
             conda install -yS r-base r-yaml ncl -c conda-forge
-            pip install . > /logs/install.txt 2>&1
+            pip install .[test] > /logs/install.txt 2>&1
             # Log versions
             dpkg -l > /logs/versions.txt
             conda env export > /logs/environment.yml
             pip freeze > /logs/requirements.txt
             # Test installation
-            python setup.py test
+            pytest -n 2
             esmvaltool version
       - save_cache:
           key: python3-install-{{ .Branch }}
@@ -70,17 +74,9 @@ jobs:
           path: test-reports/
       - store_test_results:
           path: test-reports/
-      - run:
-          when: always
-          command: |
-            if [[ -v CODACY_PROJECT_TOKEN ]]
-            then
-              echo Uploading coverage report
-              pip install codacy-coverage
-              python-codacy-coverage -r test-reports/coverage.xml
-            else
-              echo Not uploading coverage report
-            fi
+      - coverage-reporter/send_report:
+          coverage-reports: 'test-reports/coverage.xml'
+          project-token: $CODACY_PROJECT_TOKEN
 
   documentation:
     # Test building documentation
@@ -116,7 +112,7 @@ jobs:
       - image: continuumio/miniconda3
     steps:
       - checkout
-      - run: *check_changes
+      - check_changes
       - run:
           command: |
             . /opt/conda/etc/profile.d/conda.sh
@@ -134,7 +130,7 @@ jobs:
             pip freeze > /logs/requirements.txt
             # Test installation
             esmvaltool version
-            python setup.py test
+            pytest -n 2
       - store_artifacts:
           path: /logs
 
@@ -145,7 +141,7 @@ jobs:
       - image: continuumio/miniconda3
     steps:
       - checkout
-      - run: *check_changes
+      - check_changes
       - run:
           command: |
             . /opt/conda/etc/profile.d/conda.sh
@@ -184,10 +180,8 @@ jobs:
             conda env export > /logs/environment.yml
             # Test installation
             esmvaltool version
-            python -c 'from esmvalcore import *; print(__version__)'
 
 workflows:
-  version: 2
   commit:
     jobs:
       - test
diff --git a/doc/contributing.rst b/doc/contributing.rst
index 5fee80b1d..8baba0a9f 100644
--- a/doc/contributing.rst
+++ b/doc/contributing.rst
@@ -27,9 +27,9 @@ Running tests
 -------------
 
 Go to the directory where the repository is cloned and run
-``python setup.py test``. Optionally you can skip tests which require
+``pytest``. Optionally you can skip tests which require
 additional dependencies for supported diagnostic script languages by
-adding ``--addopts '-m "not installation"'`` to the previous command.
+adding ``-m 'not installation'`` to the previous command.
 Tests will also be run automatically by
 `CircleCI <https://circleci.com/gh/ESMValGroup/ESMValCore>`__.
 
diff --git a/package/meta.yaml b/package/meta.yaml
index 9b919a856..4996b4f77 100644
--- a/package/meta.yaml
+++ b/package/meta.yaml
@@ -58,14 +58,31 @@ requirements:
     - yamale==2.*  # in esmvalgroup channel
 
 test:
-  # TODO: add unit tests? This seems to require installing the tests
+  source_files:
+    - tests
+    - setup.cfg
+  requires:
+    - pytest>=3.9,!=6.0.0rc1,!=6.0.0
+    - pytest-cov
+    - pytest-env
+    - pytest-flake8
+    - pytest-html!=2.1.0
+    - pytest-metadata>=1.5.1
+    - pytest-mock
+    - pytest-xdist
+    - r-yaml
+    - ncl
+  commands:
+    - pytest -n 2 --ignore=run_test.py
+    - esmvaltool -- --help
+    - esmvaltool version
   imports:
     - esmvalcore
     - esmvalcore.cmor
+    - esmvalcore.cmor.check
+    - esmvalcore.cmor.fix
     - esmvalcore.preprocessor
 
-  commands:
-    - esmvaltool -h
 
 about:
   home: https://www.esmvaltool.org
diff --git a/setup.cfg b/setup.cfg
index ca856b2ae..dc7036dc6 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,3 @@
-[aliases]
-test=pytest
-
 [build_sphinx]
 source-dir = doc/
 build-dir = doc/build
@@ -16,6 +13,7 @@ addopts =
     --cov-report=xml:test-reports/coverage.xml
     --cov-report=html:test-reports/coverage_html
     --html=test-reports/report.html
+    --numprocesses auto
 env =
     MPLBACKEND = Agg
 flake8-ignore =
diff --git a/setup.py b/setup.py
index b6783ef28..7a875b65c 100755
--- a/setup.py
+++ b/setup.py
@@ -24,7 +24,6 @@ PACKAGES = [
 REQUIREMENTS = {
     # Installation script (this file) dependencies
     'setup': [
-        'pytest-runner',
         'setuptools_scm',
     ],
     # Installation dependencies
@@ -50,12 +49,13 @@ REQUIREMENTS = {
     # Execute 'python setup.py test' to run tests
     'test': [
         'pytest>=3.9,!=6.0.0rc1,!=6.0.0',
-        'pytest-cov',
+        'pytest-cov>=2.10.1',
         'pytest-env',
-        'pytest-flake8',
+        'pytest-flake8>=1.0.6',
         'pytest-html!=2.1.0',
         'pytest-metadata>=1.5.1',
         'pytest-mock',
+        'pytest-xdist',
     ],
     # Development dependencies
     # Use pip install -e .[develop] to install in development mode

python setup.py test is deprecated
So our documentation on running tests as well as the test scripts that run on CircleCi need to be updated.
diff --git a/tests/integration/cmor/test_table.py b/tests/integration/cmor/test_table.py
index 750e52f07..f716b518b 100644
--- a/tests/integration/cmor/test_table.py
+++ b/tests/integration/cmor/test_table.py
@@ -3,6 +3,7 @@
 import os
 import unittest
 
+import esmvalcore.cmor
 from esmvalcore.cmor.table import CMIP3Info, CMIP5Info, CMIP6Info, CustomInfo
 
 
@@ -25,9 +26,8 @@ class TestCMIP6Info(unittest.TestCase):
 
     def test_custom_tables_location(self):
         """Test constructor with custom tables location."""
-        cwd = os.path.dirname(os.path.realpath(__file__))
-        cmor_tables_path = os.path.join(cwd, '..', '..', '..', 'esmvalcore',
-                                        'cmor', 'tables', 'cmip6')
+        cmor_path = os.path.dirname(os.path.realpath(esmvalcore.cmor.__file__))
+        cmor_tables_path = os.path.join(cmor_path, 'tables', 'cmip6')
         cmor_tables_path = os.path.abspath(cmor_tables_path)
         CMIP6Info(cmor_tables_path, default=None, strict=False)
 
@@ -122,9 +122,8 @@ class Testobs4mipsInfo(unittest.TestCase):
 
     def test_custom_tables_location(self):
         """Test constructor with custom tables location."""
-        cwd = os.path.dirname(os.path.realpath(__file__))
-        cmor_tables_path = os.path.join(cwd, '..', '..', '..', 'esmvalcore',
-                                        'cmor', 'tables', 'cmip6')
+        cmor_path = os.path.dirname(os.path.realpath(esmvalcore.cmor.__file__))
+        cmor_tables_path = os.path.join(cmor_path, 'tables', 'cmip6')
         cmor_tables_path = os.path.abspath(cmor_tables_path)
         CMIP6Info(cmor_tables_path, None, True)
 
@@ -190,9 +189,8 @@ class TestCMIP5Info(unittest.TestCase):
 
     def test_custom_tables_location(self):
         """Test constructor with custom tables location."""
-        cwd = os.path.dirname(os.path.realpath(__file__))
-        cmor_tables_path = os.path.join(cwd, '..', '..', '..', 'esmvalcore',
-                                        'cmor', 'tables', 'cmip5')
+        cmor_path = os.path.dirname(os.path.realpath(esmvalcore.cmor.__file__))
+        cmor_tables_path = os.path.join(cmor_path, 'tables', 'cmip5')
         cmor_tables_path = os.path.abspath(cmor_tables_path)
         CMIP5Info(cmor_tables_path, None, True)
 
@@ -265,9 +263,8 @@ class TestCMIP3Info(unittest.TestCase):
 
     def test_custom_tables_location(self):
         """Test constructor with custom tables location."""
-        cwd = os.path.dirname(os.path.realpath(__file__))
-        cmor_tables_path = os.path.join(cwd, '..', '..', '..', 'esmvalcore',
-                                        'cmor', 'tables', 'cmip3')
+        cmor_path = os.path.dirname(os.path.realpath(esmvalcore.cmor.__file__))
+        cmor_tables_path = os.path.join(cmor_path, 'tables', 'cmip3')
         cmor_tables_path = os.path.abspath(cmor_tables_path)
         CMIP3Info(cmor_tables_path, None, True)
 
@@ -337,10 +334,8 @@ class TestCORDEXInfo(unittest.TestCase):
 
     def test_custom_tables_location(self):
         """Test constructor with custom tables location."""
-        cwd = os.path.dirname(os.path.realpath(__file__))
-        cmor_tables_path = os.path.join(cwd, '..', '..', '..', 'esmvalcore',
-                                        'cmor', 'tables', 'cordex')
-        cmor_tables_path = os.path.abspath(cmor_tables_path)
+        cmor_path = os.path.dirname(os.path.realpath(esmvalcore.cmor.__file__))
+        cmor_tables_path = os.path.join(cmor_path, 'tables', 'cordex')
         CMIP5Info(cmor_tables_path)
 
     def test_get_variable_tas(self):
@@ -367,9 +362,8 @@ class TestCustomInfo(unittest.TestCase):
 
     def test_custom_tables_location(self):
         """Test constructor with custom tables location."""
-        cwd = os.path.dirname(os.path.realpath(__file__))
-        cmor_tables_path = os.path.join(cwd, '..', '..', '..', 'esmvalcore',
-                                        'cmor', 'tables', 'cmip5')
+        cmor_path = os.path.dirname(os.path.realpath(esmvalcore.cmor.__file__))
+        cmor_tables_path = os.path.join(cmor_path, 'tables', 'cmip5')
         cmor_tables_path = os.path.abspath(cmor_tables_path)
         CustomInfo(cmor_tables_path)
 
diff --git a/tests/unit/preprocessor/_area/test_area.py b/tests/unit/preprocessor/_area/test_area.py
index f16ca8bf3..f1c67a1fb 100644
--- a/tests/unit/preprocessor/_area/test_area.py
+++ b/tests/unit/preprocessor/_area/test_area.py
@@ -1,6 +1,6 @@
 """Unit tests for the :func:`esmvalcore.preprocessor._area` module."""
-
 import unittest
+from pathlib import Path
 
 import fiona
 import iris
@@ -11,6 +11,7 @@ from iris.cube import Cube
 from shapely.geometry import Polygon, mapping
 
 import tests
+import esmvalcore.preprocessor
 from esmvalcore.preprocessor._area import (_crop_cube, area_statistics,
                                            extract_named_regions,
                                            extract_region, extract_shape)
@@ -569,10 +570,17 @@ def test_crop_cube_with_ne_file_imitation():
     np.testing.assert_allclose(result, expected)
 
 
-def test_crop_cube_with_ne_file():
+@pytest.fixture
+def ne_ocean_shapefile():
+    """Path to natural earth 50m ocean shapefile."""
+    preproc_path = Path(esmvalcore.preprocessor.__file__).parent
+    shapefile = preproc_path / "ne_masks" / "ne_50m_ocean.shp"
+    return str(shapefile)
+
+
+def test_crop_cube_with_ne_file(ne_ocean_shapefile):
     """Test for cropping a cube by shape bounds."""
-    shp_file = "esmvalcore/preprocessor/ne_masks/ne_50m_ocean.shp"
-    with fiona.open(shp_file) as geometries:
+    with fiona.open(ne_ocean_shapefile) as geometries:
         cube = _create_sample_full_cube()
         result = _crop_cube(cube, *geometries.bounds, cmor_coords=False)
         result = (result.coord("latitude").points[-1],
@@ -598,22 +606,22 @@ def test_extract_shape(make_testcube, square_shape, tmp_path, crop):
     np.testing.assert_array_equal(result.data.mask, expected.mask)
 
 
-def test_extract_shape_natural_earth(make_testcube):
+def test_extract_shape_natural_earth(make_testcube, ne_ocean_shapefile):
     """Test for extracting a shape from NE file."""
     expected = np.ones((5, 5))
     result = extract_shape(
         make_testcube,
-        "esmvalcore/preprocessor/ne_masks/ne_50m_ocean.shp",
+        ne_ocean_shapefile,
         crop=False)
     np.testing.assert_array_equal(result.data.data, expected)
 
 
-def test_extract_shape_ne_check_nans():
+def test_extract_shape_ne_check_nans(ne_ocean_shapefile):
     """Test shape from NE file with check for boundary NaN's."""
     cube = _create_sample_full_cube()
     result = extract_shape(
         cube,
-        "esmvalcore/preprocessor/ne_masks/ne_50m_ocean.shp",
+        ne_ocean_shapefile,
         crop=False)
     assert not result[:, 90, 180].data.mask.all()
 

environment.yml
pip install -e '.[develop]'
parse_log_pytest
environment.yml
pytest pytest-cov pytest-xdist pytest-mock pytest-asyncio
apt-get update apt-get install -y gcc
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.16
antlr4-python3-runtime @ file:///home/conda/feedstock_root/build_artifacts/antlr-python-runtime-meta_1662478324044/work
astroid==3.3.9
attrs==25.3.0
autodocsumm==0.2.14
babel==2.17.0
build==1.2.2.post1
Cartopy @ file:///home/conda/feedstock_root/build_artifacts/cartopy_1726175364746/work
certifi @ file:///home/conda/feedstock_root/build_artifacts/certifi_1739515848642/work/certifi
cf-units @ file:///home/conda/feedstock_root/build_artifacts/cf-units_1725441254906/work
cfgv==3.4.0
cftime @ file:///home/conda/feedstock_root/build_artifacts/cftime_1725400455427/work
charset-normalizer==3.4.1
click @ file:///home/conda/feedstock_root/build_artifacts/click_1734858813237/work
click-plugins==1.1.1
cligj==0.7.2
cloudpickle @ file:///home/conda/feedstock_root/build_artifacts/cloudpickle_1736947526808/work
codespell==2.4.1
colorama==0.4.6
contourpy @ file:///home/conda/feedstock_root/build_artifacts/contourpy_1727293517607/work
coverage==7.8.0
cycler @ file:///home/conda/feedstock_root/build_artifacts/cycler_1733332471406/work
Cython @ file:///home/conda/feedstock_root/build_artifacts/cython_1739227939853/work
dask @ file:///home/conda/feedstock_root/build_artifacts/dask-core_1722976580461/work
dill==0.3.9
distlib==0.3.9
docformatter==1.7.5
docutils==0.21.2
dodgy==0.2.1
esmpy @ file:///home/conda/feedstock_root/build_artifacts/esmpy_1743174093731/work/src/addon/esmpy
-e git+https://github.com/ESMValGroup/ESMValCore.git@df32faa09e438d2fd15e7b54b4f10daefbdfceb4#egg=ESMValCore
exceptiongroup==1.2.2
execnet==2.1.1
filelock==3.18.0
fiona==1.10.1
fire==0.7.0
flake8==7.2.0
flake8-polyfill==1.0.2
fonttools @ file:///home/conda/feedstock_root/build_artifacts/fonttools_1738940303262/work
fsspec @ file:///home/conda/feedstock_root/build_artifacts/fsspec_1743361113926/work
gitdb==4.0.12
GitPython==3.1.44
identify==2.6.9
idna==3.10
imagesize==1.4.1
importlib_metadata @ file:///home/conda/feedstock_root/build_artifacts/importlib-metadata_1737420181517/work
importlib_resources @ file:///home/conda/feedstock_root/build_artifacts/importlib_resources_1736252299705/work
iniconfig==2.1.0
isodate==0.6.1
isort==6.0.1
Jinja2 @ file:///home/conda/feedstock_root/build_artifacts/jinja2_1741263328855/work
kiwisolver @ file:///home/conda/feedstock_root/build_artifacts/kiwisolver_1725459266648/work
llvmlite==0.43.0
locket @ file:///home/conda/feedstock_root/build_artifacts/locket_1650660393415/work
lxml==5.3.1
MarkupSafe @ file:///home/conda/feedstock_root/build_artifacts/markupsafe_1733219680183/work
matplotlib==3.9.4
mccabe==0.7.0
munkres==1.1.4
nc-time-axis==1.4.1
netCDF4 @ file:///home/conda/feedstock_root/build_artifacts/netcdf4_1733253338730/work
networkx==3.2.1
nodeenv==1.9.1
numba==0.60.0
numpy @ file:///home/conda/feedstock_root/build_artifacts/numpy_1732314280888/work/dist/numpy-2.0.2-cp39-cp39-linux_x86_64.whl#sha256=62d98eb3da9f13e6b227c430d01026b7427f341b3fdcb838430f2a9e520417b1
packaging @ file:///home/conda/feedstock_root/build_artifacts/packaging_1733203243479/work
partd @ file:///home/conda/feedstock_root/build_artifacts/partd_1715026491486/work
pathspec==0.12.1
pep8-naming==0.10.0
pillow @ file:///home/conda/feedstock_root/build_artifacts/pillow_1735929703139/work
platformdirs==4.3.7
pluggy==1.5.0
pre_commit==4.2.0
prospector==1.16.1
prov==2.0.1
psutil==7.0.0
pycodestyle==2.13.0
pydocstyle==6.3.0
pydot==3.0.4
pyflakes==3.3.2
Pygments==2.19.1
pylint==3.3.6
pylint-celery==0.3
pylint-django==2.6.1
pylint-plugin-utils==0.8.2
pyparsing @ file:///home/conda/feedstock_root/build_artifacts/pyparsing_1743089729650/work
pyproj @ file:///home/conda/feedstock_root/build_artifacts/pyproj_1726679693937/work
pyproject_hooks==1.2.0
pyroma==4.2
pyshp @ file:///home/conda/feedstock_root/build_artifacts/pyshp_1733821528126/work
pytest==8.3.5
pytest-asyncio==0.26.0
pytest-cov==6.0.0
pytest-env==1.1.5
pytest-flake8==1.3.0
pytest-html==4.1.1
pytest-metadata==3.1.1
pytest-mock==3.14.0
pytest-xdist==3.6.1
python-dateutil @ file:///home/conda/feedstock_root/build_artifacts/python-dateutil_1733215673016/work
pytz==2025.2
PyYAML @ file:///home/conda/feedstock_root/build_artifacts/pyyaml_1737454647378/work
rdflib==6.3.2
requests==2.32.3
requirements-detector==1.3.2
scipy @ file:///home/conda/feedstock_root/build_artifacts/scipy-split_1716470218293/work/dist/scipy-1.13.1-cp39-cp39-linux_x86_64.whl#sha256=e6696cb8683d94467891b7648e068a3970f6bc0a1b3c1aa7f9bc89458eafd2f0
scitools-iris @ file:///home/conda/feedstock_root/build_artifacts/iris_1709571258262/work
semver==3.0.4
setoptconf-tmp==0.3.1
shapely @ file:///home/conda/feedstock_root/build_artifacts/shapely_1741166945909/work
six @ file:///home/conda/feedstock_root/build_artifacts/six_1733380938961/work
smmap==5.0.2
snowballstemmer==2.2.0
Sphinx==7.4.7
sphinx-rtd-theme==3.0.2
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
stratify @ file:///home/conda/feedstock_root/build_artifacts/python-stratify_1725548815810/work
termcolor==3.0.0
toml==0.10.2
tomli==2.2.1
tomlkit==0.13.2
toolz @ file:///home/conda/feedstock_root/build_artifacts/toolz_1733736030883/work
trove-classifiers==2025.3.19.19
typing_extensions==4.13.0
unicodedata2 @ file:///home/conda/feedstock_root/build_artifacts/unicodedata2_1736692503055/work
untokenize==0.1.1
urllib3==2.3.0
virtualenv==20.29.3
vmprof==0.4.18.1
xxhash @ file:///home/conda/feedstock_root/build_artifacts/python-xxhash_1740594800419/work
yamale==2.2.0
yamllint==1.37.0
yapf==0.43.0
zipp @ file:///home/conda/feedstock_root/build_artifacts/zipp_1732827521216/work

name: ESMValCore
channels:
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=conda_forge
  - _openmp_mutex=4.5=2_gnu
  - adwaita-icon-theme=48.0=unix_0
  - antlr-python-runtime=4.11.1=pyhd8ed1ab_0
  - at-spi2-atk=2.38.0=h0630a04_3
  - at-spi2-core=2.40.3=h0630a04_0
  - atk-1.0=2.38.0=h04ea711_2
  - attr=2.5.1=h166bdaf_1
  - binutils=2.43=h4852527_4
  - binutils_impl_linux-64=2.43=h4bf12b8_4
  - binutils_linux-64=2.43=h4852527_4
  - blosc=1.21.6=he440d0b_1
  - brotli=1.1.0=hb9d3cd8_2
  - brotli-bin=1.1.0=hb9d3cd8_2
  - bzip2=1.0.8=h4bc722e_7
  - c-ares=1.34.4=hb9d3cd8_0
  - c-compiler=1.9.0=h2b85faf_0
  - ca-certificates=2025.1.31=hbcca054_0
  - cairo=1.18.4=h3394656_0
  - cartopy=0.23.0=py39h3b40f6f_2
  - certifi=2025.1.31=pyhd8ed1ab_0
  - cf-units=3.2.0=py39hf3d9206_6
  - cftime=1.6.4=py39hf3d9206_1
  - click=8.1.8=pyh707e725_0
  - cloudpickle=3.1.1=pyhd8ed1ab_0
  - compilers=1.9.0=ha770c72_0
  - contourpy=1.3.0=py39h74842e3_2
  - cxx-compiler=1.9.0=h1a2810e_0
  - cycler=0.12.1=pyhd8ed1ab_1
  - cython=3.0.12=py39hbce0bbb_0
  - dask-core=2024.8.0=pyhd8ed1ab_0
  - dbus=1.13.6=h5008d03_3
  - epoxy=1.5.10=h166bdaf_1
  - esmf=8.8.0=mpi_mpich_h7cf99a1_100
  - esmpy=8.8.0=pyhecae5ae_1
  - expat=2.7.0=h5888daf_0
  - font-ttf-dejavu-sans-mono=2.37=hab24e00_0
  - font-ttf-inconsolata=3.000=h77eed37_0
  - font-ttf-source-code-pro=2.038=h77eed37_0
  - font-ttf-ubuntu=0.83=h77eed37_3
  - fontconfig=2.15.0=h7e30c49_1
  - fonts-conda-ecosystem=1=0
  - fonts-conda-forge=1=0
  - fonttools=4.56.0=py39h9399b63_0
  - fortran-compiler=1.9.0=h36df796_0
  - freetype=2.13.3=h48d6fc4_0
  - fribidi=1.0.10=h36c2ea0_0
  - fsspec=2025.3.1=pyhd8ed1ab_0
  - gcc=13.3.0=h9576a4e_2
  - gcc_impl_linux-64=13.3.0=h1e990d8_2
  - gcc_linux-64=13.3.0=hc28eda2_8
  - gdk-pixbuf=2.42.12=hb9ae30d_0
  - geos=3.13.1=h97f6797_0
  - gfortran=13.3.0=h9576a4e_2
  - gfortran_impl_linux-64=13.3.0=h84c1745_2
  - gfortran_linux-64=13.3.0=hb919d3a_8
  - glib-tools=2.84.0=h4833e2c_0
  - graphite2=1.3.13=h59595ed_1003
  - graphviz=12.2.1=h5ae0cbf_1
  - gtk3=3.24.43=h0c6a113_5
  - gts=0.7.6=h977cf35_4
  - gxx=13.3.0=h9576a4e_2
  - gxx_impl_linux-64=13.3.0=hae580e1_2
  - gxx_linux-64=13.3.0=h6834431_8
  - harfbuzz=11.0.0=h76408a6_0
  - hdf4=4.2.15=h2a13503_7
  - hdf5=1.14.3=mpi_mpich_h7f58efa_9
  - hicolor-icon-theme=0.17=ha770c72_2
  - icu=75.1=he02047a_0
  - importlib-metadata=8.6.1=pyha770c72_0
  - importlib-resources=6.5.2=pyhd8ed1ab_0
  - importlib_metadata=8.6.1=hd8ed1ab_0
  - importlib_resources=6.5.2=pyhd8ed1ab_0
  - iris=3.8.1=pyha770c72_0
  - jinja2=3.1.6=pyhd8ed1ab_0
  - kernel-headers_linux-64=3.10.0=he073ed8_18
  - keyutils=1.6.1=h166bdaf_0
  - kiwisolver=1.4.7=py39h74842e3_0
  - krb5=1.21.3=h659f571_0
  - lcms2=2.17=h717163a_0
  - ld_impl_linux-64=2.43=h712a8e2_4
  - lerc=4.0.0=h27087fc_0
  - libaec=1.1.3=h59595ed_0
  - libblas=3.9.0=31_h59b9bed_openblas
  - libbrotlicommon=1.1.0=hb9d3cd8_2
  - libbrotlidec=1.1.0=hb9d3cd8_2
  - libbrotlienc=1.1.0=hb9d3cd8_2
  - libcap=2.75=h39aace5_0
  - libcblas=3.9.0=31_he106b2a_openblas
  - libcups=2.3.3=h4637d8d_4
  - libcurl=8.12.1=h332b0f4_0
  - libdeflate=1.23=h4ddbbb0_0
  - libedit=3.1.20250104=pl5321h7949ede_0
  - libev=4.33=hd590300_2
  - libexpat=2.7.0=h5888daf_0
  - libfabric=2.1.0=ha770c72_0
  - libfabric1=2.1.0=h14e6f36_0
  - libffi=3.4.6=h2dba641_0
  - libgcc=14.2.0=h767d61c_2
  - libgcc-devel_linux-64=13.3.0=hc03c837_102
  - libgcc-ng=14.2.0=h69a702a_2
  - libgcrypt-lib=1.11.0=hb9d3cd8_2
  - libgd=2.3.3=h6f5c62b_11
  - libgfortran=14.2.0=h69a702a_2
  - libgfortran-ng=14.2.0=h69a702a_2
  - libgfortran5=14.2.0=hf1ad2bd_2
  - libglib=2.84.0=h2ff4ddf_0
  - libgomp=14.2.0=h767d61c_2
  - libgpg-error=1.51=hbd13f7d_1
  - libhwloc=2.11.2=default_h0d58e46_1001
  - libiconv=1.18=h4ce23a2_1
  - libjpeg-turbo=3.0.0=hd590300_1
  - liblapack=3.9.0=31_h7ac8fdf_openblas
  - liblzma=5.6.4=hb9d3cd8_0
  - libnetcdf=4.9.2=mpi_mpich_h761946e_14
  - libnghttp2=1.64.0=h161d5f1_0
  - libnl=3.11.0=hb9d3cd8_0
  - libnsl=2.0.1=hd590300_0
  - libopenblas=0.3.29=pthreads_h94d23a6_0
  - libpnetcdf=1.13.0=mpi_mpich_hdce4f7b_101
  - libpng=1.6.47=h943b412_0
  - librsvg=2.58.4=he92a37e_3
  - libsanitizer=13.3.0=he8ea267_2
  - libsqlite=3.49.1=hee588c1_2
  - libssh2=1.11.1=hf672d98_0
  - libstdcxx=14.2.0=h8f9b012_2
  - libstdcxx-devel_linux-64=13.3.0=hc03c837_102
  - libstdcxx-ng=14.2.0=h4852527_2
  - libsystemd0=257.4=h4e0b6ca_1
  - libtiff=4.7.0=hd9ff511_3
  - libudev1=257.4=hbe16f8c_1
  - libudunits2=2.2.28=h40f5838_3
  - libunwind=1.7.2=he02047a_0
  - libuuid=2.38.1=h0b41bf4_0
  - libwebp-base=1.5.0=h851e524_0
  - libxcb=1.17.0=h8a09558_0
  - libxcrypt=4.4.36=hd590300_1
  - libxkbcommon=1.8.1=hc4a0caf_0
  - libxml2=2.13.7=h8d12d68_0
  - libzip=1.11.2=h6991a6a_0
  - libzlib=1.3.1=hb9d3cd8_2
  - locket=1.0.0=pyhd8ed1ab_0
  - lz4-c=1.10.0=h5888daf_1
  - markupsafe=3.0.2=py39h9399b63_1
  - matplotlib-base=3.9.4=py39h16632d1_0
  - mpi=1.0.1=mpich
  - mpich=4.3.0=h1a8bee6_100
  - munkres=1.1.4=pyh9f0ad1d_0
  - ncurses=6.5=h2d0b736_3
  - netcdf-fortran=4.6.1=mpi_mpich_h2e543cf_8
  - netcdf4=1.7.2=nompi_py39h9d02bfe_101
  - numpy=2.0.2=py39h9cb892a_1
  - openjpeg=2.5.3=h5fbd93e_0
  - openssl=3.4.1=h7b32b05_0
  - packaging=24.2=pyhd8ed1ab_2
  - pango=1.56.3=h9ac818e_1
  - parallelio=2.6.3=mpi_mpich_h43d51f9_100
  - partd=1.4.2=pyhd8ed1ab_0
  - pcre2=10.44=hba22ea6_2
  - pillow=11.1.0=py39h15c0740_0
  - pip=25.0.1=pyh8b19718_0
  - pixman=0.44.2=h29eaf8c_0
  - proj=9.5.1=h0054346_0
  - pthread-stubs=0.4=hb9d3cd8_1002
  - pyparsing=3.2.3=pyhd8ed1ab_1
  - pyproj=3.6.1=py39h306d449_10
  - pyshp=2.3.1=pyhd8ed1ab_1
  - python=3.9.21=h9c0c6dc_1_cpython
  - python-dateutil=2.9.0.post0=pyhff2d567_1
  - python-stratify=0.3.0=py39hf3d9206_3
  - python-xxhash=3.5.0=py39h8cd3c5a_2
  - python_abi=3.9=5_cp39
  - pyyaml=6.0.2=py39h9399b63_2
  - qhull=2020.2=h434a139_5
  - rdma-core=56.0=h5888daf_0
  - readline=8.2=h8c095d6_2
  - scipy=1.13.1=py39haf93ffa_0
  - setuptools=75.8.2=pyhff2d567_0
  - shapely=2.0.7=py39h322cc2b_1
  - six=1.17.0=pyhd8ed1ab_0
  - snappy=1.2.1=h8bd8927_1
  - sqlite=3.49.1=h9eae976_2
  - sysroot_linux-64=2.17=h0157908_18
  - tk=8.6.13=noxft_h4845f30_101
  - toolz=1.0.0=pyhd8ed1ab_1
  - tzdata=2025b=h78e105d_0
  - ucx=1.18.0=hfd9a62f_2
  - udunits2=2.2.28=h40f5838_3
  - unicodedata2=16.0.0=py39h8cd3c5a_0
  - wayland=1.23.1=h3e06ad9_0
  - wheel=0.45.1=pyhd8ed1ab_1
  - xkeyboard-config=2.43=hb9d3cd8_0
  - xorg-libice=1.1.2=hb9d3cd8_0
  - xorg-libsm=1.2.6=he73a12e_0
  - xorg-libx11=1.8.12=h4f16b4b_0
  - xorg-libxau=1.0.12=hb9d3cd8_0
  - xorg-libxcomposite=0.4.6=hb9d3cd8_2
  - xorg-libxcursor=1.2.3=hb9d3cd8_0
  - xorg-libxdamage=1.1.6=hb9d3cd8_0
  - xorg-libxdmcp=1.1.5=hb9d3cd8_0
  - xorg-libxext=1.3.6=hb9d3cd8_0
  - xorg-libxfixes=6.0.1=hb9d3cd8_0
  - xorg-libxi=1.8.2=hb9d3cd8_0
  - xorg-libxinerama=1.1.5=h5888daf_1
  - xorg-libxrandr=1.5.4=hb9d3cd8_0
  - xorg-libxrender=0.9.12=hb9d3cd8_0
  - xorg-libxtst=1.2.5=hb9d3cd8_3
  - xxhash=0.8.3=hb9d3cd8_0
  - yaml=0.2.5=h7f98852_2
  - zipp=3.21.0=pyhd8ed1ab_1
  - zlib=1.3.1=hb9d3cd8_2
  - zstd=1.5.7=hb8e6e7a_2
  - pip:
      - alabaster==0.7.16
      - astroid==3.3.9
      - attrs==25.3.0
      - autodocsumm==0.2.14
      - babel==2.17.0
      - build==1.2.2.post1
      - cfgv==3.4.0
      - charset-normalizer==3.4.1
      - click-plugins==1.1.1
      - cligj==0.7.2
      - codespell==2.4.1
      - colorama==0.4.6
      - coverage==7.8.0
      - dill==0.3.9
      - distlib==0.3.9
      - docformatter==1.7.5
      - docutils==0.21.2
      - dodgy==0.2.1
      - exceptiongroup==1.2.2
      - execnet==2.1.1
      - filelock==3.18.0
      - fiona==1.10.1
      - fire==0.7.0
      - flake8==7.2.0
      - flake8-polyfill==1.0.2
      - gitdb==4.0.12
      - gitpython==3.1.44
      - identify==2.6.9
      - idna==3.10
      - imagesize==1.4.1
      - iniconfig==2.1.0
      - isodate==0.6.1
      - isort==6.0.1
      - llvmlite==0.43.0
      - lxml==5.3.1
      - mccabe==0.7.0
      - nc-time-axis==1.4.1
      - networkx==3.2.1
      - nodeenv==1.9.1
      - numba==0.60.0
      - pathspec==0.12.1
      - pep8-naming==0.10.0
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - pre-commit==4.2.0
      - prospector==1.16.1
      - prov==2.0.1
      - psutil==7.0.0
      - pycodestyle==2.13.0
      - pydocstyle==6.3.0
      - pydot==3.0.4
      - pyflakes==3.3.2
      - pygments==2.19.1
      - pylint==3.3.6
      - pylint-celery==0.3
      - pylint-django==2.6.1
      - pylint-plugin-utils==0.8.2
      - pyproject-hooks==1.2.0
      - pyroma==4.2
      - pytest==8.3.5
      - pytest-asyncio==0.26.0
      - pytest-cov==6.0.0
      - pytest-env==1.1.5
      - pytest-flake8==1.3.0
      - pytest-html==4.1.1
      - pytest-metadata==3.1.1
      - pytest-mock==3.14.0
      - pytest-xdist==3.6.1
      - pytz==2025.2
      - rdflib==6.3.2
      - requests==2.32.3
      - requirements-detector==1.3.2
      - semver==3.0.4
      - setoptconf-tmp==0.3.1
      - smmap==5.0.2
      - snowballstemmer==2.2.0
      - sphinx==7.4.7
      - sphinx-rtd-theme==3.0.2
      - sphinxcontrib-applehelp==2.0.0
      - sphinxcontrib-devhelp==2.0.0
      - sphinxcontrib-htmlhelp==2.1.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==2.0.0
      - sphinxcontrib-serializinghtml==2.0.0
      - termcolor==3.0.0
      - toml==0.10.2
      - tomli==2.2.1
      - tomlkit==0.13.2
      - trove-classifiers==2025.3.19.19
      - typing-extensions==4.13.0
      - untokenize==0.1.1
      - urllib3==2.3.0
      - virtualenv==20.29.3
      - vmprof==0.4.18.1
      - yamale==2.2.0
      - yamllint==1.37.0
      - yapf==0.43.0
prefix: /opt/conda/envs/ESMValCore

tests/integration/cmor/test_table.py::TestCustomInfo::test_custom_tables_location tests/integration/cmor/test_table.py::Testobs4mipsInfo::test_get_variable_from_custom tests/integration/cmor/test_table.py::Testobs4mipsInfo::test_get_variable_from_custom_deriving tests/integration/cmor/test_table.py::Testobs4mipsInfo::test_get_bad_variable tests/integration/cmor/test_table.py::TestCustomInfo::test_get_bad_variable tests/integration/cmor/test_table.py::TestCMIP3Info::test_get_variable_tas tests/integration/cmor/test_table.py::Testobs4mipsInfo::test_get_variable_hus_default_prefix tests/integration/cmor/test_table.py::Testobs4mipsInfo::test_get_table_frequency tests/integration/cmor/test_table.py::TestCMIP3Info::test_aermon_ta_fail_if_strict tests/integration/cmor/test_table.py::TestCMIP3Info::test_aermon_ta_succes_if_strict tests/integration/cmor/test_table.py::TestCMIP3Info::test_get_variable_zg tests/integration/cmor/test_table.py::TestCustomInfo::test_get_variable_tas tests/integration/cmor/test_table.py::TestCMIP6Info::test_get_activity_from_exp tests/integration/cmor/test_table.py::TestCMIP6Info::test_get_variable_tas tests/integration/cmor/test_table.py::Testobs4mipsInfo::test_get_variable_hus tests/integration/cmor/test_table.py::TestCMIP6Info::test_get_variable_from_custom tests/integration/cmor/test_table.py::TestCMIP3Info::test_omon_toz_succes_if_strict tests/integration/cmor/test_table.py::TestCMIP3Info::test_get_bad_variable tests/integration/cmor/test_table.py::TestCORDEXInfo::test_get_variable_tas tests/integration/cmor/test_table.py::TestCMIP6Info::test_omon_ta_succes_if_strict tests/integration/cmor/test_table.py::TestCMIP6Info::test_omon_toz_succes_if_strict tests/integration/cmor/test_table.py::TestCORDEXInfo::test_custom_tables_location tests/integration/cmor/test_table.py::TestCMIP6Info::test_get_table_frequency tests/integration/cmor/test_table.py::TestCMIP5Info::test_aermon_ta_fail_if_strict tests/integration/cmor/test_table.py::TestCMIP6Info::test_omon_ta_fail_if_strict tests/integration/cmor/test_table.py::TestCMIP3Info::test_custom_tables_location tests/integration/cmor/test_table.py::TestCORDEXInfo::test_get_bad_variable tests/integration/cmor/test_table.py::Testobs4mipsInfo::test_get_variable_ndvistderr tests/integration/cmor/test_table.py::TestCMIP6Info::test_get_variable_from_alias tests/integration/cmor/test_table.py::TestCMIP3Info::test_get_variable_from_custom tests/integration/cmor/test_table.py::TestCMIP5Info::test_omon_toz_succes_if_strict tests/integration/cmor/test_table.py::TestCMIP5Info::test_aermon_ta_succes_if_strict tests/integration/cmor/test_table.py::TestCMIP6Info::test_get_bad_variable tests/integration/cmor/test_table.py::TestCMIP5Info::test_get_bad_variable tests/integration/cmor/test_table.py::TestCMIP5Info::test_get_variable_tas tests/integration/cmor/test_table.py::TestCMIP6Info::test_get_institute_from_source tests/integration/cmor/test_table.py::TestCMIP5Info::test_get_variable_zg tests/integration/cmor/test_table.py::TestCMIP6Info::test_custom_tables_location tests/integration/cmor/test_table.py::TestCMIP5Info::test_get_variable_from_custom tests/integration/cmor/test_table.py::Testobs4mipsInfo::test_custom_tables_location tests/integration/cmor/test_table.py::TestCMIP5Info::test_custom_tables_location tests/integration/cmor/test_table.py::flake-8::FLAKE8 tests/unit/preprocessor/_area/test_area.py::flake-8::FLAKE8
setup.py doc/contributing.rst .circleci/config.yml setup.cfg package/meta.yaml
setup.py doc/contributing.rst .circleci/config.yml setup.cfg package/meta.yaml