Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelog/7270.dependency
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:user:`trexfeathers` modernised the Iris gallery tests, and set several to skip
if using the incompatible combination of PROJ>=9.8 and Cartopy<0.26.
3 changes: 3 additions & 0 deletions docs/gallery_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

import iris

pytest_plugins = ["iris.tests.conftest"]


CURRENT_DIR = pathlib.Path(__file__).resolve()
GALLERY_DIR = CURRENT_DIR.parents[1] / "gallery_code"

Expand Down
17 changes: 13 additions & 4 deletions docs/gallery_tests/test_gallery_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
import matplotlib.pyplot as plt
import pytest

from iris.tests import _RESULT_PATH
from iris.tests.graphics import check_graphic
from iris.tests import _shared_utils

from .conftest import GALLERY_DIR

Expand All @@ -29,8 +28,19 @@ def test_plot_example(
image_setup_teardown,
import_patches,
iris_future_defaults,
check_graphic_caller,
):
"""Test that all figures from example code match KGO."""
if example in (
"plot_TEC",
"plot_orca_projection",
"plot_projections_and_annotations",
):
proj_9_8_message = _shared_utils.proj_9_8_incompatible_message()
incompatible = proj_9_8_message != ""
if incompatible:
pytest.skip(proj_9_8_message)

module = importlib.import_module(example)

# Run example.
Expand All @@ -39,5 +49,4 @@ def test_plot_example(
# will find it.
for fig_num in plt.get_fignums():
plt.figure(fig_num)
image_id = f"gallery_tests.test_{example}.{fig_num - 1}"
check_graphic(image_id, _RESULT_PATH)
check_graphic_caller()
27 changes: 20 additions & 7 deletions lib/iris/tests/_shared_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1024,15 +1024,12 @@ def env_bin_path(exe_name: Optional[str] = None):
return exe_path


# TODO: Remove this decorator once problematic versions have been phased out
def skip_proj_9_8_incompatible(func: Callable):
"""A decorator that skips decorated tests when PROJ is >=9.8 and Cartopy is <0.26.
# TODO: Remove this convenience once problematic versions have been phased out
def proj_9_8_incompatible_message() -> str:
"""Return a message if Cartopy is <0.26 and PROJ is >=9.8, otherwise return an empty string.

Cartopy v0.26 addresses a known incompatibility with PROJ v9.8:
https://github.com/SciTools/cartopy/pull/2653

Implemented as a callable to avoid wasteful top-level import of these
packages - _shared_utils is imported by every test module.
"""
import cartopy
from packaging.version import Version
Expand All @@ -1042,9 +1039,25 @@ def skip_proj_9_8_incompatible(func: Callable):
proj_version = Version(pyproj.__proj_version__)

incompatible = proj_version >= Version("9.8") and cartopy_version < Version("0.26")
if incompatible:
result = "Cartopy<0.26 is incompatible with PROJ>=9.8. SciTools/cartopy#2653"
else:
result = ""
return result


# TODO: Remove this decorator once problematic versions have been phased out
def skip_proj_9_8_incompatible(func: Callable):
"""A decorator that skips decorated tests when PROJ is >=9.8 and Cartopy is <0.26.

Implemented as a callable to avoid wasteful top-level import of these
packages - _shared_utils is imported by every test module.
"""
message = proj_9_8_incompatible_message()
incompatible = message != ""
skip = pytest.mark.skipif(
incompatible,
reason="Cartopy<0.26 is incompatible with PROJ>=9.8. SciTools/cartopy#2653",
reason=message,
)
return skip(func)

Expand Down
13 changes: 11 additions & 2 deletions lib/iris/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,20 @@ def _unique_id(request: pytest.FixtureRequest, test_call_counter) -> Callable:
Used by :func:`iris.tests.graphics.check_graphic_caller` to ensure unique
image names.
"""
id_sequence = [request.module.__name__, request.node.originalname]
# Backwards compatibility for existing gallery result naming.
gallery_compat = request.module.__name__.startswith("gallery_tests.")

if gallery_compat:
id_sequence = ["gallery_tests"]
else:
id_sequence = [request.module.__name__, request.node.originalname]
if request.cls is not None:
id_sequence.insert(-1, request.cls.__name__)
if hasattr(request.node, "callspec"):
id_sequence.append(request.node.callspec.id)
callspec_id = request.node.callspec.id
if gallery_compat:
callspec_id = f"test_{callspec_id}"
id_sequence.append(callspec_id)
test_id = ".".join(id_sequence)

def generate_id():
Expand Down
359 changes: 183 additions & 176 deletions requirements/locks/py312-linux-64.lock

Large diffs are not rendered by default.

359 changes: 183 additions & 176 deletions requirements/locks/py313-linux-64.lock

Large diffs are not rendered by default.

325 changes: 163 additions & 162 deletions requirements/locks/py314-linux-64.lock

Large diffs are not rendered by default.

Loading