Skip to content

Commit

Permalink
Merge pull request #1830 from pp-mo/py3k-unicode-cf
Browse files Browse the repository at this point in the history
Py3k unicode cf
  • Loading branch information
rhattersley committed Nov 17, 2015
2 parents deedfb9 + 747fddb commit 7fed0ca
Showing 1 changed file with 19 additions and 7 deletions.
26 changes: 19 additions & 7 deletions lib/iris/fileformats/cf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)):
Expand Down Expand Up @@ -637,9 +643,10 @@ def identify(cls, variables, ignore=None, target=None, warn=True):
message = 'Missing CF-netCDF label variable %r, referenced by netCDF variable %r'
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])
# Register variable, but only allow string type.
var = variables[name]
if _is_str_dtype(var):
result[name] = CFLabelVariable(name, var)

return result

Expand Down Expand Up @@ -683,7 +690,9 @@ 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])
string_basetype = '|S%d' if six.PY2 else '|U%d'
string_dtype = string_basetype % self.shape[str_dim]
data = np.empty(new_shape, dtype=string_dtype)

for index in np.ndindex(new_shape):
# Create the slice for the label data.
Expand All @@ -692,7 +701,10 @@ def cf_label_data(self, cf_data_var):
else:
label_index = index + (slice(None, None),)

data[index] = ''.join(label_data[label_index]).strip()
label_string = b''.join(label_data[label_index]).strip()
if six.PY3:
label_string = label_string.decode('utf8')
data[index] = label_string

return data

Expand Down

0 comments on commit 7fed0ca

Please sign in to comment.