Migrate supported Python to 3.12, 3.13, 3.14#1151
Open
timtreis wants to merge 8 commits into
Open
Conversation
Drop Python 3.11 (anndata>=0.12 already requires >=3.12, so 3.11 was effectively broken) and add 3.14. - pyproject.toml: requires-python ">=3.12", ruff target-version py312 - .mypy.ini: python_version 3.12 - test.yaml: matrix 3.12/3.13/3.14; repoint bleeding-edge deps job to 3.14 and drop the obsolete requires-python sed hack Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The target-version bump to py312 enables ruff UP040. Rewrite the four explicit TypeAlias declarations to the `type` keyword and drop the now unused TypeAlias imports. Annotation-only aliases (the repo uses `from __future__ import annotations`), so no runtime behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The module __getattr__ fell through to `getattr(spatialdata.dataloader, attr_name)` for any unknown name, re-entering itself indefinitely (RecursionError) instead of raising AttributeError per PEP 562. This was latent until the docs build hit it: the PEP 695 `type` aliases live in private modules, so sphinx-autodoc-typehints probes every `spatialdata.*` submodule with getattr() looking for a public re-export, tripping the recursion and failing the RTD build. Raise AttributeError for unknown names; drop the now-unused `import spatialdata` and tighten the return type to type[ImageTilesDataset]. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ome_zarr 0.18 switched to the NGFF 0.5 layout: channel metadata moved out of the `omero` block, so overwrite_channel_names() in _io/_utils.py gets None and crashes (~48 IO test failures). This breaks main independently of the Python bump. Pin as a stopgap until NGFF 0.5 is supported. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1151 +/- ##
==========================================
- Coverage 92.44% 92.43% -0.01%
==========================================
Files 51 51
Lines 7811 7814 +3
==========================================
+ Hits 7221 7223 +2
- Misses 590 591 +1
🚀 New features to boost your workflow:
|
ome_zarr 0.18 refactored the functional write_image/write_multiscale entrypoints (ome/ome-zarr-py#515) to read omero from the top-level metadata dict; spatialdata passes it nested under metadata["metadata"], so 0.18 silently dropped it. Effects: write_channel_names() crashed (omero block absent) and plain write->read lost channel names entirely (["r","g","b"] came back as [0,1,2]). Instead of depending on ome-zarr-py to emit omero, write it ourselves: - _write_raster() now calls overwrite_channel_names() after every image write, so the omero block is always present (idempotent on 0.17). - overwrite_channel_names() defaults to an empty omero block when none exists yet. Pin ome_zarr>=0.18 so CI resolves the same version a fresh install gets (uv otherwise lands on 0.17, hiding 0.18 regressions). Verified: full tests/io suite (227) passes on 0.18. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
overwrite_channel_names() now writes the omero channel block on every image write, so building the same metadata to pass into the ome-zarr-py writer (which 0.18 ignores anyway) was dead duplication. Remove it along with the now-unused get_channel_names import, and tighten comments. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ome_zarr 0.18's label writer auto-parses unique label values and
validates each `label-value` as an integer (via ome-zarr-models), which
rejected spatialdata's float-dtype labels. Float labels are meaningless
for segmentation masks and inconsistent with the rest of the codebase
(fixtures, rasterize, relabel_sequential all assume integers), so the
correct fix is to enforce it: Labels{2,3}DModel.parse now rejects
non-integer/bool data with a clear error.
Tests that fed float data to label models (reusing image-style
generators) now use integers; test_rasterize_bins_invalid casts a parsed
integer label to float to still exercise rasterize_bins' own guard.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Our omero self-write and integer-label fixes work across 0.16/0.17/0.18 (verified), so keep the wider lower bound for ecosystem co-installability rather than forcing >=0.18. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Member
|
Let's update https://github.com/conda-forge/spatialdata-feedstock/blob/main/recipe/meta.yaml#L3 then as well and fix the broken recipe (doesn't support Python 3.13+) @LucaMarconato |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Drops Python 3.11 and adds 3.14 as a supported version. anndata>=0.12 already requires
>=3.12, so 3.11 was effectively broken.Notes
python3.pyupgradenow targets py312; apre-commit run --all-filespass may surface new auto-fixes.ome_zarr>=0.18needed two fixes:omeroblock we passed, so channel names were lost on write/read. spatialdata now writes it itself.label-values.Labels{2,3}DModel.parsenow rejects float labels (meaningless for masks). Breaking: cast float labels to int, e.g..astype(np.uint16).