From e2236e865493de200bdd4ef1b248427dad33185a Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Tue, 22 Aug 2023 11:23:59 +0100 Subject: [PATCH 1/2] import packaging.version --- lib/cartopy/mpl/contour.py | 2 +- lib/cartopy/mpl/geoaxes.py | 2 +- lib/cartopy/mpl/geocollection.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cartopy/mpl/contour.py b/lib/cartopy/mpl/contour.py index 3e4a3843f..05edf74f9 100644 --- a/lib/cartopy/mpl/contour.py +++ b/lib/cartopy/mpl/contour.py @@ -8,7 +8,7 @@ from matplotlib.contour import QuadContourSet import matplotlib.path as mpath import numpy as np -import packaging +import packaging.version class GeoContourSet(QuadContourSet): diff --git a/lib/cartopy/mpl/geoaxes.py b/lib/cartopy/mpl/geoaxes.py index 18e38a400..b1cbd9693 100644 --- a/lib/cartopy/mpl/geoaxes.py +++ b/lib/cartopy/mpl/geoaxes.py @@ -32,7 +32,7 @@ import matplotlib.transforms as mtransforms import numpy as np import numpy.ma as ma -import packaging +import packaging.version import shapely.geometry as sgeom from cartopy import config diff --git a/lib/cartopy/mpl/geocollection.py b/lib/cartopy/mpl/geocollection.py index 9f653ab10..2ae9aa218 100644 --- a/lib/cartopy/mpl/geocollection.py +++ b/lib/cartopy/mpl/geocollection.py @@ -7,7 +7,7 @@ from matplotlib.collections import QuadMesh import numpy as np import numpy.ma as ma -import packaging +import packaging.version _MPL_VERSION = packaging.version.parse(mpl.__version__) From 67cfc594d4c75736bde6cd2b999bf888eb7d820a Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Tue, 22 Aug 2023 16:58:06 +0100 Subject: [PATCH 2/2] consolidate mpl version checks --- lib/cartopy/mpl/__init__.py | 11 +++++++++++ lib/cartopy/mpl/contour.py | 6 +++--- lib/cartopy/mpl/geoaxes.py | 12 ++++-------- lib/cartopy/mpl/geocollection.py | 13 +++++-------- lib/cartopy/tests/mpl/__init__.py | 4 ---- lib/cartopy/tests/mpl/test_caching.py | 4 ++-- lib/cartopy/tests/mpl/test_crs.py | 12 ++++-------- lib/cartopy/tests/mpl/test_examples.py | 5 ++--- lib/cartopy/tests/mpl/test_mpl_integration.py | 16 +++++++--------- 9 files changed, 38 insertions(+), 45 deletions(-) diff --git a/lib/cartopy/mpl/__init__.py b/lib/cartopy/mpl/__init__.py index 4d9502643..75bcce3a9 100644 --- a/lib/cartopy/mpl/__init__.py +++ b/lib/cartopy/mpl/__init__.py @@ -3,3 +3,14 @@ # This file is part of Cartopy and is released under the LGPL license. # See COPYING and COPYING.LESSER in the root of the repository for full # licensing details. + +import matplotlib +import packaging.version + + +_MPL_VERSION = packaging.version.parse(matplotlib.__version__) +_MPL_34 = _MPL_VERSION.release[:2] >= (3, 4) +_MPL_35 = _MPL_VERSION.release[:2] >= (3, 5) +_MPL_38 = _MPL_VERSION.release[:2] >= (3, 8) + +assert _MPL_34, 'Cartopy is only supported with Matplotlib 3.4 or greater.' diff --git a/lib/cartopy/mpl/contour.py b/lib/cartopy/mpl/contour.py index 05edf74f9..7af19eaad 100644 --- a/lib/cartopy/mpl/contour.py +++ b/lib/cartopy/mpl/contour.py @@ -4,11 +4,11 @@ # See COPYING and COPYING.LESSER in the root of the repository for full # licensing details. -import matplotlib as mpl from matplotlib.contour import QuadContourSet import matplotlib.path as mpath import numpy as np -import packaging.version + +from cartopy.mpl import _MPL_38 class GeoContourSet(QuadContourSet): @@ -21,7 +21,7 @@ class GeoContourSet(QuadContourSet): # fiddling with instance.__class__. def clabel(self, *args, **kwargs): - if packaging.version.parse(mpl.__version__).release[:2] < (3, 8): + if not _MPL_38: # nb: contour labelling does not work very well for filled # contours - it is recommended to only label line contours. # This is especially true when inline=True. diff --git a/lib/cartopy/mpl/geoaxes.py b/lib/cartopy/mpl/geoaxes.py index b1cbd9693..2bbe4caf9 100644 --- a/lib/cartopy/mpl/geoaxes.py +++ b/lib/cartopy/mpl/geoaxes.py @@ -32,12 +32,12 @@ import matplotlib.transforms as mtransforms import numpy as np import numpy.ma as ma -import packaging.version import shapely.geometry as sgeom from cartopy import config import cartopy.crs as ccrs import cartopy.feature +from cartopy.mpl import _MPL_38 import cartopy.mpl.contour import cartopy.mpl.feature_artist as feature_artist import cartopy.mpl.geocollection @@ -45,10 +45,6 @@ from cartopy.mpl.slippy_image_artist import SlippyImageArtist -_MPL_VERSION = packaging.version.parse(mpl.__version__) -assert _MPL_VERSION.release >= (3, 4), \ - 'Cartopy is only supported with Matplotlib 3.4 or greater.' - # A nested mapping from path, source CRS, and target projection to the # resulting transformed paths: # {path: {(source_crs, target_projection): list_of_paths}} @@ -1604,7 +1600,7 @@ def contour(self, *args, **kwargs): result = super().contour(*args, **kwargs) # We need to compute the dataLim correctly for contours. - if _MPL_VERSION.release[:2] < (3, 8): + if not _MPL_38: bboxes = [col.get_datalim(self.transData) for col in result.collections if col.get_paths()] @@ -1655,7 +1651,7 @@ def contourf(self, *args, **kwargs): result = super().contourf(*args, **kwargs) # We need to compute the dataLim correctly for contours. - if _MPL_VERSION.release[:2] < (3, 8): + if not _MPL_38: bboxes = [col.get_datalim(self.transData) for col in result.collections if col.get_paths()] @@ -1952,7 +1948,7 @@ def _wrap_quadmesh(self, collection, **kwargs): # masked, so this will only draw a limited subset of # polygons that were actually wrapped. - if _MPL_VERSION.release[:2] < (3, 8): + if not _MPL_38: # We will add the original data mask in later to # make sure that set_array can work in future # calls on the proper sized array inputs. diff --git a/lib/cartopy/mpl/geocollection.py b/lib/cartopy/mpl/geocollection.py index 2ae9aa218..1417d526f 100644 --- a/lib/cartopy/mpl/geocollection.py +++ b/lib/cartopy/mpl/geocollection.py @@ -3,14 +3,11 @@ # This file is part of Cartopy and is released under the LGPL license. # See COPYING and COPYING.LESSER in the root of the repository for full # licensing details. -import matplotlib as mpl from matplotlib.collections import QuadMesh import numpy as np import numpy.ma as ma -import packaging.version - -_MPL_VERSION = packaging.version.parse(mpl.__version__) +from cartopy.mpl import _MPL_38 def _split_wrapped_mesh_data(C, mask): @@ -24,7 +21,7 @@ def _split_wrapped_mesh_data(C, mask): C_mask = getattr(C, 'mask', None) if C.ndim == 3: # RGB(A) array. - if _MPL_VERSION.release < (3, 8): + if not _MPL_38: raise ValueError("GeoQuadMesh wrapping for RGB(A) requires " "Matplotlib v3.8 or later") @@ -58,7 +55,7 @@ def get_array(self): if hasattr(self, '_wrapped_mask'): pcolor_data = self._wrapped_collection_fix.get_array() mask = self._wrapped_mask - if _MPL_VERSION.release[:2] < (3, 8): + if not _MPL_38: A[mask] = pcolor_data else: if A.ndim == 3: # RGB(A) data. Need to broadcast mask. @@ -72,7 +69,7 @@ def get_array(self): def set_array(self, A): # Check the shape is appropriate up front. - if _MPL_VERSION.release[:2] < (3, 8): + if not _MPL_38: # Need to figure out existing shape from the coordinates. height, width = self._coordinates.shape[0:-1] if self._shading == 'flat': @@ -102,7 +99,7 @@ def set_array(self, A): # Update the pcolor data with the wrapped masked data A, pcolor_data, _ = _split_wrapped_mesh_data(A, self._wrapped_mask) - if _MPL_VERSION.release[:2] < (3, 8): + if not _MPL_38: self._wrapped_collection_fix.set_array( pcolor_data[self._wrapped_mask].ravel()) else: diff --git a/lib/cartopy/tests/mpl/__init__.py b/lib/cartopy/tests/mpl/__init__.py index 6666e92b4..1cf5554d7 100644 --- a/lib/cartopy/tests/mpl/__init__.py +++ b/lib/cartopy/tests/mpl/__init__.py @@ -7,10 +7,6 @@ import matplotlib as mpl import matplotlib.patches as mpatches import matplotlib.pyplot as plt -import packaging.version - - -MPL_VERSION = packaging.version.parse(mpl.__version__) def show(projection, geometry): diff --git a/lib/cartopy/tests/mpl/test_caching.py b/lib/cartopy/tests/mpl/test_caching.py index 5469f6ecd..110d674a4 100644 --- a/lib/cartopy/tests/mpl/test_caching.py +++ b/lib/cartopy/tests/mpl/test_caching.py @@ -19,10 +19,10 @@ import cartopy.crs as ccrs from cartopy.io.ogc_clients import _OWSLIB_AVAILABLE, WMTSRasterSource import cartopy.io.shapereader +from cartopy.mpl import _MPL_38 from cartopy.mpl.feature_artist import FeatureArtist import cartopy.mpl.geoaxes as cgeoaxes import cartopy.mpl.patch -from cartopy.tests.mpl import MPL_VERSION def sample_data(shape=(73, 145)): @@ -121,7 +121,7 @@ def test_contourf_transform_path_counting(): with mock.patch('cartopy.mpl.patch.path_to_geos') as path_to_geos_counter: x, y, z = sample_data((30, 60)) cs = ax.contourf(x, y, z, 5, transform=ccrs.PlateCarree()) - if MPL_VERSION.release[:2] < (3, 8): + if not _MPL_38: n_geom = sum(len(c.get_paths()) for c in cs.collections) else: n_geom = len(cs.get_paths()) diff --git a/lib/cartopy/tests/mpl/test_crs.py b/lib/cartopy/tests/mpl/test_crs.py index 7c8580a59..c37036662 100644 --- a/lib/cartopy/tests/mpl/test_crs.py +++ b/lib/cartopy/tests/mpl/test_crs.py @@ -8,14 +8,12 @@ import pytest import cartopy.crs as ccrs -from cartopy.tests.mpl import MPL_VERSION +from cartopy.mpl import _MPL_35 @pytest.mark.natural_earth -@pytest.mark.mpl_image_compare(filename="igh_land.png", - tolerance=(3.6 - if MPL_VERSION.release[:2] < (3, 5) - else 0.5)) +@pytest.mark.mpl_image_compare( + filename="igh_land.png", tolerance=0.5 if _MPL_35 else 3.6) def test_igh_land(): crs = ccrs.InterruptedGoodeHomolosine(emphasis="land") ax = plt.axes(projection=crs) @@ -26,9 +24,7 @@ def test_igh_land(): @pytest.mark.natural_earth @pytest.mark.mpl_image_compare(filename="igh_ocean.png", - tolerance=(4.5 - if MPL_VERSION.release[:2] < (3, 5) - else 0.5)) + tolerance=0.5 if _MPL_35 else 4.5) def test_igh_ocean(): crs = ccrs.InterruptedGoodeHomolosine( central_longitude=-160, emphasis="ocean" diff --git a/lib/cartopy/tests/mpl/test_examples.py b/lib/cartopy/tests/mpl/test_examples.py index 76f76d292..cc171221d 100644 --- a/lib/cartopy/tests/mpl/test_examples.py +++ b/lib/cartopy/tests/mpl/test_examples.py @@ -8,7 +8,7 @@ import pytest import cartopy.crs as ccrs -from cartopy.tests.mpl import MPL_VERSION +from cartopy.mpl import _MPL_38 @pytest.mark.natural_earth @@ -33,8 +33,7 @@ def test_global_map(): @pytest.mark.natural_earth @pytest.mark.mpl_image_compare( - filename='contour_label.png', - tolerance=3.9 if MPL_VERSION.release[:2] >= (3, 8) else 0.5) + filename='contour_label.png', tolerance=3.9 if _MPL_38 else 0.5) def test_contour_label(): from cartopy.tests.mpl.test_caching import sample_data fig = plt.figure() diff --git a/lib/cartopy/tests/mpl/test_mpl_integration.py b/lib/cartopy/tests/mpl/test_mpl_integration.py index 8a60b6d96..deba9cf49 100644 --- a/lib/cartopy/tests/mpl/test_mpl_integration.py +++ b/lib/cartopy/tests/mpl/test_mpl_integration.py @@ -12,7 +12,7 @@ import pytest import cartopy.crs as ccrs -from cartopy.tests.mpl import MPL_VERSION +from cartopy.mpl import _MPL_35, _MPL_38 @pytest.mark.natural_earth @@ -197,8 +197,7 @@ def test_simple_global(): ), ]) @pytest.mark.mpl_image_compare( - tolerance=0.97 if MPL_VERSION.release[:2] < (3, 5) else 0.5, - style='mpl20') + tolerance=0.5 if _MPL_35 else 0.97, style='mpl20') def test_global_map(proj): if isinstance(proj, tuple): proj, kwargs = proj @@ -241,8 +240,7 @@ def test_cursor_values(): r.encode('ascii', 'ignore')) -SKIP_PRE_MPL38 = pytest.mark.skipif( - MPL_VERSION.release[:2] < (3, 8), reason='mpl < 3.8') +SKIP_PRE_MPL38 = pytest.mark.skipif(not _MPL_38, reason='mpl < 3.8') PARAMETRIZE_PCOLORMESH_WRAP = pytest.mark.parametrize( 'mesh_data_kind', [ @@ -357,7 +355,7 @@ def test_pcolormesh_get_array_with_mask(mesh_data_kind): result = c.get_array() expected = data2 - if MPL_VERSION.release[:2] < (3, 8): + if not _MPL_38: expected = expected.ravel() np.testing.assert_array_equal(np.ma.getmask(result), np.isnan(expected)) @@ -521,7 +519,7 @@ def test_pcolormesh_set_array_nowrap(): assert not hasattr(mesh, '_wrapped_collection_fix') expected = data - if MPL_VERSION.release[:2] < (3, 8): + if not _MPL_38: expected = expected.ravel() np.testing.assert_array_equal(mesh.get_array(), expected) @@ -681,7 +679,7 @@ def test_pcolormesh_nan_wrap(): ax = plt.axes(projection=ccrs.PlateCarree()) mesh = ax.pcolormesh(xs, ys, data) pcolor = getattr(mesh, "_wrapped_collection_fix") - if MPL_VERSION.release[:2] < (3, 8): + if not _MPL_38: assert len(pcolor.get_paths()) == 2 else: assert not pcolor.get_paths() @@ -961,7 +959,7 @@ def test_barbs_1d_transformed(): @pytest.mark.natural_earth @pytest.mark.mpl_image_compare( filename='streamplot.png', style='mpl20', - tolerance=9.77 if MPL_VERSION.release[:2] < (3, 5) else 0.5) + tolerance=0.5 if _MPL_35 else 9.77) def test_streamplot(): x = np.arange(-60, 42.5, 2.5) y = np.arange(30, 72.5, 2.5)