Skip to content

Commit 4d06023

Browse files
authored
Merge pull request #3320 from znicholls/collections-deprecation-warning
Update in preparation for Python3.8 deprecation of importing ABCs from collections
2 parents 2aa93ad + 76cee31 commit 4d06023

File tree

9 files changed

+100
-61
lines changed

9 files changed

+100
-61
lines changed

lib/iris/_constraints.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# (C) British Crown Copyright 2010 - 2017, Met Office
1+
# (C) British Crown Copyright 2010 - 2019, Met Office
22
#
33
# This file is part of Iris.
44
#
@@ -23,7 +23,10 @@
2323
from six.moves import (filter, input, map, range, zip) # noqa
2424
import six
2525

26-
import collections
26+
try: # Python 3
27+
from collections.abc import Iterable, Mapping
28+
except: # Python 2.7
29+
from collections import Iterable, Mapping
2730
import operator
2831

2932
import numpy as np
@@ -98,7 +101,7 @@ def __init__(self, name=None, cube_func=None, coord_values=None, **kwargs):
98101
raise TypeError('cube_func must be None or callable, got %r'
99102
% cube_func)
100103
if not (coord_values is None or isinstance(coord_values,
101-
collections.Mapping)):
104+
Mapping)):
102105
raise TypeError('coord_values must be None or a '
103106
'collections.Mapping, got %r' % coord_values)
104107

@@ -258,7 +261,7 @@ def extract(self, cube):
258261
try_quick = False
259262
if callable(self._coord_thing):
260263
call_func = self._coord_thing
261-
elif (isinstance(self._coord_thing, collections.Iterable) and
264+
elif (isinstance(self._coord_thing, Iterable) and
262265
not isinstance(self._coord_thing,
263266
(six.string_types, iris.coords.Cell))):
264267
desired_values = list(self._coord_thing)

lib/iris/analysis/__init__.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@
5050
from six.moves import (filter, input, map, range, zip) # noqa
5151
import six
5252

53-
import collections
53+
from collections import OrderedDict
54+
try: # Python 3
55+
from collections.abc import Iterable
56+
except: # Python 2.7
57+
from collections import Iterable
5458
from functools import wraps
5559

5660
import dask.array as da
@@ -715,7 +719,7 @@ def post_process(self, collapsed_cube, data_result, coords, **kwargs):
715719
names = [coord.name() for coord in coords]
716720
coord_name = '{}_over_{}'.format(self.name(), '_'.join(names))
717721

718-
if not isinstance(points, collections.Iterable):
722+
if not isinstance(points, Iterable):
719723
points = [points]
720724

721725
# Decorate a collapsed cube with a scalar additive coordinate
@@ -764,7 +768,7 @@ def aggregate_shape(self, **kwargs):
764768
points = kwargs[self._args[0]]
765769
shape = ()
766770

767-
if not isinstance(points, collections.Iterable):
771+
if not isinstance(points, Iterable):
768772
points = [points]
769773

770774
points = np.array(points)
@@ -1089,7 +1093,7 @@ def _percentile(data, axis, percent, fast_percentile_method=False,
10891093

10901094
# Ensure to unflatten any leading dimensions.
10911095
if shape:
1092-
if not isinstance(percent, collections.Iterable):
1096+
if not isinstance(percent, Iterable):
10931097
percent = [percent]
10941098
percent = np.array(percent)
10951099
# Account for the additive dimension.
@@ -1207,7 +1211,7 @@ def _weighted_percentile(data, axis, weights, percent, returned=False,
12071211

12081212
# Ensure to unflatten any leading dimensions.
12091213
if shape:
1210-
if not isinstance(percent, collections.Iterable):
1214+
if not isinstance(percent, Iterable):
12111215
percent = [percent]
12121216
percent = np.array(percent)
12131217
# Account for the additive dimension.
@@ -1877,10 +1881,10 @@ def __init__(self, groupby_coords, shared_coords=None):
18771881
self.coords = []
18781882
self._groupby_coords = []
18791883
self._shared_coords = []
1880-
self._slices_by_key = collections.OrderedDict()
1884+
self._slices_by_key = OrderedDict()
18811885
self._stop = None
18821886
# Ensure group-by coordinates are iterable.
1883-
if not isinstance(groupby_coords, collections.Iterable):
1887+
if not isinstance(groupby_coords, Iterable):
18841888
raise TypeError('groupby_coords must be a '
18851889
'`collections.Iterable` type.')
18861890

@@ -1891,7 +1895,7 @@ def __init__(self, groupby_coords, shared_coords=None):
18911895
# coordinates.
18921896
if shared_coords is not None:
18931897
# Ensure shared coordinates are iterable.
1894-
if not isinstance(shared_coords, collections.Iterable):
1898+
if not isinstance(shared_coords, Iterable):
18951899
raise TypeError('shared_coords must be a '
18961900
'`collections.Iterable` type.')
18971901
# Add valid shared coordinates.

lib/iris/coords.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424
import six
2525

2626
from abc import ABCMeta, abstractproperty
27-
import collections
27+
from collections import namedtuple
28+
try: # Python 3
29+
from collections.abc import Iterator
30+
except: # Python 2.7
31+
from collections import Iterator
2832
import copy
2933
from itertools import chain
3034
from six.moves import zip_longest
@@ -48,10 +52,10 @@
4852
from iris.util import points_step
4953

5054

51-
class CoordDefn(collections.namedtuple('CoordDefn',
52-
['standard_name', 'long_name',
53-
'var_name', 'units',
54-
'attributes', 'coord_system'])):
55+
class CoordDefn(namedtuple('CoordDefn',
56+
['standard_name', 'long_name',
57+
'var_name', 'units',
58+
'attributes', 'coord_system'])):
5559
"""
5660
Criterion for identifying a specific type of :class:`DimCoord` or
5761
:class:`AuxCoord` based on its metadata.
@@ -86,11 +90,11 @@ def _sort_key(defn):
8690
return _sort_key(self) < _sort_key(other)
8791

8892

89-
class CoordExtent(collections.namedtuple('_CoordExtent', ['name_or_coord',
90-
'minimum',
91-
'maximum',
92-
'min_inclusive',
93-
'max_inclusive'])):
93+
class CoordExtent(namedtuple('_CoordExtent', ['name_or_coord',
94+
'minimum',
95+
'maximum',
96+
'min_inclusive',
97+
'max_inclusive'])):
9498
"""Defines a range of values for a coordinate."""
9599

96100
def __new__(cls, name_or_coord, minimum, maximum,
@@ -139,8 +143,8 @@ def __new__(cls, name_or_coord, minimum, maximum,
139143

140144

141145
# Private named tuple class for coordinate groups.
142-
_GroupbyItem = collections.namedtuple('GroupbyItem',
143-
'groupby_point, groupby_slice')
146+
_GroupbyItem = namedtuple('GroupbyItem',
147+
'groupby_point, groupby_slice')
144148

145149

146150
def _get_2d_coord_bound_grid(bounds):
@@ -184,7 +188,7 @@ def _get_2d_coord_bound_grid(bounds):
184188
return result
185189

186190

187-
class Cell(collections.namedtuple('Cell', ['point', 'bound'])):
191+
class Cell(namedtuple('Cell', ['point', 'bound'])):
188192
"""
189193
An immutable representation of a single cell of a coordinate, including the
190194
sample point and/or boundary position.
@@ -2315,7 +2319,7 @@ def xml_element(self, doc):
23152319

23162320

23172321
# See Coord.cells() for the description/context.
2318-
class _CellIterator(collections.Iterator):
2322+
class _CellIterator(Iterator):
23192323
def __init__(self, coord):
23202324
self._coord = coord
23212325
if coord.ndim != 1:
@@ -2331,7 +2335,7 @@ def __next__(self):
23312335

23322336

23332337
# See ExplicitCoord._group() for the description/context.
2334-
class _GroupIterator(collections.Iterator):
2338+
class _GroupIterator(Iterator):
23352339
def __init__(self, points):
23362340
self._points = points
23372341
self._start = 0

lib/iris/cube.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# (C) British Crown Copyright 2010 - 2018, Met Office
1+
# (C) British Crown Copyright 2010 - 2019, Met Office
22
#
33
# This file is part of Iris.
44
#
@@ -24,7 +24,19 @@
2424
from six.moves import (filter, input, map, range, zip) # noqa
2525
import six
2626

27-
import collections
27+
from collections import namedtuple, OrderedDict
28+
try: # Python 3
29+
from collections.abc import (Iterable,
30+
Container,
31+
Mapping,
32+
MutableMapping,
33+
Iterator)
34+
except: # Python 2.7
35+
from collections import (Iterable,
36+
Container,
37+
Mapping,
38+
MutableMapping,
39+
Iterator)
2840
import copy
2941
from copy import deepcopy
3042
import datetime
@@ -58,13 +70,13 @@
5870
__all__ = ['Cube', 'CubeList', 'CubeMetadata']
5971

6072

61-
class CubeMetadata(collections.namedtuple('CubeMetadata',
62-
['standard_name',
63-
'long_name',
64-
'var_name',
65-
'units',
66-
'attributes',
67-
'cell_methods'])):
73+
class CubeMetadata(namedtuple('CubeMetadata',
74+
['standard_name',
75+
'long_name',
76+
'var_name',
77+
'units',
78+
'attributes',
79+
'cell_methods'])):
6880
"""
6981
Represents the phenomenon metadata for a single :class:`Cube`.
7082
@@ -495,7 +507,7 @@ def concatenate_cube(self, check_aux_coords=True):
495507
raise ValueError("can't concatenate an empty CubeList")
496508

497509
names = [cube.metadata.name() for cube in self]
498-
unique_names = list(collections.OrderedDict.fromkeys(names))
510+
unique_names = list(OrderedDict.fromkeys(names))
499511
if len(unique_names) == 1:
500512
res = iris._concatenate.concatenate(
501513
self, error_on_mismatch=True,
@@ -629,7 +641,7 @@ def _is_single_item(testee):
629641
630642
"""
631643
return (isinstance(testee, six.string_types) or
632-
not isinstance(testee, collections.Iterable))
644+
not isinstance(testee, Iterable))
633645

634646

635647
class Cube(CFVariableMixin):
@@ -952,7 +964,7 @@ def _check_multi_dim_metadata(self, metadata, data_dims):
952964
# Convert to a tuple of integers
953965
if data_dims is None:
954966
data_dims = tuple()
955-
elif isinstance(data_dims, collections.Container):
967+
elif isinstance(data_dims, Container):
956968
data_dims = tuple(int(d) for d in data_dims)
957969
else:
958970
data_dims = (int(data_dims),)
@@ -1064,7 +1076,7 @@ def _add_unique_dim_coord(self, dim_coord, data_dim):
10641076
raise ValueError('The dim_coord may not be an AuxCoord instance.')
10651077

10661078
# Convert data_dim to a single integer
1067-
if isinstance(data_dim, collections.Container):
1079+
if isinstance(data_dim, Container):
10681080
if len(data_dim) != 1:
10691081
raise ValueError('The supplied data dimension must be a'
10701082
' single number.')
@@ -1366,7 +1378,7 @@ def coords(self, name_or_coord=None, standard_name=None,
13661378
if guess_axis(coord_) == axis]
13671379

13681380
if attributes is not None:
1369-
if not isinstance(attributes, collections.Mapping):
1381+
if not isinstance(attributes, Mapping):
13701382
msg = 'The attributes keyword was expecting a dictionary ' \
13711383
'type, but got a %s instead.' % type(attributes)
13721384
raise ValueError(msg)
@@ -1396,7 +1408,7 @@ def attr_filter(coord_):
13961408
self.coord_dims(coord_)]
13971409

13981410
if dimensions is not None:
1399-
if not isinstance(dimensions, collections.Container):
1411+
if not isinstance(dimensions, Container):
14001412
dimensions = [dimensions]
14011413
dimensions = tuple(dimensions)
14021414
coords_and_factories = [coord_ for coord_ in coords_and_factories
@@ -3185,7 +3197,7 @@ def collapsed(self, coords, aggregator, **kwargs):
31853197
for coord in coords]
31863198

31873199
# Remove duplicate dimensions.
3188-
new_dims = collections.OrderedDict.fromkeys(
3200+
new_dims = OrderedDict.fromkeys(
31893201
d for dim in dims_to_collapse for d in dim)
31903202
# Reverse the dimensions so the order can be maintained when
31913203
# reshaping the data.
@@ -3753,7 +3765,7 @@ def regrid(self, grid, scheme):
37533765
return regridder(self)
37543766

37553767

3756-
class ClassDict(collections.MutableMapping, object):
3768+
class ClassDict(MutableMapping, object):
37573769
"""
37583770
A mapping that stores objects keyed on their superclasses and their names.
37593771
@@ -3839,7 +3851,7 @@ def sorted_axes(axes):
38393851

38403852

38413853
# See Cube.slice() for the definition/context.
3842-
class _SliceIterator(collections.Iterator):
3854+
class _SliceIterator(Iterator):
38433855
def __init__(self, cube, dims_index, requested_dims, ordered):
38443856
self._cube = cube
38453857

lib/iris/fileformats/cf.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# (C) British Crown Copyright 2010 - 2018, Met Office
1+
# (C) British Crown Copyright 2010 - 2019, Met Office
22
#
33
# This file is part of Iris.
44
#
@@ -30,7 +30,11 @@
3030
import six
3131

3232
from abc import ABCMeta, abstractmethod
33-
from collections import Iterable, MutableMapping
33+
34+
try: # Python 3
35+
from collections.abc import Iterable, MutableMapping
36+
except: # Python 2.7
37+
from collections import Iterable, MutableMapping
3438
import os
3539
import re
3640
import warnings

lib/iris/io/format_picker.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# (C) British Crown Copyright 2010 - 2015, Met Office
1+
# (C) British Crown Copyright 2010 - 2019, Met Office
22
#
33
# This file is part of Iris.
44
#
@@ -25,7 +25,7 @@
2525
import matplotlib.pyplot as plt
2626
fagent = fp.FormatAgent()
2727
png_spec = fp.FormatSpecification('PNG image', fp.MagicNumber(8),
28-
0x89504E470D0A1A0A,
28+
0x89504E470D0A1A0A,
2929
handler=lambda filename: plt.imread(filename),
3030
priority=5
3131
)
@@ -55,7 +55,10 @@
5555
from six.moves import (filter, input, map, range, zip) # noqa
5656
import six
5757

58-
import collections
58+
try: # Python 3
59+
from collections.abc import Callable
60+
except: # Python 2.7
61+
from collections import Callable
5962
import functools
6063
import os
6164
import struct
@@ -126,12 +129,12 @@ def get_spec(self, basename, buffer_obj):
126129
if buffer_obj is not None and buffer_obj.tell() != 0:
127130
# reset the buffer if tell != 0
128131
buffer_obj.seek(0)
129-
132+
130133
element_cache[repr(fmt_elem)] = \
131134
fmt_elem.get_element(basename, buffer_obj)
132135

133136
# If we have a callable object, then call it and tests its result, otherwise test using basic equality
134-
if isinstance(fmt_elem_value, collections.Callable):
137+
if isinstance(fmt_elem_value, Callable):
135138
matches = fmt_elem_value(element_cache[repr(fmt_elem)])
136139
elif element_cache[repr(fmt_elem)] == fmt_elem_value:
137140
matches = True
@@ -255,14 +258,14 @@ def __init__(self, requires_fh=True):
255258
256259
"""
257260
self.requires_fh = requires_fh
258-
261+
259262
def get_element(self, basename, file_handle):
260263
"""Called when identifying the element of a file that this FileElement is representing."""
261264
raise NotImplementedError("get_element must be defined in a subclass")
262-
265+
263266
def __hash__(self):
264267
return hash(repr(self))
265-
268+
266269
def __repr__(self):
267270
return '{}()'.format(self.__class__.__name__)
268271

0 commit comments

Comments
 (0)