Skip to content

Commit afbb8b0

Browse files
authored
Merge branch 'main' into fix/3050
2 parents 334e55c + dd161df commit afbb8b0

File tree

13 files changed

+368
-70
lines changed

13 files changed

+368
-70
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ci:
66
default_stages: [pre-commit, pre-push]
77
repos:
88
- repo: https://github.com/astral-sh/ruff-pre-commit
9-
rev: v0.9.9
9+
rev: v0.11.9
1010
hooks:
1111
- id: ruff
1212
args: ["--fix", "--show-fixes"]
@@ -40,7 +40,7 @@ repos:
4040
- hypothesis
4141
- s3fs
4242
- repo: https://github.com/scientific-python/cookie
43-
rev: 2025.01.22
43+
rev: 2025.05.02
4444
hooks:
4545
- id: sp-repo-review
4646
- repo: https://github.com/pre-commit/pygrep-hooks

changes/2913.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added a `print_debug_info` function for bug reports.

changes/3049.misc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added tests for ``AsyncArray``, ``Array`` and removed duplicate argument parsing.

changes/3062.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Using various functions to open data with ``mode='a'`` no longer deletes existing data in the store.

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ extend-select = [
310310
"RUF",
311311
"SIM", # flake8-simplify
312312
"SLOT", # flake8-slots
313-
"TCH", # flake8-type-checking
313+
"TC", # flake8-type-checking
314314
"TRY", # tryceratops
315315
"UP", # pyupgrade
316316
"W", # pycodestyle warnings
@@ -338,6 +338,7 @@ ignore = [
338338
"Q003",
339339
"COM812",
340340
"COM819",
341+
"TC006",
341342
]
342343

343344
[tool.ruff.lint.extend-per-file-ignores]

src/zarr/__init__.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,54 @@
3737
# in case setuptools scm screw up and find version to be 0.0.0
3838
assert not __version__.startswith("0.0.0")
3939

40+
41+
def print_debug_info() -> None:
42+
"""
43+
Print version info for use in bug reports.
44+
"""
45+
import platform
46+
from importlib.metadata import version
47+
48+
def print_packages(packages: list[str]) -> None:
49+
not_installed = []
50+
for package in packages:
51+
try:
52+
print(f"{package}: {version(package)}")
53+
except ModuleNotFoundError:
54+
not_installed.append(package)
55+
if not_installed:
56+
print("\n**Not Installed:**")
57+
for package in not_installed:
58+
print(package)
59+
60+
required = [
61+
"packaging",
62+
"numpy",
63+
"numcodecs",
64+
"typing_extensions",
65+
"donfig",
66+
]
67+
optional = [
68+
"botocore",
69+
"cupy-cuda12x",
70+
"fsspec",
71+
"numcodecs",
72+
"s3fs",
73+
"gcsfs",
74+
"universal-pathlib",
75+
"rich",
76+
"obstore",
77+
]
78+
79+
print(f"platform: {platform.platform()}")
80+
print(f"python: {platform.python_version()}")
81+
print(f"zarr: {__version__}\n")
82+
print("**Required dependencies:**")
83+
print_packages(required)
84+
print("\n**Optional dependencies:**")
85+
print_packages(optional)
86+
87+
4088
__all__ = [
4189
"Array",
4290
"AsyncArray",
@@ -67,6 +115,7 @@
67115
"open_consolidated",
68116
"open_group",
69117
"open_like",
118+
"print_debug_info",
70119
"save",
71120
"save_array",
72121
"save_group",

src/zarr/api/asynchronous.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888

8989
_READ_MODES: tuple[AccessModeLiteral, ...] = ("r", "r+", "a")
9090
_CREATE_MODES: tuple[AccessModeLiteral, ...] = ("a", "w", "w-")
91-
_OVERWRITE_MODES: tuple[AccessModeLiteral, ...] = ("a", "r+", "w")
91+
_OVERWRITE_MODES: tuple[AccessModeLiteral, ...] = ("w",)
9292

9393

9494
def _infer_overwrite(mode: AccessModeLiteral) -> bool:
@@ -817,7 +817,6 @@ async def open_group(
817817
warnings.warn("chunk_store is not yet implemented", RuntimeWarning, stacklevel=2)
818818

819819
store_path = await make_store_path(store, mode=mode, storage_options=storage_options, path=path)
820-
821820
if attributes is None:
822821
attributes = {}
823822

@@ -1019,11 +1018,6 @@ async def create(
10191018
warnings.warn("object_codec is not yet implemented", RuntimeWarning, stacklevel=2)
10201019
if read_only is not None:
10211020
warnings.warn("read_only is not yet implemented", RuntimeWarning, stacklevel=2)
1022-
if dimension_separator is not None and zarr_format == 3:
1023-
raise ValueError(
1024-
"dimension_separator is not supported for zarr format 3, use chunk_key_encoding instead"
1025-
)
1026-
10271021
if order is not None:
10281022
_warn_order_kwarg()
10291023
if write_empty_chunks is not None:

src/zarr/api/synchronous.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ def create_array(
858858
Ignored otherwise.
859859
overwrite : bool, default False
860860
Whether to overwrite an array with the same name in the store, if one exists.
861+
If `True`, all existing paths in the store will be deleted.
861862
config : ArrayConfigLike, optional
862863
Runtime configuration for the array.
863864
write_data : bool

src/zarr/core/array.py

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ def parse_array_metadata(data: Any) -> ArrayMetadata:
140140
if isinstance(data, ArrayMetadata):
141141
return data
142142
elif isinstance(data, dict):
143-
if data["zarr_format"] == 3:
143+
zarr_format = data.get("zarr_format")
144+
if zarr_format == 3:
144145
meta_out = ArrayV3Metadata.from_dict(data)
145146
if len(meta_out.storage_transformers) > 0:
146147
msg = (
@@ -149,9 +150,11 @@ def parse_array_metadata(data: Any) -> ArrayMetadata:
149150
)
150151
raise ValueError(msg)
151152
return meta_out
152-
elif data["zarr_format"] == 2:
153+
elif zarr_format == 2:
153154
return ArrayV2Metadata.from_dict(data)
154-
raise TypeError
155+
else:
156+
raise ValueError(f"Invalid zarr_format: {zarr_format}. Expected 2 or 3")
157+
raise TypeError # pragma: no cover
155158

156159

157160
def create_codec_pipeline(metadata: ArrayMetadata) -> CodecPipeline:
@@ -160,8 +163,7 @@ def create_codec_pipeline(metadata: ArrayMetadata) -> CodecPipeline:
160163
elif isinstance(metadata, ArrayV2Metadata):
161164
v2_codec = V2Codec(filters=metadata.filters, compressor=metadata.compressor)
162165
return get_pipeline_class().from_codecs([v2_codec])
163-
else:
164-
raise TypeError
166+
raise TypeError # pragma: no cover
165167

166168

167169
async def get_array_metadata(
@@ -268,17 +270,6 @@ def __init__(
268270
store_path: StorePath,
269271
config: ArrayConfigLike | None = None,
270272
) -> None:
271-
if isinstance(metadata, dict):
272-
zarr_format = metadata["zarr_format"]
273-
# TODO: remove this when we extensively type the dict representation of metadata
274-
_metadata = cast(dict[str, JSON], metadata)
275-
if zarr_format == 2:
276-
metadata = ArrayV2Metadata.from_dict(_metadata)
277-
elif zarr_format == 3:
278-
metadata = ArrayV3Metadata.from_dict(_metadata)
279-
else:
280-
raise ValueError(f"Invalid zarr_format: {zarr_format}. Expected 2 or 3")
281-
282273
metadata_parsed = parse_array_metadata(metadata)
283274
config_parsed = parse_array_config(config)
284275

src/zarr/testing/stateful.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import zarr
1818
from zarr import Array
1919
from zarr.abc.store import Store
20+
from zarr.codecs.bytes import BytesCodec
2021
from zarr.core.buffer import Buffer, BufferPrototype, cpu, default_buffer_prototype
2122
from zarr.core.sync import SyncMixin
2223
from zarr.storage import LocalStore, MemoryStore
@@ -108,7 +109,15 @@ def add_array(
108109
assume(self.can_add(path))
109110
note(f"Adding array: path='{path}' shape={array.shape} chunks={chunks}")
110111
for store in [self.store, self.model]:
111-
zarr.array(array, chunks=chunks, path=path, store=store, fill_value=fill_value)
112+
zarr.array(
113+
array,
114+
chunks=chunks,
115+
path=path,
116+
store=store,
117+
fill_value=fill_value,
118+
# Chose bytes codec to avoid wasting time compressing the data being written
119+
codecs=[BytesCodec()],
120+
)
112121
self.all_arrays.add(path)
113122

114123
# @precondition(lambda self: bool(self.all_groups))

0 commit comments

Comments
 (0)