Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate legacy_custom_rules #1836

Merged
merged 2 commits into from
Nov 17, 2015
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
14 changes: 2 additions & 12 deletions lib/iris/fileformats/grib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@
hindcast_workaround = False


# rules for converting a grib message to a cm cube
_load_rules = None


CENTRE_TITLES = {'egrr': 'U.K. Met Office - Exeter',
'ecmf': 'European Centre for Medium Range Weather Forecasts',
'rjtd': 'Tokyo, Japan Meteorological Agency',
Expand Down Expand Up @@ -127,13 +123,8 @@ def reset_load_rules():
.. deprecated:: 1.7

"""
# Uses this module-level variable
global _load_rules

warnings.warn('reset_load_rules was deprecated in v1.7.')

_load_rules = None


class GribDataProxy(object):
"""A reference to the data payload of a single Grib message."""
Expand Down Expand Up @@ -903,7 +894,7 @@ def load_cubes(filenames, callback=None, auto_regularise=True):
grib_loader = iris.fileformats.rules.Loader(
_GribMessage.messages_from_filename,
{},
iris.fileformats.grib._load_convert.convert, None)
iris.fileformats.grib._load_convert.convert)
else:
if auto_regularise is not None:
# The old loader supports the auto_regularise keyword, but in
Expand All @@ -916,8 +907,7 @@ def load_cubes(filenames, callback=None, auto_regularise=True):

grib_loader = iris.fileformats.rules.Loader(
grib_generator, {'auto_regularise': auto_regularise},
iris.fileformats.grib.load_rules.convert,
_load_rules)
iris.fileformats.grib.load_rules.convert)
return iris.fileformats.rules.load_cubes(filenames, callback, grib_loader)


Expand Down
28 changes: 2 additions & 26 deletions lib/iris/fileformats/pp.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@
EARTH_RADIUS = 6371229.0


# PP->Cube and Cube->PP rules are loaded on first use
_load_rules = None
# Cube->PP rules are loaded on first use
_save_rules = None


Expand Down Expand Up @@ -1891,38 +1890,15 @@ def _field_gen(filename, read_data_bytes):
yield pp_field


def _ensure_load_rules_loaded():
"""Makes sure the standard conversion and verification rules are loaded."""

# Uses these module-level variables
global _load_rules, _cross_reference_rules

rules = iris.fileformats.rules

if _load_rules is None:
basepath = iris.config.CONFIG_PATH
_load_rules = rules.RulesContainer(os.path.join(basepath, 'pp_rules.txt'))

if _cross_reference_rules is None:
basepath = iris.config.CONFIG_PATH
_cross_reference_rules = rules.RulesContainer(os.path.join(basepath, 'pp_cross_reference_rules.txt'),
rule_type=rules.ObjectReturningRule)


def reset_load_rules():
"""
Resets the PP load process to use only the standard conversion rules.

.. deprecated:: 1.7

"""
# Uses this module-level variable
global _load_rules

warnings.warn('reset_load_rules was deprecated in v1.7.')

_load_rules = None


def _ensure_save_rules_loaded():
"""Makes sure the standard save rules are loaded."""
Expand Down Expand Up @@ -2059,7 +2035,7 @@ def _load_cubes_variable_loader(filenames, callback, loading_function,
pp_filter = _convert_constraints(constraints)
pp_loader = iris.fileformats.rules.Loader(
loading_function, loading_function_kwargs or {},
iris.fileformats.pp_rules.convert, _load_rules)
iris.fileformats.pp_rules.convert)
return iris.fileformats.rules.load_cubes(filenames, callback, pp_loader,
pp_filter)

Expand Down
40 changes: 37 additions & 3 deletions lib/iris/fileformats/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -779,9 +779,41 @@ def _ensure_aligned(regrid_cache, src_cube, target_cube):
return result_cube


Loader = collections.namedtuple('Loader',
('field_generator', 'field_generator_kwargs',
'converter', 'legacy_custom_rules'))
_loader_attrs = ('field_generator', 'field_generator_kwargs',
'converter', 'legacy_custom_rules')
class Loader(collections.namedtuple('Loader', _loader_attrs)):
def __new__(cls, field_generator, field_generator_kwargs, converter,
legacy_custom_rules=None):
"""
Create a definition of a field-based Cube loader.

Args:

* field_generator
A callable that accepts a filename as its first argument and
returns an iterable of field objects.

* field_generator_kwargs
Additional arguments to be passed to the field_generator.

* converter
A callable that converts a field object into a Cube.

Kwargs:

* legacy_custom_rules
An object with a callable `verify` attribute with two
parameters: (cube, field). Legacy method for modifying
Cubes during the load process. Default is None.

.. deprecated:: 1.9

"""
if legacy_custom_rules is not None:
warnings.warn('The `legacy_custom_rules` attribute is '
'deprecated.')
return tuple.__new__(cls, (field_generator, field_generator_kwargs,
converter, legacy_custom_rules))


ConversionMetadata = collections.namedtuple('ConversionMetadata',
Expand Down Expand Up @@ -846,6 +878,8 @@ def load_cubes(filenames, user_callback, loader, filter_function=None):

# Run any custom user-provided rules.
if loader.legacy_custom_rules:
warnings.warn('The `legacy_custom_rules` attribute of '
'the `loader` is deprecated.')
loader.legacy_custom_rules.verify(cube, field)

cube = iris.io.run_callback(user_callback, cube, field, filename)
Expand Down
9 changes: 3 additions & 6 deletions lib/iris/tests/integration/test_pp_constrained_load_cubes.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ def test_pp_with_stash_constraint(self):
filenames = [tests.get_data_path(('PP', 'globClim1', 'dec_subset.pp'))]
stcon = iris.AttributeConstraint(STASH='m01s00i004')
pp_constraints = pp._convert_constraints(stcon)
pp_loader = iris.fileformats.rules.Loader(pp.load, {},
convert, pp._load_rules)
pp_loader = iris.fileformats.rules.Loader(pp.load, {}, convert)
cubes = list(load_cubes(filenames, None, pp_loader, pp_constraints))
self.assertEqual(len(cubes), 38)

Expand All @@ -46,17 +45,15 @@ def test_pp_with_stash_constraints(self):
stcon1 = iris.AttributeConstraint(STASH='m01s00i004')
stcon2 = iris.AttributeConstraint(STASH='m01s00i010')
pp_constraints = pp._convert_constraints([stcon1, stcon2])
pp_loader = iris.fileformats.rules.Loader(pp.load, {},
convert, pp._load_rules)
pp_loader = iris.fileformats.rules.Loader(pp.load, {}, convert)
cubes = list(load_cubes(filenames, None, pp_loader, pp_constraints))
self.assertEqual(len(cubes), 76)

@tests.skip_data
def test_pp_no_constraint(self):
filenames = [tests.get_data_path(('PP', 'globClim1', 'dec_subset.pp'))]
pp_constraints = pp._convert_constraints(None)
pp_loader = iris.fileformats.rules.Loader(pp.load, {},
convert, pp._load_rules)
pp_loader = iris.fileformats.rules.Loader(pp.load, {}, convert)
cubes = list(load_cubes(filenames, None, pp_loader, pp_constraints))
self.assertEqual(len(cubes), 152)

Expand Down
73 changes: 73 additions & 0 deletions lib/iris/tests/unit/fileformats/rules/test_Loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# (C) British Crown Copyright 2015, Met Office
#
# This file is part of Iris.
#
# Iris is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Iris is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Iris. If not, see <http://www.gnu.org/licenses/>.
"""Unit tests for :class:`iris.fileformats.rules.Loader`."""

from __future__ import (absolute_import, division, print_function)
from six.moves import (filter, input, map, range, zip) # noqa

# Import iris.tests first so that some things can be initialised before
# importing anything else.
import iris.tests as tests

import mock

from iris.fileformats.rules import Loader


class Test___init__(tests.IrisTest):
def test_normal(self):
with mock.patch('warnings.warn') as warn:
loader = Loader(mock.sentinel.GEN_FUNC,
mock.sentinel.GEN_FUNC_KWARGS,
mock.sentinel.CONVERTER)
self.assertEqual(warn.call_count, 0)
self.assertIs(loader.field_generator, mock.sentinel.GEN_FUNC)
self.assertIs(loader.field_generator_kwargs,
mock.sentinel.GEN_FUNC_KWARGS)
self.assertIs(loader.converter, mock.sentinel.CONVERTER)
self.assertIs(loader.legacy_custom_rules, None)

def test_normal_with_explicit_none(self):
with mock.patch('warnings.warn') as warn:
loader = Loader(mock.sentinel.GEN_FUNC,
mock.sentinel.GEN_FUNC_KWARGS,
mock.sentinel.CONVERTER, None)
self.assertEqual(warn.call_count, 0)
self.assertIs(loader.field_generator, mock.sentinel.GEN_FUNC)
self.assertIs(loader.field_generator_kwargs,
mock.sentinel.GEN_FUNC_KWARGS)
self.assertIs(loader.converter, mock.sentinel.CONVERTER)
self.assertIs(loader.legacy_custom_rules, None)

def test_deprecated_custom_rules(self):
with mock.patch('warnings.warn') as warn:
loader = Loader(mock.sentinel.GEN_FUNC,
mock.sentinel.GEN_FUNC_KWARGS,
mock.sentinel.CONVERTER,
mock.sentinel.CUSTOM_RULES)
self.assertEqual(warn.call_count, 1)
self.assertEqual(warn.call_args[0][0],
'The `legacy_custom_rules` attribute is deprecated.')
self.assertIs(loader.field_generator, mock.sentinel.GEN_FUNC)
self.assertIs(loader.field_generator_kwargs,
mock.sentinel.GEN_FUNC_KWARGS)
self.assertIs(loader.converter, mock.sentinel.CONVERTER)
self.assertIs(loader.legacy_custom_rules, mock.sentinel.CUSTOM_RULES)


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