From a293d67a8b1a75193c48fd3973f7c5c04556fec6 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Fri, 14 Aug 2026 14:18:46 +0200 Subject: [PATCH 1/2] chore(zarr-metadata): note the sdist allowlist, and let misc entries speak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #4248 gave this package's sdist an explicit allowlist and merged without a news fragment, so a user-visible packaging change was about to miss the 0.5.0 notes. Add one. Filing it as `misc` exposed that towncrier's built-in `misc` type sets `showcontent = false`: the entry would render as a bare PR link, which tells a reader nothing. Restate all five types the `changes/README.md` menu offers — declaring any type replaces the built-in set — as the defaults verbatim except for `misc`, which now shows its content. A change worth a release note is worth a sentence, whatever its category. Assisted-by: ClaudeCode:claude-opus-5 --- packages/zarr-metadata/changes/4248.misc.md | 4 +++ packages/zarr-metadata/pyproject.toml | 30 +++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 packages/zarr-metadata/changes/4248.misc.md diff --git a/packages/zarr-metadata/changes/4248.misc.md b/packages/zarr-metadata/changes/4248.misc.md new file mode 100644 index 0000000000..e21a0cf854 --- /dev/null +++ b/packages/zarr-metadata/changes/4248.misc.md @@ -0,0 +1,4 @@ +The source distribution now ships an explicit allowlist (`/src`, `/tests`, +`/docs`, `/mkdocs.yml`, `/justfile`, `/CHANGELOG.md`) rather than whatever +happens to sit in the package directory, so an sdist both tests and documents +itself and cannot pick up scratch files from the tree it was built in. diff --git a/packages/zarr-metadata/pyproject.toml b/packages/zarr-metadata/pyproject.toml index 0df3385dc7..a58d3579a1 100644 --- a/packages/zarr-metadata/pyproject.toml +++ b/packages/zarr-metadata/pyproject.toml @@ -137,3 +137,33 @@ underlines = ["", "", ""] title_format = "## {version} ({project_date})" issue_format = "[#{issue}](https://github.com/zarr-developers/zarr-python/pull/{issue})" start_string = "\n" + +# Declaring any type replaces towncrier's built-in set, so all five the +# `changes/README.md` menu offers are restated here. They are the defaults +# verbatim except for `misc`, whose `showcontent` towncrier defaults to false: +# a `misc` entry would render as a bare PR link, which tells a reader nothing. +# A change worth a release note is worth a sentence, whatever its category. +[[tool.towncrier.type]] +directory = "feature" +name = "Features" +showcontent = true + +[[tool.towncrier.type]] +directory = "bugfix" +name = "Bugfixes" +showcontent = true + +[[tool.towncrier.type]] +directory = "doc" +name = "Improved Documentation" +showcontent = true + +[[tool.towncrier.type]] +directory = "removal" +name = "Deprecations and Removals" +showcontent = true + +[[tool.towncrier.type]] +directory = "misc" +name = "Misc" +showcontent = true From 3161fca5d10b51b02443139c89900ab9bf78d83c Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Fri, 14 Aug 2026 14:19:00 +0200 Subject: [PATCH 2/2] chore(zarr-metadata): build 0.5.0 changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consume the pending news fragments — #4232's constant-naming-grammar removal note, #4264's note widening `JSONValue`'s array arm to the covariant `Sequence`, and #4248's sdist allowlist — into CHANGELOG.md via towncrier for the zarr_metadata-v0.5.0 release. Minor, not patch: the `JSONValue` widening changes a published type's meaning for every consumer that annotates against it, and #4232 removes the old version-last constant spellings outright. Assisted-by: ClaudeCode:claude-opus-5 --- packages/zarr-metadata/CHANGELOG.md | 90 +++++++++++++++++++ .../zarr-metadata/changes/4232.removal.md | 63 ------------- packages/zarr-metadata/changes/4248.misc.md | 4 - packages/zarr-metadata/changes/4264.bugfix.md | 9 -- 4 files changed, 90 insertions(+), 76 deletions(-) delete mode 100644 packages/zarr-metadata/changes/4232.removal.md delete mode 100644 packages/zarr-metadata/changes/4248.misc.md delete mode 100644 packages/zarr-metadata/changes/4264.bugfix.md diff --git a/packages/zarr-metadata/CHANGELOG.md b/packages/zarr-metadata/CHANGELOG.md index ac4ad3535a..c1e9f81a61 100644 --- a/packages/zarr-metadata/CHANGELOG.md +++ b/packages/zarr-metadata/CHANGELOG.md @@ -2,6 +2,96 @@ +## 0.5.0 (2026-08-14) + +### Bugfixes + +- `JSONValue`'s array arm is now the covariant `Sequence["JSONValue"]` rather + than the invariant `list["JSONValue"] | tuple["JSONValue", ...]`. Values typed + with a narrower element type — a `list[str]` field on a TypedDict, a + `Sequence[float]` — now count as JSON values, and TypedDicts whose fields + carry precise types are now assignable to `Mapping[str, JSONValue]`. + Type-level cost, accepted deliberately: `Sequence` says nothing about the + concrete container and admits `str`/`bytes`, so runtime code narrowing a JSON + array must exclude `str`/`bytes`/`bytearray` — as it already had to, since + `str` was always a union arm. ([#4264](https://github.com/zarr-developers/zarr-python/pull/4264)) + +### Deprecations and Removals + +- Unified the naming grammar for SCREAMING_SNAKE constants with the one used for + type names. A constant's name is now a purely syntactic transformation of the + name of the `Literal` type it manifests, so the format version is spelled + `ZARR_V2`/`ZARR_V3` and comes first, matching the `ZarrV2`/`ZarrV3` prefix on + the corresponding type: + + - `ARRAY_METADATA_STORE_KEY_V2` → `ZARR_V2_ARRAY_METADATA_STORE_KEY` + - `ARRAY_METADATA_STORE_KEY_V3` → `ZARR_V3_ARRAY_METADATA_STORE_KEY` + - `ATTRIBUTES_STORE_KEY_V2` → `ZARR_V2_ATTRIBUTES_STORE_KEY` + - `GROUP_METADATA_STORE_KEY_V2` → `ZARR_V2_GROUP_METADATA_STORE_KEY` + - `GROUP_METADATA_STORE_KEY_V3` → `ZARR_V3_GROUP_METADATA_STORE_KEY` + - `CONSOLIDATED_METADATA_STORE_KEY_V2` → `ZARR_V2_CONSOLIDATED_METADATA_STORE_KEY` + - `ARRAY_ORDER_V2` → `ZARR_V2_ARRAY_ORDER` + - `ARRAY_DIMENSION_SEPARATOR_V2` → `ZARR_V2_ARRAY_DIMENSION_SEPARATOR` + - `CONSOLIDATED_METADATA_KEY_V3` → `ZARR_V3_CONSOLIDATED_METADATA_KEY` + + The old names are removed, not aliased. This supersedes the 0.4.0 convention + under which type names put the format version first while constants put it + last: every constant that manifests a `Literal` type now follows the same rule + as that type. + + The last of those is the one rename the syntactic rule does not force: + `ZARR_V3_CONSOLIDATED_METADATA_KEY` manifests no `Literal` type, so it is + outside the rule and was renamed for consistency with its siblings. + + Digit runs stay glued to the token they follow, so spec vocabulary is + preserved: `Uint8DataTypeName` pairs with `UINT8_DATA_TYPE_NAME` (not + `UINT_8_...`) and `Crc32cCodecName` with `CRC32C_CODEC_NAME`. No dtype, codec, + chunk-grid, or chunk-key-encoding constant changed name. + + Constants that do not manifest a `Literal` type are outside the rule and are + unchanged: the `*_METADATA_*_KEYS_V2`/`_V3` key sets, the + `CANONICAL_*_HEX_FLOAT*` bit patterns, and `UNSET`. The key sets keep the + version-last spelling, so `zarr_metadata.model` exports both + `ARRAY_METADATA_REQUIRED_KEYS_V2` and `ZARR_V2_ARRAY_METADATA_STORE_KEY`. They + name validation policy rather than a spec document, have no paired type to + derive from, and renaming them would be a second breaking change buying only + cosmetic consistency — so it is deliberately deferred. + + `tests/test_public_api.py::test_constant_names_derive_from_their_type_names` + derives every constant name from the type it manifests and asserts they match, + so the two grammars cannot diverge again. + + Store keys also moved to the modules that describe the documents they name, + matching the package's layering (the `v2`/`v3` modules describe the specs; the + `model` layer is built on top of them). `ZARR_V2_ATTRIBUTES_STORE_KEY` now + lives in `zarr_metadata.v2.attributes` beside the `.zattrs` type it names, + rather than in the array model; the other five moved likewise, and + `ZarrV2AttributesStoreKey` is no longer an array-specific concept. + `zarr_metadata.model` re-exports all six, so + `from zarr_metadata.model import ZARR_V2_ARRAY_METADATA_STORE_KEY` is + unaffected. + + `CONSOLIDATED_METADATA_KEY_V3` moved to `zarr_metadata.v3.consolidated` and was + renamed to `ZARR_V3_CONSOLIDATED_METADATA_KEY` for consistency. It is not a + store key: unlike v2's `.zmetadata` file, v3 consolidated metadata is embedded + as an extension field inside the group's own `zarr.json`. + + All seven keys and the six store-key `Literal` aliases are now also exported + from the top-level `zarr_metadata` namespace, alongside the document types and + the rest of the spec vocabulary, so `from zarr_metadata import + ZARR_V2_ARRAY_METADATA_STORE_KEY` works. The model layer's validators, parsers, + type guards, and metadata key sets remain `zarr_metadata.model` imports. + + ([#4232](https://github.com/zarr-developers/zarr-python/pull/4232)) + +### Misc + +- The source distribution now ships an explicit allowlist (`/src`, `/tests`, + `/docs`, `/mkdocs.yml`, `/justfile`, `/CHANGELOG.md`) rather than whatever + happens to sit in the package directory, so an sdist both tests and documents + itself and cannot pick up scratch files from the tree it was built in. ([#4248](https://github.com/zarr-developers/zarr-python/pull/4248)) + + ## 0.4.0 (2026-07-29) ### Features diff --git a/packages/zarr-metadata/changes/4232.removal.md b/packages/zarr-metadata/changes/4232.removal.md deleted file mode 100644 index 73b2a18666..0000000000 --- a/packages/zarr-metadata/changes/4232.removal.md +++ /dev/null @@ -1,63 +0,0 @@ -Unified the naming grammar for SCREAMING_SNAKE constants with the one used for -type names. A constant's name is now a purely syntactic transformation of the -name of the `Literal` type it manifests, so the format version is spelled -`ZARR_V2`/`ZARR_V3` and comes first, matching the `ZarrV2`/`ZarrV3` prefix on -the corresponding type: - -- `ARRAY_METADATA_STORE_KEY_V2` → `ZARR_V2_ARRAY_METADATA_STORE_KEY` -- `ARRAY_METADATA_STORE_KEY_V3` → `ZARR_V3_ARRAY_METADATA_STORE_KEY` -- `ATTRIBUTES_STORE_KEY_V2` → `ZARR_V2_ATTRIBUTES_STORE_KEY` -- `GROUP_METADATA_STORE_KEY_V2` → `ZARR_V2_GROUP_METADATA_STORE_KEY` -- `GROUP_METADATA_STORE_KEY_V3` → `ZARR_V3_GROUP_METADATA_STORE_KEY` -- `CONSOLIDATED_METADATA_STORE_KEY_V2` → `ZARR_V2_CONSOLIDATED_METADATA_STORE_KEY` -- `ARRAY_ORDER_V2` → `ZARR_V2_ARRAY_ORDER` -- `ARRAY_DIMENSION_SEPARATOR_V2` → `ZARR_V2_ARRAY_DIMENSION_SEPARATOR` -- `CONSOLIDATED_METADATA_KEY_V3` → `ZARR_V3_CONSOLIDATED_METADATA_KEY` - -The old names are removed, not aliased. This supersedes the 0.4.0 convention -under which type names put the format version first while constants put it -last: every constant that manifests a `Literal` type now follows the same rule -as that type. - -The last of those is the one rename the syntactic rule does not force: -`ZARR_V3_CONSOLIDATED_METADATA_KEY` manifests no `Literal` type, so it is -outside the rule and was renamed for consistency with its siblings. - -Digit runs stay glued to the token they follow, so spec vocabulary is -preserved: `Uint8DataTypeName` pairs with `UINT8_DATA_TYPE_NAME` (not -`UINT_8_...`) and `Crc32cCodecName` with `CRC32C_CODEC_NAME`. No dtype, codec, -chunk-grid, or chunk-key-encoding constant changed name. - -Constants that do not manifest a `Literal` type are outside the rule and are -unchanged: the `*_METADATA_*_KEYS_V2`/`_V3` key sets, the -`CANONICAL_*_HEX_FLOAT*` bit patterns, and `UNSET`. The key sets keep the -version-last spelling, so `zarr_metadata.model` exports both -`ARRAY_METADATA_REQUIRED_KEYS_V2` and `ZARR_V2_ARRAY_METADATA_STORE_KEY`. They -name validation policy rather than a spec document, have no paired type to -derive from, and renaming them would be a second breaking change buying only -cosmetic consistency — so it is deliberately deferred. - -`tests/test_public_api.py::test_constant_names_derive_from_their_type_names` -derives every constant name from the type it manifests and asserts they match, -so the two grammars cannot diverge again. - -Store keys also moved to the modules that describe the documents they name, -matching the package's layering (the `v2`/`v3` modules describe the specs; the -`model` layer is built on top of them). `ZARR_V2_ATTRIBUTES_STORE_KEY` now -lives in `zarr_metadata.v2.attributes` beside the `.zattrs` type it names, -rather than in the array model; the other five moved likewise, and -`ZarrV2AttributesStoreKey` is no longer an array-specific concept. -`zarr_metadata.model` re-exports all six, so -`from zarr_metadata.model import ZARR_V2_ARRAY_METADATA_STORE_KEY` is -unaffected. - -`CONSOLIDATED_METADATA_KEY_V3` moved to `zarr_metadata.v3.consolidated` and was -renamed to `ZARR_V3_CONSOLIDATED_METADATA_KEY` for consistency. It is not a -store key: unlike v2's `.zmetadata` file, v3 consolidated metadata is embedded -as an extension field inside the group's own `zarr.json`. - -All seven keys and the six store-key `Literal` aliases are now also exported -from the top-level `zarr_metadata` namespace, alongside the document types and -the rest of the spec vocabulary, so `from zarr_metadata import -ZARR_V2_ARRAY_METADATA_STORE_KEY` works. The model layer's validators, parsers, -type guards, and metadata key sets remain `zarr_metadata.model` imports. diff --git a/packages/zarr-metadata/changes/4248.misc.md b/packages/zarr-metadata/changes/4248.misc.md deleted file mode 100644 index e21a0cf854..0000000000 --- a/packages/zarr-metadata/changes/4248.misc.md +++ /dev/null @@ -1,4 +0,0 @@ -The source distribution now ships an explicit allowlist (`/src`, `/tests`, -`/docs`, `/mkdocs.yml`, `/justfile`, `/CHANGELOG.md`) rather than whatever -happens to sit in the package directory, so an sdist both tests and documents -itself and cannot pick up scratch files from the tree it was built in. diff --git a/packages/zarr-metadata/changes/4264.bugfix.md b/packages/zarr-metadata/changes/4264.bugfix.md deleted file mode 100644 index 466bf5941d..0000000000 --- a/packages/zarr-metadata/changes/4264.bugfix.md +++ /dev/null @@ -1,9 +0,0 @@ -`JSONValue`'s array arm is now the covariant `Sequence["JSONValue"]` rather -than the invariant `list["JSONValue"] | tuple["JSONValue", ...]`. Values typed -with a narrower element type — a `list[str]` field on a TypedDict, a -`Sequence[float]` — now count as JSON values, and TypedDicts whose fields -carry precise types are now assignable to `Mapping[str, JSONValue]`. -Type-level cost, accepted deliberately: `Sequence` says nothing about the -concrete container and admits `str`/`bytes`, so runtime code narrowing a JSON -array must exclude `str`/`bytes`/`bytearray` — as it already had to, since -`str` was always a union arm.