Skip to content

Commit 3d04845

Browse files
committed
Merge remote-tracking branch 'upstream/v3' into user/tom/fix/v2-compat
2 parents a5ad0ca + b1ecdd5 commit 3d04845

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1325
-740
lines changed

.github/workflows/releases.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
with:
5656
name: releases
5757
path: dist
58-
- uses: pypa/[email protected].0
58+
- uses: pypa/[email protected].1
5959
with:
6060
user: __token__
6161
password: ${{ secrets.pypi_password }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ coverage.xml
5151

5252
# Sphinx documentation
5353
docs/_build/
54+
docs/_autoapi
5455

5556
# PyBuilder
5657
target/

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ default_language_version:
77
python: python3
88
repos:
99
- repo: https://github.com/astral-sh/ruff-pre-commit
10-
rev: v0.6.3
10+
rev: v0.6.4
1111
hooks:
1212
- id: ruff
1313
args: ["--fix", "--show-fixes"]
@@ -25,7 +25,7 @@ repos:
2525
rev: v1.11.2
2626
hooks:
2727
- id: mypy
28-
files: src|tests/v3/test_(api|array|buffer).py
28+
files: src|tests
2929
additional_dependencies:
3030
# Package dependencies
3131
- asciitree
@@ -41,7 +41,7 @@ repos:
4141
# Zarr v2
4242
- types-redis
4343
- repo: https://github.com/scientific-python/cookie
44-
rev: 2024.04.23
44+
rev: 2024.08.19
4545
hooks:
4646
- id: sp-repo-review
4747
- repo: https://github.com/pre-commit/pygrep-hooks

docs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ help:
5252
.PHONY: clean
5353
clean:
5454
rm -rf $(BUILDDIR)/*
55+
rm -rf $(BUILDDIR)/../_autoapi
5556

5657
.PHONY: html
5758
html:

docs/api/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ API Reference
44
.. toctree::
55
:maxdepth: 1
66

7-
zarr
7+
../_autoapi/zarr/index

docs/api/zarr.rst

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/conf.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@
5757

5858
autoapi_dirs = ['../src/zarr']
5959
autoapi_add_toctree_entry = False
60-
autoapi_generate_api_docs = False
60+
autoapi_generate_api_docs = True
6161
autoapi_member_order = "groupwise"
62-
autoapi_root = "api"
62+
autoapi_root = "_autoapi"
63+
autoapi_keep_files = True
6364

6465

6566
# Add any paths that contain templates here, relative to this directory.
@@ -172,8 +173,19 @@
172173
html_logo = "_static/logo1.png"
173174

174175

176+
def autoapi_skip_modules(app: sphinx.application.Sphinx, what: str, name: str, obj: object, skip: bool, options: dict[str, Any]) -> bool:
177+
"""
178+
Return True if a module should be skipped in th API docs.
179+
"""
180+
parts = name.split(".")
181+
if what == "module" and (any(part.startswith("_") for part in parts) or "v2" in name or name.startswith("zarr.core")):
182+
return True
183+
return False
184+
185+
175186
def setup(app: sphinx.application.Sphinx) -> None:
176187
app.add_css_file("custom.css")
188+
app.connect("autoapi-skip-member", autoapi_skip_modules)
177189

178190

179191
# The name of an image file (relative to this directory) to use as a favicon of
@@ -339,7 +351,7 @@ def setup(app: sphinx.application.Sphinx) -> None:
339351
# use in refs e.g:
340352
# :ref:`comparison manual <python:comparisons>`
341353
intersphinx_mapping = {
342-
"python": ("https://docs.python.org/", None),
354+
"python": ("https://docs.python.org/3/", None),
343355
"numpy": ("https://numpy.org/doc/stable/", None),
344356
"numcodecs": ("https://numcodecs.readthedocs.io/en/stable/", None),
345357
}

pyproject.toml

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ gpu = [
7979
"cupy-cuda12x",
8080
]
8181
docs = [
82-
'sphinx',
82+
'sphinx<8',
8383
'sphinx-autobuild>=2021.3.14',
84-
'sphinx-autoapi',
84+
'sphinx-autoapi<3.1',
8585
'sphinx_design',
8686
'sphinx-issues',
8787
'sphinx-copybutton',
@@ -182,7 +182,6 @@ serve = "sphinx-autobuild docs docs/_build --host 0.0.0.0"
182182

183183
[tool.ruff]
184184
line-length = 100
185-
src = ["src"]
186185
force-exclude = true
187186
extend-exclude = [
188187
".bzr",
@@ -227,6 +226,7 @@ python_version = "3.10"
227226
ignore_missing_imports = true
228227
namespace_packages = false
229228

229+
230230
strict = true
231231
warn_unreachable = true
232232

@@ -238,6 +238,23 @@ module = [
238238
]
239239
ignore_errors = true
240240

241+
[[tool.mypy.overrides]]
242+
module = [
243+
"tests.v2.*",
244+
"tests.v3.package_with_entrypoint.*",
245+
"tests.v3.test_codecs.test_codecs",
246+
"tests.v3.test_codecs.test_transpose",
247+
"tests.v3.test_metadata.*",
248+
"tests.v3.test_store.*",
249+
"tests.v3.test_config",
250+
"tests.v3.test_group",
251+
"tests.v3.test_indexing",
252+
"tests.v3.test_properties",
253+
"tests.v3.test_sync",
254+
"tests.v3.test_v2",
255+
]
256+
ignore_errors = true
257+
241258
[tool.pytest.ini_options]
242259
minversion = "7"
243260
testpaths = ["tests"]
@@ -264,6 +281,6 @@ markers = [
264281

265282
[tool.repo-review]
266283
ignore = [
267-
"PC111", # fix Python code in documentation - enable later
284+
"PC111", # fix Python code in documentation - enable later
268285
"PC180", # for JavaScript - not interested
269286
]

src/zarr/abc/store.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212

1313
class AccessMode(NamedTuple):
14+
str: AccessModeLiteral
1415
readonly: bool
1516
overwrite: bool
1617
create: bool
@@ -20,6 +21,7 @@ class AccessMode(NamedTuple):
2021
def from_literal(cls, mode: AccessModeLiteral) -> Self:
2122
if mode in ("r", "r+", "a", "w", "w-"):
2223
return cls(
24+
str=mode,
2325
readonly=mode == "r",
2426
overwrite=mode == "w",
2527
create=mode in ("a", "w", "w-"),
@@ -42,6 +44,14 @@ async def open(cls, *args: Any, **kwargs: Any) -> Self:
4244
await store._open()
4345
return store
4446

47+
def __enter__(self) -> Self:
48+
"""Enter a context manager that will close the store upon exiting."""
49+
return self
50+
51+
def __exit__(self, *args: Any) -> None:
52+
"""Close the store."""
53+
self.close()
54+
4555
async def _open(self) -> None:
4656
if self._is_open:
4757
raise ValueError("store is already open")
@@ -73,6 +83,11 @@ def _check_writable(self) -> None:
7383
if self.mode.readonly:
7484
raise ValueError("store mode does not support writing")
7585

86+
@abstractmethod
87+
def __eq__(self, value: object) -> bool:
88+
"""Equality comparison."""
89+
...
90+
7691
@abstractmethod
7792
async def get(
7893
self,
@@ -143,6 +158,12 @@ async def set(self, key: str, value: Buffer) -> None:
143158
"""
144159
...
145160

161+
@property
162+
@abstractmethod
163+
def supports_deletes(self) -> bool:
164+
"""Does the store support deletes?"""
165+
...
166+
146167
@abstractmethod
147168
async def delete(self, key: str) -> None:
148169
"""Remove a key from the store
@@ -221,7 +242,6 @@ def list_dir(self, prefix: str) -> AsyncGenerator[str, None]:
221242
def close(self) -> None:
222243
"""Close the store."""
223244
self._is_open = False
224-
pass
225245

226246

227247
@runtime_checkable

src/zarr/api/asynchronous.py

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99

1010
from zarr.core.array import Array, AsyncArray
1111
from zarr.core.common import JSON, AccessModeLiteral, ChunkCoords, MemoryOrder, ZarrFormat
12+
from zarr.core.config import config
1213
from zarr.core.group import AsyncGroup
13-
from zarr.core.metadata import ArrayV2Metadata, ArrayV3Metadata
14+
from zarr.core.metadata.v2 import ArrayV2Metadata
15+
from zarr.core.metadata.v3 import ArrayV3Metadata
1416
from zarr.store import (
1517
StoreLike,
1618
make_store_path,
@@ -125,8 +127,7 @@ def _handle_zarr_version_or_format(
125127

126128
def _default_zarr_version() -> ZarrFormat:
127129
"""return the default zarr_version"""
128-
# TODO: set default value from config
129-
return 3
130+
return cast(ZarrFormat, int(config.get("default_zarr_version", 3)))
130131

131132

132133
async def consolidate_metadata(*args: Any, **kwargs: Any) -> AsyncGroup:
@@ -336,7 +337,10 @@ async def save_group(
336337
kwargs
337338
NumPy arrays with data to save.
338339
"""
339-
zarr_format = _handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format)
340+
zarr_format = (
341+
_handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format)
342+
or _default_zarr_version()
343+
)
340344

341345
if len(args) == 0 and len(kwargs) == 0:
342346
raise ValueError("at least one array must be provided")
@@ -447,10 +451,7 @@ async def group(
447451
The new group.
448452
"""
449453

450-
zarr_format = (
451-
_handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format)
452-
or _default_zarr_version()
453-
)
454+
zarr_format = _handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format)
454455

455456
store_path = await make_store_path(store)
456457
if path is not None:
@@ -473,7 +474,7 @@ async def group(
473474
except (KeyError, FileNotFoundError):
474475
return await AsyncGroup.from_store(
475476
store=store_path,
476-
zarr_format=zarr_format,
477+
zarr_format=zarr_format or _default_zarr_version(),
477478
exists_ok=overwrite,
478479
attributes=attributes,
479480
)
@@ -482,7 +483,7 @@ async def group(
482483
async def open_group(
483484
store: StoreLike | None = None,
484485
*, # Note: this is a change from v2
485-
mode: AccessModeLiteral | None = None, # not used
486+
mode: AccessModeLiteral | None = None,
486487
cache_attrs: bool | None = None, # not used, default changed
487488
synchronizer: Any = None, # not used
488489
path: str | None = None,
@@ -497,8 +498,18 @@ async def open_group(
497498
498499
Parameters
499500
----------
500-
store : Store or string, optional
501+
store : Store, string, or mapping, optional
501502
Store or path to directory in file system or name of zip file.
503+
504+
Strings are interpreted as paths on the local file system
505+
and used as the ``root`` argument to :class:`zarr.store.LocalStore`.
506+
507+
Dictionaries are used as the ``store_dict`` argument in
508+
:class:`zarr.store.MemoryStore``.
509+
510+
By default (``store=None``) a new :class:`zarr.store.MemoryStore`
511+
is created.
512+
502513
mode : {'r', 'r+', 'a', 'w', 'w-'}, optional
503514
Persistence mode: 'r' means read only (must exist); 'r+' means
504515
read/write (must exist); 'a' means read/write (create if doesn't
@@ -527,10 +538,7 @@ async def open_group(
527538
The new group.
528539
"""
529540

530-
zarr_format = (
531-
_handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format)
532-
or _default_zarr_version()
533-
)
541+
zarr_format = _handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format)
534542

535543
if cache_attrs is not None:
536544
warnings.warn("cache_attrs is not yet implemented", RuntimeWarning, stacklevel=2)
@@ -554,7 +562,10 @@ async def open_group(
554562
return await AsyncGroup.open(store_path, zarr_format=zarr_format)
555563
except (KeyError, FileNotFoundError):
556564
return await AsyncGroup.from_store(
557-
store_path, zarr_format=zarr_format, exists_ok=True, attributes=attributes
565+
store_path,
566+
zarr_format=zarr_format or _default_zarr_version(),
567+
exists_ok=True,
568+
attributes=attributes,
558569
)
559570

560571

@@ -676,7 +687,7 @@ async def create(
676687

677688
if zarr_format == 2 and chunks is None:
678689
chunks = shape
679-
if zarr_format == 3 and chunk_shape is None:
690+
elif zarr_format == 3 and chunk_shape is None:
680691
if chunks is not None:
681692
chunk_shape = chunks
682693
chunks = None
@@ -897,8 +908,7 @@ async def open_array(
897908
if store_path.store.mode.create:
898909
return await create(
899910
store=store_path,
900-
path=path,
901-
zarr_format=zarr_format,
911+
zarr_format=zarr_format or _default_zarr_version(),
902912
overwrite=store_path.store.mode.overwrite,
903913
**kwargs,
904914
)

0 commit comments

Comments
 (0)