Skip to content

Commit dfa97da

Browse files
davidbrochartshoyer
authored andcommitted
to_zarr(append_dim='dim0') doesn't need mode='a' (#3123)
* to_zarr(append_dim='dim0') doesn't need mode='a' * Updated whats-new.rst * Default mode=None allows checking consistency with append_dim * Fix PEP8 issue * Moved mode handling from api.py to dataset.py * Fix closing bracket indentation
1 parent 1d7bcbd commit dfa97da

File tree

5 files changed

+43
-16
lines changed

5 files changed

+43
-16
lines changed

doc/io.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,9 @@ store is already present at that path, an error will be raised, preventing it
609609
from being overwritten. To override this behavior and overwrite an existing
610610
store, add ``mode='w'`` when invoking ``to_zarr``.
611611

612-
It is also possible to append to an existing store. For that, add ``mode='a'``
613-
and set ``append_dim`` to the name of the dimension along which to append.
612+
It is also possible to append to an existing store. For that, set
613+
``append_dim`` to the name of the dimension along which to append. ``mode``
614+
can be omitted as it will internally be set to ``'a'``.
614615

615616
.. ipython:: python
616617
:suppress:
@@ -628,7 +629,7 @@ and set ``append_dim`` to the name of the dimension along which to append.
628629
coords={'x': [10, 20, 30, 40],
629630
'y': [1,2,3,4,5],
630631
't': pd.date_range('2001-01-03', periods=2)})
631-
ds2.to_zarr('path/to/directory.zarr', mode='a', append_dim='t')
632+
ds2.to_zarr('path/to/directory.zarr', append_dim='t')
632633
633634
To store variable length strings use ``dtype=object``.
634635

doc/whats-new.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ New functions/methods
3131
Enhancements
3232
~~~~~~~~~~~~
3333

34+
- In :py:meth:`~xarray.Dataset.to_zarr`, passing ``mode`` is not mandatory if
35+
``append_dim`` is set, as it will automatically be set to ``'a'`` internally.
36+
By `David Brochart <https://github.com/davidbrochart>`_.
37+
3438
Bug fixes
3539
~~~~~~~~~
3640

xarray/backends/api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ def _validate_append_dim_and_encoding(ds_to_append, store, append_dim,
11021102
)
11031103

11041104

1105-
def to_zarr(dataset, store=None, mode='w-', synchronizer=None, group=None,
1105+
def to_zarr(dataset, store=None, mode=None, synchronizer=None, group=None,
11061106
encoding=None, compute=True, consolidated=False, append_dim=None):
11071107
"""This function creates an appropriate datastore for writing a dataset to
11081108
a zarr ztore
@@ -1118,7 +1118,7 @@ def to_zarr(dataset, store=None, mode='w-', synchronizer=None, group=None,
11181118
_validate_dataset_names(dataset)
11191119
_validate_attrs(dataset)
11201120

1121-
if mode == "a":
1121+
if mode == 'a':
11221122
_validate_datatypes_for_zarr_append(dataset)
11231123
_validate_append_dim_and_encoding(dataset, store, append_dim,
11241124
group=group,

xarray/core/dataset.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,7 +1390,7 @@ def to_netcdf(
13901390
def to_zarr(
13911391
self,
13921392
store: Union[MutableMapping, str, Path] = None,
1393-
mode: str = 'w-',
1393+
mode: str = None,
13941394
synchronizer=None,
13951395
group: str = None,
13961396
encoding: Mapping = None,
@@ -1408,10 +1408,13 @@ def to_zarr(
14081408
----------
14091409
store : MutableMapping, str or Path, optional
14101410
Store or path to directory in file system.
1411-
mode : {'w', 'w-', 'a'}
1411+
mode : {'w', 'w-', 'a', None}
14121412
Persistence mode: 'w' means create (overwrite if exists);
14131413
'w-' means create (fail if exists);
14141414
'a' means append (create if does not exist).
1415+
If ``append_dim`` is set, ``mode`` can be omitted as it is
1416+
internally set to ``'a'``. Otherwise, ``mode`` will default to
1417+
`w-` if not set.
14151418
synchronizer : object, optional
14161419
Array synchronizer
14171420
group : str, optional
@@ -1427,14 +1430,24 @@ def to_zarr(
14271430
If True, apply zarr's `consolidate_metadata` function to the store
14281431
after writing.
14291432
append_dim: hashable, optional
1430-
If mode='a', the dimension on which the data will be appended.
1433+
If set, the dimension on which the data will be appended.
14311434
14321435
References
14331436
----------
14341437
https://zarr.readthedocs.io/
14351438
"""
14361439
if encoding is None:
14371440
encoding = {}
1441+
if (mode == 'a') or (append_dim is not None):
1442+
if mode is None:
1443+
mode = 'a'
1444+
elif mode != 'a':
1445+
raise ValueError(
1446+
"append_dim was set along with mode='{}', either set "
1447+
"mode='a' or don't set it.".format(mode)
1448+
)
1449+
elif mode is None:
1450+
mode = 'w-'
14381451
if mode not in ['w', 'w-', 'a']:
14391452
# TODO: figure out how to handle 'r+'
14401453
raise ValueError("The only supported options for mode are 'w',"

xarray/tests/test_backends.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,7 @@ def test_write_persistence_modes(self):
16551655
# check append mode for append write
16561656
with self.create_zarr_target() as store_target:
16571657
ds.to_zarr(store_target, mode='w')
1658-
ds_to_append.to_zarr(store_target, mode='a', append_dim='time')
1658+
ds_to_append.to_zarr(store_target, append_dim='time')
16591659
original = xr.concat([ds, ds_to_append], dim='time')
16601660
assert_identical(original, xr.open_zarr(store_target))
16611661

@@ -1691,7 +1691,7 @@ def test_append_write(self):
16911691
ds, ds_to_append, _ = create_append_test_data()
16921692
with self.create_zarr_target() as store_target:
16931693
ds.to_zarr(store_target, mode='w')
1694-
ds_to_append.to_zarr(store_target, mode='a', append_dim='time')
1694+
ds_to_append.to_zarr(store_target, append_dim='time')
16951695
original = xr.concat([ds, ds_to_append], dim='time')
16961696
assert_identical(original, xr.open_zarr(store_target))
16971697

@@ -1707,8 +1707,7 @@ def test_append_with_invalid_dim_raises(self):
17071707
with pytest.raises(ValueError):
17081708
with self.create_zarr_target() as store_target:
17091709
ds.to_zarr(store_target, mode='w')
1710-
ds_to_append.to_zarr(store_target, mode='a',
1711-
append_dim='notvalid')
1710+
ds_to_append.to_zarr(store_target, append_dim='notvalid')
17121711

17131712
def test_append_with_append_dim_not_set_raises(self):
17141713

@@ -1720,6 +1719,17 @@ def test_append_with_append_dim_not_set_raises(self):
17201719
ds.to_zarr(store_target, mode='w')
17211720
ds_to_append.to_zarr(store_target, mode='a')
17221721

1722+
def test_append_with_mode_not_a_raises(self):
1723+
1724+
ds, ds_to_append, _ = create_append_test_data()
1725+
1726+
# check failure when append_dim is set and mode != 'a'
1727+
with pytest.raises(ValueError):
1728+
with self.create_zarr_target() as store_target:
1729+
ds.to_zarr(store_target, mode='w')
1730+
ds_to_append.to_zarr(store_target, mode='w',
1731+
append_dim='time')
1732+
17231733
def test_append_with_existing_encoding_raises(self):
17241734

17251735
ds, ds_to_append, _ = create_append_test_data()
@@ -1728,8 +1738,7 @@ def test_append_with_existing_encoding_raises(self):
17281738
with pytest.raises(ValueError):
17291739
with self.create_zarr_target() as store_target:
17301740
ds.to_zarr(store_target, mode='w')
1731-
ds_to_append.to_zarr(store_target, mode='a',
1732-
append_dim='time',
1741+
ds_to_append.to_zarr(store_target, append_dim='time',
17331742
encoding={'da': {'compressor': None}})
17341743

17351744
def test_check_encoding_is_consistent_after_append(self):
@@ -1742,7 +1751,7 @@ def test_check_encoding_is_consistent_after_append(self):
17421751
compressor = zarr.Blosc()
17431752
encoding = {'da': {'compressor': compressor}}
17441753
ds.to_zarr(store_target, mode='w', encoding=encoding)
1745-
ds_to_append.to_zarr(store_target, mode='a', append_dim='time')
1754+
ds_to_append.to_zarr(store_target, append_dim='time')
17461755
actual_ds = xr.open_zarr(store_target)
17471756
actual_encoding = actual_ds['da'].encoding['compressor']
17481757
assert actual_encoding.get_config() == compressor.get_config()
@@ -1803,7 +1812,7 @@ def test_to_zarr_append_compute_false_roundtrip(self):
18031812
assert_identical(ds, actual)
18041813

18051814
delayed_obj = self.save(ds_to_append, store, compute=False,
1806-
mode='a', append_dim='time')
1815+
append_dim='time')
18071816
assert isinstance(delayed_obj, Delayed)
18081817

18091818
with pytest.raises(AssertionError):

0 commit comments

Comments
 (0)