diff --git a/lib/iris/_cube_coord_common.py b/lib/iris/_cube_coord_common.py index 02614e0dd4..4332861d51 100644 --- a/lib/iris/_cube_coord_common.py +++ b/lib/iris/_cube_coord_common.py @@ -108,7 +108,7 @@ def rename(self, name): self.long_name = None except ValueError: self.standard_name = None - self.long_name = unicode(name) + self.long_name = six.text_type(name) # Always clear var_name when renaming. self.var_name = None diff --git a/lib/iris/_merge.py b/lib/iris/_merge.py index 6b26efb364..273b51d7fa 100644 --- a/lib/iris/_merge.py +++ b/lib/iris/_merge.py @@ -1361,7 +1361,7 @@ def name_in_independents(): # string like). dim_by_name[name] = dim = len(self._shape) self._nd_names.append(name) - if metadata[name].points_dtype.kind == 'S': + if metadata[name].points_dtype.kind in 'SU': self._aux_templates.append( _Template(dim, points, bounds, kwargs)) else: diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py index 094eba89e5..80213a5122 100644 --- a/lib/iris/analysis/__init__.py +++ b/lib/iris/analysis/__init__.py @@ -1930,7 +1930,7 @@ def _compute_shared_coords(self): # Create new shared bounded coordinates. for coord in self._shared_coords: - if coord.points.dtype.kind == 'S': + if coord.points.dtype.kind in 'SU': if coord.bounds is None: new_points = [] new_bounds = None diff --git a/lib/iris/coord_categorisation.py b/lib/iris/coord_categorisation.py index 93e9bc50eb..1bb06623e2 100644 --- a/lib/iris/coord_categorisation.py +++ b/lib/iris/coord_categorisation.py @@ -79,7 +79,7 @@ def add_categorised_coord(cube, name, from_coord, category_function, result = category_function(from_coord, from_coord.points.ravel()[0]) if isinstance(result, six.string_types): str_vectorised_fn = np.vectorize(category_function, otypes=[object]) - vectorised_fn = lambda *args: str_vectorised_fn(*args).astype('|S64') + vectorised_fn = lambda *args: str_vectorised_fn(*args).astype('|U64') else: vectorised_fn = np.vectorize(category_function) new_coord = iris.coords.AuxCoord(vectorised_fn(from_coord, diff --git a/lib/iris/coords.py b/lib/iris/coords.py index 7e2f9d8409..4f15526e82 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -963,10 +963,10 @@ def collapsed(self, dims_to_collapse=None): for index in np.ndindex(shape): index_slice = (slice(None),) + tuple(index) bounds.append(serialize(self.bounds[index_slice])) - dtype = np.dtype('S{}'.format(max(map(len, bounds)))) + dtype = np.dtype('U{}'.format(max(map(len, bounds)))) bounds = np.array(bounds, dtype=dtype).reshape((1,) + shape) points = serialize(self.points) - dtype = np.dtype('S{}'.format(len(points))) + dtype = np.dtype('U{}'.format(len(points))) # Create the new collapsed coordinate. coord = self.copy(points=np.array(points, dtype=dtype), bounds=bounds) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index 930fcda6c3..fbbcc17fed 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -1863,7 +1863,7 @@ def vector_summary(vector_coords, cube_header, max_line_offset): if self.attributes: attribute_lines = [] for name, value in sorted(six.iteritems(self.attributes)): - value = iris.util.clip_string(unicode(value)) + value = iris.util.clip_string(six.text_type(value)) line = u'{pad:{width}}{name}: {value}'.format(pad=' ', width=indent, name=name, @@ -1893,7 +1893,11 @@ def assert_valid(self): warnings.warn('Cube.assert_valid() has been deprecated.') def __str__(self): - return self.summary().encode(errors='replace') + # six has a decorator for this bit, but it doesn't do errors='replace'. + if six.PY3: + return self.summary() + else: + return self.summary().encode(errors='replace') def __unicode__(self): return self.summary() @@ -2302,7 +2306,8 @@ def _as_list_of_coords(self, names_or_coords): Convert a name, coord, or list of names/coords to a list of coords. """ # If not iterable, convert to list of a single item - if not hasattr(names_or_coords, '__iter__'): + if (not hasattr(names_or_coords, '__iter__') or + isinstance(names_or_coords, str)): names_or_coords = [names_or_coords] coords = [] @@ -2348,7 +2353,8 @@ def slices_over(self, ref_to_slice): """ # Required to handle a mix between types. - if not hasattr(ref_to_slice, '__iter__'): + if (not hasattr(ref_to_slice, '__iter__') or + isinstance(ref_to_slice, str)): ref_to_slice = [ref_to_slice] slice_dims = set() @@ -2408,7 +2414,8 @@ def slices(self, ref_to_slice, ordered=True): raise TypeError("'ordered' argument to slices must be boolean.") # Required to handle a mix between types - if not hasattr(ref_to_slice, '__iter__'): + if (not hasattr(ref_to_slice, '__iter__') or + isinstance(ref_to_slice, str)): ref_to_slice = [ref_to_slice] dim_to_slice = [] diff --git a/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb b/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb index a409cea898..990db99fa1 100644 --- a/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb +++ b/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb @@ -913,7 +913,7 @@ fc_extras # Set the cube global attributes. for attr_name, attr_value in six.iteritems(cf_var.cf_group.global_attributes): try: - if isinstance(attr_value, unicode): + if six.PY2 and isinstance(attr_value, six.text_type): try: cube.attributes[str(attr_name)] = str(attr_value) except UnicodeEncodeError: diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py index e635e97d04..19fcf7a1f8 100644 --- a/lib/iris/fileformats/cf.py +++ b/lib/iris/fileformats/cf.py @@ -70,6 +70,12 @@ ocean_s_coordinate_g2=['eta', 'depth']) +# NetCDF returns a different type for strings depending on Python version. +def _is_str_dtype(var): + return ((six.PY2 and np.issubdtype(var.dtype, np.str)) or + (six.PY3 and np.issubdtype(var.dtype, np.bytes_))) + + ################################################################################ class CFVariable(six.with_metaclass(ABCMeta, object)): """Abstract base class wrapper for a CF-netCDF variable.""" @@ -313,7 +319,7 @@ def identify(cls, variables, ignore=None, target=None, warn=True): warnings.warn(message % (name, nc_var_name)) else: # Restrict to non-string type i.e. not a CFLabelVariable. - if not np.issubdtype(variables[name].dtype, np.str): + if not _is_str_dtype(variables[name]): result[name] = CFAuxiliaryCoordinateVariable(name, variables[name]) return result @@ -478,7 +484,7 @@ def identify(cls, variables, ignore=None, target=None, warn=True, monotonic=Fals if nc_var_name in ignore: continue # String variables can't be coordinates - if np.issubdtype(nc_var.dtype, np.str): + if _is_str_dtype(nc_var): continue # Restrict to one-dimensional with name as dimension OR zero-dimensional scalar if not ((nc_var.ndim == 1 and nc_var_name in nc_var.dimensions) or (nc_var.ndim == 0)): @@ -638,8 +644,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): warnings.warn(message % (name, nc_var_name)) else: # Restrict to only string type. - if np.issubdtype(variables[name].dtype, np.str): - result[name] = CFLabelVariable(name, variables[name]) + if _is_str_dtype(variables[name]): + var = variables[name] + result[name] = CFLabelVariable(name, var) return result @@ -683,7 +690,7 @@ def cf_label_data(self, cf_data_var): # Calculate new label data shape (without string dimension) and create payload array. new_shape = tuple(dim_len for i, dim_len in enumerate(self.shape) if i != str_dim) - data = np.empty(new_shape, dtype='|S%d' % self.shape[str_dim]) + data = np.empty(new_shape, dtype='|U%d' % self.shape[str_dim]) for index in np.ndindex(new_shape): # Create the slice for the label data. @@ -692,7 +699,8 @@ def cf_label_data(self, cf_data_var): else: label_index = index + (slice(None, None),) - data[index] = ''.join(label_data[label_index]).strip() + data[index] = b''.join(label_data[label_index]).strip().decode( + 'utf8') return data diff --git a/lib/iris/fileformats/grib/__init__.py b/lib/iris/fileformats/grib/__init__.py index e7632f9b55..9cf20983a9 100644 --- a/lib/iris/fileformats/grib/__init__.py +++ b/lib/iris/fileformats/grib/__init__.py @@ -64,11 +64,13 @@ _load_rules = None -CENTRE_TITLES = {'egrr': 'U.K. Met Office - Exeter', - 'ecmf': 'European Centre for Medium Range Weather Forecasts', - 'rjtd': 'Tokyo, Japan Meteorological Agency', - '55' : 'San Francisco', - 'kwbc': 'US National Weather Service, National Centres for Environmental Prediction'} +CENTRE_TITLES = { + 'egrr': u'U.K. Met Office - Exeter', + 'ecmf': u'European Centre for Medium Range Weather Forecasts', + 'rjtd': u'Tokyo, Japan Meteorological Agency', + '55': u'San Francisco', + 'kwbc': u'US National Weather Service, National Centres for Environmental ' + u'Prediction'} TIME_RANGE_INDICATORS = {0:'none', 1:'none', 3:'time mean', 4:'time sum', 5:'time _difference', 10:'none', @@ -449,7 +451,7 @@ def _compute_extra_keys(self): #originating centre #TODO #574 Expand to include sub-centre self.extra_keys['_originatingCentre'] = CENTRE_TITLES.get( - centre, "unknown centre %s" % centre) + centre, u'unknown centre %s' % centre) #forecast time unit as a cm string #TODO #575 Do we want PP or GRIB style forecast delta? diff --git a/lib/iris/fileformats/name.py b/lib/iris/fileformats/name.py index a5333f0fdf..295043433a 100644 --- a/lib/iris/fileformats/name.py +++ b/lib/iris/fileformats/name.py @@ -34,7 +34,7 @@ def _get_NAME_loader(filename): import iris.fileformats.name_loaders as name_loaders load = None - with open(filename, 'r') as file_handle: + with open(filename, 'rb') as file_handle: header = name_loaders.read_header(file_handle) # Infer file type based on contents of header. diff --git a/lib/iris/fileformats/name_loaders.py b/lib/iris/fileformats/name_loaders.py index 64cbddae45..2c122eee60 100644 --- a/lib/iris/fileformats/name_loaders.py +++ b/lib/iris/fileformats/name_loaders.py @@ -78,11 +78,11 @@ def read_header(file_handle): header = {} header['NAME Version'] = next(file_handle).strip() for line in file_handle: - words = line.split(':', 1) + words = line.split(b':', 1) if len(words) != 2: break key, value = [word.strip() for word in words] - header[key] = value + header[key.decode()] = value # Cast some values into floats or integers if they match a # given name. Set any empty string values to None. @@ -97,6 +97,8 @@ def read_header(file_handle): 'Number of fields', 'Number of series']: header[key] = int(value) + else: + header[key] = value.decode() else: header[key] = None @@ -118,7 +120,7 @@ def _read_data_arrays(file_handle, n_arrays, shape): for line in file_handle: # Split the line by comma, removing the last empty column # caused by the trailing comma - vals = line.split(',')[:-1] + vals = line.split(b',')[:-1] # Cast the x and y grid positions to integers and convert # them to zero based indices @@ -518,7 +520,7 @@ def load_NAMEIII_field(filename): # Loading a file gives a generator of lines which can be progressed using # the next() function. This will come in handy as we wish to progress # through the file line by line. - with open(filename, 'r') as file_handle: + with open(filename, 'rb') as file_handle: # Create a dictionary which can hold the header metadata about this # file. header = read_header(file_handle) @@ -536,7 +538,8 @@ def load_NAMEIII_field(filename): 'Vertical Av or Int', 'Prob Perc', 'Prob Perc Ens', 'Prob Perc Time', 'Time', 'Z', 'D']: - cols = [col.strip() for col in next(file_handle).split(',')] + cols = [col.strip() + for col in next(file_handle).decode().split(',')] column_headings[column_header_name] = cols[4:-1] # Convert the time to python datetimes. @@ -588,7 +591,7 @@ def load_NAMEII_field(filename): A generator :class:`iris.cube.Cube` instances. """ - with open(filename, 'r') as file_handle: + with open(filename, 'rb') as file_handle: # Create a dictionary which can hold the header metadata about this # file. header = read_header(file_handle) @@ -607,7 +610,8 @@ def load_NAMEII_field(filename): for column_header_name in ['Species Category', 'Species', 'Time Av or Int', 'Quantity', 'Unit', 'Z', 'Time']: - cols = [col.strip() for col in next(file_handle).split(',')] + cols = [col.strip() + for col in next(file_handle).decode().split(',')] column_headings[column_header_name] = cols[4:-1] # Convert the time to python datetimes @@ -667,7 +671,7 @@ def load_NAMEIII_timeseries(filename): A generator :class:`iris.cube.Cube` instances. """ - with open(filename, 'r') as file_handle: + with open(filename, 'rb') as file_handle: # Create a dictionary which can hold the header metadata about this # file. header = read_header(file_handle) @@ -683,7 +687,8 @@ def load_NAMEIII_timeseries(filename): 'Vertical Av or Int', 'Prob Perc', 'Prob Perc Ens', 'Prob Perc Time', 'Location', 'X', 'Y', 'Z', 'D']: - cols = [col.strip() for col in next(file_handle).split(',')] + cols = [col.strip() + for col in next(file_handle).decode().split(',')] column_headings[column_header_name] = cols[1:-1] # Determine the coordinates of the data and store in namedtuples. @@ -707,10 +712,10 @@ def load_NAMEIII_timeseries(filename): for line in file_handle: # Split the line by comma, removing the last empty column caused # by the trailing comma. - vals = line.split(',')[:-1] + vals = line.split(b',')[:-1] # Time is stored in the first column. - t = vals[0].strip() + t = vals[0].decode().strip() dt = datetime.datetime.strptime(t, NAMEIII_DATETIME_FORMAT) time_list.append(dt) @@ -741,7 +746,7 @@ def load_NAMEII_timeseries(filename): A generator :class:`iris.cube.Cube` instances. """ - with open(filename, 'r') as file_handle: + with open(filename, 'rb') as file_handle: # Create a dictionary which can hold the header metadata about this # file. header = read_header(file_handle) @@ -751,7 +756,8 @@ def load_NAMEII_timeseries(filename): for column_header_name in ['Y', 'X', 'Location', 'Species Category', 'Species', 'Quantity', 'Z', 'Unit']: - cols = [col.strip() for col in next(file_handle).split(',')] + cols = [col.strip() + for col in next(file_handle).decode().split(',')] column_headings[column_header_name] = cols[1:-1] # Determine the coordinates of the data and store in namedtuples. @@ -771,10 +777,10 @@ def load_NAMEII_timeseries(filename): for line in file_handle: # Split the line by comma, removing the last empty column caused # by the trailing comma. - vals = line.split(',')[:-1] + vals = line.split(b',')[:-1] # Time is stored in the first two columns. - t = (vals[0].strip() + ' ' + vals[1].strip()) + t = (vals[0].strip() + b' ' + vals[1].strip()).decode() dt = datetime.datetime.strptime( t, NAMEII_TIMESERIES_DATETIME_FORMAT) time_list.append(dt) @@ -809,21 +815,22 @@ def load_NAMEIII_trajectory(filename): time_unit = iris.unit.Unit('hours since epoch', calendar=iris.unit.CALENDAR_GREGORIAN) - with open(filename, 'r') as infile: + with open(filename, 'rb') as infile: header = read_header(infile) # read the column headings for line in infile: - if line.startswith(" "): + if line.startswith(b' '): break - headings = [heading.strip() for heading in line.split(",")] + headings = [heading.strip() for heading in line.decode().split(',')] # read the columns columns = [[] for i in range(len(headings))] for line in infile: - values = [v.strip() for v in line.split(",")] + values = [v.strip() for v in line.split(b',')] for c, v in enumerate(values): - if "UTC" in v: + if b'UTC' in v: + v = v.decode() v = v.replace(":00 ", " ") # Strip out milliseconds. v = datetime.datetime.strptime(v, NAMEIII_DATETIME_FORMAT) else: @@ -872,6 +879,8 @@ def load_NAMEIII_trajectory(filename): elif name == "Z (FL)": name = "flight_level" long_name = name + elif values[0].dtype.kind == 'S': + values = [v.decode() for v in values] try: coord = DimCoord(values, units=units) diff --git a/lib/iris/fileformats/netcdf.py b/lib/iris/fileformats/netcdf.py index dce1f61d77..40a2fbf255 100644 --- a/lib/iris/fileformats/netcdf.py +++ b/lib/iris/fileformats/netcdf.py @@ -355,7 +355,7 @@ def _pyke_stats(engine, cf_name): def _set_attributes(attributes, key, value): """Set attributes dictionary, converting unicode strings appropriately.""" - if isinstance(value, unicode): + if isinstance(value, six.text_type): try: attributes[str(key)] = str(value) except UnicodeEncodeError: @@ -1236,6 +1236,8 @@ def _create_cf_variable(self, cube, dimension_names, coord): if np.issubdtype(coord.points.dtype, np.str): string_dimension_depth = coord.points.dtype.itemsize + if coord.points.dtype.kind == 'U': + string_dimension_depth //= 4 string_dimension_name = 'string%d' % string_dimension_depth # Determine whether to create the string length dimension. diff --git a/lib/iris/fileformats/nimrod.py b/lib/iris/fileformats/nimrod.py index dad5f0d855..ebe43e020c 100644 --- a/lib/iris/fileformats/nimrod.py +++ b/lib/iris/fileformats/nimrod.py @@ -81,7 +81,7 @@ def _read_chars(infile, num): """Read characters from the (big-endian) file.""" instr = infile.read(num) - return struct.unpack(">%ds" % num, instr)[0] + return struct.unpack(">%ds" % num, instr)[0].decode() class NimrodField(object): diff --git a/lib/iris/plot.py b/lib/iris/plot.py index d3042bb832..7951776ff0 100644 --- a/lib/iris/plot.py +++ b/lib/iris/plot.py @@ -260,7 +260,7 @@ def _draw_2d_from_bounds(draw_method_name, cube, *args, **kwargs): ['xaxis', 'yaxis'], [1, 0]): if coord: - if coord.points.dtype.char == 'S': + if coord.points.dtype.char in 'SU': if coord.points.ndim != 1: msg = 'Coord {!r} must be one-dimensional.' raise ValueError(msg.format(coord)) @@ -336,7 +336,7 @@ def _draw_2d_from_points(draw_method_name, arg_func, cube, *args, **kwargs): for values, axis_name in zip([u, v], ['xaxis', 'yaxis']): # Replace any string coordinates with "index" coordinates. - if values.dtype.char == 'S': + if values.dtype.char in 'SU': if values.ndim != 1: raise ValueError('Multi-dimensional string coordinates ' 'not supported.') @@ -446,7 +446,7 @@ def _draw_1d_from_points(draw_method_name, arg_func, *args, **kwargs): for values, axis_name in zip([u, v], ['xaxis', 'yaxis']): # Replace any string coordinates with "index" coordinates. - if values.dtype.char == 'S': + if values.dtype.char in 'SU': if values.ndim != 1: msg = 'Multi-dimensional string coordinates are not supported.' raise ValueError(msg) diff --git a/lib/iris/tests/experimental/test_raster.py b/lib/iris/tests/experimental/test_raster.py index e00343fc4f..d16aa4000e 100644 --- a/lib/iris/tests/experimental/test_raster.py +++ b/lib/iris/tests/experimental/test_raster.py @@ -17,6 +17,7 @@ from __future__ import (absolute_import, division, print_function) from six.moves import (filter, input, map, range, zip) # noqa +import six import iris.tests as tests import iris @@ -36,7 +37,7 @@ def check_tiff_header(self, geotiff_fh, reference_filename): """ im = PIL.Image.open(geotiff_fh) tiff_header = '\n'.join(str((tag, val)) - if not isinstance(val, unicode) + if not isinstance(val, six.text_type) else "(%s, '%s')" % (tag, val) for tag, val in sorted(im.tag.items())) reference_path = tests.get_result_path(reference_filename) diff --git a/lib/iris/tests/integration/test_grib2.py b/lib/iris/tests/integration/test_grib2.py index 273513c35d..38117442bc 100644 --- a/lib/iris/tests/integration/test_grib2.py +++ b/lib/iris/tests/integration/test_grib2.py @@ -123,7 +123,7 @@ def test_perturbation(self): # Get a grib_dump of the output file. dump_text = check_output(('grib_dump -O -wcount=1 ' + temp_file_path), - shell=True) + shell=True).decode() # Check that various aspects of the saved file are as expected. expect_strings = ( @@ -168,7 +168,7 @@ def test_save_load(self): # Get a grib_dump of the output file. dump_text = check_output(('grib_dump -O -wcount=1 ' + temp_file_path), - shell=True) + shell=True).decode() # Check that various aspects of the saved file are as expected. expect_strings = ( diff --git a/lib/iris/tests/results/categorisation/customcheck.cml b/lib/iris/tests/results/categorisation/customcheck.cml index 2b29987a0e..c628e66d65 100644 --- a/lib/iris/tests/results/categorisation/customcheck.cml +++ b/lib/iris/tests/results/categorisation/customcheck.cml @@ -14,7 +14,7 @@ + djfm, amjj, amjj, amjj, amjj, amjj, ason]" shape="(23,)" units="Unit('no_unit')" value_type="unicode"/> + May, May, Jun, Jul, Aug]" shape="(23,)" units="Unit('no_unit')" value_type="unicode"/> + March, April, May, May, June, July, August]" shape="(23,)" units="Unit('no_unit')" value_type="unicode"/> + mam, mam, jja, jja, jja]" shape="(23,)" units="Unit('no_unit')" value_type="unicode"/> + Sun, Sat, Fri, Thu, Wed]" shape="(23,)" units="Unit('no_unit')" value_type="unicode"/> + Friday, Thursday, Wednesday]" shape="(23,)" units="Unit('no_unit')" value_type="unicode"/> + @@ -65,7 +65,7 @@ - + @@ -99,7 +99,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_0.cml b/lib/iris/tests/results/grib_load/earth_shape_0.cml index df1683cc9c..27f3a31095 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_0.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_0.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_1.cml b/lib/iris/tests/results/grib_load/earth_shape_1.cml index aae8b1913b..075b25b57b 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_1.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_1.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_2.cml b/lib/iris/tests/results/grib_load/earth_shape_2.cml index 2f09ced57d..3ec9304114 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_2.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_2.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_3.cml b/lib/iris/tests/results/grib_load/earth_shape_3.cml index 232df261eb..dfc009953d 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_3.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_3.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_4.cml b/lib/iris/tests/results/grib_load/earth_shape_4.cml index c6b8224d98..5470d7da00 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_4.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_4.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_5.cml b/lib/iris/tests/results/grib_load/earth_shape_5.cml index bad3891a26..4ee16fb276 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_5.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_5.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_6.cml b/lib/iris/tests/results/grib_load/earth_shape_6.cml index fc05ef82e9..d72addc062 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_6.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_6.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_7.cml b/lib/iris/tests/results/grib_load/earth_shape_7.cml index d9558a1b5e..ba2d911286 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_7.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_7.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/earth_shape_grib1.cml b/lib/iris/tests/results/grib_load/earth_shape_grib1.cml index 4475a25636..88cad5a315 100644 --- a/lib/iris/tests/results/grib_load/earth_shape_grib1.cml +++ b/lib/iris/tests/results/grib_load/earth_shape_grib1.cml @@ -17,7 +17,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/ineg_jneg.cml b/lib/iris/tests/results/grib_load/ineg_jneg.cml index 8338af69c3..902410492a 100644 --- a/lib/iris/tests/results/grib_load/ineg_jneg.cml +++ b/lib/iris/tests/results/grib_load/ineg_jneg.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/ineg_jpos.cml b/lib/iris/tests/results/grib_load/ineg_jpos.cml index c7098cc05a..e8e2e8ff52 100644 --- a/lib/iris/tests/results/grib_load/ineg_jpos.cml +++ b/lib/iris/tests/results/grib_load/ineg_jpos.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/ipos_jneg.cml b/lib/iris/tests/results/grib_load/ipos_jneg.cml index df1683cc9c..27f3a31095 100644 --- a/lib/iris/tests/results/grib_load/ipos_jneg.cml +++ b/lib/iris/tests/results/grib_load/ipos_jneg.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/ipos_jpos.cml b/lib/iris/tests/results/grib_load/ipos_jpos.cml index 8c413efa61..b56e9fcb67 100644 --- a/lib/iris/tests/results/grib_load/ipos_jpos.cml +++ b/lib/iris/tests/results/grib_load/ipos_jpos.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/lambert_grib1.cml b/lib/iris/tests/results/grib_load/lambert_grib1.cml index c3fce6534f..c66bd807d7 100644 --- a/lib/iris/tests/results/grib_load/lambert_grib1.cml +++ b/lib/iris/tests/results/grib_load/lambert_grib1.cml @@ -13,7 +13,7 @@ - + - + + diff --git a/lib/iris/tests/results/grib_load/polar_stereo_grib1.cml b/lib/iris/tests/results/grib_load/polar_stereo_grib1.cml index 2b872c47c1..95950fec43 100644 --- a/lib/iris/tests/results/grib_load/polar_stereo_grib1.cml +++ b/lib/iris/tests/results/grib_load/polar_stereo_grib1.cml @@ -6,7 +6,7 @@ - + - + diff --git a/lib/iris/tests/results/grib_load/reduced_gg_grib2.cml b/lib/iris/tests/results/grib_load/reduced_gg_grib2.cml index c8c6ff059e..3325ef376e 100644 --- a/lib/iris/tests/results/grib_load/reduced_gg_grib2.cml +++ b/lib/iris/tests/results/grib_load/reduced_gg_grib2.cml @@ -27,7 +27,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/reduced_ll_grib1.cml b/lib/iris/tests/results/grib_load/reduced_ll_grib1.cml index 82edb79273..c91ee3b350 100644 --- a/lib/iris/tests/results/grib_load/reduced_ll_grib1.cml +++ b/lib/iris/tests/results/grib_load/reduced_ll_grib1.cml @@ -37,7 +37,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/reduced_ll_missing_grib1.cml b/lib/iris/tests/results/grib_load/reduced_ll_missing_grib1.cml index 7de2f8305e..eeabfffb54 100644 --- a/lib/iris/tests/results/grib_load/reduced_ll_missing_grib1.cml +++ b/lib/iris/tests/results/grib_load/reduced_ll_missing_grib1.cml @@ -37,7 +37,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/regular_gg_grib1.cml b/lib/iris/tests/results/grib_load/regular_gg_grib1.cml index fb67995f17..f895f86afe 100644 --- a/lib/iris/tests/results/grib_load/regular_gg_grib1.cml +++ b/lib/iris/tests/results/grib_load/regular_gg_grib1.cml @@ -17,7 +17,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/regular_gg_grib2.cml b/lib/iris/tests/results/grib_load/regular_gg_grib2.cml index 8933129931..a00f699f75 100644 --- a/lib/iris/tests/results/grib_load/regular_gg_grib2.cml +++ b/lib/iris/tests/results/grib_load/regular_gg_grib2.cml @@ -17,7 +17,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/rotated.cml b/lib/iris/tests/results/grib_load/rotated.cml index 387d7df3b8..bd8751e47f 100644 --- a/lib/iris/tests/results/grib_load/rotated.cml +++ b/lib/iris/tests/results/grib_load/rotated.cml @@ -16,7 +16,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/time_bound_grib1.cml b/lib/iris/tests/results/grib_load/time_bound_grib1.cml index e0d1189499..f7349e9bc2 100644 --- a/lib/iris/tests/results/grib_load/time_bound_grib1.cml +++ b/lib/iris/tests/results/grib_load/time_bound_grib1.cml @@ -17,7 +17,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/time_bound_grib2.cml b/lib/iris/tests/results/grib_load/time_bound_grib2.cml index df1683cc9c..27f3a31095 100644 --- a/lib/iris/tests/results/grib_load/time_bound_grib2.cml +++ b/lib/iris/tests/results/grib_load/time_bound_grib2.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/grib_load/y_fastest.cml b/lib/iris/tests/results/grib_load/y_fastest.cml index c111999c06..c0dd03351b 100644 --- a/lib/iris/tests/results/grib_load/y_fastest.cml +++ b/lib/iris/tests/results/grib_load/y_fastest.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEII/0_TRACER_AIR_CONCENTRATION.cml b/lib/iris/tests/results/integration/name_grib/NAMEII/0_TRACER_AIR_CONCENTRATION.cml index b965741a1a..e8e128d5d8 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEII/0_TRACER_AIR_CONCENTRATION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEII/0_TRACER_AIR_CONCENTRATION.cml @@ -21,7 +21,7 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEII/1_TRACER_DOSAGE.cml b/lib/iris/tests/results/integration/name_grib/NAMEII/1_TRACER_DOSAGE.cml index da76926663..957e7f8f52 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEII/1_TRACER_DOSAGE.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEII/1_TRACER_DOSAGE.cml @@ -21,7 +21,7 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEII/2_TRACER_WET_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEII/2_TRACER_WET_DEPOSITION.cml index 91ef38ef51..d217c8b70b 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEII/2_TRACER_WET_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEII/2_TRACER_WET_DEPOSITION.cml @@ -18,7 +18,7 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEII/3_TRACER_DRY_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEII/3_TRACER_DRY_DEPOSITION.cml index 8cac04e23b..a92b722505 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEII/3_TRACER_DRY_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEII/3_TRACER_DRY_DEPOSITION.cml @@ -18,7 +18,7 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEII/4_TRACER_TOTAL_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEII/4_TRACER_TOTAL_DEPOSITION.cml index 8cac04e23b..a92b722505 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEII/4_TRACER_TOTAL_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEII/4_TRACER_TOTAL_DEPOSITION.cml @@ -18,7 +18,7 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEIII/0_TRACER_AIR_CONCENTRATION.cml b/lib/iris/tests/results/integration/name_grib/NAMEIII/0_TRACER_AIR_CONCENTRATION.cml index 596e0126e5..3070f71849 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEIII/0_TRACER_AIR_CONCENTRATION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEIII/0_TRACER_AIR_CONCENTRATION.cml @@ -18,7 +18,7 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEIII/1_TRACER_AIR_CONCENTRATION.cml b/lib/iris/tests/results/integration/name_grib/NAMEIII/1_TRACER_AIR_CONCENTRATION.cml index ebf7907105..718a91a7e2 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEIII/1_TRACER_AIR_CONCENTRATION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEIII/1_TRACER_AIR_CONCENTRATION.cml @@ -18,7 +18,7 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEIII/2_TRACER_DRY_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEIII/2_TRACER_DRY_DEPOSITION.cml index bb77b7af2f..9de4ad2681 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEIII/2_TRACER_DRY_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEIII/2_TRACER_DRY_DEPOSITION.cml @@ -18,7 +18,7 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEIII/3_TRACER_WET_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEIII/3_TRACER_WET_DEPOSITION.cml index 9354b74b47..991f69eb27 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEIII/3_TRACER_WET_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEIII/3_TRACER_WET_DEPOSITION.cml @@ -18,7 +18,7 @@ - + diff --git a/lib/iris/tests/results/integration/name_grib/NAMEIII/4_TRACER_DEPOSITION.cml b/lib/iris/tests/results/integration/name_grib/NAMEIII/4_TRACER_DEPOSITION.cml index 63c126eecc..0528976620 100644 --- a/lib/iris/tests/results/integration/name_grib/NAMEIII/4_TRACER_DEPOSITION.cml +++ b/lib/iris/tests/results/integration/name_grib/NAMEIII/4_TRACER_DEPOSITION.cml @@ -18,7 +18,7 @@ - + diff --git a/lib/iris/tests/results/merge/separable_combination.cml b/lib/iris/tests/results/merge/separable_combination.cml index 0b95263afc..11ac2989fe 100644 --- a/lib/iris/tests/results/merge/separable_combination.cml +++ b/lib/iris/tests/results/merge/separable_combination.cml @@ -5,7 +5,7 @@ + 2502, 2502, 2502, 2502, 2502]" shape="(21,)" units="Unit('1')" value_type="unicode"/> + UK Met Office, UK Met Office, UK Met Office]" shape="(21,)" units="Unit('1')" value_type="unicode"/> + HadCM3, Sys 51, Met 18, ENSEMBLES]" shape="(21,)" units="Unit('1')" value_type="unicode"/> - + - + diff --git a/lib/iris/tests/results/merge/string_a_with_aux.cml b/lib/iris/tests/results/merge/string_a_with_aux.cml index d575ab4045..42300859a4 100644 --- a/lib/iris/tests/results/merge/string_a_with_aux.cml +++ b/lib/iris/tests/results/merge/string_a_with_aux.cml @@ -3,7 +3,7 @@ - + diff --git a/lib/iris/tests/results/merge/string_a_with_dim.cml b/lib/iris/tests/results/merge/string_a_with_dim.cml index d575ab4045..42300859a4 100644 --- a/lib/iris/tests/results/merge/string_a_with_dim.cml +++ b/lib/iris/tests/results/merge/string_a_with_dim.cml @@ -3,7 +3,7 @@ - + diff --git a/lib/iris/tests/results/merge/string_b_with_dim.cml b/lib/iris/tests/results/merge/string_b_with_dim.cml index a3efc876d4..26e934da7e 100644 --- a/lib/iris/tests/results/merge/string_b_with_dim.cml +++ b/lib/iris/tests/results/merge/string_b_with_dim.cml @@ -6,7 +6,7 @@ - + diff --git a/lib/iris/tests/results/name/NAMEIII_field.cml b/lib/iris/tests/results/name/NAMEIII_field.cml index ad9d2d9c92..95ae7b553f 100644 --- a/lib/iris/tests/results/name/NAMEIII_field.cml +++ b/lib/iris/tests/results/name/NAMEIII_field.cml @@ -53,7 +53,7 @@ - + @@ -116,7 +116,7 @@ - + @@ -178,7 +178,7 @@ - + @@ -240,7 +240,7 @@ - + @@ -302,7 +302,7 @@ - + diff --git a/lib/iris/tests/results/name/NAMEIII_timeseries.cml b/lib/iris/tests/results/name/NAMEIII_timeseries.cml index 3f05793cbd..d1c521ee4d 100644 --- a/lib/iris/tests/results/name/NAMEIII_timeseries.cml +++ b/lib/iris/tests/results/name/NAMEIII_timeseries.cml @@ -63,7 +63,7 @@ 358354.0, 358355.0, 358356.0, 358357.0]" shape="(72,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + @@ -132,7 +132,7 @@ 358354.0, 358355.0, 358356.0, 358357.0]" shape="(72,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + @@ -200,7 +200,7 @@ 358354.0, 358355.0, 358356.0, 358357.0]" shape="(72,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + @@ -268,7 +268,7 @@ 358354.0, 358355.0, 358356.0, 358357.0]" shape="(72,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + @@ -336,7 +336,7 @@ 358354.0, 358355.0, 358356.0, 358357.0]" shape="(72,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + diff --git a/lib/iris/tests/results/name/NAMEIII_trajectory.cml b/lib/iris/tests/results/name/NAMEIII_trajectory.cml index 38e72493f0..96799e36dd 100644 --- a/lib/iris/tests/results/name/NAMEIII_trajectory.cml +++ b/lib/iris/tests/results/name/NAMEIII_trajectory.cml @@ -6,13 +6,13 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -222,7 +222,7 @@ - + @@ -280,7 +280,7 @@ - + diff --git a/lib/iris/tests/results/name/NAMEII_timeseries.cml b/lib/iris/tests/results/name/NAMEII_timeseries.cml index 7bdb2e18a3..3349c18350 100644 --- a/lib/iris/tests/results/name/NAMEII_timeseries.cml +++ b/lib/iris/tests/results/name/NAMEII_timeseries.cml @@ -40,7 +40,7 @@ 370475.0, 370476.0]" shape="(132,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + @@ -86,7 +86,7 @@ 370475.0, 370476.0]" shape="(132,)" standard_name="time" units="Unit('hours since 1970-01-01 00:00:00', calendar='gregorian')" value_type="float64"/> - + diff --git a/lib/iris/tests/results/system/supported_filetype_.grib2.cml b/lib/iris/tests/results/system/supported_filetype_.grib2.cml index 0ccff3bd77..da64346e77 100644 --- a/lib/iris/tests/results/system/supported_filetype_.grib2.cml +++ b/lib/iris/tests/results/system/supported_filetype_.grib2.cml @@ -30,7 +30,7 @@ - + diff --git a/lib/iris/tests/results/unit/fileformats/grib/load_cubes/load_cubes/reduced_raw.cml b/lib/iris/tests/results/unit/fileformats/grib/load_cubes/load_cubes/reduced_raw.cml index 896fcaa9bb..b6202ca806 100644 --- a/lib/iris/tests/results/unit/fileformats/grib/load_cubes/load_cubes/reduced_raw.cml +++ b/lib/iris/tests/results/unit/fileformats/grib/load_cubes/load_cubes/reduced_raw.cml @@ -27,7 +27,7 @@ - + diff --git a/lib/iris/tests/results/uri_callback/grib_global.cml b/lib/iris/tests/results/uri_callback/grib_global.cml index fbb28f0688..3ba87d11b0 100644 --- a/lib/iris/tests/results/uri_callback/grib_global.cml +++ b/lib/iris/tests/results/uri_callback/grib_global.cml @@ -35,7 +35,7 @@ - + diff --git a/lib/iris/tests/test_cdm.py b/lib/iris/tests/test_cdm.py index 1261aa3ae6..db4d7ded97 100644 --- a/lib/iris/tests/test_cdm.py +++ b/lib/iris/tests/test_cdm.py @@ -21,6 +21,7 @@ from __future__ import (absolute_import, division, print_function) from six.moves import (filter, input, map, range, zip) # noqa +import six # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests @@ -29,6 +30,7 @@ import os import re import sys +import unittest import numpy as np import numpy.ma as ma @@ -253,7 +255,7 @@ def setUp(self): path = tests.get_data_path(('PP', 'simple_pp', 'global.pp')) self.cube_2d = iris.load_cube(path) # Generate the unicode cube up here now it's used in two tests. - unicode_str = unichr(40960) + u'abcd' + unichr(1972) + unicode_str = six.unichr(40960) + u'abcd' + six.unichr(1972) self.unicode_cube = iris.tests.stock.simple_1d() self.unicode_cube.attributes['source'] = unicode_str @@ -296,7 +298,7 @@ def test_cubelist_string(self): def test_basic_0d_cube(self): self.assertString(repr(self.cube_2d[0, 0]), ('cdm', 'str_repr', '0d_cube.__repr__.txt')) - self.assertString(unicode(self.cube_2d[0, 0]), + self.assertString(six.text_type(self.cube_2d[0, 0]), ('cdm', 'str_repr', '0d_cube.__unicode__.txt')) self.assertString(str(self.cube_2d[0, 0]), ('cdm', 'str_repr', '0d_cube.__str__.txt')) @@ -359,6 +361,7 @@ def unicode_encoding_change(self, new_encoding): sys.setdefaultencoding(default_encoding) del sys.setdefaultencoding + @unittest.skipIf(six.PY3, 'Encodings are sane in Python 3.') def test_adjusted_default_encoding(self): # Test cube str representation on non-system-default encodings. # Doing this requires access to a sys method that is removed by default @@ -378,8 +381,8 @@ def test_adjusted_default_encoding(self): def test_unicode_attribute(self): self.assertString( - unicode(self.unicode_cube), ('cdm', 'str_repr', - 'unicode_attribute.__unicode__.txt')) + six.text_type(self.unicode_cube), + ('cdm', 'str_repr', 'unicode_attribute.__unicode__.txt')) @tests.skip_data diff --git a/lib/iris/tests/test_coding_standards.py b/lib/iris/tests/test_coding_standards.py index aa40f7e3ba..4ce5a193f2 100644 --- a/lib/iris/tests/test_coding_standards.py +++ b/lib/iris/tests/test_coding_standards.py @@ -310,7 +310,7 @@ def last_change_by_fname(): output = subprocess.check_output(['git', 'whatchanged', "--pretty=TIME:%ct"], cwd=REPO_DIR) - output = output.split('\n') + output = output.decode().split('\n') res = {} for fname, dt in TestLicenseHeaders.whatchanged_parse(output): if fname not in res or dt > res[fname]: diff --git a/lib/iris/tests/test_merge.py b/lib/iris/tests/test_merge.py index 0348233019..f19b2cc979 100644 --- a/lib/iris/tests/test_merge.py +++ b/lib/iris/tests/test_merge.py @@ -194,7 +194,8 @@ def _make_cube(self, a, b, c, d, data=0): long_name='y', units='1'), 0) for name, value in zip(['a', 'b', 'c', 'd'], [a, b, c, d]): - dtype = np.str if isinstance(value, six.string_types) else np.float32 + dtype = (np.dtype(six.text_type) + if isinstance(value, six.string_types) else np.float32) cube.add_aux_coord(AuxCoord(np.array([value], dtype=dtype), long_name=name, units='1')) @@ -260,7 +261,7 @@ def _make_cube(self, a, b, data=0, a_dim=False, b_dim=False): long_name='y', units='1'), 0) for name, value, dim in zip(['a', 'b'], [a, b], [a_dim, b_dim]): - dtype = np.str if isinstance(value, six.string_types) else np.float32 + dtype = 'U' if isinstance(value, six.string_types) else np.float32 ctype = DimCoord if dim else AuxCoord coord = ctype(np.array([value], dtype=dtype), long_name=name, units='1')