Skip to content
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
86563b9
Rewrite DataTree.to_netcdf and support netCDF4 in-memory
shoyer Aug 8, 2025
cce5477
Refactor to_netcdf() and to_zarr() internals
shoyer Aug 11, 2025
a3689d4
Merge branch 'main' into to_netcdf-internals
shoyer Aug 12, 2025
f5ba356
Merge branch 'main' into to_netcdf-internals
shoyer Aug 12, 2025
c4d57f1
Merge branch 'main' into to_netcdf-internals
shoyer Aug 13, 2025
22d3387
Fixes per review
shoyer Aug 13, 2025
e68e186
Clean up comments
shoyer Aug 13, 2025
b925465
Merge branch 'main' into to_netcdf-internals
shoyer Aug 15, 2025
6d8ae1e
Fix type for to_netcdf()
shoyer Aug 15, 2025
d9da973
Add test and whats-new for cross-group redundant computation
shoyer Aug 15, 2025
205fdbe
Fix test failure on CI (and add a better test)
shoyer Aug 16, 2025
e82c334
grammar
shoyer Aug 16, 2025
24d3552
Merge branch 'to_netcdf-internals' into netcdf4-memory
shoyer Aug 16, 2025
ca5feca
Tweaks
shoyer Aug 16, 2025
1be418e
Merge branch 'main' into netcdf4-memory
shoyer Aug 19, 2025
cf22188
post merge fixes
shoyer Aug 19, 2025
487a2f7
Merge branch 'main' into netcdf4-memory
shoyer Sep 5, 2025
dc8bf9f
Fix tests
shoyer Sep 6, 2025
d6b32cb
More tests
shoyer Sep 6, 2025
0311987
Fix bug and add type annotations
shoyer Sep 8, 2025
292d63a
tweak tests
shoyer Sep 8, 2025
d633686
remove unnecessary seek
shoyer Sep 8, 2025
614f62e
Merge branch 'main' into netcdf4-memory
shoyer Sep 8, 2025
dfc651d
Add release notes
shoyer Sep 8, 2025
f267148
fix test failures
shoyer Sep 9, 2025
471ad2d
Merge branch 'main' into netcdf4-memory
shoyer Sep 9, 2025
2100673
tweak whats new
shoyer Sep 9, 2025
5a2dc42
Make scipy import no longer lazy
shoyer Sep 9, 2025
cdc7523
Update doc/whats-new.rst
shoyer Sep 9, 2025
2ee2207
Merge branch 'main' into netcdf4-memory
shoyer Sep 10, 2025
190e962
Fix error on Windows
shoyer Sep 16, 2025
4d22468
Silence Zarr v3 warnings (#10731)
max-sixty Sep 10, 2025
8eedfd8
propagate attrs on coords in `Dataset.map` (#10602)
keewis Sep 10, 2025
18af4b3
Add pep-723 style script to bug report issue template (#10707)
ianhi Sep 10, 2025
678c004
Allow `mean` with time dtypes (#10227)
dcherian Sep 11, 2025
145a445
TYP: explicit `DTypeLike | None` (#10738)
jorenham Sep 12, 2025
bc11b60
refine Claude instructions (#10744)
max-sixty Sep 15, 2025
917f238
fix bugreport.yml (#10746)
gronniger Sep 15, 2025
d9047c2
Add co-authorship instruction to CLAUDE.md (#10748)
max-sixty Sep 15, 2025
2a020c0
Revert "fix bugreport.yml (#10746)" (#10749)
max-sixty Sep 15, 2025
a5f33e8
Fix to_netcdf(compute=False) with Dask distributed (#10730)
shoyer Sep 15, 2025
f86afc3
cleanup bug report template (#10752)
ianhi Sep 15, 2025
da93f8c
Ensure that groupby.groups works even with multiple groupers (#10750)
jsignell Sep 15, 2025
74a075b
Remove xarray.tests.test_combine from mypy exclusions (#10753)
max-sixty Sep 15, 2025
c3653ce
Synchronize mypy test requirements to 1.17.1 (#10751)
shoyer Sep 15, 2025
2d56f6b
Multiple imports for an import name (#10743)
DimitriPapadopoulos Sep 15, 2025
8f9363e
Add note about breaking change
shoyer Sep 16, 2025
177db16
Merge branch 'main' into netcdf4-memory
shoyer Sep 16, 2025
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
14 changes: 14 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ v2025.09.1 (unreleased)
New Features
~~~~~~~~~~~~

- ``engine='netcdf4'`` now supports reading and writing in-memory netCDF files.
All of Xarray's netCDF backends now support in-memory reads and writes
(:pull:`10624`).
By `Stephan Hoyer <https://github.com/shoyer>`_.

Breaking changes
~~~~~~~~~~~~~~~~
Expand All @@ -29,6 +33,16 @@ Deprecations
Bug fixes
~~~~~~~~~

- Xarray objects opened from file-like objects with ``engine='h5netcdf'`` can
now be pickled, as long as the underlying file-like object also supports
pickle (:issue:`10712`).
By `Stephan Hoyer <https://github.com/shoyer>`_.

- Closing Xarray objects opened from file-like objects with ```engine='scipy'``
no longer closes the underlying file, consistent the h5netcdf backend
(:pull:`10624`).
By `Stephan Hoyer <https://github.com/shoyer>`_.

- Fix the ``align_chunks`` parameter on the :py:meth:`~xarray.Dataset.to_zarr` method, it was not being
passed to the underlying :py:meth:`~xarray.backends.api` method (:issue:`10501`, :pull:`10516`).

Expand Down
71 changes: 31 additions & 40 deletions xarray/backends/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@

def get_default_netcdf_write_engine(
format: T_NetcdfTypes | None,
to_fileobject_or_memoryview: bool,
to_fileobject: bool,
) -> Literal["netcdf4", "h5netcdf", "scipy"]:
"""Return the default netCDF library to use for writing a netCDF file."""
module_names = {
Expand All @@ -119,7 +119,7 @@ def get_default_netcdf_write_engine(
else:
raise ValueError(f"unexpected {format=}")

if to_fileobject_or_memoryview:
if to_fileobject:
candidates.remove("netcdf4")

for engine in candidates:
Expand Down Expand Up @@ -546,14 +546,12 @@ def open_dataset(
cache: bool | None = None,
decode_cf: bool | None = None,
mask_and_scale: bool | Mapping[str, bool] | None = None,
decode_times: bool
| CFDatetimeCoder
| Mapping[str, bool | CFDatetimeCoder]
| None = None,
decode_timedelta: bool
| CFTimedeltaCoder
| Mapping[str, bool | CFTimedeltaCoder]
| None = None,
decode_times: (
bool | CFDatetimeCoder | Mapping[str, bool | CFDatetimeCoder] | None
) = None,
decode_timedelta: (
bool | CFTimedeltaCoder | Mapping[str, bool | CFTimedeltaCoder] | None
) = None,
use_cftime: bool | Mapping[str, bool] | None = None,
concat_characters: bool | Mapping[str, bool] | None = None,
decode_coords: Literal["coordinates", "all"] | bool | None = None,
Expand Down Expand Up @@ -789,10 +787,9 @@ def open_dataarray(
cache: bool | None = None,
decode_cf: bool | None = None,
mask_and_scale: bool | None = None,
decode_times: bool
| CFDatetimeCoder
| Mapping[str, bool | CFDatetimeCoder]
| None = None,
decode_times: (
bool | CFDatetimeCoder | Mapping[str, bool | CFDatetimeCoder] | None
) = None,
decode_timedelta: bool | CFTimedeltaCoder | None = None,
use_cftime: bool | None = None,
concat_characters: bool | None = None,
Expand Down Expand Up @@ -1019,14 +1016,12 @@ def open_datatree(
cache: bool | None = None,
decode_cf: bool | None = None,
mask_and_scale: bool | Mapping[str, bool] | None = None,
decode_times: bool
| CFDatetimeCoder
| Mapping[str, bool | CFDatetimeCoder]
| None = None,
decode_timedelta: bool
| CFTimedeltaCoder
| Mapping[str, bool | CFTimedeltaCoder]
| None = None,
decode_times: (
bool | CFDatetimeCoder | Mapping[str, bool | CFDatetimeCoder] | None
) = None,
decode_timedelta: (
bool | CFTimedeltaCoder | Mapping[str, bool | CFTimedeltaCoder] | None
) = None,
use_cftime: bool | Mapping[str, bool] | None = None,
concat_characters: bool | Mapping[str, bool] | None = None,
decode_coords: Literal["coordinates", "all"] | bool | None = None,
Expand Down Expand Up @@ -1261,14 +1256,12 @@ def open_groups(
cache: bool | None = None,
decode_cf: bool | None = None,
mask_and_scale: bool | Mapping[str, bool] | None = None,
decode_times: bool
| CFDatetimeCoder
| Mapping[str, bool | CFDatetimeCoder]
| None = None,
decode_timedelta: bool
| CFTimedeltaCoder
| Mapping[str, bool | CFTimedeltaCoder]
| None = None,
decode_times: (
bool | CFDatetimeCoder | Mapping[str, bool | CFDatetimeCoder] | None
) = None,
decode_timedelta: (
bool | CFTimedeltaCoder | Mapping[str, bool | CFTimedeltaCoder] | None
) = None,
use_cftime: bool | Mapping[str, bool] | None = None,
concat_characters: bool | Mapping[str, bool] | None = None,
decode_coords: Literal["coordinates", "all"] | bool | None = None,
Expand Down Expand Up @@ -1524,10 +1517,9 @@ def _remove_path(


def open_mfdataset(
paths: str
| os.PathLike
| ReadBuffer
| NestedSequence[str | os.PathLike | ReadBuffer],
paths: (
str | os.PathLike | ReadBuffer | NestedSequence[str | os.PathLike | ReadBuffer]
),
chunks: T_Chunks = None,
concat_dim: (
str
Expand All @@ -1541,10 +1533,9 @@ def open_mfdataset(
compat: CompatOptions | CombineKwargDefault = _COMPAT_DEFAULT,
preprocess: Callable[[Dataset], Dataset] | None = None,
engine: T_Engine = None,
data_vars: Literal["all", "minimal", "different"]
| None
| list[str]
| CombineKwargDefault = _DATA_VARS_DEFAULT,
data_vars: (
Literal["all", "minimal", "different"] | None | list[str] | CombineKwargDefault
) = _DATA_VARS_DEFAULT,
coords=_COORDS_DEFAULT,
combine: Literal["by_coords", "nested"] = "by_coords",
parallel: bool = False,
Expand Down Expand Up @@ -2055,8 +2046,8 @@ def to_netcdf(
path_or_file = _normalize_path(path_or_file)

if engine is None:
to_fileobject_or_memoryview = not isinstance(path_or_file, str)
engine = get_default_netcdf_write_engine(format, to_fileobject_or_memoryview)
to_fileobject = isinstance(path_or_file, IOBase)
engine = get_default_netcdf_write_engine(format, to_fileobject)

# validate Dataset keys, DataArray names, and attr keys/values
_validate_dataset_names(dataset)
Expand Down
Loading
Loading