From a136915a8421864a4bb18dcc06bade3b324ff1f3 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Mon, 8 Feb 2021 11:20:36 +0000
Subject: [PATCH 01/43] Add abstract cube summary (#3987)
Co-authored-by: stephen.worsley
---
lib/iris/_representation.py | 273 ++++++++++++++++++
.../tests/unit/representation/__init__.py | 6 +
.../representation/test_representation.py | 187 ++++++++++++
3 files changed, 466 insertions(+)
create mode 100644 lib/iris/_representation.py
create mode 100644 lib/iris/tests/unit/representation/__init__.py
create mode 100644 lib/iris/tests/unit/representation/test_representation.py
diff --git a/lib/iris/_representation.py b/lib/iris/_representation.py
new file mode 100644
index 0000000000..301f4a9a22
--- /dev/null
+++ b/lib/iris/_representation.py
@@ -0,0 +1,273 @@
+# Copyright Iris contributors
+#
+# This file is part of Iris and is released under the LGPL license.
+# See COPYING and COPYING.LESSER in the root of the repository for full
+# licensing details.
+"""
+Provides objects describing cube summaries.
+"""
+
+import iris.util
+
+
+class DimensionHeader:
+ def __init__(self, cube):
+ if cube.shape == ():
+ self.scalar = True
+ self.dim_names = []
+ self.shape = []
+ self.contents = ["scalar cube"]
+ else:
+ self.scalar = False
+ self.dim_names = []
+ for dim in range(len(cube.shape)):
+ dim_coords = cube.coords(
+ contains_dimension=dim, dim_coords=True
+ )
+ if dim_coords:
+ self.dim_names.append(dim_coords[0].name())
+ else:
+ self.dim_names.append("-- ")
+ self.shape = list(cube.shape)
+ self.contents = [
+ name + ": %d" % dim_len
+ for name, dim_len in zip(self.dim_names, self.shape)
+ ]
+
+
+class FullHeader:
+ def __init__(self, cube, name_padding=35):
+ self.name = cube.name()
+ self.unit = cube.units
+ self.nameunit = "{name} / ({units})".format(
+ name=self.name, units=self.unit
+ )
+ self.name_padding = name_padding
+ self.dimension_header = DimensionHeader(cube)
+
+
+class CoordSummary:
+ def _summary_coord_extra(self, cube, coord):
+ # Returns the text needed to ensure this coordinate can be
+ # distinguished from all others with the same name.
+ extra = ""
+ similar_coords = cube.coords(coord.name())
+ if len(similar_coords) > 1:
+ # Find all the attribute keys
+ keys = set()
+ for similar_coord in similar_coords:
+ keys.update(similar_coord.attributes.keys())
+ # Look for any attributes that vary
+ vary = set()
+ attributes = {}
+ for key in keys:
+ for similar_coord in similar_coords:
+ if key not in similar_coord.attributes:
+ vary.add(key)
+ break
+ value = similar_coord.attributes[key]
+ if attributes.setdefault(key, value) != value:
+ vary.add(key)
+ break
+ keys = sorted(vary & set(coord.attributes.keys()))
+ bits = [
+ "{}={!r}".format(key, coord.attributes[key]) for key in keys
+ ]
+ if bits:
+ extra = ", ".join(bits)
+ return extra
+
+
+class VectorSummary(CoordSummary):
+ def __init__(self, cube, vector, iscoord):
+ self.name = iris.util.clip_string(vector.name())
+ dims = vector.cube_dims(cube)
+ self.dim_chars = [
+ "x" if dim in dims else "-" for dim in range(len(cube.shape))
+ ]
+ if iscoord:
+ extra = self._summary_coord_extra(cube, vector)
+ self.extra = iris.util.clip_string(extra)
+ else:
+ self.extra = ""
+
+
+class ScalarSummary(CoordSummary):
+ def __init__(self, cube, coord):
+ self.name = coord.name()
+ if (
+ coord.units in ["1", "no_unit", "unknown"]
+ or coord.units.is_time_reference()
+ ):
+ self.unit = ""
+ else:
+ self.unit = " {!s}".format(coord.units)
+ coord_cell = coord.cell(0)
+ if isinstance(coord_cell.point, str):
+ self.string_type = True
+ self.lines = [
+ iris.util.clip_string(str(item))
+ for item in coord_cell.point.split("\n")
+ ]
+ self.point = None
+ self.bound = None
+ self.content = "\n".join(self.lines)
+ else:
+ self.string_type = False
+ self.lines = None
+ self.point = "{!s}".format(coord_cell.point)
+ coord_cell_cbound = coord_cell.bound
+ if coord_cell_cbound is not None:
+ self.bound = "({})".format(
+ ", ".join(str(val) for val in coord_cell_cbound)
+ )
+ self.content = "{}{}, bound={}{}".format(
+ self.point, self.unit, self.bound, self.unit
+ )
+ else:
+ self.bound = None
+ self.content = "{}{}".format(self.point, self.unit)
+ extra = self._summary_coord_extra(cube, coord)
+ self.extra = iris.util.clip_string(extra)
+
+
+class Section:
+ def _init_(self):
+ self.contents = []
+
+ def is_empty(self):
+ return self.contents == []
+
+
+class VectorSection(Section):
+ def __init__(self, title, cube, vectors, iscoord):
+ self.title = title
+ self.contents = [
+ VectorSummary(cube, vector, iscoord) for vector in vectors
+ ]
+
+
+class ScalarSection(Section):
+ def __init__(self, title, cube, scalars):
+ self.title = title
+ self.contents = [ScalarSummary(cube, scalar) for scalar in scalars]
+
+
+class ScalarCellMeasureSection(Section):
+ def __init__(self, title, cell_measures):
+ self.title = title
+ self.contents = [cm.name() for cm in cell_measures]
+
+
+class AttributeSection(Section):
+ def __init__(self, title, attributes):
+ self.title = title
+ self.names = []
+ self.values = []
+ self.contents = []
+ for name, value in sorted(attributes.items()):
+ value = iris.util.clip_string(str(value))
+ self.names.append(name)
+ self.values.append(value)
+ content = "{}: {}".format(name, value)
+ self.contents.append(content)
+
+
+class CellMethodSection(Section):
+ def __init__(self, title, cell_methods):
+ self.title = title
+ self.contents = [str(cm) for cm in cell_methods]
+
+
+class CubeSummary:
+ def __init__(self, cube, shorten=False, name_padding=35):
+ self.section_indent = 5
+ self.item_indent = 10
+ self.extra_indent = 13
+ self.shorten = shorten
+ self.header = FullHeader(cube, name_padding)
+
+ # Cache the derived coords so we can rely on consistent
+ # object IDs.
+ derived_coords = cube.derived_coords
+ # Determine the cube coordinates that are scalar (single-valued)
+ # AND non-dimensioned.
+ dim_coords = cube.dim_coords
+ aux_coords = cube.aux_coords
+ all_coords = dim_coords + aux_coords + derived_coords
+ scalar_coords = [
+ coord
+ for coord in all_coords
+ if not cube.coord_dims(coord) and coord.shape == (1,)
+ ]
+ # Determine the cube coordinates that are not scalar BUT
+ # dimensioned.
+ scalar_coord_ids = set(map(id, scalar_coords))
+ vector_dim_coords = [
+ coord for coord in dim_coords if id(coord) not in scalar_coord_ids
+ ]
+ vector_aux_coords = [
+ coord for coord in aux_coords if id(coord) not in scalar_coord_ids
+ ]
+ vector_derived_coords = [
+ coord
+ for coord in derived_coords
+ if id(coord) not in scalar_coord_ids
+ ]
+
+ # cell measures
+ vector_cell_measures = [
+ cm for cm in cube.cell_measures() if cm.shape != (1,)
+ ]
+
+ # Ancillary Variables
+ vector_ancillary_variables = [av for av in cube.ancillary_variables()]
+
+ # Sort scalar coordinates by name.
+ scalar_coords.sort(key=lambda coord: coord.name())
+ # Sort vector coordinates by data dimension and name.
+ vector_dim_coords.sort(
+ key=lambda coord: (cube.coord_dims(coord), coord.name())
+ )
+ vector_aux_coords.sort(
+ key=lambda coord: (cube.coord_dims(coord), coord.name())
+ )
+ vector_derived_coords.sort(
+ key=lambda coord: (cube.coord_dims(coord), coord.name())
+ )
+ scalar_cell_measures = [
+ cm for cm in cube.cell_measures() if cm.shape == (1,)
+ ]
+
+ self.vector_sections = {}
+
+ def add_vector_section(title, contents, iscoord=True):
+ self.vector_sections[title] = VectorSection(
+ title, cube, contents, iscoord
+ )
+
+ add_vector_section("Dimension coordinates:", vector_dim_coords)
+ add_vector_section("Auxiliary coordinates:", vector_aux_coords)
+ add_vector_section("Derived coordinates:", vector_derived_coords)
+ add_vector_section("Cell Measures:", vector_cell_measures, False)
+ add_vector_section(
+ "Ancillary Variables:", vector_ancillary_variables, False
+ )
+
+ self.scalar_sections = {}
+
+ def add_scalar_section(section_class, title, *args):
+ self.scalar_sections[title] = section_class(title, *args)
+
+ add_scalar_section(
+ ScalarSection, "Scalar Coordinates:", cube, scalar_coords
+ )
+ add_scalar_section(
+ ScalarCellMeasureSection,
+ "Scalar cell measures:",
+ scalar_cell_measures,
+ )
+ add_scalar_section(AttributeSection, "Attributes:", cube.attributes)
+ add_scalar_section(
+ CellMethodSection, "Cell methods:", cube.cell_methods
+ )
diff --git a/lib/iris/tests/unit/representation/__init__.py b/lib/iris/tests/unit/representation/__init__.py
new file mode 100644
index 0000000000..e943ad149b
--- /dev/null
+++ b/lib/iris/tests/unit/representation/__init__.py
@@ -0,0 +1,6 @@
+# Copyright Iris contributors
+#
+# This file is part of Iris and is released under the LGPL license.
+# See COPYING and COPYING.LESSER in the root of the repository for full
+# licensing details.
+"""Unit tests for the :mod:`iris._representation` module."""
diff --git a/lib/iris/tests/unit/representation/test_representation.py b/lib/iris/tests/unit/representation/test_representation.py
new file mode 100644
index 0000000000..212f454e70
--- /dev/null
+++ b/lib/iris/tests/unit/representation/test_representation.py
@@ -0,0 +1,187 @@
+# Copyright Iris contributors
+#
+# This file is part of Iris and is released under the LGPL license.
+# See COPYING and COPYING.LESSER in the root of the repository for full
+# licensing details.
+"""Unit tests for the :mod:`iris._representation` module."""
+
+import numpy as np
+import iris.tests as tests
+import iris._representation
+from iris.cube import Cube
+from iris.coords import (
+ DimCoord,
+ AuxCoord,
+ CellMeasure,
+ AncillaryVariable,
+ CellMethod,
+)
+
+
+def example_cube():
+ cube = Cube(
+ np.arange(6).reshape([3, 2]),
+ standard_name="air_temperature",
+ long_name="screen_air_temp",
+ var_name="airtemp",
+ units="K",
+ )
+ lat = DimCoord([0, 1, 2], standard_name="latitude", units="degrees")
+ cube.add_dim_coord(lat, 0)
+ return cube
+
+
+class Test_CubeSummary(tests.IrisTest):
+ def setUp(self):
+ self.cube = example_cube()
+
+ def test_header(self):
+ rep = iris._representation.CubeSummary(self.cube)
+ header_left = rep.header.nameunit
+ header_right = rep.header.dimension_header.contents
+
+ self.assertEqual(header_left, "air_temperature / (K)")
+ self.assertEqual(header_right, ["latitude: 3", "-- : 2"])
+
+ def test_blank_cube(self):
+ cube = Cube([1, 2])
+ rep = iris._representation.CubeSummary(cube)
+
+ self.assertEqual(rep.header.nameunit, "unknown / (unknown)")
+ self.assertEqual(rep.header.dimension_header.contents, ["-- : 2"])
+
+ expected_vector_sections = [
+ "Dimension coordinates:",
+ "Auxiliary coordinates:",
+ "Derived coordinates:",
+ "Cell Measures:",
+ "Ancillary Variables:",
+ ]
+ self.assertEqual(
+ list(rep.vector_sections.keys()), expected_vector_sections
+ )
+ for title in expected_vector_sections:
+ vector_section = rep.vector_sections[title]
+ self.assertEqual(vector_section.contents, [])
+ self.assertTrue(vector_section.is_empty())
+
+ expected_scalar_sections = [
+ "Scalar Coordinates:",
+ "Scalar cell measures:",
+ "Attributes:",
+ "Cell methods:",
+ ]
+
+ self.assertEqual(
+ list(rep.scalar_sections.keys()), expected_scalar_sections
+ )
+ for title in expected_scalar_sections:
+ scalar_section = rep.scalar_sections[title]
+ self.assertEqual(scalar_section.contents, [])
+ self.assertTrue(scalar_section.is_empty())
+
+ def test_vector_coord(self):
+ rep = iris._representation.CubeSummary(self.cube)
+ dim_section = rep.vector_sections["Dimension coordinates:"]
+
+ self.assertEqual(len(dim_section.contents), 1)
+ self.assertFalse(dim_section.is_empty())
+
+ dim_summary = dim_section.contents[0]
+
+ name = dim_summary.name
+ dim_chars = dim_summary.dim_chars
+ extra = dim_summary.extra
+
+ self.assertEqual(name, "latitude")
+ self.assertEqual(dim_chars, ["x", "-"])
+ self.assertEqual(extra, "")
+
+ def test_scalar_coord(self):
+ cube = self.cube
+ scalar_coord_no_bounds = AuxCoord([10], long_name="bar", units="K")
+ scalar_coord_with_bounds = AuxCoord(
+ [10], long_name="foo", units="K", bounds=[(5, 15)]
+ )
+ scalar_coord_text = AuxCoord(
+ ["a\nb\nc"], long_name="foo", attributes={"key": "value"}
+ )
+ cube.add_aux_coord(scalar_coord_no_bounds)
+ cube.add_aux_coord(scalar_coord_with_bounds)
+ cube.add_aux_coord(scalar_coord_text)
+ rep = iris._representation.CubeSummary(cube)
+
+ scalar_section = rep.scalar_sections["Scalar Coordinates:"]
+
+ self.assertEqual(len(scalar_section.contents), 3)
+
+ no_bounds_summary = scalar_section.contents[0]
+ bounds_summary = scalar_section.contents[1]
+ text_summary = scalar_section.contents[2]
+
+ self.assertEqual(no_bounds_summary.name, "bar")
+ self.assertEqual(no_bounds_summary.content, "10 K")
+ self.assertEqual(no_bounds_summary.extra, "")
+
+ self.assertEqual(bounds_summary.name, "foo")
+ self.assertEqual(bounds_summary.content, "10 K, bound=(5, 15) K")
+ self.assertEqual(bounds_summary.extra, "")
+
+ self.assertEqual(text_summary.name, "foo")
+ self.assertEqual(text_summary.content, "a\nb\nc")
+ self.assertEqual(text_summary.extra, "key='value'")
+
+ def test_cell_measure(self):
+ cube = self.cube
+ cell_measure = CellMeasure([1, 2, 3], long_name="foo")
+ cube.add_cell_measure(cell_measure, 0)
+ rep = iris._representation.CubeSummary(cube)
+
+ cm_section = rep.vector_sections["Cell Measures:"]
+ self.assertEqual(len(cm_section.contents), 1)
+
+ cm_summary = cm_section.contents[0]
+ self.assertEqual(cm_summary.name, "foo")
+ self.assertEqual(cm_summary.dim_chars, ["x", "-"])
+
+ def test_ancillary_variable(self):
+ cube = self.cube
+ cell_measure = AncillaryVariable([1, 2, 3], long_name="foo")
+ cube.add_ancillary_variable(cell_measure, 0)
+ rep = iris._representation.CubeSummary(cube)
+
+ av_section = rep.vector_sections["Ancillary Variables:"]
+ self.assertEqual(len(av_section.contents), 1)
+
+ av_summary = av_section.contents[0]
+ self.assertEqual(av_summary.name, "foo")
+ self.assertEqual(av_summary.dim_chars, ["x", "-"])
+
+ def test_attributes(self):
+ cube = self.cube
+ cube.attributes = {"a": 1, "b": "two"}
+ rep = iris._representation.CubeSummary(cube)
+
+ attribute_section = rep.scalar_sections["Attributes:"]
+ attribute_contents = attribute_section.contents
+ expected_contents = ["a: 1", "b: two"]
+
+ self.assertEqual(attribute_contents, expected_contents)
+
+ def test_cell_methods(self):
+ cube = self.cube
+ x = AuxCoord(1, long_name="x")
+ y = AuxCoord(1, long_name="y")
+ cell_method_xy = CellMethod("mean", [x, y])
+ cell_method_x = CellMethod("mean", x)
+ cube.add_cell_method(cell_method_xy)
+ cube.add_cell_method(cell_method_x)
+
+ rep = iris._representation.CubeSummary(cube)
+ cell_method_section = rep.scalar_sections["Cell methods:"]
+ expected_contents = ["mean: x, y", "mean: x"]
+ self.assertEqual(cell_method_section.contents, expected_contents)
+
+
+if __name__ == "__main__":
+ tests.main()
From 7d73cf20a75ff55230bf108bc8689f9edd24bb76 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Tue, 9 Feb 2021 10:15:38 +0000
Subject: [PATCH 02/43] add nox session conda list (#3990)
---
.cirrus.yml | 10 +-
.../contributing_running_tests.rst | 8 +
docs/src/whatsnew/latest.rst | 4 +
noxfile.py | 148 +++++++-----------
4 files changed, 73 insertions(+), 97 deletions(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index 971bd3b81b..007bab403e 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -107,7 +107,7 @@ linux_minimal_task:
tests_script:
- echo "[Resources]" > ${SITE_CFG}
- echo "doc_dir = ${CIRRUS_WORKING_DIR}/docs" >> ${SITE_CFG}
- - nox --session tests
+ - nox --session tests -- --verbose
#
@@ -137,7 +137,7 @@ linux_task:
- echo "[Resources]" > ${SITE_CFG}
- echo "test_data_dir = ${IRIS_TEST_DATA_DIR}/test_data" >> ${SITE_CFG}
- echo "doc_dir = ${CIRRUS_WORKING_DIR}/docs" >> ${SITE_CFG}
- - nox --session tests
+ - nox --session tests -- --verbose
#
@@ -167,7 +167,7 @@ gallery_task:
- echo "[Resources]" > ${SITE_CFG}
- echo "test_data_dir = ${IRIS_TEST_DATA_DIR}/test_data" >> ${SITE_CFG}
- echo "doc_dir = ${CIRRUS_WORKING_DIR}/docs" >> ${SITE_CFG}
- - nox --session gallery
+ - nox --session gallery -- --verbose
#
@@ -201,7 +201,7 @@ doctest_task:
- mkdir -p ${MPL_RC_DIR}
- echo "backend : agg" > ${MPL_RC_FILE}
- echo "image.cmap : viridis" >> ${MPL_RC_FILE}
- - nox --session doctest
+ - nox --session doctest -- --verbose
#
@@ -224,4 +224,4 @@ link_task:
- mkdir -p ${MPL_RC_DIR}
- echo "backend : agg" > ${MPL_RC_FILE}
- echo "image.cmap : viridis" >> ${MPL_RC_FILE}
- - nox --session linkcheck
+ - nox --session linkcheck -- --verbose
diff --git a/docs/src/developers_guide/contributing_running_tests.rst b/docs/src/developers_guide/contributing_running_tests.rst
index 99ea4e831c..0fd9fa8486 100644
--- a/docs/src/developers_guide/contributing_running_tests.rst
+++ b/docs/src/developers_guide/contributing_running_tests.rst
@@ -175,6 +175,14 @@ For further `nox`_ command-line options::
nox --help
+.. tip::
+ For `nox`_ sessions that use the `conda`_ backend, you can use the ``-v`` or ``--verbose``
+ flag to display the `nox`_ `conda`_ environment package details and environment info.
+ For example::
+
+ nox --session tests -- --verbose
+
+
.. note:: `nox`_ will cache its testing environments in the `.nox` root ``iris`` project directory.
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index fbb98cb1e3..ed11f60719 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -94,6 +94,10 @@ This document explains the changes made to Iris for this release
#. `@jamesp`_ updated a test to the latest numpy version (:pull:`3977`)
+#. `@bjlittle`_ rationalised the ``noxfile.py``, and added the ability for
+ each ``nox`` session to list its ``conda`` environment packages and
+ environment info. (:pull:`3990`)
+
.. comment
Whatsnew author names (@github name) in alphabetical order. Note that,
diff --git a/noxfile.py b/noxfile.py
index fc6175bdf0..b6f9480290 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -93,6 +93,58 @@ def cache_cartopy(session):
)
+def prepare_venv(session):
+ """
+ Create and cache the nox session conda environment, and additionally
+ provide conda environment package details and info.
+
+ Note that, iris is installed into the environment using pip.
+
+ Parameters
+ ----------
+ session: object
+ A `nox.sessions.Session` object.
+
+ Notes
+ -----
+ See
+ - https://github.com/theacodes/nox/issues/346
+ - https://github.com/theacodes/nox/issues/260
+
+ """
+ if not venv_cached(session):
+ # Determine the conda requirements yaml file.
+ fname = f"requirements/ci/py{session.python.replace('.', '')}.yml"
+ # Back-door approach to force nox to use "conda env update".
+ command = (
+ "conda",
+ "env",
+ "update",
+ f"--prefix={session.virtualenv.location}",
+ f"--file={fname}",
+ "--prune",
+ )
+ session._run(*command, silent=True, external="error")
+ cache_venv(session)
+
+ cache_cartopy(session)
+ session.install("--no-deps", "--editable", ".")
+
+ # Determine whether verbose diagnostics have been requested
+ # from the command line.
+ verbose = "-v" in session.posargs or "--verbose" in session.posargs
+
+ if verbose:
+ session.run("conda", "info")
+ session.run("conda", "list", f"--prefix={session.virtualenv.location}")
+ session.run(
+ "conda",
+ "list",
+ f"--prefix={session.virtualenv.location}",
+ "--explicit",
+ )
+
+
@nox.session
def flake8(session):
"""
@@ -141,30 +193,8 @@ def tests(session):
session: object
A `nox.sessions.Session` object.
- Notes
- -----
- See
- - https://github.com/theacodes/nox/issues/346
- - https://github.com/theacodes/nox/issues/260
-
"""
- if not venv_cached(session):
- # Determine the conda requirements yaml file.
- fname = f"requirements/ci/py{session.python.replace('.', '')}.yml"
- # Back-door approach to force nox to use "conda env update".
- command = (
- "conda",
- "env",
- "update",
- f"--prefix={session.virtualenv.location}",
- f"--file={fname}",
- "--prune",
- )
- session._run(*command, silent=True, external="error")
- cache_venv(session)
-
- cache_cartopy(session)
- session.install("--no-deps", "--editable", ".")
+ prepare_venv(session)
session.run(
"python",
"-m",
@@ -184,30 +214,8 @@ def gallery(session):
session: object
A `nox.sessions.Session` object.
- Notes
- -----
- See
- - https://github.com/theacodes/nox/issues/346
- - https://github.com/theacodes/nox/issues/260
-
"""
- if not venv_cached(session):
- # Determine the conda requirements yaml file.
- fname = f"requirements/ci/py{session.python.replace('.', '')}.yml"
- # Back-door approach to force nox to use "conda env update".
- command = (
- "conda",
- "env",
- "update",
- f"--prefix={session.virtualenv.location}",
- f"--file={fname}",
- "--prune",
- )
- session._run(*command, silent=True, external="error")
- cache_venv(session)
-
- cache_cartopy(session)
- session.install("--no-deps", "--editable", ".")
+ prepare_venv(session)
session.run(
"python",
"-m",
@@ -226,30 +234,8 @@ def doctest(session):
session: object
A `nox.sessions.Session` object.
- Notes
- -----
- See
- - https://github.com/theacodes/nox/issues/346
- - https://github.com/theacodes/nox/issues/260
-
"""
- if not venv_cached(session):
- # Determine the conda requirements yaml file.
- fname = f"requirements/ci/py{session.python.replace('.', '')}.yml"
- # Back-door approach to force nox to use "conda env update".
- command = (
- "conda",
- "env",
- "update",
- f"--prefix={session.virtualenv.location}",
- f"--file={fname}",
- "--prune",
- )
- session._run(*command, silent=True, external="error")
- cache_venv(session)
-
- cache_cartopy(session)
- session.install("--no-deps", "--editable", ".")
+ prepare_venv(session)
session.cd("docs")
session.run(
"make",
@@ -274,30 +260,8 @@ def linkcheck(session):
session: object
A `nox.sessions.Session` object.
- Notes
- -----
- See
- - https://github.com/theacodes/nox/issues/346
- - https://github.com/theacodes/nox/issues/260
-
"""
- if not venv_cached(session):
- # Determine the conda requirements yaml file.
- fname = f"requirements/ci/py{session.python.replace('.', '')}.yml"
- # Back-door approach to force nox to use "conda env update".
- command = (
- "conda",
- "env",
- "update",
- f"--prefix={session.virtualenv.location}",
- f"--file={fname}",
- "--prune",
- )
- session._run(*command, silent=True, external="error")
- cache_venv(session)
-
- cache_cartopy(session)
- session.install("--no-deps", "--editable", ".")
+ prepare_venv(session)
session.cd("docs")
session.run(
"make",
From c51dab213b92b9e7eb1a95e5f650c9fec0f5b9d4 Mon Sep 17 00:00:00 2001
From: tkknight <2108488+tkknight@users.noreply.github.com>
Date: Tue, 9 Feb 2021 12:14:40 +0000
Subject: [PATCH 03/43] Added text to state the Python version used to build
the docs. (#3989)
* Added text to state the Python version used to build the docs.
* Added footer template that includes the Python version used to build.
* added new line
* Review actions
* added whatsnew
---
docs/src/_templates/footer.html | 5 +++++
docs/src/conf.py | 14 +++++++++-----
.../contributing_documentation.rst | 3 +++
docs/src/installing.rst | 4 +++-
docs/src/whatsnew/latest.rst | 4 ++++
5 files changed, 24 insertions(+), 6 deletions(-)
create mode 100644 docs/src/_templates/footer.html
diff --git a/docs/src/_templates/footer.html b/docs/src/_templates/footer.html
new file mode 100644
index 0000000000..1d5fb08b78
--- /dev/null
+++ b/docs/src/_templates/footer.html
@@ -0,0 +1,5 @@
+{% extends "!footer.html" %}
+{% block extrafooter %}
+ Built using Python {{ python_version }}.
+ {{ super() }}
+{% endblock %}
diff --git a/docs/src/conf.py b/docs/src/conf.py
index 30e6150b39..843af17944 100644
--- a/docs/src/conf.py
+++ b/docs/src/conf.py
@@ -69,8 +69,8 @@ def autolog(message):
# define the copyright information for latex builds. Note, for html builds,
# the copyright exists directly inside "_templates/layout.html"
-upper_copy_year = datetime.datetime.now().year
-copyright = "Iris Contributors"
+copyright_years = f"2010 - {datetime.datetime.now().year}"
+copyright = f"{copyright_years}, Iris Contributors"
author = "Iris Developers"
# The version info for the project you're documenting, acts as replacement for
@@ -95,9 +95,12 @@ def autolog(message):
# Create a variable that can be inserted in the rst "|copyright_years|".
# You can add more variables here if needed.
+
+build_python_version = ".".join([str(i) for i in sys.version_info[:3]])
+
rst_epilog = f"""
-.. |copyright_years| replace:: 2010 - {upper_copy_year}
-.. |python_version| replace:: {'.'.join([str(i) for i in sys.version_info[:3]])}
+.. |copyright_years| replace:: {copyright_years}
+.. |python_version| replace:: {build_python_version}
.. |iris_version| replace:: v{version}
.. |build_date| replace:: ({datetime.datetime.now().strftime('%d %b %Y')})
"""
@@ -225,7 +228,8 @@ def autolog(message):
}
html_context = {
- "copyright_years": "2010 - {}".format(upper_copy_year),
+ "copyright_years": copyright_years,
+ "python_version": build_python_version,
# menu_links and menu_links_name are used in _templates/layout.html
# to include some nice icons. See http://fontawesome.io for a list of
# icons (used in the sphinx_rtd_theme)
diff --git a/docs/src/developers_guide/contributing_documentation.rst b/docs/src/developers_guide/contributing_documentation.rst
index 75e9dfe29c..167e8937b9 100644
--- a/docs/src/developers_guide/contributing_documentation.rst
+++ b/docs/src/developers_guide/contributing_documentation.rst
@@ -24,6 +24,9 @@ The documentation uses specific packages that need to be present. Please see
Building
~~~~~~~~
+This documentation was built using the latest Python version that Iris
+supports. For more information see :ref:`installing_iris`.
+
The build can be run from the documentation directory ``docs/src``.
The build output for the html is found in the ``_build/html`` sub directory.
diff --git a/docs/src/installing.rst b/docs/src/installing.rst
index 8b3ae8d3e7..31fc497b85 100644
--- a/docs/src/installing.rst
+++ b/docs/src/installing.rst
@@ -17,7 +17,9 @@ any WSL_ distributions.
.. _WSL: https://docs.microsoft.com/en-us/windows/wsl/install-win10
.. note:: Iris currently supports and is tested against **Python 3.6** and
- **Python 3.7**.
+ **Python 3.7**.
+
+.. note:: This documentation was built using Python |python_version|.
.. _installing_using_conda:
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index ed11f60719..1efa08874a 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -83,6 +83,10 @@ This document explains the changes made to Iris for this release
#. `@bjlittle`_ added automated Iris version discovery for the ``latest.rst``
in the ``whatsnew`` documentation. (:pull:`3981`)
+#. `@tkknight`_ stated the Python version used to build the documentation
+ on :ref:`installing_iris` and to the footer of all pages. Also added the
+ copyright years to the footer. (:pull:`3989`)
+
💼 Internal
===========
From 8fb33bb8a9975f311795ae6c1f4301175b10307d Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Tue, 9 Feb 2021 13:36:18 +0000
Subject: [PATCH 04/43] Iris py38 (#3976)
* support for py38
* update CI and noxfile
* enforce alphabetical xml element attribute order
* full tests for py38 + fix docs-tests
* add whatsnew entry
* update doc-strings + review actions
* Alternate xml handling routine (#29)
* all xml tests pass for nox tests-3.8
* restored docstrings
* move sort_xml_attrs
* make sort_xml_attrs a classmethod
* update sort_xml_attr doc-string
Co-authored-by: Bill Little
* add jamesp to whatsnew + minor tweak
Co-authored-by: James Penn
---
.cirrus.yml | 12 +--
docs/src/common_links.inc | 2 +
.../contributing_running_tests.rst | 2 -
docs/src/further_topics/metadata.rst | 7 +-
docs/src/installing.rst | 4 +-
docs/src/whatsnew/latest.rst | 8 +-
lib/iris/coords.py | 77 +++++++++++++++++--
lib/iris/cube.py | 56 ++++++++++++++
lib/iris/tests/__init__.py | 4 +
noxfile.py | 2 +-
requirements/ci/iris.yml | 2 +-
requirements/ci/py38.yml | 51 ++++++++++++
12 files changed, 203 insertions(+), 24 deletions(-)
create mode 100644 requirements/ci/py38.yml
diff --git a/.cirrus.yml b/.cirrus.yml
index 007bab403e..da425a5691 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -98,6 +98,8 @@ linux_minimal_task:
PY_VER: 3.6
env:
PY_VER: 3.7
+ env:
+ PY_VER: 3.8
name: "${CIRRUS_OS}: py${PY_VER} tests (minimal)"
container:
image: gcc:latest
@@ -119,6 +121,8 @@ linux_task:
PY_VER: 3.6
env:
PY_VER: 3.7
+ env:
+ PY_VER: 3.8
name: "${CIRRUS_OS}: py${PY_VER} tests (full)"
container:
image: gcc:latest
@@ -146,9 +150,7 @@ linux_task:
gallery_task:
matrix:
env:
- PY_VER: 3.6
- env:
- PY_VER: 3.7
+ PY_VER: 3.8
name: "${CIRRUS_OS}: py${PY_VER} doc tests (gallery)"
container:
image: gcc:latest
@@ -176,7 +178,7 @@ gallery_task:
doctest_task:
matrix:
env:
- PY_VER: 3.7
+ PY_VER: 3.8
name: "${CIRRUS_OS}: py${PY_VER} doc tests"
container:
image: gcc:latest
@@ -210,7 +212,7 @@ doctest_task:
link_task:
matrix:
env:
- PY_VER: 3.7
+ PY_VER: 3.8
name: "${CIRRUS_OS}: py${PY_VER} doc link check"
container:
image: gcc:latest
diff --git a/docs/src/common_links.inc b/docs/src/common_links.inc
index 9f6a57f529..157444d65d 100644
--- a/docs/src/common_links.inc
+++ b/docs/src/common_links.inc
@@ -1,6 +1,7 @@
.. comment
Common resources in alphabetical order:
+.. _black: https://black.readthedocs.io/en/stable/
.. _.cirrus.yml: https://github.com/SciTools/iris/blob/master/.cirrus.yml
.. _.flake8.yml: https://github.com/SciTools/iris/blob/master/.flake8
.. _cirrus-ci: https://cirrus-ci.com/github/SciTools/iris
@@ -19,6 +20,7 @@
.. _legacy documentation: https://scitools.org.uk/iris/docs/v2.4.0/
.. _matplotlib: https://matplotlib.org/
.. _napolean: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/sphinxcontrib.napoleon.html
+.. _nox: https://nox.thea.codes/en/stable/
.. _New Issue: https://github.com/scitools/iris/issues/new/choose
.. _pull request: https://github.com/SciTools/iris/pulls
.. _pull requests: https://github.com/SciTools/iris/pulls
diff --git a/docs/src/developers_guide/contributing_running_tests.rst b/docs/src/developers_guide/contributing_running_tests.rst
index 0fd9fa8486..9bc2d797bd 100644
--- a/docs/src/developers_guide/contributing_running_tests.rst
+++ b/docs/src/developers_guide/contributing_running_tests.rst
@@ -186,8 +186,6 @@ For further `nox`_ command-line options::
.. note:: `nox`_ will cache its testing environments in the `.nox` root ``iris`` project directory.
-.. _black: https://black.readthedocs.io/en/stable/
-.. _nox: https://nox.thea.codes/en/latest/
.. _setuptools: https://setuptools.readthedocs.io/en/latest/
.. _tox: https://tox.readthedocs.io/en/latest/
.. _virtualenv: https://virtualenv.pypa.io/en/latest/
diff --git a/docs/src/further_topics/metadata.rst b/docs/src/further_topics/metadata.rst
index e6d6ebc57a..ab6a6450b4 100644
--- a/docs/src/further_topics/metadata.rst
+++ b/docs/src/further_topics/metadata.rst
@@ -258,12 +258,12 @@ create a **new** instance directly from the metadata class itself,
>>> DimCoordMetadata._make(values)
DimCoordMetadata(standard_name=1, long_name=2, var_name=3, units=4, attributes=5, coord_system=6, climatological=7, circular=8)
-It is also possible to easily convert ``metadata`` to an `OrderedDict`_
+It is also possible to easily convert ``metadata`` to an `dict`_
using the `namedtuple._asdict`_ method. This can be particularly handy when a
standard Python built-in container is required to represent your ``metadata``,
>>> metadata._asdict()
- OrderedDict([('standard_name', 'longitude'), ('long_name', None), ('var_name', 'longitude'), ('units', Unit('degrees')), ('attributes', {'grinning face': '🙃'}), ('coord_system', GeogCS(6371229.0)), ('climatological', False), ('circular', False)])
+ {'standard_name': 'longitude', 'long_name': None, 'var_name': 'longitude', 'units': Unit('degrees'), 'attributes': {'grinning face': '🙃'}, 'coord_system': GeogCS(6371229.0), 'climatological': False, 'circular': False}
Using the `namedtuple._replace`_ method allows you to create a new metadata
class instance, but replacing specified members with **new** associated values,
@@ -943,7 +943,7 @@ such as a `dict`_,
>>> mapping = latitude.metadata._asdict()
>>> mapping
- OrderedDict([('standard_name', 'latitude'), ('long_name', None), ('var_name', 'latitude'), ('units', Unit('degrees')), ('attributes', {}), ('coord_system', GeogCS(6371229.0)), ('climatological', False), ('circular', False)])
+ {'standard_name': 'latitude', 'long_name': None, 'var_name': 'latitude', 'units': Unit('degrees'), 'attributes': {}, 'coord_system': GeogCS(6371229.0), 'climatological': False, 'circular': False}
>>> longitude.metadata = mapping
>>> longitude.metadata
DimCoordMetadata(standard_name='latitude', long_name=None, var_name='latitude', units=Unit('degrees'), attributes={}, coord_system=GeogCS(6371229.0), climatological=False, circular=False)
@@ -1000,7 +1000,6 @@ values. All other metadata members will be left unaltered.
.. _NetCDF: https://www.unidata.ucar.edu/software/netcdf/
.. _NetCDF CF Metadata Conventions: https://cfconventions.org/
.. _NumPy: https://github.com/numpy/numpy
-.. _OrderedDict: https://docs.python.org/3/library/collections.html#collections.OrderedDict
.. _Parametric Vertical Coordinate: https://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#parametric-vertical-coordinate
.. _rich comparison: https://www.python.org/dev/peps/pep-0207/
.. _SciTools/iris: https://github.com/SciTools/iris
diff --git a/docs/src/installing.rst b/docs/src/installing.rst
index 31fc497b85..8deb7043c5 100644
--- a/docs/src/installing.rst
+++ b/docs/src/installing.rst
@@ -16,8 +16,8 @@ any WSL_ distributions.
.. _WSL: https://docs.microsoft.com/en-us/windows/wsl/install-win10
-.. note:: Iris currently supports and is tested against **Python 3.6** and
- **Python 3.7**.
+.. note:: Iris is currently supported and tested against Python ``3.6``,
+ ``3.7``, and ``3.8``.
.. note:: This documentation was built using Python |python_version|.
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index 1efa08874a..c02b61341b 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -12,7 +12,6 @@ This document explains the changes made to Iris for this release
:title: text-primary text-center font-weight-bold
:body: bg-light
:animate: fade-in
- :open:
The highlights for this major/minor release of Iris include:
@@ -96,7 +95,10 @@ This document explains the changes made to Iris for this release
#. `@tkknight`_ moved the ``docs/iris`` directory to be in the parent
directory ``docs``. (:pull:`3975`)
-#. `@jamesp`_ updated a test to the latest numpy version (:pull:`3977`)
+#. `@jamesp`_ updated a test for `numpy`_ ``1.20.0``. (:pull:`3977`)
+
+#. `@bjlittle`_ and `@jamesp`_ extended the `cirrus-ci`_ testing and `nox`_
+ testing automation to support `Python 3.8`_. (:pull:`3976`)
#. `@bjlittle`_ rationalised the ``noxfile.py``, and added the ability for
each ``nox`` session to list its ``conda`` environment packages and
@@ -117,3 +119,5 @@ This document explains the changes made to Iris for this release
.. _abstract base class: https://docs.python.org/3/library/abc.html
.. _GitHub: https://github.com/SciTools/iris/issues/new/choose
.. _Met Office: https://www.metoffice.gov.uk/
+.. _numpy: https://numpy.org/doc/stable/release/1.20.0-notes.html
+.. _Python 3.8: https://www.python.org/downloads/release/python-380/
diff --git a/lib/iris/coords.py b/lib/iris/coords.py
index cfeb24cdcb..6129b35150 100644
--- a/lib/iris/coords.py
+++ b/lib/iris/coords.py
@@ -578,7 +578,21 @@ def shape(self):
return self._values_dm.shape
def xml_element(self, doc):
- """Return a DOM element describing this metadata."""
+ """
+ Create the :class:`xml.dom.minidom.Element` that describes this
+ :class:`_DimensionalMetadata`.
+
+ Args:
+
+ * doc:
+ The parent :class:`xml.dom.minidom.Document`.
+
+ Returns:
+ The :class:`xml.dom.minidom.Element` that will describe this
+ :class:`_DimensionalMetadata`, and the dictionary of attributes
+ that require to be added to this element.
+
+ """
# Create the XML element as the camelCaseEquivalent of the
# class name.
element_name = type(self).__name__
@@ -881,6 +895,20 @@ def cube_dims(self, cube):
return cube.cell_measure_dims(self)
def xml_element(self, doc):
+ """
+ Create the :class:`xml.dom.minidom.Element` that describes this
+ :class:`CellMeasure`.
+
+ Args:
+
+ * doc:
+ The parent :class:`xml.dom.minidom.Document`.
+
+ Returns:
+ The :class:`xml.dom.minidom.Element` that describes this
+ :class:`CellMeasure`.
+
+ """
# Create the XML element as the camelCaseEquivalent of the
# class name
element = super().xml_element(doc=doc)
@@ -2228,14 +2256,26 @@ def nearest_neighbour_index(self, point):
return result_index
def xml_element(self, doc):
- """Return a DOM element describing this Coord."""
+ """
+ Create the :class:`xml.dom.minidom.Element` that describes this
+ :class:`Coord`.
+
+ Args:
+
+ * doc:
+ The parent :class:`xml.dom.minidom.Document`.
+
+ Returns:
+ The :class:`xml.dom.minidom.Element` that will describe this
+ :class:`DimCoord`, and the dictionary of attributes that require
+ to be added to this element.
+
+ """
# Create the XML element as the camelCaseEquivalent of the
# class name
element = super().xml_element(doc=doc)
- element.setAttribute("points", self._xml_array_repr(self.points))
-
- # Add bounds handling
+ # Add bounds, points are handled by the parent class.
if self.has_bounds():
element.setAttribute("bounds", self._xml_array_repr(self.bounds))
@@ -2614,7 +2654,20 @@ def is_monotonic(self):
return True
def xml_element(self, doc):
- """Return DOM element describing this :class:`iris.coords.DimCoord`."""
+ """
+ Create the :class:`xml.dom.minidom.Element` that describes this
+ :class:`DimCoord`.
+
+ Args:
+
+ * doc:
+ The parent :class:`xml.dom.minidom.Document`.
+
+ Returns:
+ The :class:`xml.dom.minidom.Element` that describes this
+ :class:`DimCoord`.
+
+ """
element = super().xml_element(doc)
if self.circular:
element.setAttribute("circular", str(self.circular))
@@ -2794,7 +2847,17 @@ def __add__(self, other):
def xml_element(self, doc):
"""
- Return a dom element describing itself
+ Create the :class:`xml.dom.minidom.Element` that describes this
+ :class:`CellMethod`.
+
+ Args:
+
+ * doc:
+ The parent :class:`xml.dom.minidom.Document`.
+
+ Returns:
+ The :class:`xml.dom.minidom.Element` that describes this
+ :class:`CellMethod`.
"""
cellMethod_xml_element = doc.createElement("cellMethod")
diff --git a/lib/iris/cube.py b/lib/iris/cube.py
index 7c7d6c58e9..5578507d28 100644
--- a/lib/iris/cube.py
+++ b/lib/iris/cube.py
@@ -225,6 +225,7 @@ def __getslice__(self, start, stop):
def xml(self, checksum=False, order=True, byteorder=True):
"""Return a string of the XML that this list of cubes represents."""
+
doc = Document()
cubes_xml_element = doc.createElement("cubes")
cubes_xml_element.setAttribute("xmlns", XML_NAMESPACE_URI)
@@ -239,6 +240,7 @@ def xml(self, checksum=False, order=True, byteorder=True):
doc.appendChild(cubes_xml_element)
# return our newly created XML string
+ doc = Cube._sort_xml_attrs(doc)
return doc.toprettyxml(indent=" ")
def extract(self, constraints):
@@ -755,6 +757,59 @@ class Cube(CFVariableMixin):
#: is similar to Fortran or Matlab, but different than numpy.
__orthogonal_indexing__ = True
+ @classmethod
+ def _sort_xml_attrs(cls, doc):
+ """
+ Takes an xml document and returns a copy with all element
+ attributes sorted in alphabetical order.
+
+ This is a private utility method required by iris to maintain
+ legacy xml behaviour beyond python 3.7.
+
+ Args:
+
+ * doc:
+ The :class:`xml.dom.minidom.Document`.
+
+ Returns:
+ The :class:`xml.dom.minidom.Document` with sorted element
+ attributes.
+
+ """
+ from xml.dom.minidom import Document
+
+ def _walk_nodes(node):
+ """Note: _walk_nodes is called recursively on child elements."""
+
+ # we don't want to copy the children here, so take a shallow copy
+ new_node = node.cloneNode(deep=False)
+
+ # Versions of python <3.8 order attributes in alphabetical order.
+ # Python >=3.8 order attributes in insert order. For consistent behaviour
+ # across both, we'll go with alphabetical order always.
+ # Remove all the attribute nodes, then add back in alphabetical order.
+ attrs = [
+ new_node.getAttributeNode(attr_name).cloneNode(deep=True)
+ for attr_name in sorted(node.attributes.keys())
+ ]
+ for attr in attrs:
+ new_node.removeAttributeNode(attr)
+ for attr in attrs:
+ new_node.setAttributeNode(attr)
+
+ if node.childNodes:
+ children = [_walk_nodes(x) for x in node.childNodes]
+ for c in children:
+ new_node.appendChild(c)
+
+ return new_node
+
+ nodes = _walk_nodes(doc.documentElement)
+ new_doc = Document()
+ new_doc.appendChild(nodes)
+
+ return new_doc
+
def __init__(
self,
data,
@@ -3403,6 +3458,7 @@ def xml(self, checksum=False, order=True, byteorder=True):
doc.appendChild(cube_xml_element)
# Print our newly created XML
+ doc = self._sort_xml_attrs(doc)
return doc.toprettyxml(indent=" ")
def _xml_element(self, doc, checksum=False, order=True, byteorder=True):
diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py
index ac0d313d76..4a85e5cdb2 100644
--- a/lib/iris/tests/__init__.py
+++ b/lib/iris/tests/__init__.py
@@ -573,6 +573,10 @@ def assertXMLElement(self, obj, reference_filename):
"""
doc = xml.dom.minidom.Document()
doc.appendChild(obj.xml_element(doc))
+ # sort the attributes on xml elements before testing against known good state.
+ # this is to be compatible with stored test output where xml attrs are stored in alphabetical order,
+ # (which was default behaviour in python <3.8, but changed to insert order in >3.8)
+ doc = iris.cube.Cube._sort_xml_attrs(doc)
pretty_xml = doc.toprettyxml(indent=" ")
reference_path = self.get_result_path(reference_filename)
self._check_same(
diff --git a/noxfile.py b/noxfile.py
index b6f9480290..028da099dc 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -19,7 +19,7 @@
PACKAGE = str("lib" / Path("iris"))
#: Cirrus-CI environment variable hook.
-PY_VER = os.environ.get("PY_VER", ["3.6", "3.7"])
+PY_VER = os.environ.get("PY_VER", ["3.6", "3.7", "3.8"])
#: Default cartopy cache directory.
CARTOPY_CACHE_DIR = os.environ.get("HOME") / Path(".local/share/cartopy")
diff --git a/requirements/ci/iris.yml b/requirements/ci/iris.yml
index e9adb956db..a76932b56e 120000
--- a/requirements/ci/iris.yml
+++ b/requirements/ci/iris.yml
@@ -1 +1 @@
-py37.yml
\ No newline at end of file
+py38.yml
\ No newline at end of file
diff --git a/requirements/ci/py38.yml b/requirements/ci/py38.yml
new file mode 100644
index 0000000000..da29d30d71
--- /dev/null
+++ b/requirements/ci/py38.yml
@@ -0,0 +1,51 @@
+name: iris-dev
+
+channels:
+ - conda-forge
+
+dependencies:
+ - python=3.8
+
+# Setup dependencies.
+ - setuptools>=40.8.0
+ - pyke
+
+# Core dependencies.
+ - cartopy>=0.18
+ - cf-units>=2
+ - cftime<1.3.0
+ - dask>=2
+ - matplotlib
+ - netcdf4
+ - numpy>=1.14
+ - python-xxhash
+ - scipy
+
+# Optional dependencies.
+ - esmpy>=7.0
+ - graphviz
+ - iris-sample-data
+ - mo_pack
+ - nc-time-axis
+ - pandas
+ - python-stratify
+ - pyugrid
+
+# Test dependencies.
+ - asv
+ - black=20.8b1
+ - filelock
+ - flake8
+ - imagehash>=4.0
+ - nose
+ - pillow<7
+ - pre-commit
+ - requests
+
+# Documentation dependencies.
+ - sphinx
+ - sphinxcontrib-napoleon
+ - sphinx-copybutton
+ - sphinx-gallery
+ - sphinx-panels
+ - sphinx_rtd_theme
From 1549bae7a2e0b726745f28161d99f5dcb28a0ffd Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Tue, 9 Feb 2021 13:36:55 +0000
Subject: [PATCH 05/43] normalise version to implicit development release
number (#3991)
---
lib/iris/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/iris/__init__.py b/lib/iris/__init__.py
index a78d0a7682..e31c7b58d7 100644
--- a/lib/iris/__init__.py
+++ b/lib/iris/__init__.py
@@ -106,7 +106,7 @@ def callback(cube, field, filename):
# Iris revision.
-__version__ = "3.1.0dev0"
+__version__ = "3.1.dev0"
# Restrict the names imported when using "from iris import *"
__all__ = [
From 93171333a4fbc1a5484b7096382178e286fbc62e Mon Sep 17 00:00:00 2001
From: Ruth Comer
Date: Wed, 10 Feb 2021 09:25:45 +0000
Subject: [PATCH 06/43] Gallery: update COP maps example (#3934)
* update cop maps example
* comment tweaks
* minor comment tweak + whatsnew
* reinstate whatsnew addition
* remove duplicate whatsnew
---
.../gallery_code/meteorology/plot_COP_maps.py | 134 ++++++++----------
docs/src/whatsnew/latest.rst | 4 +-
2 files changed, 61 insertions(+), 77 deletions(-)
diff --git a/docs/gallery_code/meteorology/plot_COP_maps.py b/docs/gallery_code/meteorology/plot_COP_maps.py
index 5555a0b85c..5e158346a9 100644
--- a/docs/gallery_code/meteorology/plot_COP_maps.py
+++ b/docs/gallery_code/meteorology/plot_COP_maps.py
@@ -38,34 +38,32 @@ def cop_metadata_callback(cube, field, filename):
filename.
"""
- # Extract the experiment name (such as a1b or e1) from the filename (in
- # this case it is just the parent folder's name)
- containing_folder = os.path.dirname(filename)
- experiment_label = os.path.basename(containing_folder)
+ # Extract the experiment name (such as A1B or E1) from the filename (in
+ # this case it is just the start of the file name, before the first ".").
+ fname = os.path.basename(filename) # filename without path.
+ experiment_label = fname.split(".")[0]
- # Create a coordinate with the experiment label in it
+ # Create a coordinate with the experiment label in it...
exp_coord = coords.AuxCoord(
experiment_label, long_name="Experiment", units="no_unit"
)
- # and add it to the cube
+ # ...and add it to the cube.
cube.add_aux_coord(exp_coord)
def main():
- # Load e1 and a1 using the callback to update the metadata
- e1 = iris.load_cube(
- iris.sample_data_path("E1.2098.pp"), callback=cop_metadata_callback
- )
- a1b = iris.load_cube(
- iris.sample_data_path("A1B.2098.pp"), callback=cop_metadata_callback
- )
+ # Load E1 and A1B scenarios using the callback to update the metadata.
+ scenario_files = [
+ iris.sample_data_path(fname) for fname in ["E1.2098.pp", "A1B.2098.pp"]
+ ]
+ scenarios = iris.load(scenario_files, callback=cop_metadata_callback)
- # Load the global average data and add an 'Experiment' coord it
- global_avg = iris.load_cube(iris.sample_data_path("pre-industrial.pp"))
+ # Load the preindustrial reference data.
+ preindustrial = iris.load_cube(iris.sample_data_path("pre-industrial.pp"))
# Define evenly spaced contour levels: -2.5, -1.5, ... 15.5, 16.5 with the
- # specific colours
+ # specific colours.
levels = np.arange(20) - 2.5
red = (
np.array(
@@ -147,81 +145,67 @@ def main():
)
# Put those colours into an array which can be passed to contourf as the
- # specific colours for each level
- colors = np.array([red, green, blue]).T
+ # specific colours for each level.
+ colors = np.stack([red, green, blue], axis=1)
- # Subtract the global
+ # Make a wider than normal figure to house two maps side-by-side.
+ fig, ax_array = plt.subplots(1, 2, figsize=(12, 5))
- # Iterate over each latitude longitude slice for both e1 and a1b scenarios
- # simultaneously
- for e1_slice, a1b_slice in zip(
- e1.slices(["latitude", "longitude"]),
- a1b.slices(["latitude", "longitude"]),
+ # Loop over our scenarios to make a plot for each.
+ for ax, experiment, label in zip(
+ ax_array, ["E1", "A1B"], ["E1", "A1B-Image"]
):
-
- time_coord = a1b_slice.coord("time")
-
- # Calculate the difference from the mean
- delta_e1 = e1_slice - global_avg
- delta_a1b = a1b_slice - global_avg
-
- # Make a wider than normal figure to house two maps side-by-side
- fig = plt.figure(figsize=(12, 5))
-
- # Get the time datetime from the coordinate
- time = time_coord.units.num2date(time_coord.points[0])
- # Set a title for the entire figure, giving the time in a nice format
- # of "MonthName Year". Also, set the y value for the title so that it
- # is not tight to the top of the plot.
- fig.suptitle(
- "Annual Temperature Predictions for " + time.strftime("%Y"),
- y=0.9,
- fontsize=18,
+ exp_cube = scenarios.extract_cube(
+ iris.Constraint(Experiment=experiment)
)
+ time_coord = exp_cube.coord("time")
- # Add the first subplot showing the E1 scenario
- plt.subplot(121)
- plt.title("HadGEM2 E1 Scenario", fontsize=10)
- iplt.contourf(delta_e1, levels, colors=colors, extend="both")
- plt.gca().coastlines()
- # get the current axes' subplot for use later on
- plt1_ax = plt.gca()
+ # Calculate the difference from the preindustial control run.
+ exp_anom_cube = exp_cube - preindustrial
- # Add the second subplot showing the A1B scenario
- plt.subplot(122)
- plt.title("HadGEM2 A1B-Image Scenario", fontsize=10)
+ # Plot this anomaly.
+ plt.sca(ax)
+ ax.set_title(f"HadGEM2 {label} Scenario", fontsize=10)
contour_result = iplt.contourf(
- delta_a1b, levels, colors=colors, extend="both"
+ exp_anom_cube, levels, colors=colors, extend="both"
)
plt.gca().coastlines()
- # get the current axes' subplot for use later on
- plt2_ax = plt.gca()
- # Now add a colourbar who's leftmost point is the same as the leftmost
- # point of the left hand plot and rightmost point is the rightmost
- # point of the right hand plot
+ # Now add a colourbar who's leftmost point is the same as the leftmost
+ # point of the left hand plot and rightmost point is the rightmost
+ # point of the right hand plot.
- # Get the positions of the 2nd plot and the left position of the 1st
- # plot
- left, bottom, width, height = plt2_ax.get_position().bounds
- first_plot_left = plt1_ax.get_position().bounds[0]
+ # Get the positions of the 2nd plot and the left position of the 1st plot.
+ left, bottom, width, height = ax_array[1].get_position().bounds
+ first_plot_left = ax_array[0].get_position().bounds[0]
- # the width of the colorbar should now be simple
- width = left - first_plot_left + width
+ # The width of the colorbar should now be simple.
+ width = left - first_plot_left + width
- # Add axes to the figure, to place the colour bar
- colorbar_axes = fig.add_axes([first_plot_left, 0.18, width, 0.03])
+ # Add axes to the figure, to place the colour bar.
+ colorbar_axes = fig.add_axes([first_plot_left, 0.18, width, 0.03])
- # Add the colour bar
- cbar = plt.colorbar(
- contour_result, colorbar_axes, orientation="horizontal"
- )
+ # Add the colour bar.
+ cbar = plt.colorbar(
+ contour_result, colorbar_axes, orientation="horizontal"
+ )
- # Label the colour bar and add ticks
- cbar.set_label(e1_slice.units)
- cbar.ax.tick_params(length=0)
+ # Label the colour bar and add ticks.
+ cbar.set_label(preindustrial.units)
+ cbar.ax.tick_params(length=0)
+
+ # Get the time datetime from the coordinate.
+ time = time_coord.units.num2date(time_coord.points[0])
+ # Set a title for the entire figure, using the year from the datetime
+ # object. Also, set the y value for the title so that it is not tight to
+ # the top of the plot.
+ fig.suptitle(
+ f"Annual Temperature Predictions for {time.year}",
+ y=0.9,
+ fontsize=18,
+ )
- iplt.show()
+ iplt.show()
if __name__ == "__main__":
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index c02b61341b..b290b7ab5a 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -69,8 +69,8 @@ This document explains the changes made to Iris for this release
📚 Documentation
================
-#. `@rcomer`_ updated the "Seasonal ensemble model plots" Gallery example.
- (:pull:`3933`)
+#. `@rcomer`_ updated the "Seasonal ensemble model plots" and "Global average
+ annual temperature maps" Gallery examples. (:pull:`3933` and :pull:`3934`)
#. `@MHBalsmeier`_ described non-conda installation on Debian-based distros.
(:pull:`3958`)
From e378eb8caaf869e4ce07ed9ff12b3b3f64148e2c Mon Sep 17 00:00:00 2001
From: Ruth Comer
Date: Wed, 10 Feb 2021 09:35:11 +0000
Subject: [PATCH 07/43] don't support mpl v1.2 (#3941)
---
docs/gallery_code/meteorology/plot_deriving_phenomena.py | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/docs/gallery_code/meteorology/plot_deriving_phenomena.py b/docs/gallery_code/meteorology/plot_deriving_phenomena.py
index 0bb1fa53a4..b600941f35 100644
--- a/docs/gallery_code/meteorology/plot_deriving_phenomena.py
+++ b/docs/gallery_code/meteorology/plot_deriving_phenomena.py
@@ -26,14 +26,7 @@ def limit_colorbar_ticks(contour_object):
number of ticks on the colorbar to 4.
"""
- # Under Matplotlib v1.2.x the colorbar attribute of a contour object is
- # a tuple containing the colorbar and an axes object, whereas under
- # Matplotlib v1.3.x it is simply the colorbar.
- try:
- colorbar = contour_object.colorbar[0]
- except (AttributeError, TypeError):
- colorbar = contour_object.colorbar
-
+ colorbar = contour_object.colorbar
colorbar.locator = matplotlib.ticker.MaxNLocator(4)
colorbar.update_ticks()
From e3c190543733ee53d1b5af84ec590a4c876b6071 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Wed, 10 Feb 2021 11:38:22 +0000
Subject: [PATCH 08/43] Cubesummary tidy (#3988)
* Extra tests; fix for array attributes.
* Docstring for CubeSummary, and remove some unused parts.
* Fix section name capitalisation, in line with existing cube summary.
* Handle array differences; quote strings in extras and if 'awkward'-printing.
* Ensure scalar string coord 'content' prints on one line.
---
lib/iris/_representation.py | 72 +++++++--
.../representation/test_representation.py | 149 ++++++++++++++++--
2 files changed, 191 insertions(+), 30 deletions(-)
diff --git a/lib/iris/_representation.py b/lib/iris/_representation.py
index 301f4a9a22..ee1e1a0d55 100644
--- a/lib/iris/_representation.py
+++ b/lib/iris/_representation.py
@@ -6,8 +6,10 @@
"""
Provides objects describing cube summaries.
"""
+import re
import iris.util
+from iris.common.metadata import _hexdigest as quickhash
class DimensionHeader:
@@ -46,6 +48,35 @@ def __init__(self, cube, name_padding=35):
self.dimension_header = DimensionHeader(cube)
+def string_repr(text, quote_strings=False):
+ """Produce a one-line printable form of a text string."""
+ if re.findall("[\n\t]", text) or quote_strings:
+ # Replace the string with its repr (including quotes).
+ text = repr(text)
+ return text
+
+
+def array_repr(arr):
+ """Produce a single-line printable repr of an array."""
+ # First take whatever numpy produces..
+ text = repr(arr)
+ # ..then reduce any multiple spaces and newlines.
+ text = re.sub("[ \t\n]+", " ", text)
+ return text
+
+
+def value_repr(value, quote_strings=False):
+ """
+ Produce a single-line printable version of an attribute or scalar value.
+ """
+ if hasattr(value, "dtype"):
+ value = array_repr(value)
+ elif isinstance(value, str):
+ value = string_repr(value, quote_strings=quote_strings)
+ value = str(value)
+ return value
+
+
class CoordSummary:
def _summary_coord_extra(self, cube, coord):
# Returns the text needed to ensure this coordinate can be
@@ -66,12 +97,21 @@ def _summary_coord_extra(self, cube, coord):
vary.add(key)
break
value = similar_coord.attributes[key]
- if attributes.setdefault(key, value) != value:
+ # Like "if attributes.setdefault(key, value) != value:"
+ # ..except setdefault fails if values are numpy arrays.
+ if key not in attributes:
+ attributes[key] = value
+ elif quickhash(attributes[key]) != quickhash(value):
+ # NOTE: fast and array-safe comparison, as used in
+ # :mod:`iris.common.metadata`.
vary.add(key)
break
keys = sorted(vary & set(coord.attributes.keys()))
bits = [
- "{}={!r}".format(key, coord.attributes[key]) for key in keys
+ "{}={}".format(
+ key, value_repr(coord.attributes[key], quote_strings=True)
+ )
+ for key in keys
]
if bits:
extra = ", ".join(bits)
@@ -105,13 +145,17 @@ def __init__(self, cube, coord):
coord_cell = coord.cell(0)
if isinstance(coord_cell.point, str):
self.string_type = True
+ # 'lines' is value split on '\n', and _each one_ length-clipped.
self.lines = [
iris.util.clip_string(str(item))
for item in coord_cell.point.split("\n")
]
self.point = None
self.bound = None
- self.content = "\n".join(self.lines)
+ # 'content' contains a one-line printable version of the string,
+ content = string_repr(coord_cell.point)
+ content = iris.util.clip_string(content)
+ self.content = content
else:
self.string_type = False
self.lines = None
@@ -132,9 +176,6 @@ def __init__(self, cube, coord):
class Section:
- def _init_(self):
- self.contents = []
-
def is_empty(self):
return self.contents == []
@@ -166,7 +207,8 @@ def __init__(self, title, attributes):
self.values = []
self.contents = []
for name, value in sorted(attributes.items()):
- value = iris.util.clip_string(str(value))
+ value = value_repr(value)
+ value = iris.util.clip_string(value)
self.names.append(name)
self.values.append(value)
content = "{}: {}".format(name, value)
@@ -180,11 +222,13 @@ def __init__(self, title, cell_methods):
class CubeSummary:
+ """
+ This class provides a structure for output representations of an Iris cube.
+ TODO: use to produce the printout of :meth:`iris.cube.Cube.__str__`.
+
+ """
+
def __init__(self, cube, shorten=False, name_padding=35):
- self.section_indent = 5
- self.item_indent = 10
- self.extra_indent = 13
- self.shorten = shorten
self.header = FullHeader(cube, name_padding)
# Cache the derived coords so we can rely on consistent
@@ -249,9 +293,9 @@ def add_vector_section(title, contents, iscoord=True):
add_vector_section("Dimension coordinates:", vector_dim_coords)
add_vector_section("Auxiliary coordinates:", vector_aux_coords)
add_vector_section("Derived coordinates:", vector_derived_coords)
- add_vector_section("Cell Measures:", vector_cell_measures, False)
+ add_vector_section("Cell measures:", vector_cell_measures, False)
add_vector_section(
- "Ancillary Variables:", vector_ancillary_variables, False
+ "Ancillary variables:", vector_ancillary_variables, False
)
self.scalar_sections = {}
@@ -260,7 +304,7 @@ def add_scalar_section(section_class, title, *args):
self.scalar_sections[title] = section_class(title, *args)
add_scalar_section(
- ScalarSection, "Scalar Coordinates:", cube, scalar_coords
+ ScalarSection, "Scalar coordinates:", cube, scalar_coords
)
add_scalar_section(
ScalarCellMeasureSection,
diff --git a/lib/iris/tests/unit/representation/test_representation.py b/lib/iris/tests/unit/representation/test_representation.py
index 212f454e70..69d2a71a97 100644
--- a/lib/iris/tests/unit/representation/test_representation.py
+++ b/lib/iris/tests/unit/representation/test_representation.py
@@ -54,8 +54,8 @@ def test_blank_cube(self):
"Dimension coordinates:",
"Auxiliary coordinates:",
"Derived coordinates:",
- "Cell Measures:",
- "Ancillary Variables:",
+ "Cell measures:",
+ "Ancillary variables:",
]
self.assertEqual(
list(rep.vector_sections.keys()), expected_vector_sections
@@ -66,7 +66,7 @@ def test_blank_cube(self):
self.assertTrue(vector_section.is_empty())
expected_scalar_sections = [
- "Scalar Coordinates:",
+ "Scalar coordinates:",
"Scalar cell measures:",
"Attributes:",
"Cell methods:",
@@ -103,21 +103,28 @@ def test_scalar_coord(self):
scalar_coord_with_bounds = AuxCoord(
[10], long_name="foo", units="K", bounds=[(5, 15)]
)
- scalar_coord_text = AuxCoord(
- ["a\nb\nc"], long_name="foo", attributes={"key": "value"}
+ scalar_coord_simple_text = AuxCoord(
+ ["this and that"],
+ long_name="foo",
+ attributes={"key": 42, "key2": "value-str"},
+ )
+ scalar_coord_awkward_text = AuxCoord(
+ ["a is\nb\n and c"], long_name="foo_2"
)
cube.add_aux_coord(scalar_coord_no_bounds)
cube.add_aux_coord(scalar_coord_with_bounds)
- cube.add_aux_coord(scalar_coord_text)
+ cube.add_aux_coord(scalar_coord_simple_text)
+ cube.add_aux_coord(scalar_coord_awkward_text)
rep = iris._representation.CubeSummary(cube)
- scalar_section = rep.scalar_sections["Scalar Coordinates:"]
+ scalar_section = rep.scalar_sections["Scalar coordinates:"]
- self.assertEqual(len(scalar_section.contents), 3)
+ self.assertEqual(len(scalar_section.contents), 4)
no_bounds_summary = scalar_section.contents[0]
bounds_summary = scalar_section.contents[1]
- text_summary = scalar_section.contents[2]
+ text_summary_simple = scalar_section.contents[2]
+ text_summary_awkward = scalar_section.contents[3]
self.assertEqual(no_bounds_summary.name, "bar")
self.assertEqual(no_bounds_summary.content, "10 K")
@@ -127,9 +134,15 @@ def test_scalar_coord(self):
self.assertEqual(bounds_summary.content, "10 K, bound=(5, 15) K")
self.assertEqual(bounds_summary.extra, "")
- self.assertEqual(text_summary.name, "foo")
- self.assertEqual(text_summary.content, "a\nb\nc")
- self.assertEqual(text_summary.extra, "key='value'")
+ self.assertEqual(text_summary_simple.name, "foo")
+ self.assertEqual(text_summary_simple.content, "this and that")
+ self.assertEqual(text_summary_simple.lines, ["this and that"])
+ self.assertEqual(text_summary_simple.extra, "key=42, key2='value-str'")
+
+ self.assertEqual(text_summary_awkward.name, "foo_2")
+ self.assertEqual(text_summary_awkward.content, r"'a is\nb\n and c'")
+ self.assertEqual(text_summary_awkward.lines, ["a is", "b", " and c"])
+ self.assertEqual(text_summary_awkward.extra, "")
def test_cell_measure(self):
cube = self.cube
@@ -137,7 +150,7 @@ def test_cell_measure(self):
cube.add_cell_measure(cell_measure, 0)
rep = iris._representation.CubeSummary(cube)
- cm_section = rep.vector_sections["Cell Measures:"]
+ cm_section = rep.vector_sections["Cell measures:"]
self.assertEqual(len(cm_section.contents), 1)
cm_summary = cm_section.contents[0]
@@ -150,7 +163,7 @@ def test_ancillary_variable(self):
cube.add_ancillary_variable(cell_measure, 0)
rep = iris._representation.CubeSummary(cube)
- av_section = rep.vector_sections["Ancillary Variables:"]
+ av_section = rep.vector_sections["Ancillary variables:"]
self.assertEqual(len(av_section.contents), 1)
av_summary = av_section.contents[0]
@@ -159,12 +172,14 @@ def test_ancillary_variable(self):
def test_attributes(self):
cube = self.cube
- cube.attributes = {"a": 1, "b": "two"}
+ cube.attributes = {"a": 1, "b": "two", "c": " this \n that\tand."}
rep = iris._representation.CubeSummary(cube)
attribute_section = rep.scalar_sections["Attributes:"]
attribute_contents = attribute_section.contents
- expected_contents = ["a: 1", "b: two"]
+ expected_contents = ["a: 1", "b: two", "c: ' this \\n that\\tand.'"]
+ # Note: a string with \n or \t in it gets "repr-d".
+ # Other strings don't (though in coord 'extra' lines, they do.)
self.assertEqual(attribute_contents, expected_contents)
@@ -182,6 +197,108 @@ def test_cell_methods(self):
expected_contents = ["mean: x, y", "mean: x"]
self.assertEqual(cell_method_section.contents, expected_contents)
+ def test_scalar_cube(self):
+ cube = self.cube
+ while cube.ndim > 0:
+ cube = cube[0]
+ rep = iris._representation.CubeSummary(cube)
+ self.assertEqual(rep.header.nameunit, "air_temperature / (K)")
+ self.assertTrue(rep.header.dimension_header.scalar)
+ self.assertEqual(rep.header.dimension_header.dim_names, [])
+ self.assertEqual(rep.header.dimension_header.shape, [])
+ self.assertEqual(rep.header.dimension_header.contents, ["scalar cube"])
+ self.assertEqual(len(rep.vector_sections), 5)
+ self.assertTrue(
+ all(sect.is_empty() for sect in rep.vector_sections.values())
+ )
+ self.assertEqual(len(rep.scalar_sections), 4)
+ self.assertEqual(
+ len(rep.scalar_sections["Scalar coordinates:"].contents), 1
+ )
+ self.assertTrue(
+ rep.scalar_sections["Scalar cell measures:"].is_empty()
+ )
+ self.assertTrue(rep.scalar_sections["Attributes:"].is_empty())
+ self.assertTrue(rep.scalar_sections["Cell methods:"].is_empty())
+
+ def test_coord_attributes(self):
+ cube = self.cube
+ co1 = cube.coord("latitude")
+ co1.attributes.update(dict(a=1, b=2))
+ co2 = co1.copy()
+ co2.attributes.update(dict(a=7, z=77, text="ok", text2="multi\nline"))
+ cube.add_aux_coord(co2, cube.coord_dims(co1))
+ rep = iris._representation.CubeSummary(cube)
+ co1_summ = rep.vector_sections["Dimension coordinates:"].contents[0]
+ co2_summ = rep.vector_sections["Auxiliary coordinates:"].contents[0]
+ # Notes: 'b' is same so does not appear; sorted order; quoted strings.
+ self.assertEqual(co1_summ.extra, "a=1")
+ self.assertEqual(
+ co2_summ.extra, "a=7, text='ok', text2='multi\\nline', z=77"
+ )
+
+ def test_array_attributes(self):
+ cube = self.cube
+ co1 = cube.coord("latitude")
+ co1.attributes.update(dict(a=1, array=np.array([1.2, 3])))
+ co2 = co1.copy()
+ co2.attributes.update(dict(b=2, array=np.array([3.2, 1])))
+ cube.add_aux_coord(co2, cube.coord_dims(co1))
+ rep = iris._representation.CubeSummary(cube)
+ co1_summ = rep.vector_sections["Dimension coordinates:"].contents[0]
+ co2_summ = rep.vector_sections["Auxiliary coordinates:"].contents[0]
+ self.assertEqual(co1_summ.extra, "array=array([1.2, 3. ])")
+ self.assertEqual(co2_summ.extra, "array=array([3.2, 1. ]), b=2")
+
+ def test_attributes_subtle_differences(self):
+ cube = Cube([0])
+
+ # Add a pair that differ only in having a list instead of an array.
+ co1a = DimCoord(
+ [0],
+ long_name="co1_list_or_array",
+ attributes=dict(x=1, arr1=np.array(2), arr2=np.array([1, 2])),
+ )
+ co1b = co1a.copy()
+ co1b.attributes.update(dict(arr2=[1, 2]))
+ for co in (co1a, co1b):
+ cube.add_aux_coord(co)
+
+ # Add a pair that differ only in an attribute array dtype.
+ co2a = AuxCoord(
+ [0],
+ long_name="co2_dtype",
+ attributes=dict(x=1, arr1=np.array(2), arr2=np.array([3, 4])),
+ )
+ co2b = co2a.copy()
+ co2b.attributes.update(dict(arr2=np.array([3.0, 4.0])))
+ assert co2b != co2a
+ for co in (co2a, co2b):
+ cube.add_aux_coord(co)
+
+ # Add a pair that differ only in an attribute array shape.
+ co3a = DimCoord(
+ [0],
+ long_name="co3_shape",
+ attributes=dict(x=1, arr1=np.array([5, 6]), arr2=np.array([3, 4])),
+ )
+ co3b = co3a.copy()
+ co3b.attributes.update(dict(arr1=np.array([[5], [6]])))
+ for co in (co3a, co3b):
+ cube.add_aux_coord(co)
+
+ rep = iris._representation.CubeSummary(cube)
+ co_summs = rep.scalar_sections["Scalar coordinates:"].contents
+ co1a_summ, co1b_summ = co_summs[0:2]
+ self.assertEqual(co1a_summ.extra, "arr2=array([1, 2])")
+ self.assertEqual(co1b_summ.extra, "arr2=[1, 2]")
+ co2a_summ, co2b_summ = co_summs[2:4]
+ self.assertEqual(co2a_summ.extra, "arr2=array([3, 4])")
+ self.assertEqual(co2b_summ.extra, "arr2=array([3., 4.])")
+ co3a_summ, co3b_summ = co_summs[4:6]
+ self.assertEqual(co3a_summ.extra, "arr1=array([5, 6])")
+ self.assertEqual(co3b_summ.extra, "arr1=array([[5], [6]])")
+
if __name__ == "__main__":
tests.main()
From b2cef9152998bf3e14262d67010554767916281f Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Sun, 14 Feb 2021 16:05:33 +0000
Subject: [PATCH 09/43] update intersphinx mapping and matplotlib urls (#4003)
* update intersphinx mapping and matplotlib urls
* use matplotlib intersphinx where possible
* review actions
* review actions
---
.../general/plot_anomaly_log_colouring.py | 13 +++++-------
docs/src/common_links.inc | 2 +-
docs/src/conf.py | 12 +++++------
docs/src/whatsnew/3.0.1.rst | 21 ++++++++-----------
docs/src/whatsnew/3.0.rst | 21 ++++++++-----------
docs/src/whatsnew/latest.rst | 3 +++
6 files changed, 33 insertions(+), 39 deletions(-)
diff --git a/docs/gallery_code/general/plot_anomaly_log_colouring.py b/docs/gallery_code/general/plot_anomaly_log_colouring.py
index 778f92db1b..846816aff7 100644
--- a/docs/gallery_code/general/plot_anomaly_log_colouring.py
+++ b/docs/gallery_code/general/plot_anomaly_log_colouring.py
@@ -12,18 +12,15 @@
"zero band" which is plotted in white.
To do this, we create a custom value mapping function (normalization) using
-the matplotlib Norm class `matplotlib.colours.SymLogNorm
-`_.
-We use this to make a cell-filled pseudocolour plot with a colorbar.
+the matplotlib Norm class :obj:`matplotlib.colors.SymLogNorm`.
+We use this to make a cell-filled pseudocolor plot with a colorbar.
NOTE: By "pseudocolour", we mean that each data point is drawn as a "cell"
region on the plot, coloured according to its data value.
This is provided in Iris by the functions :meth:`iris.plot.pcolor` and
:meth:`iris.plot.pcolormesh`, which call the underlying matplotlib
-functions of the same names (i.e. `matplotlib.pyplot.pcolor
-`_
-and `matplotlib.pyplot.pcolormesh
-`_).
+functions of the same names (i.e., :obj:`matplotlib.pyplot.pcolor`
+and :obj:`matplotlib.pyplot.pcolormesh`).
See also: http://en.wikipedia.org/wiki/False_color#Pseudocolor.
"""
@@ -65,7 +62,7 @@ def main():
# Use a standard colour map which varies blue-white-red.
# For suitable options, see the 'Diverging colormaps' section in:
- # http://matplotlib.org/examples/color/colormaps_reference.html
+ # http://matplotlib.org/stable/gallery/color/colormap_reference.html
anom_cmap = "bwr"
# Create a 'logarithmic' data normalization.
diff --git a/docs/src/common_links.inc b/docs/src/common_links.inc
index 157444d65d..3c465b67dc 100644
--- a/docs/src/common_links.inc
+++ b/docs/src/common_links.inc
@@ -18,7 +18,7 @@
.. _issue: https://github.com/SciTools/iris/issues
.. _issues: https://github.com/SciTools/iris/issues
.. _legacy documentation: https://scitools.org.uk/iris/docs/v2.4.0/
-.. _matplotlib: https://matplotlib.org/
+.. _matplotlib: https://matplotlib.org/stable/
.. _napolean: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/sphinxcontrib.napoleon.html
.. _nox: https://nox.thea.codes/en/stable/
.. _New Issue: https://github.com/scitools/iris/issues/new/choose
diff --git a/docs/src/conf.py b/docs/src/conf.py
index 843af17944..9bab5850b8 100644
--- a/docs/src/conf.py
+++ b/docs/src/conf.py
@@ -184,18 +184,18 @@ def autolog(message):
# -- intersphinx extension ----------------------------------------------------
# See https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html
intersphinx_mapping = {
- "cartopy": ("http://scitools.org.uk/cartopy/docs/latest/", None),
- "matplotlib": ("http://matplotlib.org/", None),
- "numpy": ("http://docs.scipy.org/doc/numpy/", None),
- "python": ("http://docs.python.org/2.7", None),
- "scipy": ("http://docs.scipy.org/doc/scipy/reference/", None),
+ "cartopy": ("https://scitools.org.uk/cartopy/docs/latest/", None),
+ "matplotlib": ("https://matplotlib.org/stable/", None),
+ "numpy": ("https://numpy.org/doc/stable/", None),
+ "python": ("https://docs.python.org/3/", None),
+ "scipy": ("https://docs.scipy.org/doc/scipy/reference/", None),
}
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
# -- plot_directive extension -------------------------------------------------
-# See https://matplotlib.org/3.1.3/devel/plot_directive.html#options
+# See https://matplotlib.org/stable/api/sphinxext_plot_directive_api.html#options
plot_formats = [
("png", 100),
]
diff --git a/docs/src/whatsnew/3.0.1.rst b/docs/src/whatsnew/3.0.1.rst
index 163fe4ff3e..05bf41ce18 100644
--- a/docs/src/whatsnew/3.0.1.rst
+++ b/docs/src/whatsnew/3.0.1.rst
@@ -167,12 +167,12 @@ This document explains the changes made to Iris for this release
``volume`` are the only accepted values. (:pull:`3533`)
#. `@trexfeathers`_ set **all** plot types in :mod:`iris.plot` to now use
- `matplotlib.dates.date2num`_ to format date/time coordinates for use on a plot
+ :obj:`matplotlib.dates.date2num` to format date/time coordinates for use on a plot
axis (previously :meth:`~iris.plot.pcolor` and :meth:`~iris.plot.pcolormesh`
did not include this behaviour). (:pull:`3762`)
#. `@trexfeathers`_ changed date/time axis labels in :mod:`iris.quickplot` to
- now **always** be based on the ``epoch`` used in `matplotlib.dates.date2num`_
+ now **always** be based on the ``epoch`` used in :obj:`matplotlib.dates.date2num`
(previously would take the unit from a time coordinate, if present, even
though the coordinate's value had been changed via ``date2num``).
(:pull:`3762`)
@@ -189,7 +189,7 @@ This document explains the changes made to Iris for this release
#. `@stephenworsley`_ changed the way tick labels are assigned from string coords.
Previously, the first tick label would occasionally be duplicated. This also
- removes the use of Matplotlib's deprecated ``IndexFormatter``. (:pull:`3857`)
+ removes the use of the deprecated `matplotlib`_ ``IndexFormatter``. (:pull:`3857`)
#. `@znicholls`_ fixed :meth:`~iris.quickplot._title` to only check
``units.is_time_reference`` if the ``units`` symbol is not used. (:pull:`3902`)
@@ -295,11 +295,11 @@ This document explains the changes made to Iris for this release
#. `@stephenworsley`_ and `@trexfeathers`_ pinned Iris to require
`Cartopy`_ ``>=0.18``, in order to remain compatible with the latest version
- of `Matplotlib`_. (:pull:`3762`)
+ of `matplotlib`_. (:pull:`3762`)
-#. `@bjlittle`_ unpinned Iris to use the latest version of `Matplotlib`_.
+#. `@bjlittle`_ unpinned Iris to use the latest version of `matplotlib`_.
Supporting ``Iris`` for both ``Python2`` and ``Python3`` had resulted in
- pinning our dependency on `Matplotlib`_ at ``v2.x``. But this is no longer
+ pinning our dependency on `matplotlib`_ at ``v2.x``. But this is no longer
necessary now that ``Python2`` support has been dropped. (:pull:`3468`)
#. `@stephenworsley`_ and `@trexfeathers`_ unpinned Iris to use the latest version
@@ -422,11 +422,11 @@ This document explains the changes made to Iris for this release
grid-line spacing in `Cartopy`_. (:pull:`3762`) (see also `Cartopy#1117`_)
#. `@trexfeathers`_ added additional acceptable graphics test targets to account
- for very minor changes in `Matplotlib`_ version ``3.3`` (colormaps, fonts and
+ for very minor changes in `matplotlib`_ version ``3.3`` (colormaps, fonts and
axes borders). (:pull:`3762`)
-#. `@rcomer`_ corrected the Matplotlib backend in Iris tests to ignore
- `matplotlib.rcdefaults`_, instead the tests will **always** use ``agg``.
+#. `@rcomer`_ corrected the `matplotlib`_ backend in Iris tests to ignore
+ :obj:`matplotlib.rcdefaults`, instead the tests will **always** use ``agg``.
(:pull:`3846`)
#. `@bjlittle`_ migrated the `black`_ support from ``19.10b0`` to ``20.8b1``.
@@ -470,7 +470,6 @@ This document explains the changes made to Iris for this release
with `flake8`_ and `black`_. (:pull:`3928`)
.. _Read the Docs: https://scitools-iris.readthedocs.io/en/latest/
-.. _Matplotlib: https://matplotlib.org/
.. _CF units rules: https://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#units
.. _CF Ancillary Data: https://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#ancillary-data
.. _Quality Flags: https://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#flags
@@ -480,7 +479,6 @@ This document explains the changes made to Iris for this release
.. _Cartopy#1105: https://github.com/SciTools/cartopy/pull/1105
.. _Cartopy#1117: https://github.com/SciTools/cartopy/pull/1117
.. _Dask: https://github.com/dask/dask
-.. _matplotlib.dates.date2num: https://matplotlib.org/api/dates_api.html#matplotlib.dates.date2num
.. _Proj: https://github.com/OSGeo/PROJ
.. _black: https://black.readthedocs.io/en/stable/
.. _Proj#1292: https://github.com/OSGeo/PROJ/pull/1292
@@ -510,7 +508,6 @@ This document explains the changes made to Iris for this release
.. _numpy: https://github.com/numpy/numpy
.. _xxHash: https://github.com/Cyan4973/xxHash
.. _PyKE: https://pypi.org/project/scitools-pyke/
-.. _matplotlib.rcdefaults: https://matplotlib.org/3.1.1/api/matplotlib_configuration_api.html?highlight=rcdefaults#matplotlib.rcdefaults
.. _@owena11: https://github.com/owena11
.. _GitHub: https://github.com/SciTools/iris/issues/new/choose
.. _readthedocs: https://readthedocs.org/
diff --git a/docs/src/whatsnew/3.0.rst b/docs/src/whatsnew/3.0.rst
index 0f61d62033..7fdc2e3400 100644
--- a/docs/src/whatsnew/3.0.rst
+++ b/docs/src/whatsnew/3.0.rst
@@ -150,12 +150,12 @@ This document explains the changes made to Iris for this release
``volume`` are the only accepted values. (:pull:`3533`)
#. `@trexfeathers`_ set **all** plot types in :mod:`iris.plot` to now use
- `matplotlib.dates.date2num`_ to format date/time coordinates for use on a plot
+ :obj:`matplotlib.dates.date2num` to format date/time coordinates for use on a plot
axis (previously :meth:`~iris.plot.pcolor` and :meth:`~iris.plot.pcolormesh`
did not include this behaviour). (:pull:`3762`)
#. `@trexfeathers`_ changed date/time axis labels in :mod:`iris.quickplot` to
- now **always** be based on the ``epoch`` used in `matplotlib.dates.date2num`_
+ now **always** be based on the ``epoch`` used in :obj:`matplotlib.dates.date2num`
(previously would take the unit from a time coordinate, if present, even
though the coordinate's value had been changed via ``date2num``).
(:pull:`3762`)
@@ -172,7 +172,7 @@ This document explains the changes made to Iris for this release
#. `@stephenworsley`_ changed the way tick labels are assigned from string coords.
Previously, the first tick label would occasionally be duplicated. This also
- removes the use of Matplotlib's deprecated ``IndexFormatter``. (:pull:`3857`)
+ removes the use of the deprecated `matplotlib`_ ``IndexFormatter``. (:pull:`3857`)
#. `@znicholls`_ fixed :meth:`~iris.quickplot._title` to only check
``units.is_time_reference`` if the ``units`` symbol is not used. (:pull:`3902`)
@@ -278,11 +278,11 @@ This document explains the changes made to Iris for this release
#. `@stephenworsley`_ and `@trexfeathers`_ pinned Iris to require
`Cartopy`_ ``>=0.18``, in order to remain compatible with the latest version
- of `Matplotlib`_. (:pull:`3762`)
+ of `matplotlib`_. (:pull:`3762`)
-#. `@bjlittle`_ unpinned Iris to use the latest version of `Matplotlib`_.
+#. `@bjlittle`_ unpinned Iris to use the latest version of `matplotlib`_.
Supporting ``Iris`` for both ``Python2`` and ``Python3`` had resulted in
- pinning our dependency on `Matplotlib`_ at ``v2.x``. But this is no longer
+ pinning our dependency on `matplotlib`_ at ``v2.x``. But this is no longer
necessary now that ``Python2`` support has been dropped. (:pull:`3468`)
#. `@stephenworsley`_ and `@trexfeathers`_ unpinned Iris to use the latest version
@@ -405,11 +405,11 @@ This document explains the changes made to Iris for this release
grid-line spacing in `Cartopy`_. (:pull:`3762`) (see also `Cartopy#1117`_)
#. `@trexfeathers`_ added additional acceptable graphics test targets to account
- for very minor changes in `Matplotlib`_ version ``3.3`` (colormaps, fonts and
+ for very minor changes in `matplotlib`_ version ``3.3`` (colormaps, fonts and
axes borders). (:pull:`3762`)
-#. `@rcomer`_ corrected the Matplotlib backend in Iris tests to ignore
- `matplotlib.rcdefaults`_, instead the tests will **always** use ``agg``.
+#. `@rcomer`_ corrected the `matplotlib`_ backend in Iris tests to ignore
+ :obj:`matplotlib.rcdefaults`, instead the tests will **always** use ``agg``.
(:pull:`3846`)
#. `@bjlittle`_ migrated the `black`_ support from ``19.10b0`` to ``20.8b1``.
@@ -453,7 +453,6 @@ This document explains the changes made to Iris for this release
with `flake8`_ and `black`_. (:pull:`3928`)
.. _Read the Docs: https://scitools-iris.readthedocs.io/en/latest/
-.. _Matplotlib: https://matplotlib.org/
.. _CF units rules: https://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#units
.. _CF Ancillary Data: https://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#ancillary-data
.. _Quality Flags: https://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#flags
@@ -463,7 +462,6 @@ This document explains the changes made to Iris for this release
.. _Cartopy#1105: https://github.com/SciTools/cartopy/pull/1105
.. _Cartopy#1117: https://github.com/SciTools/cartopy/pull/1117
.. _Dask: https://github.com/dask/dask
-.. _matplotlib.dates.date2num: https://matplotlib.org/api/dates_api.html#matplotlib.dates.date2num
.. _Proj: https://github.com/OSGeo/PROJ
.. _black: https://black.readthedocs.io/en/stable/
.. _Proj#1292: https://github.com/OSGeo/PROJ/pull/1292
@@ -493,7 +491,6 @@ This document explains the changes made to Iris for this release
.. _numpy: https://github.com/numpy/numpy
.. _xxHash: https://github.com/Cyan4973/xxHash
.. _PyKE: https://pypi.org/project/scitools-pyke/
-.. _matplotlib.rcdefaults: https://matplotlib.org/3.1.1/api/matplotlib_configuration_api.html?highlight=rcdefaults#matplotlib.rcdefaults
.. _@owena11: https://github.com/owena11
.. _GitHub: https://github.com/SciTools/iris/issues/new/choose
.. _readthedocs: https://readthedocs.org/
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index b290b7ab5a..f96cb8c7eb 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -86,6 +86,9 @@ This document explains the changes made to Iris for this release
on :ref:`installing_iris` and to the footer of all pages. Also added the
copyright years to the footer. (:pull:`3989`)
+#. `@bjlittle`_ updated the ``intersphinx_mapping`` and fixed documentation
+ to use ``stable`` URLs for `matplotlib`_. (:pull:`4003`)
+
💼 Internal
===========
From e5cb25960e22f3befd36e78bc449add7ac16d859 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Sun, 14 Feb 2021 17:13:14 +0000
Subject: [PATCH 10/43] update readme badges (#4004)
* update readme badges
* pimp twitter badge
---
README.md | 20 +++++++++++++-------
docs/src/whatsnew/latest.rst | 5 +++++
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 0ceac7e089..c6cd4de47f 100644
--- a/README.md
+++ b/README.md
@@ -13,18 +13,24 @@
-
-
+
+
+
+
+
+
-
+
@@ -35,8 +41,8 @@
-
+
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index f96cb8c7eb..68872beb64 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -89,6 +89,8 @@ This document explains the changes made to Iris for this release
#. `@bjlittle`_ updated the ``intersphinx_mapping`` and fixed documentation
to use ``stable`` URLs for `matplotlib`_. (:pull:`4003`)
+#. `@bjlittle`_ added the |PyPI|_ badge to the `README.md`_. (:pull:`4004`)
+
💼 Internal
===========
@@ -123,4 +125,7 @@ This document explains the changes made to Iris for this release
.. _GitHub: https://github.com/SciTools/iris/issues/new/choose
.. _Met Office: https://www.metoffice.gov.uk/
.. _numpy: https://numpy.org/doc/stable/release/1.20.0-notes.html
+.. |PyPI| image:: https://img.shields.io/pypi/v/scitools-iris?color=orange&label=pypi%7Cscitools-iris
+.. _PyPI: https://pypi.org/project/scitools-iris/
.. _Python 3.8: https://www.python.org/downloads/release/python-380/
+.. _README.md: https://github.com/SciTools/iris#-----
From 343e7a4e84e3783e343a7b814f766f2d8973b342 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Sun, 14 Feb 2021 17:13:40 +0000
Subject: [PATCH 11/43] update readme logo img src and href (#4006)
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index c6cd4de47f..e460f4a01a 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
- 
+
+ 
From f569a55e4644af1e1c0019c61a908bf3cda420ce Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Sun, 14 Feb 2021 17:14:08 +0000
Subject: [PATCH 12/43] update setuptools description (#4008)
---
setup.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index b1c8939fdd..f4bfe4cf08 100644
--- a/setup.py
+++ b/setup.py
@@ -263,7 +263,7 @@ def long_description():
author="UK Met Office",
author_email="scitools-iris-dev@googlegroups.com",
description="A powerful, format-agnostic, community-driven Python "
- "library for analysing and visualising Earth science data",
+ "package for analysing and visualising Earth science data",
long_description=long_description(),
long_description_content_type="text/markdown",
packages=find_package_tree("lib/iris", "iris"),
From 105af0e2aaeb87c50efb79227ea5aad17f6708be Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Mon, 15 Feb 2021 10:19:57 +0000
Subject: [PATCH 13/43] cirrus-ci compute credits (#4007)
---
.cirrus.yml | 52 +++++++++++++++++++++++-------------
docs/src/whatsnew/latest.rst | 3 +++
2 files changed, 36 insertions(+), 19 deletions(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index da425a5691..3f9e45b5ea 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,5 +1,6 @@
# Reference:
# - https://cirrus-ci.org/guide/writing-tasks/
+# - https://cirrus-ci.org/guide/writing-tasks/#environment-variables
# - https://cirrus-ci.org/guide/tips-and-tricks/#sharing-configuration-between-tasks
# - https://cirrus-ci.org/guide/linux/
# - https://cirrus-ci.org/guide/macOS/
@@ -35,25 +36,6 @@ env:
IRIS_TEST_DATA_DIR: ${HOME}/iris-test-data
-#
-# Linting
-#
-lint_task:
- auto_cancellation: true
- name: "${CIRRUS_OS}: flake8 and black"
- pip_cache:
- folder: ~/.cache/pip
- fingerprint_script:
- - echo "${CIRRUS_TASK_NAME}"
- - echo "$(date +%Y).$(($(date +%U) / ${CACHE_PERIOD})):${PIP_CACHE_BUILD} ${PIP_CACHE_PACKAGES}"
- lint_script:
- - pip list
- - python -m pip install --retries 3 --upgrade ${PIP_CACHE_PACKAGES}
- - pip list
- - nox --session flake8
- - nox --session black
-
-
#
# YAML alias for common linux test infra-structure.
#
@@ -89,10 +71,38 @@ linux_task_template: &LINUX_TASK_TEMPLATE
- sha256sum ${CIRRUS_WORKING_DIR}/requirements/ci/py$(echo ${PY_VER} | tr -d ".").yml
+#
+# YAML alias for compute credits
+#
+compute_credits_template: &CREDITS_TEMPLATE
+ # Only use credits for non-DRAFT pull-requests to SciTools/iris master branch by collaborators
+ use_compute_credits: $CIRRUS_REPO_FULL_NAME == 'SciTools/iris' && $CIRRUS_USER_COLLABORATOR == 'true' && $CIRRUS_PR_DRAFT == 'false' && $CIRRUS_BASE_BRANCH == 'master' && $CIRRUS_PR != ''
+
+#
+# Linting
+#
+lint_task:
+ << : *CREDITS_TEMPLATE
+ auto_cancellation: true
+ name: "${CIRRUS_OS}: flake8 and black"
+ pip_cache:
+ folder: ~/.cache/pip
+ fingerprint_script:
+ - echo "${CIRRUS_TASK_NAME}"
+ - echo "$(date +%Y).$(($(date +%U) / ${CACHE_PERIOD})):${PIP_CACHE_BUILD} ${PIP_CACHE_PACKAGES}"
+ lint_script:
+ - pip list
+ - python -m pip install --retries 3 --upgrade ${PIP_CACHE_PACKAGES}
+ - pip list
+ - nox --session flake8
+ - nox --session black
+
+
#
# Testing Minimal (Linux)
#
linux_minimal_task:
+ << : *CREDITS_TEMPLATE
matrix:
env:
PY_VER: 3.6
@@ -116,6 +126,7 @@ linux_minimal_task:
# Testing Full (Linux)
#
linux_task:
+ << : *CREDITS_TEMPLATE
matrix:
env:
PY_VER: 3.6
@@ -148,6 +159,7 @@ linux_task:
# Testing Documentation Gallery (Linux)
#
gallery_task:
+ << : *CREDITS_TEMPLATE
matrix:
env:
PY_VER: 3.8
@@ -176,6 +188,7 @@ gallery_task:
# Testing Documentation (Linux)
#
doctest_task:
+ << : *CREDITS_TEMPLATE
matrix:
env:
PY_VER: 3.8
@@ -210,6 +223,7 @@ doctest_task:
# Testing Documentation Link Check (Linux)
#
link_task:
+ << : *CREDITS_TEMPLATE
matrix:
env:
PY_VER: 3.8
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index 68872beb64..a70385a7ed 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -109,6 +109,9 @@ This document explains the changes made to Iris for this release
each ``nox`` session to list its ``conda`` environment packages and
environment info. (:pull:`3990`)
+#. `@bjlittle`_ enabled `cirrus-ci`_ compute credits for non-draft pull-requests
+ from collaborators targeting the Iris ``master`` branch. (:pull:`4007`)
+
.. comment
Whatsnew author names (@github name) in alphabetical order. Note that,
From ce5975acee31c9618683c7cd114c9bfca4dc1c9d Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Mon, 15 Feb 2021 10:47:52 +0000
Subject: [PATCH 14/43] update release process (#4010)
---
docs/src/developers_guide/release.rst | 97 +++++++++++++++------------
1 file changed, 55 insertions(+), 42 deletions(-)
diff --git a/docs/src/developers_guide/release.rst b/docs/src/developers_guide/release.rst
index 56328f910f..90938b32d3 100644
--- a/docs/src/developers_guide/release.rst
+++ b/docs/src/developers_guide/release.rst
@@ -3,8 +3,7 @@
Releases
========
-A release of Iris is a `tag on the SciTools/Iris`_
-Github repository.
+A release of Iris is a `tag on the SciTools/Iris`_ Github repository.
The summary below is of the main areas that constitute the release. The final
section details the :ref:`iris_development_releases_steps` to take.
@@ -24,8 +23,8 @@ number of releases, is in :ref:`iris_development_deprecations`.
Release Branch
--------------
-Once the features intended for the release are on master, a release branch
-should be created, in the SciTools/Iris repository. This will have the name:
+Once the features intended for the release are on ``master``, a release branch
+should be created, in the ``SciTools/iris`` repository. This will have the name:
:literal:`v{major release number}.{minor release number}.x`
@@ -41,10 +40,10 @@ Release Candidate
-----------------
Prior to a release, a release candidate tag may be created, marked as a
-pre-release in github, with a tag ending with :literal:`rc` followed by a
-number, e.g.:
+pre-release in GitHub, with a tag ending with :literal:`rc` followed by a
+number (0-based), e.g.,:
- :literal:`v1.9.0rc1`
+ :literal:`v1.9.0rc0`
If created, the pre-release shall be available for a minimum of two weeks
prior to the release being cut. However a 4 week period should be the goal
@@ -57,11 +56,16 @@ point release.
If new features are required for a release after a release candidate has been
cut, a new pre-release shall be issued first.
+Make the release candidate available as a conda package on the
+`conda-forge Anaconda channel`_ using the `rc_iris`_ label. To do this visit
+the `conda-forge iris-feedstock`_ and follow `CFEP-05`_. For further information
+see the `conda-forge User Documentation`_.
+
Documentation
-------------
-The documentation should include all of the what's new entries for the release.
+The documentation should include all of the ``whatsnew`` entries for the release.
This content should be reviewed and adapted as required.
Steps to achieve this can be found in the :ref:`iris_development_releases_steps`.
@@ -70,50 +74,48 @@ Steps to achieve this can be found in the :ref:`iris_development_releases_steps`
The Release
-----------
-The final steps are to change the version string in the source of
-:literal:`Iris.__init__.py` and include the release date in the relevant what's
-new page within the documentation.
+The final steps of the release are to change the version string ``__version__``
+in the source of :literal:`iris.__init__.py` and ensure the release date and details
+are correct in the relevant ``whatsnew`` page within the documentation.
Once all checks are complete, the release is cut by the creation of a new tag
-in the SciTools Iris repository.
+in the ``SciTools/iris`` repository.
Conda Recipe
------------
-Once a release is cut, the `Iris feedstock`_ for the conda recipe must be
-updated to build the latest release of Iris and push this artefact to
-`conda forge`_.
+Once a release is cut on GitHub, update the Iris conda recipe on the
+`conda-forge iris-feedstock`_ for the release. This will build and publish the
+conda package on the `conda-forge Anaconda channel`_.
-.. _Iris feedstock: https://github.com/conda-forge/iris-feedstock/tree/master/recipe
-.. _conda forge: https://anaconda.org/conda-forge/iris
Merge Back
----------
-After the release is cut, the changes shall be merged back onto the
-Scitools/iris master branch.
+After the release is cut, the changes from the release branch should be merged
+back onto the ``SciTools/iris`` ``master`` branch.
-To achieve this, first cut a local branch from the release branch,
-:literal:`{release}.x`. Next add a commit changing the release string to match
-the release string on scitools/master. This branch can now be proposed as a
-pull request to master. This work flow ensures that the commit identifiers are
-consistent between the :literal:`.x` branch and :literal:`master`.
+To achieve this, first cut a local branch from the latest ``master`` branch,
+and `git merge` the :literal:`.x` release branch into it. Ensure that the
+``iris.__version__``, ``docs/src/whatsnew/index.rst`` and ``docs/src/whatsnew/latest.rst``
+are correct, before committing these changes and then proposing a pull-request
+on the ``master`` branch of ``SciTools/iris``.
Point Releases
--------------
-Bug fixes may be implemented and targeted as the :literal:`.x` branch. These
-should lead to a new point release, another tag. For example, a fix for a
-problem with 1.9.0 will be merged into 1.9.x, and then released by tagging
-1.9.1.
+Bug fixes may be implemented and targeted on the :literal:`.x` release branch.
+These should lead to a new point release, and another tag. For example, a fix
+for a problem with the ``v1.9.0`` release will be merged into ``v1.9.x`` release
+branch, and then released by tagging ``v1.9.1``.
New features shall not be included in a point release, these are for bug fixes.
A point release does not require a release candidate, but the rest of the
release process is to be followed, including the merge back of changes into
-:literal:`master`.
+``master``.
.. _iris_development_releases_steps:
@@ -121,19 +123,19 @@ release process is to be followed, including the merge back of changes into
Maintainer Steps
----------------
-These steps assume a release for ``v1.9`` is to be created.
+These steps assume a release for ``1.9.0`` is to be created.
Release Steps
~~~~~~~~~~~~~
-#. Create the release feature branch ``1.9.x`` on `SciTools/iris`_.
+#. Create the release feature branch ``v1.9.x`` on `SciTools/iris`_.
The only exception is for a point/bugfix release, as it should already exist
#. Update the ``iris.__init__.py`` version string e.g., to ``1.9.0``
-#. Update the what's new for the release:
+#. Update the ``whatsnew`` for the release:
- * Use git to rename ``docs/src/whatsnew/latest.rst`` to the release
+ * Use ``git`` to rename ``docs/src/whatsnew/latest.rst`` to the release
version file ``v1.9.rst``
- * Use git to delete the ``docs/src/whatsnew/latest.rst.template`` file
+ * Use ``git`` to delete the ``docs/src/whatsnew/latest.rst.template`` file
* In ``v1.9.rst`` remove the ``[unreleased]`` caption from the page title.
Note that, the Iris version and release date are updated automatically
when the documentation is built
@@ -141,10 +143,10 @@ Release Steps
* Work with the development team to populate the ``Release Highlights``
dropdown at the top of the file, which provides extra detail on notable
changes
- * Use git to add and commit all changes, including removal of
+ * Use ``git`` to add and commit all changes, including removal of
``latest.rst.template``
-#. Update the what's new index ``docs/src/whatsnew/index.rst``
+#. Update the ``whatsnew`` index ``docs/src/whatsnew/index.rst``
* Remove the reference to ``latest.rst``
* Add a reference to ``v1.9.rst`` to the top of the list
@@ -159,20 +161,31 @@ Post Release Steps
~~~~~~~~~~~~~~~~~~
#. Check the documentation has built on `Read The Docs`_. The build is
- triggered by any commit to master. Additionally check that the versions
+ triggered by any commit to ``master``. Additionally check that the versions
available in the pop out menu in the bottom left corner include the new
release version. If it is not present you will need to configure the
- versions available in the **admin** dashboard in Read The Docs
+ versions available in the **admin** dashboard in `Read The Docs`_.
+#. Review the `Active Versions`_ for the ``scitools-iris`` project on
+ `Read The Docs`_ to ensure that the appropriate versions are ``Active``
+ and/or ``Hidden``. To do this ``Edit`` the appropriate version e.g.,
+ see `Editing v3.0.0rc0`_.
#. Copy ``docs/src/whatsnew/latest.rst.template`` to
``docs/src/whatsnew/latest.rst``. This will reset
- the file with the ``unreleased`` heading and placeholders for the what's
- new headings
-#. Add back in the reference to ``latest.rst`` to the what's new index
+ the file with the ``unreleased`` heading and placeholders for the
+ ``whatsnew`` headings
+#. Add back in the reference to ``latest.rst`` to the ``whatsnew`` index
``docs/src/whatsnew/index.rst``
#. Update ``iris.__init__.py`` version string to show as ``1.10.dev0``
-#. Merge back to master
+#. Merge back to ``master``
.. _Read The Docs: https://readthedocs.org/projects/scitools-iris/builds/
.. _SciTools/iris: https://github.com/SciTools/iris
.. _tag on the SciTools/Iris: https://github.com/SciTools/iris/releases
+.. _conda-forge Anaconda channel: https://anaconda.org/conda-forge/iris
+.. _conda-forge iris-feedstock: https://github.com/conda-forge/iris-feedstock
+.. _CFEP-05: https://github.com/conda-forge/cfep/blob/master/cfep-05.md
+.. _conda-forge User Documentation: https://conda-forge.org/docs/user/00_intro.html
+.. _Active Versions: https://readthedocs.org/projects/scitools-iris/versions/
+.. _Editing v3.0.0rc0: https://readthedocs.org/dashboard/scitools-iris/version/v3.0.0rc0/
+.. _rc_iris: https://anaconda.org/conda-forge/iris/labels
From 343d3297b547b0837b794d8b1f60e9eb46aee34c Mon Sep 17 00:00:00 2001
From: Alexander Kuhn-Regnier
Date: Tue, 16 Feb 2021 13:51:18 +0000
Subject: [PATCH 15/43] Stop using deprecated aliases of builtin types (#3997)
* Stopped using deprecated aliases of builtin types.
This is required to avoid warnings starting with NumPy 1.20.0.
* Update lib/iris/tests/test_cell.py
Co-authored-by: Bill Little
* Update lib/iris/tests/test_cell.py
Co-authored-by: Bill Little
* Updated whatsnew.
Co-authored-by: Bill Little
---
docs/src/whatsnew/latest.rst | 5 ++
lib/iris/_constraints.py | 2 +-
lib/iris/analysis/__init__.py | 2 +-
lib/iris/analysis/_regrid.py | 2 +-
lib/iris/experimental/regrid.py | 4 +-
lib/iris/fileformats/_ff.py | 2 +-
lib/iris/fileformats/pp.py | 2 +-
lib/iris/fileformats/pp_load_rules.py | 2 +-
lib/iris/tests/__init__.py | 12 ++---
.../test_regrid_conservative_via_esmpy.py | 6 +--
lib/iris/tests/test_cell.py | 4 +-
lib/iris/tests/test_concatenate.py | 8 ++--
lib/iris/tests/test_merge.py | 4 +-
.../analysis/cartography/test_rotate_winds.py | 2 +-
.../regrid/test_RectilinearRegridder.py | 30 ++++++------
.../unit/aux_factory/test_OceanSFactory.py | 4 +-
.../unit/aux_factory/test_OceanSg1Factory.py | 4 +-
.../unit/aux_factory/test_OceanSg2Factory.py | 4 +-
.../aux_factory/test_OceanSigmaFactory.py | 4 +-
.../aux_factory/test_OceanSigmaZFactory.py | 8 ++--
.../unit/common/metadata/test_BaseMetadata.py | 4 +-
.../unit/common/metadata/test__hexdigest.py | 20 ++++----
...rid_weighted_curvilinear_to_rectilinear.py | 4 +-
.../unit/fileformats/cf/test_CFReader.py | 46 +++++++++++--------
.../tests/unit/fileformats/pp/test_PPField.py | 8 ++--
.../pp/test__data_bytes_to_shaped_array.py | 4 +-
.../unit/lazy_data/test_lazy_elementwise.py | 2 +-
27 files changed, 105 insertions(+), 94 deletions(-)
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index a70385a7ed..5a7f682c23 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -112,11 +112,15 @@ This document explains the changes made to Iris for this release
#. `@bjlittle`_ enabled `cirrus-ci`_ compute credits for non-draft pull-requests
from collaborators targeting the Iris ``master`` branch. (:pull:`4007`)
+#. `@akuhnregnier`_ replaced `deprecated numpy 1.20 aliases for builtin types`_.
+ (:pull:`3997`)
+
.. comment
Whatsnew author names (@github name) in alphabetical order. Note that,
core dev names are automatically included by the common_links.inc:
+.. _@akuhnregnier: https://github.com/akuhnregnier
.. _@gcaria: https://github.com/gcaria
.. _@MHBalsmeier: https://github.com/MHBalsmeier
@@ -125,6 +129,7 @@ This document explains the changes made to Iris for this release
Whatsnew resources in alphabetical order:
.. _abstract base class: https://docs.python.org/3/library/abc.html
+.. _deprecated numpy 1.20 aliases for builtin types: https://numpy.org/doc/1.20/release/1.20.0-notes.html#using-the-aliases-of-builtin-types-like-np-int-is-deprecated
.. _GitHub: https://github.com/SciTools/iris/issues/new/choose
.. _Met Office: https://www.metoffice.gov.uk/
.. _numpy: https://numpy.org/doc/stable/release/1.20.0-notes.html
diff --git a/lib/iris/_constraints.py b/lib/iris/_constraints.py
index 0f6a8ab6c6..5179d89039 100644
--- a/lib/iris/_constraints.py
+++ b/lib/iris/_constraints.py
@@ -294,7 +294,7 @@ def call_func(c):
except TypeError:
try_quick = False
if try_quick:
- r = np.zeros(coord.shape, dtype=np.bool)
+ r = np.zeros(coord.shape, dtype=np.bool_)
if coord.cell(i) == self._coord_thing:
r[i] = True
else:
diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py
index a049d060c2..cf9f258be1 100644
--- a/lib/iris/analysis/__init__.py
+++ b/lib/iris/analysis/__init__.py
@@ -1454,7 +1454,7 @@ def interp_order(length):
slices[-1] = endslice
slices = tuple(slices) # Numpy>=1.16 : index with tuple, *not* list.
- if isinstance(array.dtype, np.float):
+ if isinstance(array.dtype, np.float64):
data = array[slices]
else:
# Cast non-float data type.
diff --git a/lib/iris/analysis/_regrid.py b/lib/iris/analysis/_regrid.py
index 7063fdef43..b0341fafaa 100644
--- a/lib/iris/analysis/_regrid.py
+++ b/lib/iris/analysis/_regrid.py
@@ -696,7 +696,7 @@ def _regrid(
if ma.isMaskedArray(src_data):
data = ma.empty(shape, dtype=dtype)
- data.mask = np.zeros(data.shape, dtype=np.bool)
+ data.mask = np.zeros(data.shape, dtype=np.bool_)
else:
data = np.empty(shape, dtype=dtype)
diff --git a/lib/iris/experimental/regrid.py b/lib/iris/experimental/regrid.py
index e08b71c403..7608b2608a 100644
--- a/lib/iris/experimental/regrid.py
+++ b/lib/iris/experimental/regrid.py
@@ -498,9 +498,9 @@ def _regrid_area_weighted_array(src_data, x_dim, y_dim, weights_info, mdtol=0):
# Flag to indicate whether the original data was a masked array.
src_masked = src_data.mask.any() if ma.isMaskedArray(src_data) else False
if src_masked:
- src_area_masks = np.full(src_areas_shape, True, dtype=np.bool)
+ src_area_masks = np.full(src_areas_shape, True, dtype=np.bool_)
else:
- new_data_mask = np.full(new_shape, False, dtype=np.bool)
+ new_data_mask = np.full(new_shape, False, dtype=np.bool_)
# Axes of data over which the weighted mean is calculated.
axis = (y_dim, x_dim)
diff --git a/lib/iris/fileformats/_ff.py b/lib/iris/fileformats/_ff.py
index 1b1b2377ff..a198bb5740 100644
--- a/lib/iris/fileformats/_ff.py
+++ b/lib/iris/fileformats/_ff.py
@@ -816,7 +816,7 @@ def __iter__(self):
return pp._interpret_fields(self._extract_field())
-def _parse_binary_stream(file_like, dtype=np.float, count=-1):
+def _parse_binary_stream(file_like, dtype=np.float64, count=-1):
"""
Replacement :func:`numpy.fromfile` due to python3 performance issues.
diff --git a/lib/iris/fileformats/pp.py b/lib/iris/fileformats/pp.py
index 406da925b1..0627bcc4a2 100644
--- a/lib/iris/fileformats/pp.py
+++ b/lib/iris/fileformats/pp.py
@@ -752,7 +752,7 @@ def _data_bytes_to_shaped_array(
# However, we still mask any MDI values in the array (below).
pass
else:
- land_mask = mask.data.astype(np.bool)
+ land_mask = mask.data.astype(np.bool_)
sea_mask = ~land_mask
new_data = np.ma.masked_all(land_mask.shape)
new_data.fill_value = mdi
diff --git a/lib/iris/fileformats/pp_load_rules.py b/lib/iris/fileformats/pp_load_rules.py
index 53d9f4dc35..ab99b5c7f8 100644
--- a/lib/iris/fileformats/pp_load_rules.py
+++ b/lib/iris/fileformats/pp_load_rules.py
@@ -580,7 +580,7 @@ def _epoch_date_hours(epoch_hours_unit, datetime):
# numpy.float64. The behaviour of round is to recast this to an
# int, which is not the desired behaviour for PP files.
# So, cast the answer to numpy.float_ to be safe.
- epoch_hours = np.float_(epoch_hours_unit.date2num(datetime))
+ epoch_hours = np.float64(epoch_hours_unit.date2num(datetime))
if days_offset is not None:
# Correct for any modifications to achieve a valid date.
diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py
index 4a85e5cdb2..b2eebc4f03 100644
--- a/lib/iris/tests/__init__.py
+++ b/lib/iris/tests/__init__.py
@@ -483,26 +483,26 @@ def assertDataAlmostEqual(self, data, reference_filename, **kwargs):
stats.get("max", 0.0),
stats.get("min", 0.0),
),
- dtype=np.float_,
+ dtype=np.float64,
)
if math.isnan(stats.get("mean", 0.0)):
self.assertTrue(math.isnan(data.mean()))
else:
data_stats = np.array(
(data.mean(), data.std(), data.max(), data.min()),
- dtype=np.float_,
+ dtype=np.float64,
)
self.assertArrayAllClose(nstats, data_stats, **kwargs)
else:
self._ensure_folder(reference_path)
stats = collections.OrderedDict(
[
- ("std", np.float_(data.std())),
- ("min", np.float_(data.min())),
- ("max", np.float_(data.max())),
+ ("std", np.float64(data.std())),
+ ("min", np.float64(data.min())),
+ ("max", np.float64(data.max())),
("shape", data.shape),
("masked", ma.is_masked(data)),
- ("mean", np.float_(data.mean())),
+ ("mean", np.float64(data.mean())),
]
)
with open(reference_path, "w") as reference_file:
diff --git a/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py b/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py
index 5dc258dfb4..fa2da8e60c 100644
--- a/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py
+++ b/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py
@@ -675,7 +675,7 @@ def test_rotated(self):
[100, 100, 100, 100, 100, 100, 100, 100, 100],
[100, 100, 100, 100, 100, 100, 100, 100, 100],
],
- dtype=np.float,
+ dtype=np.float64,
)
c1_areasum = _cube_area_sum(c1)
@@ -715,7 +715,7 @@ def test_rotated(self):
[100, 100, 199, 199, 100],
[100, 100, 199, 199, 199],
],
- dtype=np.float,
+ dtype=np.float64,
)
c2_areasum = _cube_area_sum(c2)
@@ -770,7 +770,7 @@ def test_missing_data_rotated(self):
[100, 100, 100, 100, 100, 100, 100, 100, 100],
[100, 100, 100, 100, 100, 100, 100, 100, 100],
],
- dtype=np.float,
+ dtype=np.float64,
)
if do_add_missing:
diff --git a/lib/iris/tests/test_cell.py b/lib/iris/tests/test_cell.py
index d6c6ace808..4690cedfa6 100644
--- a/lib/iris/tests/test_cell.py
+++ b/lib/iris/tests/test_cell.py
@@ -130,7 +130,7 @@ class Terry:
self.assertEqual(self.d.__ne__(Terry()), NotImplemented)
def test_numpy_int_equality(self):
- dtypes = (np.int, np.int16, np.int32, np.int64)
+ dtypes = (np.int_, np.int16, np.int32, np.int64)
for dtype in dtypes:
val = dtype(3)
cell = iris.coords.Cell(val, None)
@@ -138,7 +138,7 @@ def test_numpy_int_equality(self):
def test_numpy_float_equality(self):
dtypes = (
- np.float,
+ np.float_,
np.float16,
np.float32,
np.float64,
diff --git a/lib/iris/tests/test_concatenate.py b/lib/iris/tests/test_concatenate.py
index d45a884a2f..1f6c5c3843 100644
--- a/lib/iris/tests/test_concatenate.py
+++ b/lib/iris/tests/test_concatenate.py
@@ -415,7 +415,7 @@ def test_concat_masked_2x2d(self):
self.assertEqual(result[0].shape, (2, 4))
mask = np.array(
[[True, False, False, True], [False, True, True, False]],
- dtype=np.bool,
+ dtype=np.bool_,
)
self.assertArrayEqual(result[0].data.mask, mask)
@@ -436,7 +436,7 @@ def test_concat_masked_2y2d(self):
self.assertEqual(result[0].shape, (4, 2))
mask = np.array(
[[True, False], [False, True], [False, True], [True, False]],
- dtype=np.bool,
+ dtype=np.bool_,
)
self.assertArrayEqual(result[0].data.mask, mask)
@@ -458,7 +458,7 @@ def test_concat_masked_2y2d_with_concrete_and_lazy(self):
self.assertEqual(result[0].shape, (4, 2))
mask = np.array(
[[True, False], [False, True], [False, True], [True, False]],
- dtype=np.bool,
+ dtype=np.bool_,
)
self.assertArrayEqual(result[0].data.mask, mask)
@@ -480,7 +480,7 @@ def test_concat_masked_2y2d_with_lazy_and_concrete(self):
self.assertEqual(result[0].shape, (4, 2))
mask = np.array(
[[True, False], [False, True], [False, True], [True, False]],
- dtype=np.bool,
+ dtype=np.bool_,
)
self.assertArrayEqual(result[0].data.mask, mask)
diff --git a/lib/iris/tests/test_merge.py b/lib/iris/tests/test_merge.py
index e404216143..185beb1bae 100644
--- a/lib/iris/tests/test_merge.py
+++ b/lib/iris/tests/test_merge.py
@@ -468,7 +468,7 @@ def _make_cube(self, a, b, c, d, data=0):
)
for name, value in zip(["a", "b", "c", "d"], [a, b, c, d]):
- dtype = np.str if isinstance(value, str) else np.float32
+ dtype = np.str_ if isinstance(value, str) else np.float32
cube.add_aux_coord(
AuxCoord(
np.array([value], dtype=dtype), long_name=name, units="1"
@@ -613,7 +613,7 @@ def _make_cube(self, a, b, data=0, a_dim=False, b_dim=False):
)
for name, value, dim in zip(["a", "b"], [a, b], [a_dim, b_dim]):
- dtype = np.str if isinstance(value, str) else np.float32
+ dtype = np.str_ if isinstance(value, str) else np.float32
ctype = DimCoord if dim else AuxCoord
coord = ctype(
np.array([value], dtype=dtype), long_name=name, units="1"
diff --git a/lib/iris/tests/unit/analysis/cartography/test_rotate_winds.py b/lib/iris/tests/unit/analysis/cartography/test_rotate_winds.py
index 8ac86da7ec..0741a24926 100644
--- a/lib/iris/tests/unit/analysis/cartography/test_rotate_winds.py
+++ b/lib/iris/tests/unit/analysis/cartography/test_rotate_winds.py
@@ -431,7 +431,7 @@ def test_rotated_to_osgb(self):
[1, 1, 1, 1, 1, 0, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 0, 0, 1, 1, 1],
],
- np.bool,
+ np.bool_,
)
self.assertArrayEqual(expected_mask, ut.data.mask)
self.assertArrayEqual(expected_mask, vt.data.mask)
diff --git a/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py b/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py
index f1e385731a..5c7b5ea7d4 100644
--- a/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py
+++ b/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py
@@ -266,7 +266,7 @@ def _regrid(self, data, method, extrapolation_mode=None):
def test_default_ndarray(self):
# NaN -> NaN
# Extrapolated -> NaN
- data = np.arange(12, dtype=np.float).reshape(3, 4)
+ data = np.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
for method in self.methods:
result = self._regrid(data, method)
@@ -278,7 +278,7 @@ def test_default_maskedarray(self):
# NaN -> NaN
# Extrapolated -> Masked
# Masked -> Masked
- data = ma.arange(12, dtype=np.float).reshape(3, 4)
+ data = ma.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
data[2, 3] = ma.masked
for method in self.methods:
@@ -293,7 +293,7 @@ def test_default_maskedarray_none_masked(self):
# NaN -> NaN
# Extrapolated -> Masked
# Masked -> N/A
- data = ma.arange(12, dtype=np.float).reshape(3, 4)
+ data = ma.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
for method in self.methods:
result = self._regrid(data, method)
@@ -307,7 +307,7 @@ def test_default_maskedarray_none_masked_expanded(self):
# NaN -> NaN
# Extrapolated -> Masked
# Masked -> N/A
- data = ma.arange(12, dtype=np.float).reshape(3, 4)
+ data = ma.arange(12, dtype=np.float64).reshape(3, 4)
# Make sure the mask has been expanded
data.mask = False
data[0, 0] = np.nan
@@ -322,7 +322,7 @@ def test_default_maskedarray_none_masked_expanded(self):
def test_method_ndarray(self):
# NaN -> NaN
# Extrapolated -> linear
- data = np.arange(12, dtype=np.float).reshape(3, 4)
+ data = np.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
for method in self.methods:
result = self._regrid(data, method, "extrapolate")
@@ -334,7 +334,7 @@ def test_method_maskedarray(self):
# NaN -> NaN
# Extrapolated -> linear
# Masked -> Masked
- data = ma.arange(12, dtype=np.float).reshape(3, 4)
+ data = ma.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
data[2, 3] = ma.masked
for method in self.methods:
@@ -348,7 +348,7 @@ def test_method_maskedarray(self):
def test_nan_ndarray(self):
# NaN -> NaN
# Extrapolated -> NaN
- data = np.arange(12, dtype=np.float).reshape(3, 4)
+ data = np.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
for method in self.methods:
result = self._regrid(data, method, "nan")
@@ -360,7 +360,7 @@ def test_nan_maskedarray(self):
# NaN -> NaN
# Extrapolated -> NaN
# Masked -> Masked
- data = ma.arange(12, dtype=np.float).reshape(3, 4)
+ data = ma.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
data[2, 3] = ma.masked
for method in self.methods:
@@ -373,7 +373,7 @@ def test_nan_maskedarray(self):
def test_error_ndarray(self):
# Values irrelevant - the function raises an error.
- data = np.arange(12, dtype=np.float).reshape(3, 4)
+ data = np.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
for method in self.methods:
with self.assertRaisesRegex(ValueError, "out of bounds"):
@@ -381,7 +381,7 @@ def test_error_ndarray(self):
def test_error_maskedarray(self):
# Values irrelevant - the function raises an error.
- data = ma.arange(12, dtype=np.float).reshape(3, 4)
+ data = ma.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
data[2, 3] = ma.masked
for method in self.methods:
@@ -392,7 +392,7 @@ def test_mask_ndarray(self):
# NaN -> NaN
# Extrapolated -> Masked (this is different from all the other
# modes)
- data = np.arange(12, dtype=np.float).reshape(3, 4)
+ data = np.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
for method in self.methods:
result = self._regrid(data, method, "mask")
@@ -406,7 +406,7 @@ def test_mask_maskedarray(self):
# NaN -> NaN
# Extrapolated -> Masked
# Masked -> Masked
- data = ma.arange(12, dtype=np.float).reshape(3, 4)
+ data = ma.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
data[2, 3] = ma.masked
for method in self.methods:
@@ -420,7 +420,7 @@ def test_mask_maskedarray(self):
def test_nanmask_ndarray(self):
# NaN -> NaN
# Extrapolated -> NaN
- data = np.arange(12, dtype=np.float).reshape(3, 4)
+ data = np.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
for method in self.methods:
result = self._regrid(data, method, "nanmask")
@@ -432,7 +432,7 @@ def test_nanmask_maskedarray(self):
# NaN -> NaN
# Extrapolated -> Masked
# Masked -> Masked
- data = ma.arange(12, dtype=np.float).reshape(3, 4)
+ data = ma.arange(12, dtype=np.float64).reshape(3, 4)
data[0, 0] = np.nan
data[2, 3] = ma.masked
for method in self.methods:
@@ -444,7 +444,7 @@ def test_nanmask_maskedarray(self):
self.assertMaskedArrayEqual(result, expected)
def test_invalid(self):
- data = np.arange(12, dtype=np.float).reshape(3, 4)
+ data = np.arange(12, dtype=np.float64).reshape(3, 4)
emsg = "Invalid extrapolation mode"
for method in self.methods:
with self.assertRaisesRegex(ValueError, emsg):
diff --git a/lib/iris/tests/unit/aux_factory/test_OceanSFactory.py b/lib/iris/tests/unit/aux_factory/test_OceanSFactory.py
index 6e8e40cd1b..a5cb5480a0 100644
--- a/lib/iris/tests/unit/aux_factory/test_OceanSFactory.py
+++ b/lib/iris/tests/unit/aux_factory/test_OceanSFactory.py
@@ -195,12 +195,12 @@ def setUp(self):
np.arange(-0.975, 0, 0.05, dtype=float), units="1", long_name="s"
)
self.eta = AuxCoord(
- np.arange(-1, 3, dtype=np.float).reshape(2, 2),
+ np.arange(-1, 3, dtype=np.float64).reshape(2, 2),
long_name="eta",
units="m",
)
self.depth = AuxCoord(
- np.arange(4, dtype=np.float).reshape(2, 2) * 1e3,
+ np.arange(4, dtype=np.float64).reshape(2, 2) * 1e3,
long_name="depth",
units="m",
)
diff --git a/lib/iris/tests/unit/aux_factory/test_OceanSg1Factory.py b/lib/iris/tests/unit/aux_factory/test_OceanSg1Factory.py
index 238df2f073..321a013ef8 100644
--- a/lib/iris/tests/unit/aux_factory/test_OceanSg1Factory.py
+++ b/lib/iris/tests/unit/aux_factory/test_OceanSg1Factory.py
@@ -179,12 +179,12 @@ def setUp(self):
np.linspace(-0.959, -0.001, 36), units="1", long_name="c"
)
self.eta = AuxCoord(
- np.arange(-1, 3, dtype=np.float).reshape(2, 2),
+ np.arange(-1, 3, dtype=np.float64).reshape(2, 2),
long_name="eta",
units="m",
)
self.depth = AuxCoord(
- np.array([[5, 200], [1000, 4000]], dtype=np.float),
+ np.array([[5, 200], [1000, 4000]], dtype=np.float64),
long_name="depth",
units="m",
)
diff --git a/lib/iris/tests/unit/aux_factory/test_OceanSg2Factory.py b/lib/iris/tests/unit/aux_factory/test_OceanSg2Factory.py
index fb3ada382e..d16285cd5d 100644
--- a/lib/iris/tests/unit/aux_factory/test_OceanSg2Factory.py
+++ b/lib/iris/tests/unit/aux_factory/test_OceanSg2Factory.py
@@ -179,12 +179,12 @@ def setUp(self):
np.linspace(-0.959, -0.001, 36), units="1", long_name="c"
)
self.eta = AuxCoord(
- np.arange(-1, 3, dtype=np.float).reshape(2, 2),
+ np.arange(-1, 3, dtype=np.float64).reshape(2, 2),
long_name="eta",
units="m",
)
self.depth = AuxCoord(
- np.array([[5, 200], [1000, 4000]], dtype=np.float),
+ np.array([[5, 200], [1000, 4000]], dtype=np.float64),
long_name="depth",
units="m",
)
diff --git a/lib/iris/tests/unit/aux_factory/test_OceanSigmaFactory.py b/lib/iris/tests/unit/aux_factory/test_OceanSigmaFactory.py
index 69a8a32c6e..d4c0a33fdf 100644
--- a/lib/iris/tests/unit/aux_factory/test_OceanSigmaFactory.py
+++ b/lib/iris/tests/unit/aux_factory/test_OceanSigmaFactory.py
@@ -102,12 +102,12 @@ def setUp(self):
np.linspace(-0.05, -1, 5), long_name="sigma", units="1"
)
self.eta = AuxCoord(
- np.arange(-1, 3, dtype=np.float).reshape(2, 2),
+ np.arange(-1, 3, dtype=np.float64).reshape(2, 2),
long_name="eta",
units="m",
)
self.depth = AuxCoord(
- np.arange(4, dtype=np.float).reshape(2, 2) * 1e3,
+ np.arange(4, dtype=np.float64).reshape(2, 2) * 1e3,
long_name="depth",
units="m",
)
diff --git a/lib/iris/tests/unit/aux_factory/test_OceanSigmaZFactory.py b/lib/iris/tests/unit/aux_factory/test_OceanSigmaZFactory.py
index 4a4e30b9ca..b8a574258d 100644
--- a/lib/iris/tests/unit/aux_factory/test_OceanSigmaZFactory.py
+++ b/lib/iris/tests/unit/aux_factory/test_OceanSigmaZFactory.py
@@ -199,22 +199,22 @@ def derive(sigma, eta, depth, depth_c, nsigma, zlev, coord=True):
def setUp(self):
self.sigma = DimCoord(
- np.arange(5, dtype=np.float) * 10, long_name="sigma", units="1"
+ np.arange(5, dtype=np.float64) * 10, long_name="sigma", units="1"
)
self.eta = AuxCoord(
- np.arange(4, dtype=np.float).reshape(2, 2),
+ np.arange(4, dtype=np.float64).reshape(2, 2),
long_name="eta",
units="m",
)
self.depth = AuxCoord(
- np.arange(4, dtype=np.float).reshape(2, 2) * 10,
+ np.arange(4, dtype=np.float64).reshape(2, 2) * 10,
long_name="depth",
units="m",
)
self.depth_c = AuxCoord([15], long_name="depth_c", units="m")
self.nsigma = AuxCoord([3], long_name="nsigma")
self.zlev = DimCoord(
- np.arange(5, dtype=np.float) * 10, long_name="zlev", units="m"
+ np.arange(5, dtype=np.float64) * 10, long_name="zlev", units="m"
)
self.kwargs = dict(
sigma=self.sigma,
diff --git a/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py b/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py
index 71fabe6c73..4ff8ec0de6 100644
--- a/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py
+++ b/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py
@@ -1074,8 +1074,8 @@ def setUp(self):
self.values = OrderedDict(
one=sentinel.one,
two=sentinel.two,
- three=np.float(3.14),
- four=np.arange(10, dtype=np.float),
+ three=np.float64(3.14),
+ four=np.arange(10, dtype=np.float64),
five=ma.arange(10, dtype=np.int16),
)
self.cls = BaseMetadata
diff --git a/lib/iris/tests/unit/common/metadata/test__hexdigest.py b/lib/iris/tests/unit/common/metadata/test__hexdigest.py
index 798f71bcd0..546327a21b 100644
--- a/lib/iris/tests/unit/common/metadata/test__hexdigest.py
+++ b/lib/iris/tests/unit/common/metadata/test__hexdigest.py
@@ -49,18 +49,18 @@ def test_string(self):
self.assertEqual(expected, hexdigest(value))
def test_numpy_array_int(self):
- value = np.arange(10, dtype=np.int)
+ value = np.arange(10, dtype=np.int_)
expected = self._ndarray(value)
self.assertEqual(expected, hexdigest(value))
def test_numpy_array_float(self):
- value = np.arange(10, dtype=np.float)
+ value = np.arange(10, dtype=np.float64)
expected = self._ndarray(value)
self.assertEqual(expected, hexdigest(value))
def test_numpy_array_float_not_int(self):
- ivalue = np.arange(10, dtype=np.int)
- fvalue = np.arange(10, dtype=np.float)
+ ivalue = np.arange(10, dtype=np.int_)
+ fvalue = np.arange(10, dtype=np.float64)
expected = self._ndarray(ivalue)
self.assertNotEqual(expected, hexdigest(fvalue))
@@ -75,7 +75,7 @@ def test_numpy_array_reshape_not_flat(self):
self.assertNotEqual(expected, hexdigest(value.flatten()))
def test_masked_array_int(self):
- value = ma.arange(10, dtype=np.int)
+ value = ma.arange(10, dtype=np.int_)
expected = self._masked(value)
self.assertEqual(expected, hexdigest(value))
@@ -85,7 +85,7 @@ def test_masked_array_int(self):
self.assertEqual(expected, hexdigest(value))
def test_masked_array_float(self):
- value = ma.arange(10, dtype=np.float)
+ value = ma.arange(10, dtype=np.float64)
expected = self._masked(value)
self.assertEqual(expected, hexdigest(value))
@@ -95,8 +95,8 @@ def test_masked_array_float(self):
self.assertEqual(expected, hexdigest(value))
def test_masked_array_float_not_int(self):
- ivalue = ma.arange(10, dtype=np.int)
- fvalue = ma.arange(10, dtype=np.float)
+ ivalue = ma.arange(10, dtype=np.int_)
+ fvalue = ma.arange(10, dtype=np.float64)
expected = self._masked(ivalue)
self.assertNotEqual(expected, hexdigest(fvalue))
@@ -127,7 +127,7 @@ def test_int(self):
self.assertEqual(expected, hexdigest(value))
def test_numpy_int(self):
- value = np.int(123)
+ value = int(123)
expected = self._expected(value)
self.assertEqual(expected, hexdigest(value))
@@ -137,7 +137,7 @@ def test_float(self):
self.assertEqual(expected, hexdigest(value))
def test_numpy_float(self):
- value = np.float(123.4)
+ value = float(123.4)
expected = self._expected(value)
self.assertEqual(expected, hexdigest(value))
diff --git a/lib/iris/tests/unit/experimental/regrid/test_regrid_weighted_curvilinear_to_rectilinear.py b/lib/iris/tests/unit/experimental/regrid/test_regrid_weighted_curvilinear_to_rectilinear.py
index f61b489c2b..6b8064faca 100644
--- a/lib/iris/tests/unit/experimental/regrid/test_regrid_weighted_curvilinear_to_rectilinear.py
+++ b/lib/iris/tests/unit/experimental/regrid/test_regrid_weighted_curvilinear_to_rectilinear.py
@@ -37,7 +37,7 @@ def setUp(self):
# Source cube.
self.test_src_name = "air_temperature"
self.test_src_units = "K"
- self.test_src_data = ma.arange(1, 13, dtype=np.float).reshape(3, 4)
+ self.test_src_data = ma.arange(1, 13, dtype=np.float64).reshape(3, 4)
self.test_src_attributes = dict(wibble="wobble")
self.test_scalar_coord = iris.coords.DimCoord(
[1], long_name="test_scalar_coord"
@@ -135,7 +135,7 @@ def setUp(self):
)
def _weighted_mean(self, points):
- points = np.asarray(points, dtype=np.float)
+ points = np.asarray(points, dtype=np.float64)
weights = points * self.weight_factor
numerator = denominator = 0
for point, weight in zip(points, weights):
diff --git a/lib/iris/tests/unit/fileformats/cf/test_CFReader.py b/lib/iris/tests/unit/fileformats/cf/test_CFReader.py
index 7d4bf232fc..26296daccf 100644
--- a/lib/iris/tests/unit/fileformats/cf/test_CFReader.py
+++ b/lib/iris/tests/unit/fileformats/cf/test_CFReader.py
@@ -59,7 +59,7 @@ def netcdf_variable(
class Test_translate__global_attributes(tests.IrisTest):
def setUp(self):
- ncvar = netcdf_variable("ncvar", "height", np.float)
+ ncvar = netcdf_variable("ncvar", "height", np.float64)
ncattrs = mock.Mock(return_value=["dimensions"])
getncattr = mock.Mock(return_value="something something_else")
self.dataset = mock.Mock(
@@ -80,24 +80,24 @@ def test_create_global_attributes(self):
class Test_translate__formula_terms(tests.IrisTest):
def setUp(self):
self.delta = netcdf_variable(
- "delta", "height", np.float, bounds="delta_bnds"
+ "delta", "height", np.float64, bounds="delta_bnds"
)
self.delta_bnds = netcdf_variable(
"delta_bnds", "height bnds", np.float
)
self.sigma = netcdf_variable(
- "sigma", "height", np.float, bounds="sigma_bnds"
+ "sigma", "height", np.float64, bounds="sigma_bnds"
)
self.sigma_bnds = netcdf_variable(
"sigma_bnds", "height bnds", np.float
)
- self.orography = netcdf_variable("orography", "lat lon", np.float)
+ self.orography = netcdf_variable("orography", "lat lon", np.float64)
formula_terms = "a: delta b: sigma orog: orography"
standard_name = "atmosphere_hybrid_height_coordinate"
self.height = netcdf_variable(
"height",
"height",
- np.float,
+ np.float64,
formula_terms=formula_terms,
bounds="height_bnds",
standard_name=standard_name,
@@ -106,13 +106,16 @@ def setUp(self):
# which will be ignored by the cf loader.
formula_terms = "a: delta_bnds b: sigma_bnds orog: orography"
self.height_bnds = netcdf_variable(
- "height_bnds", "height bnds", np.float, formula_terms=formula_terms
+ "height_bnds",
+ "height bnds",
+ np.float64,
+ formula_terms=formula_terms,
)
- self.lat = netcdf_variable("lat", "lat", np.float)
- self.lon = netcdf_variable("lon", "lon", np.float)
+ self.lat = netcdf_variable("lat", "lat", np.float64)
+ self.lon = netcdf_variable("lon", "lon", np.float64)
# Note that, only lat and lon are explicitly associated as coordinates.
self.temp = netcdf_variable(
- "temp", "height lat lon", np.float, coordinates="lat lon"
+ "temp", "height lat lon", np.float64, coordinates="lat lon"
)
self.variables = dict(
@@ -179,24 +182,24 @@ def test_create_formula_terms(self):
class Test_build_cf_groups__formula_terms(tests.IrisTest):
def setUp(self):
self.delta = netcdf_variable(
- "delta", "height", np.float, bounds="delta_bnds"
+ "delta", "height", np.float64, bounds="delta_bnds"
)
self.delta_bnds = netcdf_variable(
"delta_bnds", "height bnds", np.float
)
self.sigma = netcdf_variable(
- "sigma", "height", np.float, bounds="sigma_bnds"
+ "sigma", "height", np.float64, bounds="sigma_bnds"
)
self.sigma_bnds = netcdf_variable(
"sigma_bnds", "height bnds", np.float
)
- self.orography = netcdf_variable("orography", "lat lon", np.float)
+ self.orography = netcdf_variable("orography", "lat lon", np.float64)
formula_terms = "a: delta b: sigma orog: orography"
standard_name = "atmosphere_hybrid_height_coordinate"
self.height = netcdf_variable(
"height",
"height",
- np.float,
+ np.float64,
formula_terms=formula_terms,
bounds="height_bnds",
standard_name=standard_name,
@@ -205,15 +208,18 @@ def setUp(self):
# which will be ignored by the cf loader.
formula_terms = "a: delta_bnds b: sigma_bnds orog: orography"
self.height_bnds = netcdf_variable(
- "height_bnds", "height bnds", np.float, formula_terms=formula_terms
+ "height_bnds",
+ "height bnds",
+ np.float64,
+ formula_terms=formula_terms,
)
- self.lat = netcdf_variable("lat", "lat", np.float)
- self.lon = netcdf_variable("lon", "lon", np.float)
- self.x = netcdf_variable("x", "lat lon", np.float)
- self.y = netcdf_variable("y", "lat lon", np.float)
+ self.lat = netcdf_variable("lat", "lat", np.float64)
+ self.lon = netcdf_variable("lon", "lon", np.float64)
+ self.x = netcdf_variable("x", "lat lon", np.float64)
+ self.y = netcdf_variable("y", "lat lon", np.float64)
# Note that, only lat and lon are explicitly associated as coordinates.
self.temp = netcdf_variable(
- "temp", "height lat lon", np.float, coordinates="x y"
+ "temp", "height lat lon", np.float64, coordinates="x y"
)
self.variables = dict(
@@ -332,7 +338,7 @@ def test_auxiliary_ignore(self):
self.assertEqual(warn.call_count, 1)
def test_promoted_auxiliary_ignore(self):
- self.wibble = netcdf_variable("wibble", "lat wibble", np.float)
+ self.wibble = netcdf_variable("wibble", "lat wibble", np.float64)
self.variables["wibble"] = self.wibble
self.orography.coordinates = "wibble"
with mock.patch(
diff --git a/lib/iris/tests/unit/fileformats/pp/test_PPField.py b/lib/iris/tests/unit/fileformats/pp/test_PPField.py
index 7c3ef33182..20a431994c 100644
--- a/lib/iris/tests/unit/fileformats/pp/test_PPField.py
+++ b/lib/iris/tests/unit/fileformats/pp/test_PPField.py
@@ -199,8 +199,8 @@ def test_odd_bplon_rotated(self):
class Test__init__(tests.IrisTest):
def setUp(self):
- header_longs = np.zeros(pp.NUM_LONG_HEADERS, dtype=np.int)
- header_floats = np.zeros(pp.NUM_FLOAT_HEADERS, dtype=np.float)
+ header_longs = np.zeros(pp.NUM_LONG_HEADERS, dtype=np.int_)
+ header_floats = np.zeros(pp.NUM_FLOAT_HEADERS, dtype=np.float64)
self.header = list(header_longs) + list(header_floats)
def test_no_headers(self):
@@ -232,8 +232,8 @@ def test_raw_lbpack(self):
class Test__getattr__(tests.IrisTest):
def setUp(self):
- header_longs = np.zeros(pp.NUM_LONG_HEADERS, dtype=np.int)
- header_floats = np.zeros(pp.NUM_FLOAT_HEADERS, dtype=np.float)
+ header_longs = np.zeros(pp.NUM_LONG_HEADERS, dtype=np.int_)
+ header_floats = np.zeros(pp.NUM_FLOAT_HEADERS, dtype=np.float64)
self.header = list(header_longs) + list(header_floats)
def test_attr_singular_long(self):
diff --git a/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py b/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py
index b6b9cb3263..8bf9a0435b 100644
--- a/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py
+++ b/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py
@@ -32,7 +32,7 @@ def setUp(self):
decompressed = np.arange(data_len).reshape(*self.data_shape)
decompressed *= np.arange(self.data_shape[1]) % 3 + 1
- decompressed_mask = np.zeros(self.data_shape, np.bool)
+ decompressed_mask = np.zeros(self.data_shape, np.bool_)
decompressed_mask[
y_halo + rim : -(y_halo + rim), x_halo + rim : -(x_halo + rim)
] = True
@@ -81,7 +81,7 @@ def setUp(self):
self.land = np.array(
[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1]], dtype=np.float64
)
- sea = ~self.land.astype(np.bool)
+ sea = ~self.land.astype(np.bool_)
self.land_masked_data = np.array([1, 3, 4.5])
self.sea_masked_data = np.array([1, 3, 4.5, -4, 5, 0, 1, 2, 3])
diff --git a/lib/iris/tests/unit/lazy_data/test_lazy_elementwise.py b/lib/iris/tests/unit/lazy_data/test_lazy_elementwise.py
index c8aebc34e4..f02b86cf33 100644
--- a/lib/iris/tests/unit/lazy_data/test_lazy_elementwise.py
+++ b/lib/iris/tests/unit/lazy_data/test_lazy_elementwise.py
@@ -44,7 +44,7 @@ def test_dtype_change(self):
lazy_array = as_lazy_data(concrete_array)
wrapped = lazy_elementwise(lazy_array, _test_elementwise_op)
self.assertTrue(is_lazy_data(wrapped))
- self.assertEqual(wrapped.dtype, np.int)
+ self.assertEqual(wrapped.dtype, np.int_)
self.assertEqual(wrapped.compute().dtype, wrapped.dtype)
From 48b8e2488d4576b1afacefafffad3a609ec903d7 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Wed, 17 Feb 2021 11:42:13 +0000
Subject: [PATCH 16/43] celebrate first time iris contributors (#4013)
---
docs/src/whatsnew/latest.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index 5a7f682c23..181c1d3d7f 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -27,6 +27,11 @@ This document explains the changes made to Iris for this release
#. Congratulations to `@jamesp`_ who recently became an Iris core developer
after joining the Iris development team at the `Met Office`_. 🎉
+#. A special thanks goes to `@akuhnregnier`_, `@gcaria`_, `@jamesp`_ and
+ `@MHBalsmeier`_ all of whom made their first contributions to Iris, which
+ were gratefully received and included in this release. Keep up the awesome
+ work! 🍻
+
✨ Features
===========
From 065970a0acf9ca60886023c146a45616c19d09df Mon Sep 17 00:00:00 2001
From: tkknight <2108488+tkknight@users.noreply.github.com>
Date: Sat, 20 Feb 2021 21:50:07 +0000
Subject: [PATCH 17/43] Docs unreleased banner (#3999)
* baseline
* removed debug comments
* reverted
* remove line
* Testing
* testing extensions
* testing rtd_version
* fixed if
* removed line
* tidy up
* tidy comments
* debug of pre-existing rtd variables
* added reminder
* testing
* testing still
* updated comments
* added whatsnew
* expanded the if conditiion
* review actions
* Update layout.html
Remove alternative banner that used the RestructuredText notation.
* review actions
---
docs/src/_static/theme_override.css | 14 ++++++++++++++
docs/src/_templates/layout.html | 22 ++++++++++++++++++++++
docs/src/common_links.inc | 1 +
docs/src/conf.py | 10 ++++++----
docs/src/whatsnew/latest.rst | 4 ++++
5 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/docs/src/_static/theme_override.css b/docs/src/_static/theme_override.css
index 5edc286630..c56b720f69 100644
--- a/docs/src/_static/theme_override.css
+++ b/docs/src/_static/theme_override.css
@@ -26,3 +26,17 @@ table.docutils td {
word-wrap: break-word;
}
+/* Used for very strong warning */
+#slim-red-box-message {
+ background: #ff0000;
+ box-sizing: border-box;
+ color: #ffffff;
+ font-weight: normal;
+ padding: 0.5em;
+}
+
+#slim-red-box-message a {
+ color: #ffffff;
+ font-weight: normal;
+ text-decoration:underline;
+}
diff --git a/docs/src/_templates/layout.html b/docs/src/_templates/layout.html
index 9b4983697e..96a2e0913e 100644
--- a/docs/src/_templates/layout.html
+++ b/docs/src/_templates/layout.html
@@ -1,5 +1,27 @@
{% extends "!layout.html" %}
+{# This uses blocks. See:
+ https://www.sphinx-doc.org/en/master/templating.html
+#}
+
+/*---------------------------------------------------------------------------*/
+
+{%- block document %}
+ {% if READTHEDOCS and rtd_version == 'latest' %}
+
+ You are viewing the
latest unreleased documentation
+
v{{ version }}. You may prefer a
+
stable
+ version.
+
+
+ {%- endif %}
+
+ {{ super() }}
+{%- endblock %}
+
+/*-----------------------------------------------------z----------------------*/
+
{% block menu %}
{{ super() }}
diff --git a/docs/src/common_links.inc b/docs/src/common_links.inc
index 3c465b67dc..23a933367e 100644
--- a/docs/src/common_links.inc
+++ b/docs/src/common_links.inc
@@ -24,6 +24,7 @@
.. _New Issue: https://github.com/scitools/iris/issues/new/choose
.. _pull request: https://github.com/SciTools/iris/pulls
.. _pull requests: https://github.com/SciTools/iris/pulls
+.. _Read the Docs: https://scitools-iris.readthedocs.io/en/latest/
.. _readthedocs.yml: https://github.com/SciTools/iris/blob/master/requirements/ci/readthedocs.yml
.. _SciTools: https://github.com/SciTools
.. _sphinx: https://www.sphinx-doc.org/en/master/
diff --git a/docs/src/conf.py b/docs/src/conf.py
index 9bab5850b8..ab05312fca 100644
--- a/docs/src/conf.py
+++ b/docs/src/conf.py
@@ -43,6 +43,9 @@ def autolog(message):
for item, value in os.environ.items():
autolog("[READTHEDOCS] {} = {}".format(item, value))
+# This is the rtd reference to the version, such as: latest, stable, v3.0.1 etc
+# For local testing purposes this could be explicitly set latest or stable.
+rtd_version = os.environ.get("READTHEDOCS_VERSION")
# -- Path setup --------------------------------------------------------------
@@ -131,7 +134,6 @@ def autolog(message):
"custom_data_autodoc",
"generate_package_rst",
]
-
# -- panels extension ---------------------------------------------------------
# See https://sphinx-panels.readthedocs.io/en/latest/
@@ -165,7 +167,7 @@ def autolog(message):
# See https://sphinx-copybutton.readthedocs.io/en/latest/
copybutton_prompt_text = ">>> "
-# sphinx.ext.todo configuration
+# sphinx.ext.todo configuration -----------------------------------------------
# See https://www.sphinx-doc.org/en/master/usage/extensions/todo.html
todo_include_todos = True
@@ -228,6 +230,8 @@ def autolog(message):
}
html_context = {
+ "rtd_version": rtd_version,
+ "version": version,
"copyright_years": copyright_years,
"python_version": build_python_version,
# menu_links and menu_links_name are used in _templates/layout.html
@@ -296,7 +300,6 @@ def autolog(message):
"ignore_pattern": r"__init__\.py",
}
-
# -----------------------------------------------------------------------------
# Remove matplotlib agg warnings from generated doc when using plt.show
warnings.filterwarnings(
@@ -306,7 +309,6 @@ def autolog(message):
" non-GUI backend, so cannot show the figure.",
)
-
# -- numfig options (built-in) ------------------------------------------------
# Enable numfig.
numfig = True
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index 181c1d3d7f..59e75942b0 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -96,6 +96,10 @@ This document explains the changes made to Iris for this release
#. `@bjlittle`_ added the |PyPI|_ badge to the `README.md`_. (:pull:`4004`)
+#. `@tkknight`_ added a banner at the top of every page of the unreleased
+ development documentation if being viewed on `Read the Docs`_.
+ (:pull:`3999`)
+
💼 Internal
===========
From fdfd1c745532c7ed8331a273bebc1b5176108334 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Sat, 20 Feb 2021 22:15:24 +0000
Subject: [PATCH 18/43] drop __unicode__ method usage (#4018)
---
lib/iris/cube.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/lib/iris/cube.py b/lib/iris/cube.py
index 5578507d28..a15951900b 100644
--- a/lib/iris/cube.py
+++ b/lib/iris/cube.py
@@ -2652,9 +2652,6 @@ def vector_summary(
def __str__(self):
return self.summary()
- def __unicode__(self):
- return self.summary()
-
def __repr__(self):
return "" % self.summary(
shorten=True, name_padding=1
From 55be054f9b2d2a65e659892bcb2632359e580105 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Sun, 21 Feb 2021 21:22:18 +0000
Subject: [PATCH 19/43] cirrus-ci conditional tasks (#4019)
* cirrus-ci conditional tasks
* use bc for bash arithmetic
* revert back to sed
* use expr
* reword
* minor documentation changes
* review actions
---
.cirrus.yml | 30 ++++++--
docs/src/common_links.inc | 1 +
.../contributing_ci_tests.rst | 74 ++++++++++++++-----
.../contributing_code_formatting.rst | 2 -
docs/src/whatsnew/latest.rst | 4 +
5 files changed, 85 insertions(+), 26 deletions(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index 3f9e45b5ea..0a7c972821 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -18,6 +18,16 @@ container:
env:
+ # Skip specific tasks by name. Set to a non-empty string to skip.
+ SKIP_LINT_TASK: ""
+ SKIP_TEST_MINIMAL_TASK: ""
+ SKIP_TEST_FULL_TASK: ""
+ SKIP_GALLERY_TASK: ""
+ SKIP_DOCTEST_TASK: ""
+ SKIP_LINKCHECK_TASK: ""
+ # Skip task groups by type. Set to a non-empty string to skip.
+ SKIP_ALL_TEST_TASKS: ""
+ SKIP_ALL_DOC_TASKS: ""
# Maximum cache period (in weeks) before forcing a new cache upload.
CACHE_PERIOD: "2"
# Increment the build number to force new cartopy cache upload.
@@ -50,7 +60,7 @@ linux_task_template: &LINUX_TASK_TEMPLATE
fingerprint_script:
- wget --quiet https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
- echo "${CIRRUS_OS} $(sha256sum miniconda.sh)"
- - echo "$(date +%Y).$(($(date +%U) / ${CACHE_PERIOD})):${CONDA_CACHE_BUILD}"
+ - echo "$(date +%Y).$(expr $(date +%U) / ${CACHE_PERIOD}):${CONDA_CACHE_BUILD}"
populate_script:
- bash miniconda.sh -b -p ${HOME}/miniconda
- conda config --set always_yes yes --set changeps1 no
@@ -62,12 +72,12 @@ linux_task_template: &LINUX_TASK_TEMPLATE
folder: ${HOME}/.local/share/cartopy
fingerprint_script:
- echo "${CIRRUS_OS}"
- - echo "$(date +%Y).$(($(date +%U) / ${CACHE_PERIOD})):${CARTOPY_CACHE_BUILD}"
+ - echo "$(date +%Y).$(expr $(date +%U) / ${CACHE_PERIOD}):${CARTOPY_CACHE_BUILD}"
nox_cache:
folder: ${CIRRUS_WORKING_DIR}/.nox
fingerprint_script:
- echo "${CIRRUS_TASK_NAME}"
- - echo "$(date +%Y).$(($(date +%U) / ${CACHE_PERIOD})):${NOX_CACHE_BUILD}"
+ - echo "$(date +%Y).$(expr $(date +%U) / ${CACHE_PERIOD}):${NOX_CACHE_BUILD}"
- sha256sum ${CIRRUS_WORKING_DIR}/requirements/ci/py$(echo ${PY_VER} | tr -d ".").yml
@@ -82,6 +92,7 @@ compute_credits_template: &CREDITS_TEMPLATE
# Linting
#
lint_task:
+ only_if: $SKIP_LINT_TASK == ""
<< : *CREDITS_TEMPLATE
auto_cancellation: true
name: "${CIRRUS_OS}: flake8 and black"
@@ -89,7 +100,7 @@ lint_task:
folder: ~/.cache/pip
fingerprint_script:
- echo "${CIRRUS_TASK_NAME}"
- - echo "$(date +%Y).$(($(date +%U) / ${CACHE_PERIOD})):${PIP_CACHE_BUILD} ${PIP_CACHE_PACKAGES}"
+ - echo "$(date +%Y).$(expr $(date +%U) / ${CACHE_PERIOD}):${PIP_CACHE_BUILD} ${PIP_CACHE_PACKAGES}"
lint_script:
- pip list
- python -m pip install --retries 3 --upgrade ${PIP_CACHE_PACKAGES}
@@ -101,7 +112,8 @@ lint_task:
#
# Testing Minimal (Linux)
#
-linux_minimal_task:
+test_minimal_task:
+ only_if: $SKIP_TEST_MINIMAL_TASK == "" && $SKIP_ALL_TEST_TASKS == ""
<< : *CREDITS_TEMPLATE
matrix:
env:
@@ -125,7 +137,8 @@ linux_minimal_task:
#
# Testing Full (Linux)
#
-linux_task:
+test_full_task:
+ only_if: $SKIP_TEST_FULL_TASK == "" && $SKIP_ALL_TEST_TASKS == ""
<< : *CREDITS_TEMPLATE
matrix:
env:
@@ -159,6 +172,7 @@ linux_task:
# Testing Documentation Gallery (Linux)
#
gallery_task:
+ only_if: $SKIP_GALLERY_TASK == "" && $SKIP_ALL_DOC_TASKS == ""
<< : *CREDITS_TEMPLATE
matrix:
env:
@@ -188,6 +202,7 @@ gallery_task:
# Testing Documentation (Linux)
#
doctest_task:
+ only_if: $SKIP_DOCTEST_TASK == "" && $SKIP_ALL_DOC_TASKS == ""
<< : *CREDITS_TEMPLATE
matrix:
env:
@@ -222,7 +237,8 @@ doctest_task:
#
# Testing Documentation Link Check (Linux)
#
-link_task:
+linkcheck_task:
+ only_if: $SKIP_LINKCHECK_TASK == "" && $SKIP_ALL_DOC_TASKS == ""
<< : *CREDITS_TEMPLATE
matrix:
env:
diff --git a/docs/src/common_links.inc b/docs/src/common_links.inc
index 23a933367e..d9df15be8b 100644
--- a/docs/src/common_links.inc
+++ b/docs/src/common_links.inc
@@ -3,6 +3,7 @@
.. _black: https://black.readthedocs.io/en/stable/
.. _.cirrus.yml: https://github.com/SciTools/iris/blob/master/.cirrus.yml
+.. _flake8: https://flake8.pycqa.org/en/stable/
.. _.flake8.yml: https://github.com/SciTools/iris/blob/master/.flake8
.. _cirrus-ci: https://cirrus-ci.com/github/SciTools/iris
.. _conda: https://docs.conda.io/en/latest/
diff --git a/docs/src/developers_guide/contributing_ci_tests.rst b/docs/src/developers_guide/contributing_ci_tests.rst
index a6bdac4ae0..8594612fe1 100644
--- a/docs/src/developers_guide/contributing_ci_tests.rst
+++ b/docs/src/developers_guide/contributing_ci_tests.rst
@@ -5,9 +5,9 @@
Continuous Integration (CI) Testing
===================================
-The `Iris`_ GitHub repository is configured to run checks on the code
-automatically when a pull request is created, updated or merged against
-Iris **master**. The checks performed are:
+The `Iris`_ GitHub repository is configured to run checks against all its
+branches automatically whenever a pull request is created, updated or merged.
+The checks performed are:
* :ref:`testing_cla`
* :ref:`testing_cirrus`
@@ -18,9 +18,9 @@ Iris **master**. The checks performed are:
SciTools CLA Checker
********************
-A bot that checks the user who created the pull request has signed the
-**Contributor's License Agreement (CLA)**. For more information on this this
-please see https://scitools.org.uk/organisation.html#governance
+A bot which checks that the GitHub author of the pull request has signed the
+**SciTools Contributor's License Agreement (CLA)**. For more information on
+this please see https://scitools.org.uk/organisation.html#governance.
.. _testing_cirrus:
@@ -28,19 +28,55 @@ please see https://scitools.org.uk/organisation.html#governance
Cirrus-CI
*********
-The unit and integration tests in Iris are an essential mechanism to ensure
+Iris unit and integration tests are an essential mechanism to ensure
that the Iris code base is working as expected. :ref:`developer_running_tests`
-may be run manually but to ensure the checks are performed a
-continuous integration testing tool named `cirrus-ci`_ is used.
+may be performed manually by a developer locally. However Iris is configured to
+use the `cirrus-ci`_ service for automated Continuous Integration (CI) testing.
-A `cirrus-ci`_ configuration file named `.cirrus.yml`_
-is in the Iris repository which tells Cirrus-CI what commands to run. The
-commands include retrieving the Iris code base and associated test files using
-conda and then running the tests. `cirrus-ci`_ allows for a matrix of tests to
-be performed to ensure that all expected variations test successfully.
+The `cirrus-ci`_ configuration file `.cirrus.yml`_ in the root of the Iris repository
+defines the tasks to be performed by `cirrus-ci`_. For further details
+refer to the `Cirrus-CI Documentation`_. The tasks performed during CI include:
+
+* linting the code base and ensuring it adheres to the `black`_ format
+* running the system, integration and unit tests for Iris
+* ensuring the documentation gallery builds successfully
+* performing all doc-tests within the code base
+* checking all URL references within the code base and documentation are valid
+
+The above `cirrus-ci`_ tasks are run automatically against all `Iris`_ branches
+on GitHub whenever a pull request is submitted, updated or merged. See the
+`Cirrus-CI Dashboard`_ for details of recent past and active Iris jobs.
+
+.. _skipping Cirrus-CI tasks:
+
+Skipping Cirrus-CI Tasks
+------------------------
+
+As a developer you may wish to not run all the CI tasks when you are actively
+developing e.g., you are writing documentation and there is no need for linting,
+or long running compute intensive testing tasks to be executed.
+
+As a convenience, it is possible to easily skip one or more tasks by setting
+the appropriate environment variable within the `.cirrus.yml`_ file to a
+**non-empty** string:
+
+* ``SKIP_LINT_TASK`` to skip `flake8`_ linting and `black`_ formatting
+* ``SKIP_TEST_MINIMAL_TASK`` to skip restricted unit and integration testing
+* ``SKIP_TEST_FULL_TASK`` to skip full unit and integration testing
+* ``SKIP_GALLERY_TASK`` to skip building the documentation gallery
+* ``SKIP_DOCTEST_TASK`` to skip running the documentation doc-tests
+* ``SKIP_LINKCHECK_TASK`` to skip checking for broken documentation URL references
+* ``SKIP_ALL_TEST_TASKS`` which is equivalent to setting ``SKIP_TEST_MINIMAL_TASK`` and ``SKIP_TEST_FULL_TASK``
+* ``SKIP_ALL_DOC_TASKS`` which is equivalent to setting ``SKIP_GALLERY_TASK``, ``SKIP_DOCTEST_TASK``, and ``SKIP_LINKCHECK_TASK``
+
+e.g., to skip the linting task, the following are all equivalent::
+
+ SKIP_LINT_TASK: "1"
+ SKIP_LINT_TASK: "true"
+ SKIP_LINT_TASK: "false"
+ SKIP_LINT_TASK: "skip"
+ SKIP_LINT_TASK: "unicorn"
-The `cirrus-ci`_ tests are run automatically against the `Iris`_ master
-repository when a pull request is submitted, updated or merged.
GitHub Checklist
****************
@@ -50,6 +86,10 @@ passing:
.. image:: ci_checks.png
-If any CI checks fail, then the pull request is unlikely to be merged to the
+If any CI tasks fail, then the pull request is unlikely to be merged to the
Iris target branch by a core developer.
+
+.. _Cirrus-CI Dashboard: https://cirrus-ci.com/github/SciTools/iris
+.. _Cirrus-CI Documentation: https://cirrus-ci.org/guide/writing-tasks/
+
diff --git a/docs/src/developers_guide/contributing_code_formatting.rst b/docs/src/developers_guide/contributing_code_formatting.rst
index 6bf8dca717..1a3573d135 100644
--- a/docs/src/developers_guide/contributing_code_formatting.rst
+++ b/docs/src/developers_guide/contributing_code_formatting.rst
@@ -58,6 +58,4 @@ will look similar to::
their officially documentation for more information.
-.. _black: https://black.readthedocs.io/en/stable/
-.. _flake8: https://flake8.pycqa.org/en/stable/
.. _pre-commit: https://pre-commit.com/
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index 59e75942b0..4abf1e1192 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -124,6 +124,10 @@ This document explains the changes made to Iris for this release
#. `@akuhnregnier`_ replaced `deprecated numpy 1.20 aliases for builtin types`_.
(:pull:`3997`)
+#. `@bjlittle`_ added conditional task execution to `.cirrus.yml`_ to allow
+ developers to easily disable `cirrus-ci`_ tasks. See
+ :ref:`skipping Cirrus-CI tasks`. (:pull:`4019`)
+
.. comment
Whatsnew author names (@github name) in alphabetical order. Note that,
From b8ae91045ed2ff8268c3523f5806a74c1c398166 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Mon, 22 Feb 2021 09:14:34 +0000
Subject: [PATCH 20/43] make iris.common.metadata._hexdigest public (#4020)
---
docs/src/whatsnew/latest.rst | 7 ++
lib/iris/_representation.py | 4 +-
lib/iris/common/metadata.py | 67 +++++++++++--------
.../{test__hexdigest.py => test_hexdigest.py} | 4 +-
4 files changed, 51 insertions(+), 31 deletions(-)
rename lib/iris/tests/unit/common/metadata/{test__hexdigest.py => test_hexdigest.py} (97%)
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index 4abf1e1192..6fcdcfb7bc 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -42,6 +42,12 @@ This document explains the changes made to Iris for this release
``iris.plot.plot(z_cube)`` will produce a z-vs-phenomenon plot, where before
it would have produced a phenomenon-vs-z plot. (:pull:`3906`)
+#. `@bjlittle`_ introduced :func:`iris.common.metadata.hexdigest` to the
+ public API. Previously it was a private function introduced in ``v3.0.0``.
+ Given any object, :func:`~iris.common.metadata.hexdigest` returns a string
+ representation of the 64-bit non-cryptographic hash of the object using the
+ extremely fast `xxhash`_ hashing algorithm. (:pull:`4020`)
+
🐛 Bugs Fixed
=============
@@ -150,3 +156,4 @@ This document explains the changes made to Iris for this release
.. _PyPI: https://pypi.org/project/scitools-iris/
.. _Python 3.8: https://www.python.org/downloads/release/python-380/
.. _README.md: https://github.com/SciTools/iris#-----
+.. _xxhash: http://cyan4973.github.io/xxHash/
diff --git a/lib/iris/_representation.py b/lib/iris/_representation.py
index ee1e1a0d55..63974d1e50 100644
--- a/lib/iris/_representation.py
+++ b/lib/iris/_representation.py
@@ -9,7 +9,7 @@
import re
import iris.util
-from iris.common.metadata import _hexdigest as quickhash
+from iris.common.metadata import hexdigest
class DimensionHeader:
@@ -101,7 +101,7 @@ def _summary_coord_extra(self, cube, coord):
# ..except setdefault fails if values are numpy arrays.
if key not in attributes:
attributes[key] = value
- elif quickhash(attributes[key]) != quickhash(value):
+ elif hexdigest(attributes[key]) != hexdigest(value):
# NOTE: fast and array-safe comparison, as used in
# :mod:`iris.common.metadata`.
vary.add(key)
diff --git a/lib/iris/common/metadata.py b/lib/iris/common/metadata.py
index 9b1d3278f3..e0546b3c0b 100644
--- a/lib/iris/common/metadata.py
+++ b/lib/iris/common/metadata.py
@@ -37,6 +37,7 @@
"CoordMetadata",
"CubeMetadata",
"DimCoordMetadata",
+ "hexdigest",
"metadata_manager_factory",
]
@@ -48,34 +49,46 @@
logger = get_logger(__name__, fmt="[%(cls)s.%(funcName)s]")
-def _hexdigest(value):
+def hexdigest(item):
"""
- Return a hexidecimal string hash representation of the provided value.
+ Calculate a hexidecimal string hash representation of the provided item.
- Calculates a 64-bit non-cryptographic hash of the provided value,
- and returns the hexdigest string representation of the calculated hash.
+ Calculates a 64-bit non-cryptographic hash of the provided item, using
+ the extremely fast ``xxhash`` hashing algorithm, and returns the hexdigest
+ string representation of the hash.
+
+ This provides a means to compare large and/or complex objects through
+ simple string hexdigest comparison.
+
+ Args:
+
+ * item (object):
+ The item that requires to have its hexdigest calculated.
+
+ Returns:
+ The string hexidecimal representation of the item's 64-bit hash.
"""
# Special case: deal with numpy arrays.
- if ma.isMaskedArray(value):
+ if ma.isMaskedArray(item):
parts = (
- value.shape,
- xxh64_hexdigest(value.data),
- xxh64_hexdigest(value.mask),
+ item.shape,
+ xxh64_hexdigest(item.data),
+ xxh64_hexdigest(item.mask),
)
- value = str(parts)
- elif isinstance(value, np.ndarray):
- parts = (value.shape, xxh64_hexdigest(value))
- value = str(parts)
+ item = str(parts)
+ elif isinstance(item, np.ndarray):
+ parts = (item.shape, xxh64_hexdigest(item))
+ item = str(parts)
try:
# Calculate single-shot hash to avoid allocating state on the heap
- result = xxh64_hexdigest(value)
+ result = xxh64_hexdigest(item)
except TypeError:
# xxhash expects a bytes-like object, so try hashing the
- # string representation of the provided value instead, but
+ # string representation of the provided item instead, but
# also fold in the object type...
- parts = (type(value), value)
+ parts = (type(item), item)
result = xxh64_hexdigest(str(parts))
return result
@@ -338,8 +351,8 @@ def _combine_lenient_attributes(left, right):
# Use xxhash to perform an extremely fast non-cryptographic hash of
# each dictionary key rvalue, thus ensuring that the dictionary is
# completely hashable, as required by a set.
- sleft = {(k, _hexdigest(v)) for k, v in left.items()}
- sright = {(k, _hexdigest(v)) for k, v in right.items()}
+ sleft = {(k, hexdigest(v)) for k, v in left.items()}
+ sright = {(k, hexdigest(v)) for k, v in right.items()}
# Intersection of common items.
common = sleft & sright
# Items in sleft different from sright.
@@ -367,8 +380,8 @@ def _combine_strict_attributes(left, right):
# Use xxhash to perform an extremely fast non-cryptographic hash of
# each dictionary key rvalue, thus ensuring that the dictionary is
# completely hashable, as required by a set.
- sleft = {(k, _hexdigest(v)) for k, v in left.items()}
- sright = {(k, _hexdigest(v)) for k, v in right.items()}
+ sleft = {(k, hexdigest(v)) for k, v in left.items()}
+ sright = {(k, hexdigest(v)) for k, v in right.items()}
# Intersection of common items.
common = sleft & sright
# Now bring the result together.
@@ -426,8 +439,8 @@ def _compare_lenient_attributes(left, right):
# Use xxhash to perform an extremely fast non-cryptographic hash of
# each dictionary key rvalue, thus ensuring that the dictionary is
# completely hashable, as required by a set.
- sleft = {(k, _hexdigest(v)) for k, v in left.items()}
- sright = {(k, _hexdigest(v)) for k, v in right.items()}
+ sleft = {(k, hexdigest(v)) for k, v in left.items()}
+ sright = {(k, hexdigest(v)) for k, v in right.items()}
# Items in sleft different from sright.
dsleft = dict(sleft - sright)
# Items in sright different from sleft.
@@ -443,8 +456,8 @@ def _compare_strict_attributes(left, right):
# Use xxhash to perform an extremely fast non-cryptographic hash of
# each dictionary key rvalue, thus ensuring that the dictionary is
# completely hashable, as required by a set.
- sleft = {(k, _hexdigest(v)) for k, v in left.items()}
- sright = {(k, _hexdigest(v)) for k, v in right.items()}
+ sleft = {(k, hexdigest(v)) for k, v in left.items()}
+ sright = {(k, hexdigest(v)) for k, v in right.items()}
return sleft == sright
@@ -512,8 +525,8 @@ def _difference_lenient_attributes(left, right):
# Use xxhash to perform an extremely fast non-cryptographic hash of
# each dictionary key rvalue, thus ensuring that the dictionary is
# completely hashable, as required by a set.
- sleft = {(k, _hexdigest(v)) for k, v in left.items()}
- sright = {(k, _hexdigest(v)) for k, v in right.items()}
+ sleft = {(k, hexdigest(v)) for k, v in left.items()}
+ sright = {(k, hexdigest(v)) for k, v in right.items()}
# Items in sleft different from sright.
dsleft = dict(sleft - sright)
# Items in sright different from sleft.
@@ -540,8 +553,8 @@ def _difference_strict_attributes(left, right):
# Use xxhash to perform an extremely fast non-cryptographic hash of
# each dictionary key rvalue, thus ensuring that the dictionary is
# completely hashable, as required by a set.
- sleft = {(k, _hexdigest(v)) for k, v in left.items()}
- sright = {(k, _hexdigest(v)) for k, v in right.items()}
+ sleft = {(k, hexdigest(v)) for k, v in left.items()}
+ sright = {(k, hexdigest(v)) for k, v in right.items()}
# Items in sleft different from sright.
dsleft = dict(sleft - sright)
# Items in sright different from sleft.
diff --git a/lib/iris/tests/unit/common/metadata/test__hexdigest.py b/lib/iris/tests/unit/common/metadata/test_hexdigest.py
similarity index 97%
rename from lib/iris/tests/unit/common/metadata/test__hexdigest.py
rename to lib/iris/tests/unit/common/metadata/test_hexdigest.py
index 546327a21b..55c697ea6d 100644
--- a/lib/iris/tests/unit/common/metadata/test__hexdigest.py
+++ b/lib/iris/tests/unit/common/metadata/test_hexdigest.py
@@ -4,7 +4,7 @@
# See COPYING and COPYING.LESSER in the root of the repository for full
# licensing details.
"""
-Unit tests for the :func:`iris.common.metadata._hexdigest`.
+Unit tests for the :func:`iris.common.metadata.hexdigest`.
"""
@@ -18,7 +18,7 @@
import numpy as np
from xxhash import xxh64, xxh64_hexdigest
-from iris.common.metadata import _hexdigest as hexdigest
+from iris.common.metadata import hexdigest
class TestBytesLikeObject(tests.IrisTest):
From 4ad21d7380e3d01a7e8f4b880280f0bf975cf4bc Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Mon, 22 Feb 2021 17:02:00 +0000
Subject: [PATCH 21/43] cirrus-ci uses iris-test-data release version (#4024)
---
.cirrus.yml | 46 ++++++++++++++++++++--------------------------
1 file changed, 20 insertions(+), 26 deletions(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index 0a7c972821..c477f0cefe 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -41,7 +41,7 @@ env:
# Pip package to be upgraded/installed.
PIP_CACHE_PACKAGES: "pip setuptools wheel nox"
# Git commit hash for iris test data.
- IRIS_TEST_DATA_REF: "fffb9b14b9cb472c5eb2ebb7fd19acb7f6414a30"
+ IRIS_TEST_DATA_VERSION: "2.0.0"
# Base directory for the iris-test-data.
IRIS_TEST_DATA_DIR: ${HOME}/iris-test-data
@@ -82,12 +82,27 @@ linux_task_template: &LINUX_TASK_TEMPLATE
#
-# YAML alias for compute credits
+# YAML alias for compute credits.
#
compute_credits_template: &CREDITS_TEMPLATE
# Only use credits for non-DRAFT pull-requests to SciTools/iris master branch by collaborators
use_compute_credits: $CIRRUS_REPO_FULL_NAME == 'SciTools/iris' && $CIRRUS_USER_COLLABORATOR == 'true' && $CIRRUS_PR_DRAFT == 'false' && $CIRRUS_BASE_BRANCH == 'master' && $CIRRUS_PR != ''
+
+#
+# YAML alias for the iris-test-data cache.
+#
+iris_test_data_template: &IRIS_TEST_DATA_TEMPLATE
+ data_cache:
+ folder: ${IRIS_TEST_DATA_DIR}
+ fingerprint_script:
+ - echo "iris-test-data v${IRIS_TEST_DATA_VERSION}"
+ populate_script:
+ - wget --quiet https://github.com/SciTools/iris-test-data/archive/v${IRIS_TEST_DATA_VERSION}.zip -O iris-test-data.zip
+ - unzip -q iris-test-data.zip
+ - mv iris-test-data-${IRIS_TEST_DATA_VERSION} ${IRIS_TEST_DATA_DIR}
+
+
#
# Linting
#
@@ -152,14 +167,7 @@ test_full_task:
image: gcc:latest
cpu: 6
memory: 8G
- data_cache:
- folder: ${IRIS_TEST_DATA_DIR}
- fingerprint_script:
- - echo "${IRIS_TEST_DATA_REF}"
- populate_script:
- - wget --quiet https://github.com/SciTools/iris-test-data/archive/${IRIS_TEST_DATA_REF}.zip -O iris-test-data.zip
- - unzip -q iris-test-data.zip
- - mv iris-test-data-$(echo "${IRIS_TEST_DATA_REF}" | sed "s/^v//") ${IRIS_TEST_DATA_DIR}
+ << : *IRIS_TEST_DATA_TEMPLATE
<< : *LINUX_TASK_TEMPLATE
tests_script:
- echo "[Resources]" > ${SITE_CFG}
@@ -182,14 +190,7 @@ gallery_task:
image: gcc:latest
cpu: 2
memory: 4G
- data_cache:
- folder: ${IRIS_TEST_DATA_DIR}
- fingerprint_script:
- - echo "${IRIS_TEST_DATA_REF}"
- populate_script:
- - wget --quiet https://github.com/SciTools/iris-test-data/archive/${IRIS_TEST_DATA_REF}.zip -O iris-test-data.zip
- - unzip -q iris-test-data.zip
- - mv iris-test-data-$(echo "${IRIS_TEST_DATA_REF}" | sed "s/^v//") ${IRIS_TEST_DATA_DIR}
+ << : *IRIS_TEST_DATA_TEMPLATE
<< : *LINUX_TASK_TEMPLATE
tests_script:
- echo "[Resources]" > ${SITE_CFG}
@@ -215,14 +216,7 @@ doctest_task:
env:
MPL_RC_DIR: ${HOME}/.config/matplotlib
MPL_RC_FILE: ${HOME}/.config/matplotlib/matplotlibrc
- data_cache:
- folder: ${IRIS_TEST_DATA_DIR}
- fingerprint_script:
- - echo "${IRIS_TEST_DATA_REF}"
- populate_script:
- - wget --quiet https://github.com/SciTools/iris-test-data/archive/${IRIS_TEST_DATA_REF}.zip -O iris-test-data.zip
- - unzip -q iris-test-data.zip
- - mv iris-test-data-$(echo "${IRIS_TEST_DATA_REF}" | sed "s/^v//") ${IRIS_TEST_DATA_DIR}
+ << : *IRIS_TEST_DATA_TEMPLATE
<< : *LINUX_TASK_TEMPLATE
tests_script:
- echo "[Resources]" > ${SITE_CFG}
From bdbec276a0b989cfdaae686199ede2a55be1d720 Mon Sep 17 00:00:00 2001
From: tkknight <2108488+tkknight@users.noreply.github.com>
Date: Tue, 23 Feb 2021 16:12:59 +0000
Subject: [PATCH 22/43] added iris version to index title (#4030)
---
docs/src/index.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/src/index.rst b/docs/src/index.rst
index 80aa696ba1..8c3455aba9 100644
--- a/docs/src/index.rst
+++ b/docs/src/index.rst
@@ -1,7 +1,7 @@
.. _iris_docs:
-Iris Documentation
-==================
+Iris |version|
+========================
**A powerful, format-agnostic, community-driven Python package for analysing
and visualising Earth science data.**
From cbaa95524649378779f148cf5897611f208c76fb Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Fri, 26 Feb 2021 14:47:37 +0000
Subject: [PATCH 23/43] docs post-release update pypi howto (#4038)
---
docs/src/common_links.inc | 1 +
docs/src/developers_guide/release.rst | 52 +++++++++++++++++++++++++--
docs/src/whatsnew/latest.rst | 3 ++
3 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/docs/src/common_links.inc b/docs/src/common_links.inc
index d9df15be8b..fcd66e0017 100644
--- a/docs/src/common_links.inc
+++ b/docs/src/common_links.inc
@@ -28,6 +28,7 @@
.. _Read the Docs: https://scitools-iris.readthedocs.io/en/latest/
.. _readthedocs.yml: https://github.com/SciTools/iris/blob/master/requirements/ci/readthedocs.yml
.. _SciTools: https://github.com/SciTools
+.. _scitools-iris: https://pypi.org/project/scitools-iris/
.. _sphinx: https://www.sphinx-doc.org/en/master/
.. _test-iris-imagehash: https://github.com/SciTools/test-iris-imagehash
.. _using git: https://docs.github.com/en/github/using-git
diff --git a/docs/src/developers_guide/release.rst b/docs/src/developers_guide/release.rst
index 90938b32d3..0802d5de22 100644
--- a/docs/src/developers_guide/release.rst
+++ b/docs/src/developers_guide/release.rst
@@ -1,3 +1,5 @@
+.. include:: ../common_links.inc
+
.. _iris_development_releases:
Releases
@@ -82,14 +84,59 @@ Once all checks are complete, the release is cut by the creation of a new tag
in the ``SciTools/iris`` repository.
-Conda Recipe
-------------
+Update conda-forge
+------------------
Once a release is cut on GitHub, update the Iris conda recipe on the
`conda-forge iris-feedstock`_ for the release. This will build and publish the
conda package on the `conda-forge Anaconda channel`_.
+.. _update_pypi:
+
+Update PyPI
+-----------
+
+Update the `scitools-iris`_ project on PyPI with the latest Iris release.
+
+To do this perform the following steps.
+
+Create a conda environment with the appropriate conda packages to build the
+source distribution (``sdist``) and pure Python wheel (``bdist_wheel``)::
+
+ > conda create -n iris-pypi -c conda-forge --yes pip pyke python setuptools twine wheel
+ > . activate iris-pypi
+
+Checkout the lastest Iris ```` tag::
+
+ > git fetch --tags
+ > git checkout
+
+Build the source distribution and wheel from the Iris root directory::
+
+ > python setup.py sdist bdist_wheel
+
+This ``./dist`` directory should now be populated with the source archive
+``.tar.gz`` file, and built distribution ``.whl`` file.
+
+Sufficient maintainer privileges will be required to upload these artifacts
+to `scitools-iris`_ on PyPI::
+
+ > python -m twine upload --repository-url https://upload.pypi.org/legecy/ ./dist/*
+
+Ensure that the artifacts are successfully uploaded and available on
+`scitools-iris`_ before creating a conda test environment to install Iris
+from PyPI::
+
+ > conda deactivate
+ > conda env create --file ./requrements/ci/iris.yml
+ > . activate iris-dev
+ > conda install -c conda-forge pip
+ > python -m pip install --no-deps scitools-iris
+
+For futher details on how to test Iris, see :ref:`developer_running_tests`.
+
+
Merge Back
----------
@@ -179,7 +226,6 @@ Post Release Steps
#. Merge back to ``master``
-.. _Read The Docs: https://readthedocs.org/projects/scitools-iris/builds/
.. _SciTools/iris: https://github.com/SciTools/iris
.. _tag on the SciTools/Iris: https://github.com/SciTools/iris/releases
.. _conda-forge Anaconda channel: https://anaconda.org/conda-forge/iris
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index 6fcdcfb7bc..689a41ac53 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -106,6 +106,9 @@ This document explains the changes made to Iris for this release
development documentation if being viewed on `Read the Docs`_.
(:pull:`3999`)
+#. `@bjlittle`_ added post-release instructions on how to :ref:`update_pypi`
+ with `scitools-iris`_. (:pull:`4038`)
+
💼 Internal
===========
From 8750dabc7d737953ffcc5f0fcbe314a224031389 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Mon, 1 Mar 2021 09:42:06 +0000
Subject: [PATCH 24/43] docs add pypi references (#4042)
---
docs/src/developers_guide/release.rst | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/docs/src/developers_guide/release.rst b/docs/src/developers_guide/release.rst
index 0802d5de22..666d66ec86 100644
--- a/docs/src/developers_guide/release.rst
+++ b/docs/src/developers_guide/release.rst
@@ -134,7 +134,12 @@ from PyPI::
> conda install -c conda-forge pip
> python -m pip install --no-deps scitools-iris
-For futher details on how to test Iris, see :ref:`developer_running_tests`.
+For further details on how to test Iris, see :ref:`developer_running_tests`.
+
+.. seealso::
+
+ For further information on packaging and uploading a project to PyPI, please
+ refer to `Generating Distribution Archives`_ and `Packaging Your Project`_.
Merge Back
@@ -235,3 +240,5 @@ Post Release Steps
.. _Active Versions: https://readthedocs.org/projects/scitools-iris/versions/
.. _Editing v3.0.0rc0: https://readthedocs.org/dashboard/scitools-iris/version/v3.0.0rc0/
.. _rc_iris: https://anaconda.org/conda-forge/iris/labels
+.. _Generating Distribution Archives: https://packaging.python.org/tutorials/packaging-projects/#generating-distribution-archives
+.. _Packaging Your Project: https://packaging.python.org/guides/distributing-packages-using-setuptools/#packaging-your-project
From 7f67d1f65dbf80636ba3ea8a0032fdeed25cce11 Mon Sep 17 00:00:00 2001
From: Ruth Comer
Date: Mon, 1 Mar 2021 13:43:29 +0000
Subject: [PATCH 25/43] metadata string reduction (#4040)
* implement metadata string
* review actions
---
docs/src/whatsnew/latest.rst | 4 ++++
lib/iris/common/metadata.py | 10 ++++++++++
2 files changed, 14 insertions(+)
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index 689a41ac53..8b986e0ac3 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -48,6 +48,10 @@ This document explains the changes made to Iris for this release
representation of the 64-bit non-cryptographic hash of the object using the
extremely fast `xxhash`_ hashing algorithm. (:pull:`4020`)
+#. `@rcomer`_ implemented a ``__str__`` method for metadata classes, so
+ printing these objects skips metadata elements that are set to None or an
+ empty string or dictionary. (:pull:`4040`)
+
🐛 Bugs Fixed
=============
diff --git a/lib/iris/common/metadata.py b/lib/iris/common/metadata.py
index e0546b3c0b..f25f58be1e 100644
--- a/lib/iris/common/metadata.py
+++ b/lib/iris/common/metadata.py
@@ -227,6 +227,16 @@ def __ne__(self, other):
return result
+ def __str__(self):
+ field_strings = []
+ for field in self._fields:
+ value = getattr(self, field)
+ if value is None or isinstance(value, (str, dict)) and not value:
+ continue
+ field_strings.append(f"{field}={value}")
+
+ return f"{type(self).__name__}({', '.join(field_strings)})"
+
def _api_common(
self, other, func_service, func_operation, action, lenient=None
):
From a9ae72fa3c420da408fb4f69bba4035c2c43f769 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Mon, 1 Mar 2021 14:08:15 +0000
Subject: [PATCH 26/43] add basemetadata str unit test (#4043)
---
.../tests/unit/common/metadata/test_BaseMetadata.py | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py b/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py
index 4ff8ec0de6..7cb8e3394b 100644
--- a/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py
+++ b/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py
@@ -53,6 +53,19 @@ def test_repr(self):
)
self.assertEqual(expected, repr(metadata))
+ def test_str(self):
+ metadata = self.cls(
+ standard_name="",
+ long_name=None,
+ var_name=self.var_name,
+ units=self.units,
+ attributes={},
+ )
+ expected = (
+ f"BaseMetadata(var_name={self.var_name!r}, units={self.units!r})"
+ )
+ self.assertEqual(expected, str(metadata))
+
def test__fields(self):
expected = (
"standard_name",
From 5e593c195878e08d0fafac56ddb355309335205a Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Tue, 2 Mar 2021 14:05:16 +0000
Subject: [PATCH 27/43] remove unused cirrus-ci variable (#4045)
---
.cirrus.yml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index c477f0cefe..09b5469201 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -52,7 +52,6 @@ env:
linux_task_template: &LINUX_TASK_TEMPLATE
auto_cancellation: true
env:
- IRIS_REPO_DIR: ${CIRRUS_WORKING_DIR}
PATH: ${HOME}/miniconda/bin:${PATH}
SITE_CFG: ${CIRRUS_WORKING_DIR}/lib/iris/etc/site.cfg
conda_cache:
From 4047aa1833966f5838f64207c26679990c2d1116 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Wed, 3 Mar 2021 06:38:29 +0000
Subject: [PATCH 28/43] cirrus-ci add python version to lint task fingerprint
(#4047)
---
.cirrus.yml | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index 09b5469201..6c57c5f82d 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -85,7 +85,7 @@ linux_task_template: &LINUX_TASK_TEMPLATE
#
compute_credits_template: &CREDITS_TEMPLATE
# Only use credits for non-DRAFT pull-requests to SciTools/iris master branch by collaborators
- use_compute_credits: $CIRRUS_REPO_FULL_NAME == 'SciTools/iris' && $CIRRUS_USER_COLLABORATOR == 'true' && $CIRRUS_PR_DRAFT == 'false' && $CIRRUS_BASE_BRANCH == 'master' && $CIRRUS_PR != ''
+ use_compute_credits: ${CIRRUS_REPO_FULL_NAME} == "SciTools/iris" && ${CIRRUS_USER_COLLABORATOR} == "true" && ${CIRRUS_PR_DRAFT} == "false" && ${CIRRUS_BASE_BRANCH} == "master" && ${CIRRUS_PR} != ""
#
@@ -106,14 +106,14 @@ iris_test_data_template: &IRIS_TEST_DATA_TEMPLATE
# Linting
#
lint_task:
- only_if: $SKIP_LINT_TASK == ""
+ only_if: ${SKIP_LINT_TASK} == ""
<< : *CREDITS_TEMPLATE
auto_cancellation: true
name: "${CIRRUS_OS}: flake8 and black"
pip_cache:
folder: ~/.cache/pip
fingerprint_script:
- - echo "${CIRRUS_TASK_NAME}"
+ - echo "${CIRRUS_TASK_NAME} py${PYTHON_VERSION}"
- echo "$(date +%Y).$(expr $(date +%U) / ${CACHE_PERIOD}):${PIP_CACHE_BUILD} ${PIP_CACHE_PACKAGES}"
lint_script:
- pip list
@@ -127,7 +127,7 @@ lint_task:
# Testing Minimal (Linux)
#
test_minimal_task:
- only_if: $SKIP_TEST_MINIMAL_TASK == "" && $SKIP_ALL_TEST_TASKS == ""
+ only_if: ${SKIP_TEST_MINIMAL_TASK} == "" && ${SKIP_ALL_TEST_TASKS} == ""
<< : *CREDITS_TEMPLATE
matrix:
env:
@@ -152,7 +152,7 @@ test_minimal_task:
# Testing Full (Linux)
#
test_full_task:
- only_if: $SKIP_TEST_FULL_TASK == "" && $SKIP_ALL_TEST_TASKS == ""
+ only_if: ${SKIP_TEST_FULL_TASK} == "" && ${SKIP_ALL_TEST_TASKS} == ""
<< : *CREDITS_TEMPLATE
matrix:
env:
@@ -179,7 +179,7 @@ test_full_task:
# Testing Documentation Gallery (Linux)
#
gallery_task:
- only_if: $SKIP_GALLERY_TASK == "" && $SKIP_ALL_DOC_TASKS == ""
+ only_if: ${SKIP_GALLERY_TASK} == "" && ${SKIP_ALL_DOC_TASKS} == ""
<< : *CREDITS_TEMPLATE
matrix:
env:
@@ -202,7 +202,7 @@ gallery_task:
# Testing Documentation (Linux)
#
doctest_task:
- only_if: $SKIP_DOCTEST_TASK == "" && $SKIP_ALL_DOC_TASKS == ""
+ only_if: ${SKIP_DOCTEST_TASK} == "" && ${SKIP_ALL_DOC_TASKS} == ""
<< : *CREDITS_TEMPLATE
matrix:
env:
@@ -231,7 +231,7 @@ doctest_task:
# Testing Documentation Link Check (Linux)
#
linkcheck_task:
- only_if: $SKIP_LINKCHECK_TASK == "" && $SKIP_ALL_DOC_TASKS == ""
+ only_if: ${SKIP_LINKCHECK_TASK} == "" && ${SKIP_ALL_DOC_TASKS} == ""
<< : *CREDITS_TEMPLATE
matrix:
env:
From 0e3a6ce9696d6be187167fab8ef1c9218ccb5f67 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Fri, 5 Mar 2021 11:26:18 +0000
Subject: [PATCH 29/43] fix html case (#4050)
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index e460f4a01a..4e8c5073e3 100644
--- a/README.md
+++ b/README.md
@@ -47,4 +47,4 @@
See the documentation for the latest development version of Iris.
-
+
From 2051e0323083bafd5efee115347cb702bf8fb822 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Fri, 5 Mar 2021 11:27:56 +0000
Subject: [PATCH 30/43] cirrus-ci conda cache packages part of fingerprint
(#4048)
---
.cirrus.yml | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index 6c57c5f82d..7244296a6c 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -38,8 +38,10 @@ env:
NOX_CACHE_BUILD: "0"
# Increment the build number to force new pip cache upload.
PIP_CACHE_BUILD: "0"
- # Pip package to be upgraded/installed.
+ # Pip packages to be upgraded/installed.
PIP_CACHE_PACKAGES: "pip setuptools wheel nox"
+ # Conda packages to be installed.
+ CONDA_CACHE_PACKAGES: "nox pip"
# Git commit hash for iris test data.
IRIS_TEST_DATA_VERSION: "2.0.0"
# Base directory for the iris-test-data.
@@ -59,6 +61,7 @@ linux_task_template: &LINUX_TASK_TEMPLATE
fingerprint_script:
- wget --quiet https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
- echo "${CIRRUS_OS} $(sha256sum miniconda.sh)"
+ - echo "${CONDA_CACHE_PACKAGES}"
- echo "$(date +%Y).$(expr $(date +%U) / ${CACHE_PERIOD}):${CONDA_CACHE_BUILD}"
populate_script:
- bash miniconda.sh -b -p ${HOME}/miniconda
@@ -66,7 +69,7 @@ linux_task_template: &LINUX_TASK_TEMPLATE
- conda config --set show_channel_urls True
- conda config --add channels conda-forge
- conda update --quiet --name base conda
- - conda install --quiet --name base nox pip
+ - conda install --quiet --name base ${CONDA_CACHE_PACKAGES}
cartopy_cache:
folder: ${HOME}/.local/share/cartopy
fingerprint_script:
From 72ce1f3450713cf6b34daa741f36f4d55b90d133 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Mon, 8 Mar 2021 10:19:44 +0000
Subject: [PATCH 31/43] fix sphinxext api generate (#4056)
---
docs/src/sphinxext/generate_package_rst.py | 60 +++++++++++-----------
1 file changed, 29 insertions(+), 31 deletions(-)
diff --git a/docs/src/sphinxext/generate_package_rst.py b/docs/src/sphinxext/generate_package_rst.py
index 5ce9f6d014..ec153c768f 100644
--- a/docs/src/sphinxext/generate_package_rst.py
+++ b/docs/src/sphinxext/generate_package_rst.py
@@ -313,14 +313,13 @@ def do_package(package_name):
)
paths.sort()
+ excluded_paths = [item[0] for item in exclude_modules]
# check for any modules to exclude
- for exclude_module in exclude_modules:
- if exclude_module[0] in paths:
- autolog(
- "Excluding module in package: {}".format(exclude_module[0])
- )
- paths.remove(exclude_module[0])
+ for excluded_path in excluded_paths:
+ if excluded_path in paths:
+ autolog(f"Excluding module in package: {excluded_path!r}")
+ paths.remove(excluded_path)
doc = auto_doc_package(package_path, package, root_package, paths)
@@ -341,33 +340,32 @@ def do_package(package_name):
with open(out_path, "w") as fh:
fh.write(doc)
+ excluded_imports = [item[1] for item in exclude_modules]
+
for import_name, module_path in module_folders.get(package, []):
# check for any modules to exclude
- for exclude_module in exclude_modules:
- if import_name == exclude_module[1]:
- autolog(
- "Excluding module file: {}".format(exclude_module[1])
- )
- else:
- doc = auto_doc_module(
- module_path, import_name, root_package
- )
- out_path = (
- out_dir
- + import_name.replace(".", os.path.sep)
- + ".rst"
- )
- if not os.path.exists(out_path):
- autolog("Creating {} ...".format(out_path))
- with open(out_path, "w") as fh:
- fh.write(doc)
- else:
- with open(out_path, "r") as fh:
- existing_content = "".join(fh.readlines())
- if doc != existing_content:
- autolog("Creating {} ...".format(out_path))
- with open(out_path, "w") as fh:
- fh.write(doc)
+ if import_name in excluded_imports:
+ autolog(f"Excluding module file: {import_name!r}")
+ continue
+ doc = auto_doc_module(
+ module_path, import_name, root_package
+ )
+ out_path = (
+ out_dir
+ + import_name.replace(".", os.path.sep)
+ + ".rst"
+ )
+ if not os.path.exists(out_path):
+ autolog("Creating {} ...".format(out_path))
+ with open(out_path, "w") as fh:
+ fh.write(doc)
+ else:
+ with open(out_path, "r") as fh:
+ existing_content = "".join(fh.readlines())
+ if doc != existing_content:
+ autolog("Creating {} ...".format(out_path))
+ with open(out_path, "w") as fh:
+ fh.write(doc)
def setup(app):
From afd2c25d090f95148ad17e990ad3d33088912158 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Mon, 8 Mar 2021 13:13:44 +0000
Subject: [PATCH 32/43] update pre-commit hooks (#4055)
---
.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 153687ad0c..76fb7b6740 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -2,7 +2,7 @@
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: 'v2.4.0'
+ rev: 'v3.4.0'
hooks:
# Prevent giant files from being committed.
- id: check-added-large-files
@@ -24,7 +24,7 @@ repos:
pass_filenames: false
args: [--config=./pyproject.toml, .]
- repo: https://gitlab.com/pycqa/flake8
- rev: '3.8.3'
+ rev: '3.8.4'
hooks:
# Run flake8.
- id: flake8
From a7044f641bf082e9391a906dade4f654a6c1116a Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Fri, 12 Mar 2021 10:12:40 +0000
Subject: [PATCH 33/43] cirrus-ci credits for non-master (#4060)
---
.cirrus.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index 7244296a6c..ca569feb63 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -88,7 +88,7 @@ linux_task_template: &LINUX_TASK_TEMPLATE
#
compute_credits_template: &CREDITS_TEMPLATE
# Only use credits for non-DRAFT pull-requests to SciTools/iris master branch by collaborators
- use_compute_credits: ${CIRRUS_REPO_FULL_NAME} == "SciTools/iris" && ${CIRRUS_USER_COLLABORATOR} == "true" && ${CIRRUS_PR_DRAFT} == "false" && ${CIRRUS_BASE_BRANCH} == "master" && ${CIRRUS_PR} != ""
+ use_compute_credits: ${CIRRUS_REPO_FULL_NAME} == "SciTools/iris" && ${CIRRUS_USER_COLLABORATOR} == "true" && ${CIRRUS_PR_DRAFT} == "false" && ${CIRRUS_PR} != ""
#
From 4648bea404a5a543694d7d7022fdd6861dc4b719 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Fri, 12 Mar 2021 12:35:00 +0000
Subject: [PATCH 34/43] add pre-commit.ci badge and doc support (#4061)
* add pre-commit.ci badge and doc support
* review actions
---
README.md | 3 ++
docs/src/common_links.inc | 1 +
.../contributing_ci_tests.rst | 47 ++++++++++++-------
docs/src/whatsnew/latest.rst | 5 ++
4 files changed, 40 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index 4e8c5073e3..719686f379 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,9 @@
+
+
diff --git a/docs/src/common_links.inc b/docs/src/common_links.inc
index fcd66e0017..7209d85c09 100644
--- a/docs/src/common_links.inc
+++ b/docs/src/common_links.inc
@@ -23,6 +23,7 @@
.. _napolean: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/sphinxcontrib.napoleon.html
.. _nox: https://nox.thea.codes/en/stable/
.. _New Issue: https://github.com/scitools/iris/issues/new/choose
+.. _pre-commit: https://pre-commit.com/
.. _pull request: https://github.com/SciTools/iris/pulls
.. _pull requests: https://github.com/SciTools/iris/pulls
.. _Read the Docs: https://scitools-iris.readthedocs.io/en/latest/
diff --git a/docs/src/developers_guide/contributing_ci_tests.rst b/docs/src/developers_guide/contributing_ci_tests.rst
index 8594612fe1..14bc6a2612 100644
--- a/docs/src/developers_guide/contributing_ci_tests.rst
+++ b/docs/src/developers_guide/contributing_ci_tests.rst
@@ -6,21 +6,12 @@ Continuous Integration (CI) Testing
===================================
The `Iris`_ GitHub repository is configured to run checks against all its
-branches automatically whenever a pull request is created, updated or merged.
+branches automatically whenever a pull-request is created, updated or merged.
The checks performed are:
-* :ref:`testing_cla`
* :ref:`testing_cirrus`
-
-
-.. _testing_cla:
-
-SciTools CLA Checker
-********************
-
-A bot which checks that the GitHub author of the pull request has signed the
-**SciTools Contributor's License Agreement (CLA)**. For more information on
-this please see https://scitools.org.uk/organisation.html#governance.
+* :ref:`testing_cla`
+* :ref:`pre_commit_ci`
.. _testing_cirrus:
@@ -44,7 +35,7 @@ refer to the `Cirrus-CI Documentation`_. The tasks performed during CI include:
* checking all URL references within the code base and documentation are valid
The above `cirrus-ci`_ tasks are run automatically against all `Iris`_ branches
-on GitHub whenever a pull request is submitted, updated or merged. See the
+on GitHub whenever a pull-request is submitted, updated or merged. See the
`Cirrus-CI Dashboard`_ for details of recent past and active Iris jobs.
.. _skipping Cirrus-CI tasks:
@@ -79,17 +70,41 @@ e.g., to skip the linting task, the following are all equivalent::
GitHub Checklist
-****************
+----------------
-An example snapshot from a successful GitHub pull request shows all tests
+An example snapshot from a successful GitHub pull-request shows all tests
passing:
.. image:: ci_checks.png
-If any CI tasks fail, then the pull request is unlikely to be merged to the
+If any CI tasks fail, then the pull-request is unlikely to be merged to the
Iris target branch by a core developer.
+.. _testing_cla:
+
+SciTools CLA Checker
+********************
+
+A bot which checks that the GitHub author of the pull-request has signed the
+**SciTools Contributor's License Agreement (CLA)**. For more information on
+this please see https://scitools.org.uk/organisation.html#governance.
+
+
+.. _pre_commit_ci:
+
+pre-commit CI
+*************
+
+A CI service for the `pre-commit`_ framework that checks and auto fixes all
+pull-requests given the `Iris`_ GitHub repository `.pre-commit-config.yaml`_.
+
+See the `pre-commit.ci dashboard`_ for details of recent past and active Iris jobs.
+
+
+
.. _Cirrus-CI Dashboard: https://cirrus-ci.com/github/SciTools/iris
.. _Cirrus-CI Documentation: https://cirrus-ci.org/guide/writing-tasks/
+.. _.pre-commit-config.yaml: https://github.com/SciTools/iris/blob/master/.pre-commit-config.yaml
+.. _pre-commit.ci dashboard: https://results.pre-commit.ci/repo/github/5312648
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index 8b986e0ac3..72fc506353 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -113,6 +113,9 @@ This document explains the changes made to Iris for this release
#. `@bjlittle`_ added post-release instructions on how to :ref:`update_pypi`
with `scitools-iris`_. (:pull:`4038`)
+#. `@bjlittle`_ added the |pre-commit.ci|_ badge to the `README.md`_.
+ See :ref:`pre_commit_ci` for further details. (:pull:`4061`)
+
💼 Internal
===========
@@ -159,6 +162,8 @@ This document explains the changes made to Iris for this release
.. _GitHub: https://github.com/SciTools/iris/issues/new/choose
.. _Met Office: https://www.metoffice.gov.uk/
.. _numpy: https://numpy.org/doc/stable/release/1.20.0-notes.html
+.. |pre-commit.ci| image:: https://results.pre-commit.ci/badge/github/SciTools/iris/master.svg
+.. _pre-commit.ci: https://results.pre-commit.ci/latest/github/SciTools/iris/master
.. |PyPI| image:: https://img.shields.io/pypi/v/scitools-iris?color=orange&label=pypi%7Cscitools-iris
.. _PyPI: https://pypi.org/project/scitools-iris/
.. _Python 3.8: https://www.python.org/downloads/release/python-380/
From f78aa9d7b617ec00203b4b7861ed6a15993c4d5a Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Mon, 15 Mar 2021 13:24:26 +0000
Subject: [PATCH 35/43] conda requirements add pip (#4062)
---
requirements/ci/py36.yml | 1 +
requirements/ci/py37.yml | 1 +
requirements/ci/py38.yml | 1 +
3 files changed, 3 insertions(+)
diff --git a/requirements/ci/py36.yml b/requirements/ci/py36.yml
index 4d9d25d7c6..f778704803 100644
--- a/requirements/ci/py36.yml
+++ b/requirements/ci/py36.yml
@@ -28,6 +28,7 @@ dependencies:
- mo_pack
- nc-time-axis
- pandas
+ - pip
- python-stratify
- pyugrid
diff --git a/requirements/ci/py37.yml b/requirements/ci/py37.yml
index bdb097796a..5b21e9f778 100644
--- a/requirements/ci/py37.yml
+++ b/requirements/ci/py37.yml
@@ -28,6 +28,7 @@ dependencies:
- mo_pack
- nc-time-axis
- pandas
+ - pip
- python-stratify
- pyugrid
diff --git a/requirements/ci/py38.yml b/requirements/ci/py38.yml
index da29d30d71..e09a7a7164 100644
--- a/requirements/ci/py38.yml
+++ b/requirements/ci/py38.yml
@@ -28,6 +28,7 @@ dependencies:
- mo_pack
- nc-time-axis
- pandas
+ - pip
- python-stratify
- pyugrid
From fe6198b257070fbc6cc02d82e434b6415010f51f Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Thu, 18 Mar 2021 10:30:37 +0000
Subject: [PATCH 36/43] Add GitHub discussions badge (#4070)
* add github discussions badge
* rationalise badges
* lower case text
---
README.md | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index 719686f379..cdef50096e 100644
--- a/README.md
+++ b/README.md
@@ -20,12 +20,6 @@
-
-
-
-
@@ -43,6 +37,9 @@
+
+
From f76288cb82eefc5bc3c74461bfd8f397618eda14 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Thu, 18 Mar 2021 10:31:30 +0000
Subject: [PATCH 37/43] update flake8 pre-commit (#4067)
---
.pre-commit-config.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 76fb7b6740..2c1cbdb68c 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -24,7 +24,7 @@ repos:
pass_filenames: false
args: [--config=./pyproject.toml, .]
- repo: https://gitlab.com/pycqa/flake8
- rev: '3.8.4'
+ rev: '3.9.0'
hooks:
# Run flake8.
- id: flake8
From 3fec756c6107ea71e64e0fe7a07882f8dbde3071 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Mon, 29 Mar 2021 09:44:03 +0100
Subject: [PATCH 38/43] update docs pypi instructions (#4077)
---
docs/src/developers_guide/release.rst | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/docs/src/developers_guide/release.rst b/docs/src/developers_guide/release.rst
index 666d66ec86..cf8dcc42cb 100644
--- a/docs/src/developers_guide/release.rst
+++ b/docs/src/developers_guide/release.rst
@@ -119,10 +119,19 @@ Build the source distribution and wheel from the Iris root directory::
This ``./dist`` directory should now be populated with the source archive
``.tar.gz`` file, and built distribution ``.whl`` file.
-Sufficient maintainer privileges will be required to upload these artifacts
-to `scitools-iris`_ on PyPI::
+Check that the package description will render properly on PyPI for each
+of the built artifacts::
- > python -m twine upload --repository-url https://upload.pypi.org/legecy/ ./dist/*
+ > python -m twine check dist/*
+
+To list and check the contents of the binary wheel::
+
+ > python -m zipfile --list dist/*.whl
+
+If all seems well, sufficient maintainer privileges will be required to
+upload these artifacts to `scitools-iris`_ on PyPI::
+
+ > python -m twine upload --repository-url https://upload.pypi.org/legecy/ dist/*
Ensure that the artifacts are successfully uploaded and available on
`scitools-iris`_ before creating a conda test environment to install Iris
From 98baee21721826a2a3c25d9169ed7e97e16e5e12 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Thu, 8 Apr 2021 15:55:14 +0100
Subject: [PATCH 39/43] linux kernel version fix for conda 4.10+ (#4084)
---
.cirrus.yml | 7 +++++++
lib/iris/fileformats/netcdf.py | 4 ++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index ca569feb63..250e9c37c9 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -63,7 +63,9 @@ linux_task_template: &LINUX_TASK_TEMPLATE
- echo "${CIRRUS_OS} $(sha256sum miniconda.sh)"
- echo "${CONDA_CACHE_PACKAGES}"
- echo "$(date +%Y).$(expr $(date +%U) / ${CACHE_PERIOD}):${CONDA_CACHE_BUILD}"
+ - uname -r
populate_script:
+ - export CONDA_OVERRIDE_LINUX="$(uname -r | cut -d'+' -f1)"
- bash miniconda.sh -b -p ${HOME}/miniconda
- conda config --set always_yes yes --set changeps1 no
- conda config --set show_channel_urls True
@@ -146,6 +148,7 @@ test_minimal_task:
memory: 4G
<< : *LINUX_TASK_TEMPLATE
tests_script:
+ - export CONDA_OVERRIDE_LINUX="$(uname -r | cut -d'+' -f1)"
- echo "[Resources]" > ${SITE_CFG}
- echo "doc_dir = ${CIRRUS_WORKING_DIR}/docs" >> ${SITE_CFG}
- nox --session tests -- --verbose
@@ -172,6 +175,7 @@ test_full_task:
<< : *IRIS_TEST_DATA_TEMPLATE
<< : *LINUX_TASK_TEMPLATE
tests_script:
+ - export CONDA_OVERRIDE_LINUX="$(uname -r | cut -d'+' -f1)"
- echo "[Resources]" > ${SITE_CFG}
- echo "test_data_dir = ${IRIS_TEST_DATA_DIR}/test_data" >> ${SITE_CFG}
- echo "doc_dir = ${CIRRUS_WORKING_DIR}/docs" >> ${SITE_CFG}
@@ -195,6 +199,7 @@ gallery_task:
<< : *IRIS_TEST_DATA_TEMPLATE
<< : *LINUX_TASK_TEMPLATE
tests_script:
+ - export CONDA_OVERRIDE_LINUX="$(uname -r | cut -d'+' -f1)"
- echo "[Resources]" > ${SITE_CFG}
- echo "test_data_dir = ${IRIS_TEST_DATA_DIR}/test_data" >> ${SITE_CFG}
- echo "doc_dir = ${CIRRUS_WORKING_DIR}/docs" >> ${SITE_CFG}
@@ -221,6 +226,7 @@ doctest_task:
<< : *IRIS_TEST_DATA_TEMPLATE
<< : *LINUX_TASK_TEMPLATE
tests_script:
+ - export CONDA_OVERRIDE_LINUX="$(uname -r | cut -d'+' -f1)"
- echo "[Resources]" > ${SITE_CFG}
- echo "test_data_dir = ${IRIS_TEST_DATA_DIR}/test_data" >> ${SITE_CFG}
- echo "doc_dir = ${CIRRUS_WORKING_DIR}/docs" >> ${SITE_CFG}
@@ -249,6 +255,7 @@ linkcheck_task:
MPL_RC_FILE: ${HOME}/.config/matplotlib/matplotlibrc
<< : *LINUX_TASK_TEMPLATE
tests_script:
+ - export CONDA_OVERRIDE_LINUX="$(uname -r | cut -d'+' -f1)"
- mkdir -p ${MPL_RC_DIR}
- echo "backend : agg" > ${MPL_RC_FILE}
- echo "image.cmap : viridis" >> ${MPL_RC_FILE}
diff --git a/lib/iris/fileformats/netcdf.py b/lib/iris/fileformats/netcdf.py
index bb7a870d58..def393f0a3 100644
--- a/lib/iris/fileformats/netcdf.py
+++ b/lib/iris/fileformats/netcdf.py
@@ -1043,7 +1043,7 @@ def write(
dtype(i.e. 'i2', 'short', 'u4') or a dict of packing parameters as
described below. This provides support for netCDF data packing as
described in
- http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#bp_Packed-Data-Values
+ http://www.unidata.ucar.edu/software/netcdf/documentation/NUG/best_practices.html#bp_Packed-Data-Values
If this argument is a type (or type string), appropriate values of
scale_factor and add_offset will be automatically calculated based
on `cube.data` and possible masking. For more control, pass a dict
@@ -2589,7 +2589,7 @@ def save(
(i.e. 'i2', 'short', 'u4') or a dict of packing parameters as described
below or an iterable of such types, strings, or dicts.
This provides support for netCDF data packing as described in
- http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#bp_Packed-Data-Values
+ http://www.unidata.ucar.edu/software/netcdf/documentation/NUG/best_practices.html#bp_Packed-Data-Values
If this argument is a type (or type string), appropriate values of
scale_factor and add_offset will be automatically calculated based
on `cube.data` and possible masking. For more control, pass a dict with
From 7fd7960e25cefc48c49a6e518cfd02f42fa860ea Mon Sep 17 00:00:00 2001
From: tkknight <2108488+tkknight@users.noreply.github.com>
Date: Fri, 9 Apr 2021 12:18:42 +0100
Subject: [PATCH 40/43] Update readme docs stable (#4089)
* added stable docs links.
* changed layout
* updated layout
* tdy up html tags
---
README.md | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index cdef50096e..d06e6758a1 100644
--- a/README.md
+++ b/README.md
@@ -12,39 +12,42 @@
+ alt="Cirrus-CI">
+ alt="Documentation Status">
+ alt="pre-commit.ci status">
+ alt="conda-forge">
+ alt="pypi">
+ alt="latest release">
+ alt="Commits since last release">
+ alt="zenodo">
+ alt="black">
+ alt="github discussions">
+ alt="twitter scitools_iris">
-See the documentation for the latest development version of Iris.
+For documentation see the
+latest
+developer version or the most recent released
+stable version.
From 148edc33c3f0dcb0e9c5bc5608847eb30a8b447a Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Fri, 9 Apr 2021 15:09:57 +0100
Subject: [PATCH 41/43] Fix cirrus ci and mpl (#4087)
* fix mpl SymLogNorm
* update graphics tests phashes
* add whatsnew entries
* gallery image phash update
---
.../general/plot_anomaly_log_colouring.py | 6 +-
docs/src/whatsnew/latest.rst | 6 +
lib/iris/tests/results/imagerepo.json | 107 ++++++++++++------
3 files changed, 80 insertions(+), 39 deletions(-)
diff --git a/docs/gallery_code/general/plot_anomaly_log_colouring.py b/docs/gallery_code/general/plot_anomaly_log_colouring.py
index 846816aff7..5bde12ca39 100644
--- a/docs/gallery_code/general/plot_anomaly_log_colouring.py
+++ b/docs/gallery_code/general/plot_anomaly_log_colouring.py
@@ -68,14 +68,14 @@ def main():
# Create a 'logarithmic' data normalization.
anom_norm = mcols.SymLogNorm(
linthresh=minimum_log_level,
- linscale=0,
+ linscale=1,
vmin=-maximum_scale_level,
vmax=maximum_scale_level,
)
# Setting "linthresh=minimum_log_level" makes its non-logarithmic
# data range equal to our 'zero band'.
- # Setting "linscale=0" maps the whole zero band to the middle colour value
- # (i.e. 0.5), which is the neutral point of a "diverging" style colormap.
+ # Setting "linscale=1" maps the whole zero band to the middle colour value
+ # (i.e., 0.5), which is the neutral point of a "diverging" style colormap.
# Create an Axes, specifying the map projection.
plt.axes(projection=ccrs.LambertConformal())
diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst
index 72fc506353..0b8c517421 100644
--- a/docs/src/whatsnew/latest.rst
+++ b/docs/src/whatsnew/latest.rst
@@ -144,6 +144,12 @@ This document explains the changes made to Iris for this release
developers to easily disable `cirrus-ci`_ tasks. See
:ref:`skipping Cirrus-CI tasks`. (:pull:`4019`)
+#. `@bjlittle`_ and `@jamesp`_ addressed a regression in behaviour when using
+ `conda`_ 4.10.0 within `cirrus-ci`_. (:pull:`4084`)
+
+#. `@bjlittle`_ updated the perceptual imagehash graphical test support for
+ `matplotlib`_ 3.4.1. (:pull:`4087`)
+
.. comment
Whatsnew author names (@github name) in alphabetical order. Note that,
diff --git a/lib/iris/tests/results/imagerepo.json b/lib/iris/tests/results/imagerepo.json
index 6c2bf66ba6..d73c8492e5 100644
--- a/lib/iris/tests/results/imagerepo.json
+++ b/lib/iris/tests/results/imagerepo.json
@@ -23,7 +23,8 @@
"gallery_tests.test_plot_anomaly_log_colouring.TestAnomalyLogColouring.test_plot_anomaly_log_colouring.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/ec4464e185a39f93931e9b1e91696d2949dde6e63e26a47a5ad391938d9a5a0c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ecc164e78e979b19b3789b0885a564a56cc2c65e3ec69469db1bdb9a853c1e24.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ece164e68e979b19b3781b0885a564a56ccac65e3ec69469db1bdb9a853c1e24.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ece164e68e979b19b3781b0885a564a56ccac65e3ec69469db1bdb9a853c1e24.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ece164e796979a1b39781b2881a564a56ccac6da3e87947bcb1bdb9a843c1e24.png"
],
"gallery_tests.test_plot_atlantic_profiles.TestAtlanticProfiles.test_plot_atlantic_profiles.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc5d08fcd00fdb1c93fcb21c.png",
@@ -210,13 +211,15 @@
],
"iris.tests.test_mapping.TestBoundedCube.test_pcolormesh.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81e535857e92ca8ec23d21b13ce15e7a811ea5c47e1a5ac17b652d3b05e4f2.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81c17a857e1ea5857e634a7a81cd257e8584da857e3b29817e68f47a81c791.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81c17a857e1ea5857e634a7a81cd257e8584da857e3b29817e68f47a81c791.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81c17a857e1ea5857e734a7a81cd257e8484da857e3b29817a68f47a81c799.png"
],
"iris.tests.test_mapping.TestLimitedAreaCube.test_grid.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2b1c17f1d0ac4f7c8d739a637202749699b6bb3ce3666e4b048944d9d89.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2f1c17f1d0ac457c8d619a637213749699b6bb34e3666e4b04e944d9d89.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea05392995bac6d691ce3f21666569d86a96c6360ee195cb91e8ce54953b313b.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea05392995bac6d691ea3f21666569d86a97c6320ee195cb91e8ce559539391b.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea05392995bac6d691ea3f21666569d86a97c6320ee195cb91e8ce559539391b.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa1585e885ea7a1785fa7a157a177a017a1585e817a885ea85e86a1785fa7a17.png"
],
"iris.tests.test_mapping.TestLimitedAreaCube.test_outline.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e3e80857e7a817a817a817a81817f7a81857e857e857e857e7a81.png",
@@ -226,7 +229,8 @@
],
"iris.tests.test_mapping.TestLimitedAreaCube.test_pcolormesh.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/bf81e6b1c17e1d4884bfc8df39a43720374969db69b34e26c4e4b0ca904f9d89.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea57396995a8c6d691ea3f25664569d86b16c63686ed958991ea4a549531393b.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea57396995a8c6d691ea3f25664569d86b16c63686ed958991ea4a549531393b.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea57396995a8c6d691ea3e25664569d96b16c63684e9958b91ea4a559431793b.png"
],
"iris.tests.test_mapping.TestLimitedAreaCube.test_scatter.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d894346b24f3477acf68ad39329ed8c696e136c1ab9a71.png",
@@ -392,7 +396,8 @@
],
"iris.tests.test_plot.TestAttributePositive.test_2d_positive_down.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba684e194fb901b3a0587641ad03b1ae7674e64c15a5b99c767c47e3a98.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba484e194dbc01f3665c0e4399a3f0fc2653f90c99e3f613e64c81e3f81.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba484e194dbc01f3665c0e4399a3f0fc2653f90c99e3f613e64c81e3f81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fb966ba6846194dbd01f3665c0e4399a3f1bc2653f90c99e2f613e64c01e3f81.png"
],
"iris.tests.test_plot.TestAttributePositive.test_2d_positive_up.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/ee176c7f93e093a0c50f9383815e6e156859e17e6e15e17a9be08e2d851a9b83.png",
@@ -506,7 +511,8 @@
"https://scitools.github.io/test-iris-imagehash/images/v4/fa816ac1857e853cc17f957ac15f3e849486c8f43e81c13b3f813e91c07e3f46.png"
],
"iris.tests.test_plot.TestMissingCoord.test_no_u.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a954ac17f954a807e3f48951ac07e3e81c0ff7ea16a81c0ff3f81.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a954ac17f954a807e3f48951ac07e3e81c0ff7ea16a81c0ff3f81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a954ac17f954ac07e3f44951ac07e3e81c07f7ea16aa1c0ff3e81.png"
],
"iris.tests.test_plot.TestMissingCoord.test_no_u.1": [
"https://scitools.github.io/test-iris-imagehash/images/v4/ea956ab5954a954ac17e954a817f2f60950ac07f3e80c07f7a856aa5c2ff3f80.png"
@@ -585,7 +591,8 @@
"iris.tests.test_plot.TestPcolormesh.test_ty.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eabc789722.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea953f83954ac2fc956ac07e956a3509c0de61796ab57a816a854ad16ab590fb.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea953f83954ac2fc956ac07e956a3509c0de61796ab57a816a854ad16ab590fb.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea953f83954ac2bc956ac07e956a3509c0de61796ab57a916a856a916ab590fb.png"
],
"iris.tests.test_plot.TestPcolormesh.test_tz.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png",
@@ -597,7 +604,8 @@
],
"iris.tests.test_plot.TestPcolormesh.test_zx.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a16d5a97a17d5a97a17806785a7816685a7e86685ad687.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e6e05857e7a81857e7a81a0577a816a8585fa7a85857e7a81857e.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e6e05857e7a81857e7a81a0577a816a8585fa7a85857e7a81857e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857a7e01857e7a81857e7a81a0577a816a8585fa7a85857e7a85857e.png"
],
"iris.tests.test_plot.TestPcolormesh.test_zy.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f002d527f002f427fa82f42d6a8.png",
@@ -607,7 +615,8 @@
"iris.tests.test_plot.TestPcolormeshNoBounds.test_tx.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d84f17a1d94e2c11d938e9463678e.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1d94e2c11993ae9463678c.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea858782957a703f957a3878957a7a65957e6bc06ae56f806ad50fd06a859c50.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea858782957a703f957a3878957a7a65957e6bc06ae56f806ad50fd06a859c50.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea858782957a703f957a3878957a7a65957a6b806ae56f846ad50fd46a859c50.png"
],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_ty.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a1695a96a53c1f711b3c0f791b97b46943c3e06c436b5a.png",
@@ -615,7 +624,8 @@
],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_tz.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a56b40c3f06be2c1c0c3f07c0b3ebe96a13c1e6d5b694a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa813e81857e857a857e7a81857e6a85817b00e63eb93e857e81c17e7a81956e.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa813e81857e857a857e7a81857e6a85817b00e63eb93e857e81c17e7a81956e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa813e81857e857a857e7a81857e6a85817b0aa63e993e857e81c17e7a81956e.png"
],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_yx.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc785c39986cdc78ec792e7a6960d584939793c3438703873.png",
@@ -669,23 +679,27 @@
],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/fe8142f5c17ebd2cc16eb548954a9542916a347a915e60bd4afd68793f916296.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea853f10956ac5e1957a854e957a203e955e6aa76ae17aa16a856aaf6ab19e12.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea853f10956ac5e1957a854e957a203e955e6aa76ae17aa16a856aaf6ab19e12.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea853f10957a85e1957a854e957a203e955e6aa76ae17aa16a856a8f6ab1de12.png"
],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.1": [
"https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6b91d968c161b972d76aa462b5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6a91d96ac163b972d36aa462b5.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea853a85857a857a957a857a957ad05a857b3e946a606b917a816f647a853af4.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea853a85857a857a957a857a957ad05a857b3e946a606b917a816f647a853af4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea853a85957a857a957a857a957ac05ac56b3ac46ae16b817a816f647a853af4.png"
],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.2": [
"https://scitools.github.io/test-iris-imagehash/images/v4/8bf88f457a03b5307e16b561f007b53ed067217ac1786afec0f570bf8178681a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8bf98f057a03b5307e16b561f007b53ad067217ac1786afec0f570bf8178685a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eafdcec9bc219530b696a56694c2852a95656b7b81986acdc0e516adad186eda.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/eafdcec9f4219530b696a56694c3852a95656b7b85986acdc06516adad186e9a.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eafdcec9f4219530b696a56694c3852a95656b7b85986acdc06516adad186e9a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eafd86c9f8219430fe96a56684c3852e95656b7b85b86acdc0e5162da5186eda.png"
],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.3": [
"https://scitools.github.io/test-iris-imagehash/images/v4/8ffe8f367e05952afe05a50b980ded4bd05d69c2c1fb71c1c06272f4d0a06af4.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aff24ab7bd05952fbd0f950f914fcd48c47860f3e1b9329094266e345a850f6c.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/aff24ab7fd05952dbd0f950f914fcd40c47868f3e1b9329094266e345a850f6c.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aff24ab7fd05952dbd0f950f914fcd40c47868f3e1b9329094266e345a850f6c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aff21eb6bd04952cbc0f950f914fedc1c0f961f3e1f9329084266e345a850f6c.png"
],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.4": [
"https://scitools.github.io/test-iris-imagehash/images/v4/aa953d0f85fab50fd0f2956a7a1785fafa176877d00f68f1d02c60f2f008d0f0.png",
@@ -693,13 +707,15 @@
"https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e95b5419e97950d6853953ee053617ad05560fad01570fef001dabe.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebfaa56f96a1856cd681a56ee8162d52e8467e12c50c7e8095ad7e0095ad03ff.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eaa9b5699556854e9456854ed05625f9c0a92bfdc0a90afd81f97e00857e6af6.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/eaa9b5699556854e9456854ed05625f9d0a92bfdc0a90afd81f97e00855e7ab6.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaa9b5699556854e9456854ed05625f9d0a92bfdc0a90afd81f97e00855e7ab6.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaa9b5299d56854e9156856ed05625fdc0292bfdc0a90afd85b97e00857e6ad6.png"
],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.5": [
"https://scitools.github.io/test-iris-imagehash/images/v4/ebfaaf439e87b5019687b5019687b56ac05561fae07103fe6079687a607178f8.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebfa2d4b968795059e87970f6854697ae055697ac08561fad041d7aef001d6ae.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eb7a3e0c978187a4950190bc6856687a607e687bc0fcc1e394acfc0197fc2bfb.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/eaf73e0d9503852c950395ac9528c1fad16cc0f2d1ec6af2c0ec6a536a1797f3.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaf73e0d9503852c950395ac9528c1fad16cc0f2d1ec6af2c0ec6a536a1797f3.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaf73e0c9402952c950195acd528c1fac1ecc1f3c1ec63f3c0ec6a536a179ff2.png"
],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_x.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/aeb8b5095a87cd60386592d9ec97ad6dd23ca4f6d0797827f0096216c1f878e6.png",
@@ -807,7 +823,8 @@
],
"iris.tests.test_plot.TestPlotOtherCoordSystems.test_plot_tmerc.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/e63399cd99cd64b29999335965369b262649c98c9b3966c6998d3319ccd69333.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e665326d999ecc9b3319b3246666cce69b496cccccc9669923193336666699a6.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e665326d999ecc9b3319b3246666cce69b496cccccc9669923193336666699a6.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e665326d999acc9b3319b3246666cce69b496cccccc966996719333666669986.png"
],
"iris.tests.test_plot.TestQuickplotPlot.test_t.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5d67fd4e5962211d9c6a443da77d5389c8ed346d923d011d968dc00da48.png",
@@ -834,10 +851,12 @@
"https://scitools.github.io/test-iris-imagehash/images/v4/a3ffc1de7e009c7030019786f438cde3810fd93c9b734a778ce47c9799b02731.png"
],
"iris.tests.test_plot.TestSimple.test_bounds.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85954a957ac17e954ac17a9c3e956ac07e3e80c07f3e857aa5c27d3f80.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85954a957ac17e954ac17a9c3e956ac07e3e80c07f3e857aa5c27d3f80.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85954a957ac17e954ac17a9d22956ac0fe3e81c07f3e857aa5c27d3f80.png"
],
"iris.tests.test_plot.TestSimple.test_points.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a957ac17e954ac17e1ca2950bc07e3e80c07f3e807a85c1ff3f81.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a957ac17e954ac17e1ca2950bc07e3e80c07f3e807a85c1ff3f81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a957ac17e954ac17e0da2954bc07e3e81c07f3a806a85c1ff3f81.png"
],
"iris.tests.test_plot.TestSymbols.test_cloud_cover.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/e95a330c96a5ccf2695a330c96a5ccf2695a330c96b5ccf3694a330c96b5ccf3.png",
@@ -848,33 +867,40 @@
"https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad2f0c1f66ac1c55a4af4e550a52b3e05905e1e419e6f937e3b21.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad3f0c1f66a81e55a4af4e550a52b3e05905e1e419e6f937e1b21.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be8137f4954ac03fc0ff3e81d03f496a6d00b4af3ea0c07f6fa232c0db7f2d00.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/be813fe0954ac07fc0ff3e81c03fc97a6d0094af3f80c17f36a53240d97f2d82.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be813fe0954ac07fc0ff3e81c03fc97a6d0094af3f80c17f36a53240d97f2d82.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be8137e0954ac05fc0ff3e81c07fc97a6d0094af3fa0c17f36a53244d97e2da0.png"
],
"iris.tests.test_quickplot.TestLabels.test_contour.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee321fc96666919b6ec15fdca593600d2586785a259dfa5a01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee3217c9e66691996ec15fdca593680d2586785a259dfa5a01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a7fd95da7a01654a3217c962e4819a56c96f3c8593624da584da3b658db662db.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7fd955a7a016d1a3217c962e4819a56c96f3c859b624d2584de3a6999b662db.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7fd955a7a016d1a3217c962e4819a56c96f3c859b624d2584de3a6999b662db.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd95ea6a11258c3217c966e4019a56c96f3c859b62492584fe7a699db46adb.png"
],
"iris.tests.test_quickplot.TestLabels.test_contour.1": [
"https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf802f85c17fc17fc07eb42ac07f3f929130c07e3f80c07f7aa02e85c07f3e81.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf802f85c17fc17fc07eb42ac07f3f929130c07e3f80c07f7aa02e85c07f3e81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf802e85c07fc17fc07eb42ac17f3f829161c06e3f81c07f7ba02e85c07f3e81.png"
],
"iris.tests.test_quickplot.TestLabels.test_contourf.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/fe812f88957a955a857a9257c17f7aa5c03dc0bf5a85c07e7f402d40a57a3f01.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/be816a95957a957ac0fe1e8bc07f7f806e01c07f3f80c07f3fa23f00c07f3d00.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be816a95957a957ac0fe1e8bc07f7f806e01c07f3f80c07f3fa23f00c07f3d00.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be816a85957a955ac0ff1e8bc07f7f806e01c07f3f80c07f3fa23f80c07f3d00.png"
],
"iris.tests.test_quickplot.TestLabels.test_contourf.1": [
"https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf802f85c17fc17fc07eb42ac07f3f929130c07e3f80c07f7aa02e85c07f3e81.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf802f85c17fc17fc07eb42ac07f3f929130c07e3f80c07f7aa02e85c07f3e81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf802e85c07fc17fc07eb42ac17f3f829161c06e3f81c07f7ba02e85c07f3e81.png"
],
"iris.tests.test_quickplot.TestLabels.test_contourf.2": [
"https://scitools.github.io/test-iris-imagehash/images/v4/fa852f81955ac532c0bf9e89c57edae69357e13f4ea0c05a3f8561a4935a3e01.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/be816a95907ae508c17e955ac07f3fa0945bc07f3f80c07f3aa36f01c0ff3f80.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be816a95907ae508c17e955ac07f3fa0945bc07f3f80c07f3aa36f01c0ff3f80.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be816ab5907ae508c17e955ac07f3fa0945ac07f3f80c07f3aa32f81c0ff3f80.png"
],
"iris.tests.test_quickplot.TestLabels.test_contourf_nameless.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/faa52ec1955ac536c0bf9e09c57edae69357e13f4e80c0da2f81618493da3f01.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/be816af5907ee508c17e955ac03f3f809419c07f3f80c07f3a8b6f81c0ff3f80.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be816af5907ee508c17e955ac03f3f809419c07f3f80c07f3a8b6f81c0ff3f80.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be816ab5907ee508c17e975ac07f3fa09459c07f3f80c07f3a812f81c0ff3f80.png"
],
"iris.tests.test_quickplot.TestLabels.test_map.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png",
@@ -890,36 +916,45 @@
],
"iris.tests.test_quickplot.TestLabels.test_pcolor.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/bb423d4e94a5c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f2f81c07e3fa12da1c2fe3f80.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f2f81c07e3fa12da1c2fe3f80.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eea16abfc05ab500956e974ac13f3da0925ac07f3fa1c07e3fa12da1c25e3f80.png"
],
"iris.tests.test_quickplot.TestLabels.test_pcolormesh.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/bb433d4e94a4c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f3f81c07e3fa12da1c27e3f80.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f3f81c07e3fa12da1c27e3f80.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eea16abfc05ab500956e974ac13f3da0925ac07f3fa1c07e3fa12da1c25e3f80.png"
],
"iris.tests.test_quickplot.TestLabels.test_pcolormesh_str_symbol.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f3f80c07e3fa12da1c27f3f80.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f3f80c07e3fa12da1c27f3f80.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eea16abfc05ab500956e974ac13f3da0925ac07f3fa1c07e3fa12da1c25e3f80.png"
],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_non_cube_coordinate.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85857a955ae17e957ec57e7a81855fc17e3a81c57e1a813a85c57a1a05.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe816a85857a957ac07f957ac07f3e80956ac07f3e80c07f3e813e85c07e3f80.png"
],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a956ac17f950a807e3f4c951ac07e3f81c0ff3ea16aa1c0bd3f81.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a956ac17f950a807e3f4c951ac07e3f81c0ff3ea16aa1c0bd3f81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a954ac17f950ac07e3f44951ac07e3f81c0ff3ea16aa1c0ff3e81.png"
],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a957ac17e954ac17e1ca2950bc07e3e80c07f3e807a85c1ff3f81.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a957ac17e954ac17e1ca2950bc07e3e80c07f3e807a85c1ff3f81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a957ac17e954ac17e0da2954bc07e3e81c07f3a806a85c1ff3f81.png"
],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eafdeec9f729943032168d66d4cb896e9567497b81304aedc96514ad8d18669a.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eafdeec9f729943032168d66d4cb896e9567497b81304aedc96514ad8d18669a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaf9a6c9f728943032168d66d4cb8d2e9567497b81304aedc9e51e2d9d186ada.png"
],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a6fb4b967f00950eb00f9d0f900fcd62dc7868f2c1bb3a909c266e34daa52f6c.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a6fb4b967f00950eb00f9d0f900fcd62dc7868f2c1bb3a909c266e34daa52f6c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a6fa1e967f00950eb00f9d0f914fcdc2d560c9f3c1fb3a9084266e34daa52f6c.png"
],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eaa9b549f756854ea0168d6ed556896dd8e909ed88290afdd9e97e008d6e2296.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaa9b549f756854ea0168d6ed556896dd8e909ed88290afdd9e97e008d6e2296.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaa9b529f756850ea0169566d1568d6dd86909ed88290afd9ded7e008d666ad6.png"
],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/aad73e0df78085ac840395ac9428d9fad56cd8f2906c48f2d0ec7a536a1737f3.png"
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aad73e0df78085ac840395ac9428d9fad56cd8f2906c48f2d0ec7a536a1737f3.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aad73e0cf710952c840195acd528c1e2d1ecc9f3c1ec49f3c1ec6a536a1737f3.png"
],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_x.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/a6ffb5097e84cde2224598d1649f8d6cd2388c76d0799867d009da76c9f8d866.png",
@@ -1013,4 +1048,4 @@
"https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002addd4002805dd28df67d9a9d4625bfddc209841de20.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/82fa80997f547799a0037a00d52f0956ddaf9f7e98a1816e09f5d8260bfffe00.png"
]
-}
+}
\ No newline at end of file
From b14a11499c4d1736a126aac698123335346970eb Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Fri, 9 Apr 2021 15:28:54 +0100
Subject: [PATCH 42/43] pre-commit-ci update (#4092)
---
.pre-commit-config.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 2c1cbdb68c..cea9d3585d 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -23,7 +23,7 @@ repos:
# Force black to run on whole repo, using settings from pyproject.toml
pass_filenames: false
args: [--config=./pyproject.toml, .]
-- repo: https://gitlab.com/pycqa/flake8
+- repo: https://github.com/PyCQA/flake8
rev: '3.9.0'
hooks:
# Run flake8.
From 8f6bb4406be10634b7c84bd355b0bae6552e4bb3 Mon Sep 17 00:00:00 2001
From: Bill Little
Date: Fri, 9 Apr 2021 17:19:04 +0100
Subject: [PATCH 43/43] fix merge conflict for cirrus-ci env variable
---
.cirrus.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.cirrus.yml b/.cirrus.yml
index d182bf6aa7..11e257af30 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -43,7 +43,7 @@ env:
# Conda packages to be installed.
CONDA_CACHE_PACKAGES: "nox pip"
# Git commit hash for iris test data.
- IRIS_TEST_DATA_REF: "v2.2"
+ IRIS_TEST_DATA_VERSION: "2.2"
# Base directory for the iris-test-data.
IRIS_TEST_DATA_DIR: ${HOME}/iris-test-data