Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Py3k unicode cf #1830

Merged
merged 3 commits into from
Nov 17, 2015
Merged
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
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