diff --git a/lib/iris/fileformats/__init__.py b/lib/iris/fileformats/__init__.py index 0af0888b3f..8de17eb5b8 100644 --- a/lib/iris/fileformats/__init__.py +++ b/lib/iris/fileformats/__init__.py @@ -155,6 +155,20 @@ def _load_grib(*args, **kwargs): ) +# +# Zarr files. +# +FORMAT_AGENT.add_spec( + FormatSpecification( + "zarr", + FileExtension(requires_fh=False), + ".zarr#mode=nczarr,file", + netcdf.load_cubes, + priority=3, + ) +) + + # # UM Fieldsfiles. # diff --git a/lib/iris/fileformats/netcdf/saver.py b/lib/iris/fileformats/netcdf/saver.py index 98c565e990..fc420a2a99 100644 --- a/lib/iris/fileformats/netcdf/saver.py +++ b/lib/iris/fileformats/netcdf/saver.py @@ -418,7 +418,11 @@ def __init__(self, filename, netcdf_format, compute=True): else: # Given a filepath string/path : create a dataset from that try: - self.filepath = Path(filename).absolute() + filepath = Path(filename) + if ".zarr" not in filepath.suffix: + self.filepath = filepath.absolute() + else: + self.filepath = filepath self._dataset = _thread_safe_nc.DatasetWrapper( self.filepath, mode="w", format=netcdf_format ) diff --git a/lib/iris/io/__init__.py b/lib/iris/io/__init__.py index 1a895ff1a3..3a6f38c44d 100644 --- a/lib/iris/io/__init__.py +++ b/lib/iris/io/__init__.py @@ -129,7 +129,10 @@ def decode_uri(uri, default="file"): # put - last in the brackets so it refers to the character, not a range # reference on valid schemes: https://tools.ietf.org/html/std66#section-3.1 match = re.match(r"^([a-zA-Z][a-zA-Z0-9+.-]+):(.+)", uri) - if match: + if ".zarr" in uri: + scheme = "zarr" + part = uri + elif match: scheme = match.group(1) part = match.group(2) else: diff --git a/lib/iris/loading.py b/lib/iris/loading.py index 68042847c1..69bfab30e3 100644 --- a/lib/iris/loading.py +++ b/lib/iris/loading.py @@ -97,6 +97,10 @@ def _generate_cubes(uris, callback, constraints): urls = [":".join(x) for x in groups] for cube in iris.io.load_http(urls, callback): yield cube + elif scheme == "zarr": + urls = [x[1] for x in groups] + for cube in iris.io.load_http(urls, callback): + yield cube elif scheme == "data": data_objects = [x[1] for x in groups] for cube in iris.io.load_data_objects(data_objects, callback): diff --git a/lib/iris/tests/results/file_load/known_loaders.txt b/lib/iris/tests/results/file_load/known_loaders.txt index 98ac3e4a07..8aa7afc4e1 100644 --- a/lib/iris/tests/results/file_load/known_loaders.txt +++ b/lib/iris/tests/results/file_load/known_loaders.txt @@ -14,4 +14,5 @@ * UM Fieldsfile (FF) converted with ieee to 32 bit (priority 3) * UM Fieldsfile (FF) pre v3.1 (priority 3) * UM Post Processing file (PP) little-endian (priority 3) + * zarr (priority 3) * GRIB (priority 1) \ No newline at end of file