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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions lib/iris/fileformats/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ def _resolve_factory_references(cube, factories, concrete_reference_targets,


def _load_pairs_from_fields_and_filenames(fields_and_filenames, converter,
user_callback=None):
user_callback_wrapper=None):
# The underlying mechanism for the public 'load_pairs_from_fields' and
# 'load_cubes'.
# Slightly more complicated than 'load_pairs_from_fields', only because it
Expand All @@ -962,10 +962,14 @@ def _load_pairs_from_fields_and_filenames(fields_and_filenames, converter,
cube, factories, references = _make_cube(field, converter)

# Post modify the new cube with a user-callback.
# This an ordinary Iris load callback, so it takes the filename.
cube = iris.io.run_callback(user_callback, cube, field, filename)

# Cross referencing
# This is an ordinary Iris load callback, so it takes the filename.
cube = iris.io.run_callback(user_callback_wrapper,
cube, field, filename)
# Callback mechanism may return None, which must not be yielded.
if cube is None:
continue

# Cross referencing.
for reference in references:
name = reference.name
# Register this cube as a source cube for the named reference.
Expand Down Expand Up @@ -1017,7 +1021,7 @@ def load_cubes(filenames, user_callback, loader, filter_function=None):
def _generate_all_fields_and_filenames():
for filename in filenames:
for field in loader.field_generator(
filename, **loader.field_generator_kwargs):
filename, **loader.field_generator_kwargs):
# evaluate field against format specific desired attributes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dkillick This private functions doesn't appear to have changed, apart from its position in the file.

Sorry for being a pain, but could you paste it back, as it introduces unnecessary noise, thanks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops! Swap did occur 😒 Will shift it back!

# load if no format specific desired attributes are violated
if filter_function is None or filter_function(field):
Expand All @@ -1031,13 +1035,15 @@ def loadcubes_user_callback_wrapper(cube, field, filename):
loader.legacy_custom_rules.verify(cube, field)

# Then also run user-provided original callback function.
cube = iris.io.run_callback(user_callback, cube, field, filename)
return cube
result = cube
if user_callback is not None:
result = user_callback(cube, field, filename)
return result

all_fields_and_filenames = _generate_all_fields_and_filenames()
for cube, field in _load_pairs_from_fields_and_filenames(
all_fields_and_filenames,
converter=loader.converter,
user_callback=loadcubes_user_callback_wrapper):
user_callback_wrapper=loadcubes_user_callback_wrapper):
yield cube

23 changes: 23 additions & 0 deletions lib/iris/tests/integration/test_pp.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from iris.cube import Cube
import iris.fileformats.pp
import iris.fileformats.pp_rules
from iris.exceptions import IgnoreCubeException
from iris.tests import mock
from iris.fileformats.pp import load_pairs_from_fields

Expand Down Expand Up @@ -636,5 +637,27 @@ def test_time_mean_and_zonal_mean(self):
self.assertEqual(int(field.lbproc), 192)


class TestCallbackLoad(tests.IrisTest):
def setUp(self):
self.pass_name = 'air_potential_temperature'

def callback_wrapper(self):
# Wrap the `iris.exceptions.IgnoreCubeException`-calling callback.
def callback_ignore_cube_exception(cube, field, filename):
if cube.name() != self.pass_name:
raise IgnoreCubeException
return callback_ignore_cube_exception

def test_ignore_cube_callback(self):
test_dataset = tests.get_data_path(
['PP', 'globClim1', 'dec_subset.pp'])
exception_callback = self.callback_wrapper()
result_cubes = iris.load(test_dataset, callback=exception_callback)
n_result_cubes = len(result_cubes)
# We ignore all but one cube (the `air_potential_temperature` cube).
self.assertEqual(n_result_cubes, 1)
self.assertEqual(result_cubes[0].name(), self.pass_name)


if __name__ == "__main__":
tests.main()