From 90df204e960efaa35252106c7c498abbaee7d713 Mon Sep 17 00:00:00 2001 From: Bill Little Date: Mon, 22 Feb 2021 22:24:53 +0000 Subject: [PATCH 1/2] minor fixes --- lib/iris/common/metadata.py | 29 +++++++++++++------ lib/iris/experimental/ugrid.py | 11 ++++--- .../common/metadata/test_metadata_filter.py | 20 ++++++++++++- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/lib/iris/common/metadata.py b/lib/iris/common/metadata.py index e81c6b206c..801ba57c44 100644 --- a/lib/iris/common/metadata.py +++ b/lib/iris/common/metadata.py @@ -27,10 +27,6 @@ __all__ = [ - "SERVICES_COMBINE", - "SERVICES_DIFFERENCE", - "SERVICES_EQUAL", - "SERVICES", "AncillaryVariableMetadata", "BaseMetadata", "CellMeasureMetadata", @@ -38,7 +34,12 @@ "CubeMetadata", "DimCoordMetadata", "hexdigest", + "metadata_filter", "metadata_manager_factory", + "SERVICES", + "SERVICES_COMBINE", + "SERVICES_DIFFERENCE", + "SERVICES_EQUAL", ] @@ -1353,13 +1354,13 @@ def metadata_filter( ): """ Filter a collection of objects by their metadata to fit the given metadata - criteria. Criteria be one or both of: specific properties / other objects + criteria. Criteria can be one or both of: specific properties / other objects carrying metadata to be matched. Args: * instances - An iterable of objects to be filtered. + One or more objects to be filtered. Kwargs: @@ -1408,6 +1409,10 @@ def metadata_filter( else: obj = item + # apply de morgan's law for one less logical operation + if not (isinstance(instances, str) or isinstance(instances, Iterable)): + instances = [instances] + result = instances if name is not None: @@ -1449,10 +1454,16 @@ def attr_filter(instance): if axis is not None: axis = axis.upper() + + def get_axis(instance): + if hasattr(instance, "axis"): + axis = instance.axis.upper() + else: + axis = guess_coord_axis(instance) + return axis + result = [ - instance - for instance in result - if guess_coord_axis(instance) == axis + instance for instance in result if get_axis(instance) == axis ] if obj is not None: diff --git a/lib/iris/experimental/ugrid.py b/lib/iris/experimental/ugrid.py index 45c94dbf16..54200a4d1c 100644 --- a/lib/iris/experimental/ugrid.py +++ b/lib/iris/experimental/ugrid.py @@ -11,7 +11,7 @@ """ from abc import ABC, abstractmethod -from collections import namedtuple +from collections import Iterable, namedtuple from functools import wraps import dask.array as da @@ -20,18 +20,18 @@ from .. import _lazy_data as _lazy from ..common.metadata import ( BaseMetadata, + metadata_filter, metadata_manager_factory, SERVICES, SERVICES_COMBINE, SERVICES_EQUAL, SERVICES_DIFFERENCE, - metadata_filter, ) from ..common.lenient import _lenient_service as lenient_service from ..common.mixin import CFVariableMixin from ..config import get_logger from ..coords import _DimensionalMetadata, AuxCoord -from ..exceptions import CoordinateNotFoundError, ConnectivityNotFoundError +from ..exceptions import ConnectivityNotFoundError, CoordinateNotFoundError from ..util import guess_coord_axis @@ -831,6 +831,7 @@ def __init__( self, topology_dimension, node_coords_and_axes, + connectivities, standard_name=None, long_name=None, var_name=None, @@ -838,7 +839,6 @@ def __init__( attributes=None, edge_coords_and_axes=None, face_coords_and_axes=None, - connectivities=None, node_dimension=None, edge_dimension=None, face_dimension=None, @@ -896,6 +896,9 @@ def normalise(location, axis): ) raise ValueError(emsg) + if not isinstance(connectivities, Iterable): + connectivities = [connectivities] + if self.topology_dimension == 1: self._coord_manager = _Mesh1DCoordinateManager(**kwargs) self._connectivity_manager = _Mesh1DConnectivityManager( diff --git a/lib/iris/tests/unit/common/metadata/test_metadata_filter.py b/lib/iris/tests/unit/common/metadata/test_metadata_filter.py index dafb50554b..b5dad2864c 100644 --- a/lib/iris/tests/unit/common/metadata/test_metadata_filter.py +++ b/lib/iris/tests/unit/common/metadata/test_metadata_filter.py @@ -25,6 +25,13 @@ class Test_standard(tests.IrisTest): + def test_instances_non_iterable(self): + item = Mock() + item.name.return_value = "one" + result = metadata_filter(item, item="one") + self.assertEqual(1, len(result)) + self.assertIn(item, result) + def test_name(self): name_one = Mock() name_one.name.return_value = "one" @@ -101,14 +108,25 @@ def test_invalid_attributes(self): attributes="one", ) - def test_axis(self): + def test_axis__by_guess(self): + # see https://docs.python.org/3/library/unittest.mock.html#deleting-attributes axis_lon = Mock(standard_name="longitude") + del axis_lon.axis axis_lat = Mock(standard_name="latitude") + del axis_lat.axis input_list = [axis_lon, axis_lat] result = metadata_filter(input_list, axis="x") self.assertIn(axis_lon, result) self.assertNotIn(axis_lat, result) + def test_axis__by_member(self): + axis_x = Mock(axis="x") + axis_y = Mock(axis="y") + input_list = [axis_x, axis_y] + result = metadata_filter(input_list, axis="x") + self.assertEqual(1, len(result)) + self.assertIn(axis_x, result) + def test_multiple_args(self): coord_one = Mock(__class__=AuxCoord, long_name="one") coord_two = Mock(__class__=AuxCoord, long_name="two") From ae1d142b116fda86377230d67f30729df08b5b94 Mon Sep 17 00:00:00 2001 From: Bill Little Date: Tue, 23 Feb 2021 08:17:00 +0000 Subject: [PATCH 2/2] wip --- lib/iris/experimental/ugrid.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/iris/experimental/ugrid.py b/lib/iris/experimental/ugrid.py index 54200a4d1c..f9f6b8a10f 100644 --- a/lib/iris/experimental/ugrid.py +++ b/lib/iris/experimental/ugrid.py @@ -874,6 +874,12 @@ def normalise(location, axis): raise ValueError(emsg) return f"{location}_{axis}" + if not isinstance(node_coords_and_axes, Iterable): + node_coords_and_axes = [node_coords_and_axes] + + if not isinstance(connectivities, Iterable): + connectivities = [connectivities] + kwargs = {} for coord, axis in node_coords_and_axes: kwargs[normalise("node", axis)] = coord @@ -896,9 +902,6 @@ def normalise(location, axis): ) raise ValueError(emsg) - if not isinstance(connectivities, Iterable): - connectivities = [connectivities] - if self.topology_dimension == 1: self._coord_manager = _Mesh1DCoordinateManager(**kwargs) self._connectivity_manager = _Mesh1DConnectivityManager(