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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/iris/_concatenate.py
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,12 @@ def concatenate(self):

# Build the new cube.
kwargs = cube_signature.defn._asdict()
# Hack for now just to make this work, since we added a "global_attributes"
# field to CubeMetadata, which we are not yet using, but we have no matching
# keyword in the Cube constructor call.
kwargs.pop("global_attributes")
# TODO-splitattrs: in future we will provide some way of passing separate
# local+global attributes into the Cube constructor. Fix this properly then.
cube = iris.cube.Cube(
data,
dim_coords_and_dims=dim_coords_and_dims,
Expand Down
9 changes: 9 additions & 0 deletions lib/iris/_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,9 @@ def _defn_msgs(self, other_defn):
)
)
if self_defn.attributes != other_defn.attributes:
# TODO-splitattrs: this needs to change to handle both global + local
# attributes, when they are in active use. We probably *ought* to be using
# metadata.difference for this.
diff_keys = set(self_defn.attributes.keys()) ^ set(
other_defn.attributes.keys()
)
Expand Down Expand Up @@ -1594,6 +1597,12 @@ def _get_cube(self, data):
for coord, dims in self._aux_coords_and_dims
]
kwargs = dict(zip(CubeMetadata._fields, signature.defn))
# Hack for now just to make this work, since we added a "global_attributes"
# field to CubeMetadata, which we are not yet using, but we have no matching
# keyword in the Cube constructor call.
kwargs.pop("global_attributes")
# TODO-splitattrs: in future we will provide some way of passing separate
# local+global attributes into the Cube constructor. Fix this properly then.

cms_and_dims = [
(deepcopy(cm), dims) for cm, dims in self._cell_measures_and_dims
Expand Down
51 changes: 39 additions & 12 deletions lib/iris/common/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ def _difference_strict_attributes(left, right):
def _is_attributes(field, left, right):
"""Determine whether we have two 'attributes' dictionaries."""
return (
field == "attributes"
field in ("attributes", "global_attributes")
and isinstance(left, Mapping)
and isinstance(right, Mapping)
)
Expand Down Expand Up @@ -1081,7 +1081,7 @@ class CubeMetadata(BaseMetadata):

"""

_members = "cell_methods"
_members = ("cell_methods", "global_attributes")

__slots__ = ()

Expand All @@ -1101,7 +1101,11 @@ def __lt__(self, other):
def _sort_key(item):
keys = []
for field in item._fields:
if field not in ("attributes", "cell_methods"):
if field not in (
"attributes",
"global_attributes",
"cell_methods",
):
value = getattr(item, field)
keys.extend((value is not None, value))
return tuple(keys)
Expand All @@ -1121,16 +1125,30 @@ def _combine_lenient(self, other):
A list of combined metadata member values.

"""
# Perform lenient combination of parent (BaseMetadata) members.
result = super()._combine_lenient(other)
# Perform "strict" combination for "cell_methods".
value = (
self.cell_methods
if self.cell_methods == other.cell_methods
else None
)
# Perform lenient combination of the other parent members.
result = super()._combine_lenient(other)
result.append(value)

# Perform lenient combination for "global_attributes"
left = self.global_attributes
right = other.global_attributes
value = None
if self._is_attributes("global_attributes", left, right):
value = self._combine_lenient_attributes(left, right)
else:
# Default logic is the general fallback for member comparison
if left == right:
value = left
elif left is None:
value = right
elif right is None:
value = left
result.append(value)
return result

def _compare_lenient(self, other):
Expand All @@ -1149,8 +1167,13 @@ def _compare_lenient(self, other):
# Perform "strict" comparison for "cell_methods".
result = self.cell_methods == other.cell_methods
if result:
# Perform lenient comparison of global_attributes.
result = self._compare_lenient_attributes(
self.global_attributes, other.global_attributes
)
if result:
# Compare BaseMetadata aspects.
result = super()._compare_lenient(other)

return result

def _difference_lenient(self, other):
Expand All @@ -1166,16 +1189,20 @@ def _difference_lenient(self, other):
A list of difference metadata member values.

"""
# Perform "strict" difference for "cell_methods".
value = (
# Perform lenient difference of the other parent members.
result = super()._difference_lenient(other)
# Calculate + add "strict" difference for "cell_methods".
cms_value = (
None
if self.cell_methods == other.cell_methods
else (self.cell_methods, other.cell_methods)
)
# Perform lenient difference of the other parent members.
result = super()._difference_lenient(other)
result.append(value)
# Calculate + add "lenient" difference for "global_attributes".
gattrs_value = self._difference_lenient_attributes(
self.global_attributes, other.global_attributes
)

result.extend([cms_value, gattrs_value])
return result

@property
Expand Down
6 changes: 5 additions & 1 deletion lib/iris/common/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,8 @@ def metadata(self, metadata):

# Ensure to always set state through the individual mixin/container
# setter functions.
setattr(self, field, value)
# Since we don't have a 'global_attributes' cube property, we need to avoid
# setting a property that doesn't exist.
# TODO - splitattrs: fix this properly later.
if hasattr(self, field):
setattr(self, field, value)
5 changes: 4 additions & 1 deletion lib/iris/experimental/stratify.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,10 @@ def relevel(cube, src_levels, tgt_levels, axis=None, interpolator=None):
new_data = interpolator(tgt_levels, src_data, cube_data, axis=axis)

# Create a result cube with the correct shape and metadata.
result = Cube(new_data, **cube.copy().metadata._asdict())
# TODO-splitattrs: fix this
kwargs = cube.metadata._asdict()
kwargs.pop("global_attributes")
result = Cube(new_data, **kwargs)

# Copy across non z-dimension coordinates from the source cube
# to the result cube.
Expand Down
13 changes: 10 additions & 3 deletions lib/iris/tests/test_cdm.py
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,15 @@ def test_metadata_nop(self):
self.assertEqual(self.t.cell_methods, ())

def test_metadata_tuple(self):
metadata = ("air_pressure", "foo", "bar", "", {"random": "12"}, ())
metadata = (
"air_pressure",
"foo",
"bar",
"",
{"random": "12"},
(),
{"extra": 4},
)
self.t.metadata = metadata
self.assertEqual(self.t.standard_name, "air_pressure")
self.assertEqual(self.t.long_name, "foo")
Expand Down Expand Up @@ -989,7 +997,7 @@ class Metadata:
metadata.units = ""
metadata.attributes = {"random": "12"}
metadata.cell_methods = ()
metadata.cell_measures_and_dims = []
metadata.global_attributes = {"extra": 4}
self.t.metadata = metadata
self.assertEqual(self.t.standard_name, "air_pressure")
self.assertEqual(self.t.long_name, "foo")
Expand All @@ -998,7 +1006,6 @@ class Metadata:
self.assertEqual(self.t.attributes, metadata.attributes)
self.assertIsNot(self.t.attributes, metadata.attributes)
self.assertEqual(self.t.cell_methods, ())
self.assertEqual(self.t._cell_measures_and_dims, [])

def test_metadata_fail(self):
with self.assertRaises(TypeError):
Expand Down
Loading