diff --git a/docs/iris/src/userguide/saving_iris_cubes.rst b/docs/iris/src/userguide/saving_iris_cubes.rst index d1658ef70e..ecf2210810 100644 --- a/docs/iris/src/userguide/saving_iris_cubes.rst +++ b/docs/iris/src/userguide/saving_iris_cubes.rst @@ -82,7 +82,7 @@ For example, a GRIB2 message with a particular known long_name may need to be sa Similarly a PP field may need to be written out with a specific value for LBEXP. This can be achieved by:: def tweaked_fields(cube): - for cube, field in iris.fileformats.pp.as_pairs(cube): + for cube, field in iris.fileformats.pp.save_pairs_from_cube(cube): # post process the PP field, prior to saving if cube.name() == 'air_pressure': field.lbexp = 'meaxp' diff --git a/lib/iris/fileformats/pp.py b/lib/iris/fileformats/pp.py index 5f79a8966e..c69e08f4c8 100644 --- a/lib/iris/fileformats/pp.py +++ b/lib/iris/fileformats/pp.py @@ -58,11 +58,9 @@ pp_packing = None -__all__ = ['load', 'save', 'load_cubes', 'PPField', - 'reset_load_rules', 'add_save_rules', - 'as_fields', 'load_pairs_from_fields', 'as_pairs', - 'save_pairs_from_cube', 'reset_save_rules', - 'save_fields', 'STASH', 'EARTH_RADIUS'] +__all__ = ['load', 'save', 'load_cubes', 'PPField', 'as_fields', + 'load_pairs_from_fields', 'save_pairs_from_cube', 'save_fields', + 'STASH', 'EARTH_RADIUS'] EARTH_RADIUS = 6371229.0 @@ -716,87 +714,9 @@ def __init__(self, value): 'splittable integers object') self._value = value - def __len__(self): - """ - Base ten length. - - .. deprecated:: 1.8 - - The value of a BitwiseInt only makes sense in base-two. - - """ - warn_deprecated('Length is deprecated') - return len(str(self._value)) - def __setattr__(self, name, value): object.__setattr__(self, name, value) - def __getitem__(self, key): - """ - Base ten indexing support. - - .. deprecated:: 1.8 - - The value of an _LBProc only makes sense in base-two. - - """ - warn_deprecated('Indexing is deprecated') - try: - value = int('0' + str(self._value)[::-1][key][::-1]) - except IndexError: - value = 0 - # If the key returns a list of values, then combine them - # together to an integer. - if isinstance(value, list): - value = sum(10**i * val for i, val in enumerate(value)) - return value - - def __setitem__(self, key, value): - """ - Base ten indexing support. - - .. deprecated:: 1.8 - - The value of an _LBProc only makes sense in base-two. - - """ - warn_deprecated('Indexing is deprecated') - if (not isinstance(value, int) or value < 0): - msg = 'Can only set {} as a positive integer value.'.format(key) - raise ValueError(msg) - - if isinstance(key, slice): - if ((key.start is not None and key.start < 0) or - (key.step is not None and key.step < 0) or - (key.stop is not None and key.stop < 0)): - raise ValueError('Cannot assign a value with slice ' - 'objects containing negative indices.') - - # calculate the current length of the value of this string - current_length = len(range(*key.indices(len(self)))) - - # Get indices for as many digits as have been requested. - # Putting the upper limit on the number of digits at 100. - indices = range(*key.indices(100)) - if len(indices) < len(str(value)): - fmt = 'Cannot put {} into {} as it has too many digits.' - raise ValueError(fmt.format(value, key)) - - # Iterate over each of the indices in the slice, zipping - # them together with the associated digit. - filled_value = str(value).zfill(current_length) - for index, digit in zip(indices, filled_value[::-1]): - # assign each digit to the associated index - self.__setitem__(index, int(digit)) - else: - if value > 9: - raise ValueError('Can only set a single digit') - # Setting a single digit. - factor = 10 ** key - head, tail = divmod(self._value, factor) - head = head // 10 - self._value = (head * 10 + value) * factor + tail - def __iadd__(self, value): self._value += value return self @@ -821,13 +741,6 @@ def __repr__(self): def __str__(self): return str(self._value) - @property - def flags(self): - warn_deprecated('The `flags` attribute is deprecated - please use ' - 'integer bitwise operators instead.') - return tuple(2 ** i for i in range(self.NUM_BITS) - if self._value & 2 ** i) - class PPDataProxy(object): """A reference to the data payload of a single PP field.""" @@ -2012,16 +1925,6 @@ def _field_gen(filename, read_data_bytes, little_ended=False): yield pp_field -def reset_load_rules(): - """ - Resets the PP load process to use only the standard conversion rules. - - .. deprecated:: 1.7 - - """ - warn_deprecated('reset_load_rules was deprecated in v1.7.') - - def _ensure_save_rules_loaded(): """Makes sure the standard save rules are loaded.""" @@ -2037,53 +1940,6 @@ def _ensure_save_rules_loaded(): rules_filename, iris.fileformats.rules.ProcedureRule) -def add_save_rules(filename): - """ - Registers a rules file for use during the PP save process. - - Registered files are processed after the standard conversion rules, and in - the order they were registered. - - .. deprecated:: 1.10 - - If you need to customise pp field saving, please refer to the functions - :func:`as_fields`, :func:`save_pairs_from_cube` and :func:`save_fields` - for an alternative solution. - - """ - warn_deprecated( - 'custom pp save rules are deprecated from v1.10.\n' - 'If you need to customise pp field saving, please refer to the ' - 'functions iris.fileformats.pp.as_fields, ' - 'iris.fileformats.pp.save_pairs_from_cube and ' - 'iris.fileformats.pp.save_fields for an alternative solution.') - _ensure_save_rules_loaded() - _save_rules.import_rules(filename) - - -def reset_save_rules(): - """ - Resets the PP save process to use only the standard conversion rules. - - .. deprecated:: 1.10 - - If you need to customise pp field saving, please refer to the functions - :func:`as_fields`, :func:`save_pairs_from_cube` and :func:`save_fields` - for an alternative solution. - - """ - warn_deprecated( - 'custom pp save rules are deprecated from v1.10.\n' - 'If you need to customise pp field saving, please refer to the ' - 'functions iris.fileformats.pp.as_fields, ' - 'iris.fileformats.pp.save_pairs_from_cube and ' - 'iris.fileformats.pp.save_fields for an alternative solution.') - # Uses this module-level variable - global _save_rules - - _save_rules = None - - # Stash codes not to be filtered (reference altitude and pressure fields). _STASH_ALLOW = [STASH(1, 0, 33), STASH(1, 0, 1)] @@ -2324,19 +2180,6 @@ def save(cube, target, append=False, field_coords=None): save_fields(fields, target, append=append) -def as_pairs(cube, field_coords=None, target=None): - """ - .. deprecated:: 1.10 - Please use :func:`iris.fileformats.pp.save_pairs_from_cube` for the same - functionality. - - """ - warn_deprecated('as_pairs is deprecated in v1.10; please use' - ' save_pairs_from_cube instead.') - return save_pairs_from_cube(cube, field_coords=field_coords, - target=target) - - def save_pairs_from_cube(cube, field_coords=None, target=None): """ Use the PP saving rules (and any user rules) to convert a cube or diff --git a/lib/iris/tests/test_cube_to_pp.py b/lib/iris/tests/test_cube_to_pp.py index 7041d4216a..6ee905a1ff 100644 --- a/lib/iris/tests/test_cube_to_pp.py +++ b/lib/iris/tests/test_cube_to_pp.py @@ -88,30 +88,6 @@ def test_pp_save_rules(self): with self.cube_save_test(reference_txt_path, reference_cubes=cubes) as temp_pp_path: iris.save(cubes, temp_pp_path) - def test_user_pp_save_rules(self): - # Test pp save rules with user rules. - - #create a user rules file - user_rules_filename = iris.util.create_temp_filename(suffix='.txt') - try: - with open(user_rules_filename, "wt") as user_rules_file: - user_rules_file.write("IF\ncm.standard_name == 'air_temperature'\nTHEN\npp.lbuser[3] = 9222") - with iris.fileformats.rules._disable_deprecation_warnings(): - iris.fileformats.pp.add_save_rules(user_rules_filename) - try: - #read pp - in_filename = tests.get_data_path(('PP', 'simple_pp', 'global.pp')) - cubes = iris.load(in_filename, callback=itab_callback) - - reference_txt_path = tests.get_result_path(('cube_to_pp', 'user_rules.txt')) - with self.cube_save_test(reference_txt_path, reference_cubes=cubes) as temp_pp_path: - iris.save(cubes, temp_pp_path) - - finally: - iris.fileformats.pp.reset_save_rules() - finally: - os.remove(user_rules_filename) - def test_pp_append_singles(self): # Test pp append saving - single cubes. diff --git a/lib/iris/tests/test_pp_module.py b/lib/iris/tests/test_pp_module.py index fee4523de4..542143639e 100644 --- a/lib/iris/tests/test_pp_module.py +++ b/lib/iris/tests/test_pp_module.py @@ -122,12 +122,10 @@ def test_lbtim_setter(self): def test_lbproc_access(self): # lbproc == 65539 with mock.patch('warnings.warn') as warn: - self.assertEqual(self.pp.lbproc[0], 9) - self.assertEqual(self.pp.lbproc[19], 0) self.assertEqual(self.pp.lbproc.flag1, 1) self.assertEqual(self.pp.lbproc.flag65536, 1) self.assertEqual(self.pp.lbproc.flag131072, 0) - self.assertEqual(warn.call_count, 5) + self.assertEqual(warn.call_count, 3) def test_set_lbuser(self): self.pp.stash = 'm02s12i003' diff --git a/lib/iris/tests/unit/fileformats/pp/test__LBProc.py b/lib/iris/tests/unit/fileformats/pp/test__LBProc.py index 64da14ce23..18670874d5 100644 --- a/lib/iris/tests/unit/fileformats/pp/test__LBProc.py +++ b/lib/iris/tests/unit/fileformats/pp/test__LBProc.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014 - 2015, Met Office +# (C) British Crown Copyright 2014 - 2017, Met Office # # This file is part of Iris. # @@ -210,15 +210,6 @@ def test(self): self.assertEqual(int(lbproc), 13) -class Test_flags(tests.IrisTest): - def test(self): - lbproc = _LBProc(26) - with mock.patch('warnings.warn') as warn: - flags = lbproc.flags - self.assertEqual(warn.call_count, 1) - self.assertEqual(flags, (2, 8, 16)) - - class Test___repr__(tests.IrisTest): def test(self): lbproc = _LBProc(8641) @@ -231,102 +222,5 @@ def test(self): self.assertEqual(str(lbproc), '8641') -class Test___len__(tests.IrisTest): - def test_zero(self): - lbproc = _LBProc(0) - with mock.patch('warnings.warn') as warn: - length = len(lbproc) - self.assertEqual(warn.call_count, 1) - self.assertEqual(length, 1) - - def test_positive(self): - lbproc = _LBProc(24) - with mock.patch('warnings.warn') as warn: - length = len(lbproc) - self.assertEqual(warn.call_count, 1) - self.assertEqual(length, 2) - - -class Test___getitem__(tests.IrisTest): - def test_normal_scalar(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - digit = lbproc[1] - self.assertEqual(warn.call_count, 1) - self.assertEqual(digit, 3) - - def test_out_of_bounds_scalar(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - digit = lbproc[45] - self.assertEqual(warn.call_count, 1) - self.assertEqual(digit, 0) - - def test_single_digit_slice(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - digit = lbproc[1:2] - self.assertEqual(warn.call_count, 1) - self.assertEqual(digit, 3) - - def test_double_digit_slice(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - digit = lbproc[1:3] - self.assertEqual(warn.call_count, 1) - self.assertEqual(digit, 23) - - def test_out_of_bounds_slice(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - digit = lbproc[10:] - self.assertEqual(warn.call_count, 1) - self.assertEqual(digit, 0) - - -class Test___setitem__(tests.IrisTest): - def test_ok(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - lbproc[1] = 9 - self.assertEqual(warn.call_count, 1) - self.assertEqual(int(lbproc), 1294) - - def test_invalid(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - with self.assertRaises(ValueError): - lbproc[1] = 81 - self.assertEqual(warn.call_count, 1) - - def test_out_of_bounds_scalar(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - lbproc[9] = 4 - self.assertEqual(warn.call_count, 1) - self.assertEqual(lbproc, 4000001234) - - def test_single_digit_slice(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - lbproc[1:2] = 6 - self.assertEqual(warn.call_count, 3) - self.assertEqual(lbproc, 1264) - - def test_double_digit_slice(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - lbproc[1:3] = 65 - self.assertEqual(warn.call_count, 4) - self.assertEqual(lbproc, 1654) - - def test_out_of_bounds_slice(self): - lbproc = _LBProc(1234) - with mock.patch('warnings.warn') as warn: - lbproc[6:] = 49 - self.assertEqual(warn.call_count, 4) - self.assertEqual(lbproc, 49001234) - - if __name__ == '__main__': tests.main() diff --git a/lib/iris/tests/unit/fileformats/pp/test_as_pairs.py b/lib/iris/tests/unit/fileformats/pp/test_as_pairs.py deleted file mode 100644 index 7ba752d90f..0000000000 --- a/lib/iris/tests/unit/fileformats/pp/test_as_pairs.py +++ /dev/null @@ -1,63 +0,0 @@ -# (C) British Crown Copyright 2015 - 2017, 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 . -"""Unit tests for the `iris.fileformats.pp.as_pairs` function.""" - -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 - -from iris.coords import DimCoord -from iris.fileformats._ff_cross_references import STASH_TRANS -import iris.fileformats.pp as pp -from iris.tests import mock -import iris.tests.stock as stock - - -class TestAsFields(tests.IrisTest): - def setUp(self): - self.cube = stock.realistic_3d() - - def test_cube_only(self): - slices_and_fields = pp.as_pairs(self.cube) - for aslice, field in slices_and_fields: - self.assertEqual(aslice.shape, (9, 11)) - self.assertEqual(field.lbcode, 101) - - def test_field_coords(self): - slices_and_fields = pp.as_pairs(self.cube, - field_coords=['grid_longitude', - 'grid_latitude']) - for aslice, field in slices_and_fields: - self.assertEqual(aslice.shape, (11, 9)) - self.assertEqual(field.lbcode, 101) - - def test_lazy_data(self): - cube = self.cube.copy() - # "Rebase" the cube onto a lazy version of its data. - cube.replace(cube.lazy_data(), dtype=cube.dtype, - fill_value=cube.fill_value) - # Check that lazy data is preserved in save-pairs generation. - slices_and_fields = pp.as_pairs(cube) - for aslice, _ in slices_and_fields: - self.assertTrue(aslice.has_lazy_data()) - - -if __name__ == "__main__": - tests.main()