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
2 changes: 1 addition & 1 deletion docs/iris/src/userguide/saving_iris_cubes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
163 changes: 3 additions & 160 deletions lib/iris/fileformats/pp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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."""
Expand Down Expand Up @@ -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."""

Expand All @@ -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)]

Expand Down Expand Up @@ -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
Expand Down
24 changes: 0 additions & 24 deletions lib/iris/tests/test_cube_to_pp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
4 changes: 1 addition & 3 deletions lib/iris/tests/test_pp_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
108 changes: 1 addition & 107 deletions lib/iris/tests/unit/fileformats/pp/test__LBProc.py
Original file line number Diff line number Diff line change
@@ -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.
#
Expand Down Expand Up @@ -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)
Expand All @@ -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()
Loading