Skip to content

Commit

Permalink
BUG: fix writing to groups with h5netcdf (#2181)
Browse files Browse the repository at this point in the history
* BUG: fix writing to groups with h5netcdf

Fixes GH2177

Our test suite was inadvertently not checking this.

* what's new note
  • Loading branch information
shoyer committed May 25, 2018
1 parent 48d55ee commit b48e096
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 12 deletions.
6 changes: 5 additions & 1 deletion doc/whats-new.rst
Expand Up @@ -64,7 +64,11 @@ Bug fixes
longer falsely returns an empty array when the slice includes the value in
the index) (:issue:`2165`).
By `Spencer Clark <https://github.com/spencerkclark>`_.


- Fix Dataset.to_netcdf() cannot create group with engine="h5netcdf"
(:issue:`2177`).
By `Stephan Hoyer <https://github.com/shoyer>`_

.. _whats-new.0.10.4:

v0.10.4 (May 16, 2018)
Expand Down
9 changes: 7 additions & 2 deletions xarray/backends/h5netcdf_.py
Expand Up @@ -12,7 +12,7 @@
HDF5_LOCK, DataStorePickleMixin, WritableCFDataStore, find_root)
from .netCDF4_ import (
BaseNetCDF4Array, _encode_nc4_variable, _extract_nc4_variable_encoding,
_get_datatype, _nc4_group)
_get_datatype, _nc4_require_group)


class H5NetCDFArrayWrapper(BaseNetCDF4Array):
Expand Down Expand Up @@ -57,11 +57,16 @@ def _read_attributes(h5netcdf_var):
lsd_okay=False, h5py_okay=True, backend='h5netcdf')


def _h5netcdf_create_group(dataset, name):
return dataset.create_group(name)


def _open_h5netcdf_group(filename, mode, group):
import h5netcdf
ds = h5netcdf.File(filename, mode=mode)
with close_on_error(ds):
return _nc4_group(ds, group, mode)
return _nc4_require_group(
ds, group, mode, create_group=_h5netcdf_create_group)


class H5NetCDFStore(WritableCFDataStore, DataStorePickleMixin):
Expand Down
10 changes: 7 additions & 3 deletions xarray/backends/netCDF4_.py
Expand Up @@ -108,7 +108,11 @@ def _nc4_dtype(var):
return dtype


def _nc4_group(ds, group, mode):
def _netcdf4_create_group(dataset, name):
return dataset.createGroup(name)


def _nc4_require_group(ds, group, mode, create_group=_netcdf4_create_group):
if group in set([None, '', '/']):
# use the root group
return ds
Expand All @@ -123,7 +127,7 @@ def _nc4_group(ds, group, mode):
ds = ds.groups[key]
except KeyError as e:
if mode != 'r':
ds = ds.createGroup(key)
ds = create_group(ds, key)
else:
# wrap error to provide slightly more helpful message
raise IOError('group not found: %s' % key, e)
Expand Down Expand Up @@ -210,7 +214,7 @@ def _open_netcdf4_group(filename, mode, group=None, **kwargs):
ds = nc4.Dataset(filename, mode=mode, **kwargs)

with close_on_error(ds):
ds = _nc4_group(ds, group, mode)
ds = _nc4_require_group(ds, group, mode)

_disable_auto_decode_group(ds)

Expand Down
12 changes: 6 additions & 6 deletions xarray/tests/test_backends.py
Expand Up @@ -892,7 +892,7 @@ def test_open_group(self):

# check equivalent ways to specify group
for group in 'foo', '/foo', 'foo/', '/foo/':
with open_dataset(tmp_file, group=group) as actual:
with self.open(tmp_file, group=group) as actual:
assert_equal(actual['x'], expected['x'])

# check that missing group raises appropriate exception
Expand Down Expand Up @@ -920,18 +920,18 @@ def test_open_subgroup(self):

# check equivalent ways to specify group
for group in 'foo/bar', '/foo/bar', 'foo/bar/', '/foo/bar/':
with open_dataset(tmp_file, group=group) as actual:
with self.open(tmp_file, group=group) as actual:
assert_equal(actual['x'], expected['x'])

def test_write_groups(self):
data1 = create_test_data()
data2 = data1 * 2
with create_tmp_file() as tmp_file:
data1.to_netcdf(tmp_file, group='data/1')
data2.to_netcdf(tmp_file, group='data/2', mode='a')
with open_dataset(tmp_file, group='data/1') as actual1:
self.save(data1, tmp_file, group='data/1')
self.save(data2, tmp_file, group='data/2', mode='a')
with self.open(tmp_file, group='data/1') as actual1:
assert_identical(data1, actual1)
with open_dataset(tmp_file, group='data/2') as actual2:
with self.open(tmp_file, group='data/2') as actual2:
assert_identical(data2, actual2)

def test_roundtrip_string_with_fill_value_vlen(self):
Expand Down

0 comments on commit b48e096

Please sign in to comment.