anndata 0.12.0rc3__tar.gz → 0.12.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. anndata-0.12.1/.github/workflows/test-cpu.yml +125 -0
  2. {anndata-0.12.0rc3 → anndata-0.12.1}/.gitignore +1 -0
  3. {anndata-0.12.0rc3 → anndata-0.12.1}/.pre-commit-config.yaml +2 -2
  4. {anndata-0.12.0rc3 → anndata-0.12.1}/PKG-INFO +11 -35
  5. {anndata-0.12.0rc3 → anndata-0.12.1}/benchmarks/asv.conf.json +2 -0
  6. anndata-0.12.1/benchmarks/benchmarks/dataset2d.py +61 -0
  7. {anndata-0.12.0rc3 → anndata-0.12.1}/benchmarks/benchmarks/sparse_dataset.py +18 -7
  8. {anndata-0.12.0rc3 → anndata-0.12.1}/biome.jsonc +2 -2
  9. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/api.md +4 -3
  10. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/conf.py +27 -3
  11. anndata-0.12.1/docs/extensions/autosummary_skip_inherited.py +55 -0
  12. anndata-0.12.1/docs/release-notes/0.12.0.md +51 -0
  13. anndata-0.12.1/docs/release-notes/0.12.1.md +10 -0
  14. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/tutorials/zarr-v3.md +17 -0
  15. {anndata-0.12.0rc3 → anndata-0.12.1}/hatch.toml +4 -0
  16. {anndata-0.12.0rc3 → anndata-0.12.1}/pyproject.toml +12 -14
  17. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/aligned_df.py +1 -1
  18. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/aligned_mapping.py +1 -1
  19. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/anndata.py +1 -1
  20. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/index.py +2 -10
  21. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/merge.py +71 -91
  22. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/sparse_dataset.py +24 -7
  23. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/storage.py +2 -2
  24. anndata-0.12.1/src/anndata/_core/xarray.py +404 -0
  25. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_io/h5ad.py +1 -1
  26. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_io/read.py +5 -1
  27. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_io/specs/lazy_methods.py +52 -19
  28. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_io/specs/methods.py +18 -16
  29. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_io/specs/registry.py +16 -5
  30. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_io/zarr.py +0 -14
  31. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_settings.py +5 -2
  32. anndata-0.12.1/src/anndata/_settings.pyi +49 -0
  33. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_types.py +7 -0
  34. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/compat/__init__.py +12 -0
  35. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/experimental/__init__.py +9 -1
  36. anndata-0.12.1/src/anndata/experimental/backed/__init__.py +7 -0
  37. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/experimental/backed/_io.py +2 -7
  38. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/experimental/backed/_lazy_arrays.py +39 -9
  39. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/tests/helpers.py +36 -42
  40. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/utils.py +3 -4
  41. {anndata-0.12.0rc3 → anndata-0.12.1}/src/testing/anndata/_pytest.py +4 -0
  42. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/conftest.py +13 -1
  43. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/lazy/conftest.py +12 -3
  44. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/lazy/test_concat.py +4 -1
  45. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/lazy/test_read.py +38 -4
  46. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_awkward.py +2 -1
  47. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_backed_hdf5.py +8 -5
  48. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_backed_sparse.py +31 -23
  49. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_base.py +3 -1
  50. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_concatenate.py +75 -97
  51. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_concatenate_disk.py +12 -5
  52. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_deprecations.py +2 -2
  53. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_io_backwards_compat.py +3 -3
  54. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_io_dispatched.py +10 -5
  55. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_io_elementwise.py +85 -15
  56. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_io_warnings.py +2 -2
  57. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_readwrite.py +32 -4
  58. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_settings.py +19 -0
  59. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_structured_arrays.py +12 -21
  60. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_utils.py +4 -2
  61. anndata-0.12.1/tests/test_xarray.py +320 -0
  62. anndata-0.12.0rc3/.github/workflows/test-cpu.yml +0 -123
  63. anndata-0.12.0rc3/docs/release-notes/0.12.0rc1.md +0 -26
  64. anndata-0.12.0rc3/docs/release-notes/0.12.0rc2.md +0 -14
  65. anndata-0.12.0rc3/docs/release-notes/0.12.0rc3.md +0 -6
  66. anndata-0.12.0rc3/src/anndata/_core/xarray.py +0 -145
  67. anndata-0.12.0rc3/src/anndata/experimental/backed/__init__.py +0 -5
  68. anndata-0.12.0rc3/tests/test_xarray.py +0 -91
  69. {anndata-0.12.0rc3 → anndata-0.12.1}/.cirun.yml +0 -0
  70. {anndata-0.12.0rc3 → anndata-0.12.1}/.codecov.yml +0 -0
  71. {anndata-0.12.0rc3 → anndata-0.12.1}/.editorconfig +0 -0
  72. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  73. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  74. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/ISSUE_TEMPLATE/enhancement-request.yml +0 -0
  75. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/ISSUE_TEMPLATE/question.yml +0 -0
  76. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  77. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/workflows/benchmark.yml +0 -0
  78. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/workflows/check-pr-milestoned.yml +0 -0
  79. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/workflows/close-stale.yml +0 -0
  80. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/workflows/codespell.yml +0 -0
  81. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/workflows/label-stale.yml +0 -0
  82. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/workflows/publish.yml +0 -0
  83. {anndata-0.12.0rc3 → anndata-0.12.1}/.github/workflows/test-gpu.yml +0 -0
  84. {anndata-0.12.0rc3 → anndata-0.12.1}/.gitmodules +0 -0
  85. {anndata-0.12.0rc3 → anndata-0.12.1}/.prettierignore +0 -0
  86. {anndata-0.12.0rc3 → anndata-0.12.1}/.prettierrc.yaml +0 -0
  87. {anndata-0.12.0rc3 → anndata-0.12.1}/.readthedocs.yml +0 -0
  88. {anndata-0.12.0rc3 → anndata-0.12.1}/.taplo.toml +0 -0
  89. {anndata-0.12.0rc3 → anndata-0.12.1}/.vscode/launch.json +0 -0
  90. {anndata-0.12.0rc3 → anndata-0.12.1}/.vscode/settings.json +0 -0
  91. {anndata-0.12.0rc3 → anndata-0.12.1}/LICENSE +0 -0
  92. {anndata-0.12.0rc3 → anndata-0.12.1}/README.md +0 -0
  93. {anndata-0.12.0rc3 → anndata-0.12.1}/benchmarks/README.md +0 -0
  94. {anndata-0.12.0rc3 → anndata-0.12.1}/benchmarks/benchmarks/__init__.py +0 -0
  95. {anndata-0.12.0rc3 → anndata-0.12.1}/benchmarks/benchmarks/anndata.py +0 -0
  96. {anndata-0.12.0rc3 → anndata-0.12.1}/benchmarks/benchmarks/readwrite.py +0 -0
  97. {anndata-0.12.0rc3 → anndata-0.12.1}/benchmarks/benchmarks/utils.py +0 -0
  98. {anndata-0.12.0rc3 → anndata-0.12.1}/ci/constraints.txt +0 -0
  99. {anndata-0.12.0rc3 → anndata-0.12.1}/ci/scripts/min-deps.py +0 -0
  100. {anndata-0.12.0rc3 → anndata-0.12.1}/ci/scripts/towncrier_automation.py +0 -0
  101. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/Makefile +0 -0
  102. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/_key_contributors.rst +0 -0
  103. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/_static/img/anndata_schema.svg +0 -0
  104. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/_templates/autosummary/class.rst +0 -0
  105. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/benchmark-read-write.ipynb +0 -0
  106. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/benchmarks.md +0 -0
  107. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/concatenation.rst +0 -0
  108. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/contributing.md +0 -0
  109. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/extensions/no_skip_abc_members.py +0 -0
  110. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/extensions/patch_myst_cite.py +0 -0
  111. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/fileformat-prose.md +0 -0
  112. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/index.md +0 -0
  113. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/interoperability.md +0 -0
  114. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/news.md +0 -0
  115. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/references.rst +0 -0
  116. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.10.0.md +0 -0
  117. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.10.1.md +0 -0
  118. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.10.2.md +0 -0
  119. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.10.3.md +0 -0
  120. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.10.4.md +0 -0
  121. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.10.5.md +0 -0
  122. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.10.6.md +0 -0
  123. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.10.7.md +0 -0
  124. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.10.8.md +0 -0
  125. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.10.9.md +0 -0
  126. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.11.0.md +0 -0
  127. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.11.1.md +0 -0
  128. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.11.2.md +0 -0
  129. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.11.3.md +0 -0
  130. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.11.4.md +0 -0
  131. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.4.0.md +0 -0
  132. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.5.0.md +0 -0
  133. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.6.0.md +0 -0
  134. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.6.x.md +0 -0
  135. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.7.0.md +0 -0
  136. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.7.2.md +0 -0
  137. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.7.3.md +0 -0
  138. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.7.4.md +0 -0
  139. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.7.5.md +0 -0
  140. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.7.6.md +0 -0
  141. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.7.7.md +0 -0
  142. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.7.8.md +0 -0
  143. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.8.0.md +0 -0
  144. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.9.0.md +0 -0
  145. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.9.1.md +0 -0
  146. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/0.9.2.md +0 -0
  147. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/release-notes/index.md +0 -0
  148. {anndata-0.12.0rc3 → anndata-0.12.1}/docs/tutorials/index.md +0 -0
  149. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/__init__.py +0 -0
  150. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/__init__.py +0 -0
  151. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/access.py +0 -0
  152. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/extensions.py +0 -0
  153. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/file_backing.py +0 -0
  154. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/raw.py +0 -0
  155. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_core/views.py +0 -0
  156. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_io/__init__.py +0 -0
  157. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_io/specs/__init__.py +0 -0
  158. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_io/utils.py +0 -0
  159. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_io/write.py +0 -0
  160. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_version.py +0 -0
  161. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/_warnings.py +0 -0
  162. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/abc.py +0 -0
  163. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/experimental/_dispatch_io.py +0 -0
  164. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/experimental/backed/_compat.py +0 -0
  165. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/experimental/merge.py +0 -0
  166. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/experimental/multi_files/__init__.py +0 -0
  167. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/experimental/multi_files/_anncollection.py +0 -0
  168. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/experimental/pytorch/__init__.py +0 -0
  169. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/experimental/pytorch/_annloader.py +0 -0
  170. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/io.py +0 -0
  171. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/logging.py +0 -0
  172. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/tests/__init__.py +0 -0
  173. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/types.py +0 -0
  174. {anndata-0.12.0rc3 → anndata-0.12.1}/src/anndata/typing.py +0 -0
  175. {anndata-0.12.0rc3 → anndata-0.12.1}/src/testing/anndata/__init__.py +0 -0
  176. {anndata-0.12.0rc3 → anndata-0.12.1}/src/testing/anndata/_doctest.py +0 -0
  177. {anndata-0.12.0rc3 → anndata-0.12.1}/src/testing/anndata/py.typed +0 -0
  178. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/data/adata-comments.tsv +0 -0
  179. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/data/adata.csv +0 -0
  180. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/data/archives/readme.md +0 -0
  181. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/data/archives/v0.7.0/adata.h5ad +0 -0
  182. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/data/archives/v0.7.0/adata.zarr.zip +0 -0
  183. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/data/archives/v0.7.8/adata.h5ad +0 -0
  184. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/data/archives/v0.7.8/adata.zarr.zip +0 -0
  185. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/data/excel.xlsx +0 -0
  186. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/data/umi_tools.tsv.gz +0 -0
  187. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/lazy/test_write.py +0 -0
  188. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_anncollection.py +0 -0
  189. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_annot.py +0 -0
  190. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_backed_dense.py +0 -0
  191. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_dask.py +0 -0
  192. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_dask_view_mem.py +0 -0
  193. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_extensions.py +0 -0
  194. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_get_vector.py +0 -0
  195. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_gpu.py +0 -0
  196. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_helpers.py +0 -0
  197. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_inplace_subset.py +0 -0
  198. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_io_conversion.py +0 -0
  199. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_io_partial.py +0 -0
  200. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_io_utils.py +0 -0
  201. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_layers.py +0 -0
  202. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_obsmvarm.py +0 -0
  203. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_obspvarp.py +0 -0
  204. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_raw.py +0 -0
  205. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_repr.py +0 -0
  206. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_transpose.py +0 -0
  207. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_uns.py +0 -0
  208. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_views.py +0 -0
  209. {anndata-0.12.0rc3 → anndata-0.12.1}/tests/test_x.py +0 -0
@@ -0,0 +1,125 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - "[0-9]+.[0-9]+.x"
8
+ pull_request:
9
+
10
+ env:
11
+ FORCE_COLOR: "1"
12
+
13
+ defaults:
14
+ run:
15
+ shell: bash -el {0}
16
+
17
+ # Cancel the job if new commits are pushed
18
+ # https://stackoverflow.com/questions/66335225/how-to-cancel-previous-runs-in-the-pr-when-you-push-new-commitsupdate-the-curre
19
+ concurrency:
20
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
21
+ cancel-in-progress: true
22
+
23
+ jobs:
24
+ get-environments:
25
+ runs-on: ubuntu-latest
26
+ outputs:
27
+ envs: ${{ steps.get-envs.outputs.envs }}
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ with:
31
+ filter: blob:none
32
+ fetch-depth: 0
33
+ - uses: astral-sh/setup-uv@v5
34
+ with:
35
+ enable-cache: false
36
+ - id: get-envs
37
+ run: |
38
+ ENVS_JSON=$(NO_COLOR=1 uvx hatch env show --json | jq -c 'to_entries
39
+ | map(
40
+ select(.key | startswith("hatch-test"))
41
+ | { name: .key, python: .value.python }
42
+ )')
43
+ echo "envs=${ENVS_JSON}" | tee $GITHUB_OUTPUT
44
+ test:
45
+ needs: get-environments
46
+ runs-on: ubuntu-latest
47
+ strategy:
48
+ matrix:
49
+ env: ${{ fromJSON(needs.get-environments.outputs.envs) }}
50
+ io_mark: ["zarr_io", "not zarr_io"]
51
+ env: # environment variable for use in codecov’s env_vars tagging
52
+ ENV_NAME: ${{ matrix.env.name }}
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+ with:
56
+ fetch-depth: 0
57
+ filter: blob:none
58
+
59
+ - name: Set up Python ${{ matrix.env.python }}
60
+ uses: actions/setup-python@v5
61
+ with:
62
+ python-version: ${{ matrix.env.python }}
63
+
64
+ - name: Install UV
65
+ uses: astral-sh/setup-uv@v5
66
+ with:
67
+ enable-cache: true
68
+ cache-dependency-glob: pyproject.toml
69
+
70
+ - name: Install dependencies
71
+ run: uvx hatch -v env create ${{ matrix.env.name }}
72
+
73
+ - name: Run tests
74
+ run: uvx hatch run ${{ matrix.env.name }}:run-cov -v --color=yes -n auto --cov --cov-report=xml --junitxml=test-data/test-results.xml -m "${{matrix.io_mark}}"
75
+
76
+ - name: Upload coverage data
77
+ uses: codecov/codecov-action@v5
78
+ with:
79
+ token: ${{ secrets.CODECOV_TOKEN }}
80
+ env_vars: ENV_NAME
81
+ fail_ci_if_error: true
82
+ files: test-data/coverage.xml
83
+
84
+ build:
85
+ runs-on: ubuntu-22.04
86
+ steps:
87
+ - uses: actions/checkout@v4
88
+ with:
89
+ fetch-depth: 0
90
+ filter: blob:none
91
+
92
+ - name: Set up Python 3.13
93
+ uses: actions/setup-python@v5
94
+ with:
95
+ python-version: '3.13'
96
+
97
+ - name: Install build tools and requirements
98
+ run: |
99
+ python -m pip install --upgrade pip
100
+ pip install build twine
101
+
102
+ - name: Display installed versions
103
+ run: pip list
104
+
105
+ - name: Build & Twine check
106
+ run: |
107
+ python -m build --sdist --wheel .
108
+ twine check dist/*
109
+
110
+ - name: Check runtime version
111
+ run: |
112
+ pip install dist/*.whl
113
+ python -c 'import anndata; print(anndata.__version__)'
114
+
115
+ check:
116
+ if: always()
117
+ needs:
118
+ - get-environments
119
+ - test
120
+ - build
121
+ runs-on: ubuntu-latest
122
+ steps:
123
+ - uses: re-actors/alls-green@release/v1
124
+ with:
125
+ jobs: ${{ toJSON(needs) }}
@@ -12,6 +12,7 @@ __pycache__/
12
12
  # Distribution / packaging
13
13
  /dist/
14
14
  /ci/min-deps.txt
15
+ /ci/pre-deps.txt
15
16
  /requirements*.lock
16
17
  /.python-version
17
18
 
@@ -1,6 +1,6 @@
1
1
  repos:
2
2
  - repo: https://github.com/astral-sh/ruff-pre-commit
3
- rev: v0.11.4
3
+ rev: v0.12.4
4
4
  hooks:
5
5
  - id: ruff
6
6
  args: ["--fix"]
@@ -10,7 +10,7 @@ repos:
10
10
  id: ruff
11
11
  args: ["--preview", "--select=PLR0917"]
12
12
  - repo: https://github.com/biomejs/pre-commit
13
- rev: v1.9.4
13
+ rev: v2.1.2
14
14
  hooks:
15
15
  - id: biome-format
16
16
  - repo: https://github.com/ComPWA/taplo-pre-commit
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anndata
3
- Version: 0.12.0rc3
3
+ Version: 0.12.1
4
4
  Summary: Annotated data.
5
5
  Project-URL: Documentation, https://anndata.readthedocs.io/
6
6
  Project-URL: Source, https://github.com/scverse/anndata
@@ -28,11 +28,11 @@ Requires-Dist: array-api-compat>=1.7.1
28
28
  Requires-Dist: h5py>=3.8
29
29
  Requires-Dist: legacy-api-wrap
30
30
  Requires-Dist: natsort
31
- Requires-Dist: numpy>=1.25
31
+ Requires-Dist: numpy>=1.26
32
32
  Requires-Dist: packaging>=24.2
33
- Requires-Dist: pandas!=2.1.0rc0,!=2.1.2,>=2.0.0
34
- Requires-Dist: scipy>=1.11
35
- Requires-Dist: zarr!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3,!=3.0.4,!=3.0.5,!=3.0.6,!=3.0.7,>=2.18.7
33
+ Requires-Dist: pandas!=2.1.2,>=2.1.0
34
+ Requires-Dist: scipy>=1.12
35
+ Requires-Dist: zarr!=3.0.*,>=2.18.7
36
36
  Provides-Extra: cu11
37
37
  Requires-Dist: cupy-cuda11x; extra == 'cu11'
38
38
  Provides-Extra: cu12
@@ -40,31 +40,8 @@ Requires-Dist: cupy-cuda12x; extra == 'cu12'
40
40
  Provides-Extra: dask
41
41
  Requires-Dist: dask[array]!=2024.8.*,!=2024.9.*,<2025.2.0,>=2023.5.1; extra == 'dask'
42
42
  Provides-Extra: dev
43
- Requires-Dist: aiohttp; extra == 'dev'
44
- Requires-Dist: awkward>=2.3.2; extra == 'dev'
45
- Requires-Dist: boltons; extra == 'dev'
46
- Requires-Dist: dask[array]!=2024.8.*,!=2024.9.*,<2025.2.0,>=2023.5.1; extra == 'dev'
47
- Requires-Dist: dask[distributed]; extra == 'dev'
48
- Requires-Dist: filelock; extra == 'dev'
49
43
  Requires-Dist: hatch-vcs; extra == 'dev'
50
- Requires-Dist: httpx; extra == 'dev'
51
- Requires-Dist: joblib; extra == 'dev'
52
- Requires-Dist: loompy>=3.0.5; extra == 'dev'
53
- Requires-Dist: matplotlib; extra == 'dev'
54
- Requires-Dist: openpyxl; extra == 'dev'
55
- Requires-Dist: pandas>=2.1.0; extra == 'dev'
56
- Requires-Dist: pyarrow; extra == 'dev'
57
- Requires-Dist: pytest-cov; extra == 'dev'
58
- Requires-Dist: pytest-memray; extra == 'dev'
59
- Requires-Dist: pytest-mock; extra == 'dev'
60
- Requires-Dist: pytest-randomly; extra == 'dev'
61
- Requires-Dist: pytest-xdist[psutil]; extra == 'dev'
62
- Requires-Dist: pytest<8.3.4,>=8.2; extra == 'dev'
63
- Requires-Dist: requests; extra == 'dev'
64
- Requires-Dist: scanpy>=1.10; extra == 'dev'
65
- Requires-Dist: scikit-learn; extra == 'dev'
66
44
  Requires-Dist: towncrier>=24.8.0; extra == 'dev'
67
- Requires-Dist: xarray>=2025.04.0; extra == 'dev'
68
45
  Provides-Extra: dev-doc
69
46
  Requires-Dist: towncrier>=24.8.0; extra == 'dev-doc'
70
47
  Provides-Extra: doc
@@ -89,7 +66,7 @@ Provides-Extra: lazy
89
66
  Requires-Dist: aiohttp; extra == 'lazy'
90
67
  Requires-Dist: dask[array]!=2024.8.*,!=2024.9.*,<2025.2.0,>=2023.5.1; extra == 'lazy'
91
68
  Requires-Dist: requests; extra == 'lazy'
92
- Requires-Dist: xarray>=2025.04.0; extra == 'lazy'
69
+ Requires-Dist: xarray>=2025.06.1; extra == 'lazy'
93
70
  Provides-Extra: test
94
71
  Requires-Dist: aiohttp; extra == 'test'
95
72
  Requires-Dist: awkward>=2.3.2; extra == 'test'
@@ -97,13 +74,12 @@ Requires-Dist: boltons; extra == 'test'
97
74
  Requires-Dist: dask[array]!=2024.8.*,!=2024.9.*,<2025.2.0,>=2023.5.1; extra == 'test'
98
75
  Requires-Dist: dask[distributed]; extra == 'test'
99
76
  Requires-Dist: filelock; extra == 'test'
100
- Requires-Dist: httpx; extra == 'test'
77
+ Requires-Dist: httpx<1.0; extra == 'test'
101
78
  Requires-Dist: joblib; extra == 'test'
102
79
  Requires-Dist: loompy>=3.0.5; extra == 'test'
103
80
  Requires-Dist: matplotlib; extra == 'test'
104
81
  Requires-Dist: openpyxl; extra == 'test'
105
- Requires-Dist: pandas>=2.1.0; extra == 'test'
106
- Requires-Dist: pyarrow; extra == 'test'
82
+ Requires-Dist: pyarrow<21; extra == 'test'
107
83
  Requires-Dist: pytest-cov; extra == 'test'
108
84
  Requires-Dist: pytest-memray; extra == 'test'
109
85
  Requires-Dist: pytest-mock; extra == 'test'
@@ -113,19 +89,19 @@ Requires-Dist: pytest<8.3.4,>=8.2; extra == 'test'
113
89
  Requires-Dist: requests; extra == 'test'
114
90
  Requires-Dist: scanpy>=1.10; extra == 'test'
115
91
  Requires-Dist: scikit-learn; extra == 'test'
116
- Requires-Dist: xarray>=2025.04.0; extra == 'test'
92
+ Requires-Dist: xarray>=2025.06.1; extra == 'test'
117
93
  Provides-Extra: test-min
118
94
  Requires-Dist: awkward>=2.3.2; extra == 'test-min'
119
95
  Requires-Dist: boltons; extra == 'test-min'
120
96
  Requires-Dist: dask[array]!=2024.8.*,!=2024.9.*,<2025.2.0,>=2023.5.1; extra == 'test-min'
121
97
  Requires-Dist: dask[distributed]; extra == 'test-min'
122
98
  Requires-Dist: filelock; extra == 'test-min'
123
- Requires-Dist: httpx; extra == 'test-min'
99
+ Requires-Dist: httpx<1.0; extra == 'test-min'
124
100
  Requires-Dist: joblib; extra == 'test-min'
125
101
  Requires-Dist: loompy>=3.0.5; extra == 'test-min'
126
102
  Requires-Dist: matplotlib; extra == 'test-min'
127
103
  Requires-Dist: openpyxl; extra == 'test-min'
128
- Requires-Dist: pyarrow; extra == 'test-min'
104
+ Requires-Dist: pyarrow<21; extra == 'test-min'
129
105
  Requires-Dist: pytest-cov; extra == 'test-min'
130
106
  Requires-Dist: pytest-memray; extra == 'test-min'
131
107
  Requires-Dist: pytest-mock; extra == 'test-min'
@@ -70,6 +70,8 @@
70
70
  "pytoml": [""],
71
71
  "pytest": [""],
72
72
  "pooch": [""],
73
+ "xarray": [""],
74
+ "dask": [""],
73
75
  // "scanpy": [""],
74
76
  // "psutil": [""]
75
77
  },
@@ -0,0 +1,61 @@
1
+ from __future__ import annotations
2
+
3
+ import tempfile
4
+ from pathlib import Path
5
+ from typing import TYPE_CHECKING
6
+
7
+ import h5py
8
+ import numpy as np
9
+ import pandas as pd
10
+ import zarr
11
+
12
+ import anndata as ad
13
+
14
+ if TYPE_CHECKING:
15
+ from collections.abc import Callable
16
+
17
+
18
+ class Dataset2D:
19
+ param_names = ("gen_store", "chunks")
20
+ params = (
21
+ (
22
+ lambda: h5py.File(Path(tempfile.mkdtemp()) / "data.h5ad", mode="w"),
23
+ lambda: zarr.open(
24
+ Path(tempfile.mkdtemp()) / "data.zarr", mode="w", zarr_version=2
25
+ ),
26
+ ),
27
+ ((-1,), None),
28
+ )
29
+
30
+ def setup(
31
+ self, gen_store: Callable[[], zarr.Group | h5py.File], chunks: None | tuple[int]
32
+ ):
33
+ self.n_obs = 100000
34
+ df = pd.DataFrame(
35
+ {
36
+ "a": pd.Categorical(np.array(["a"] * self.n_obs)),
37
+ "b": np.arange(self.n_obs),
38
+ },
39
+ index=[f"cell{i}" for i in range(self.n_obs)],
40
+ )
41
+ store = gen_store()
42
+ ad.io.write_elem(store, "obs", df)
43
+ self.ds = ad.experimental.read_elem_lazy(store["obs"], chunks=chunks)
44
+
45
+ def time_getitem_slice(self, *_):
46
+ self.ds.iloc[0 : (self.n_obs // 2)].to_memory()
47
+
48
+ def peakmem_getitem_slice(self, *_):
49
+ self.ds.iloc[0 : (self.n_obs // 2)].to_memory()
50
+
51
+ def time_full_to_memory(self, *_):
52
+ self.ds.to_memory()
53
+
54
+ def peakmem_full_to_memory(self, *_):
55
+ self.ds.to_memory()
56
+
57
+ def time_getitem_bool_mask(self, *_):
58
+ self.ds.iloc[np.random.randint(0, self.n_obs, self.n_obs // 2)].to_memory()
59
+
60
+ def peakmem_getitem_bool_mask(self, *_):
61
+ self.ds.iloc[np.random.randint(0, self.n_obs, self.n_obs // 2)].to_memory()
@@ -4,11 +4,13 @@ from types import MappingProxyType
4
4
 
5
5
  import numpy as np
6
6
  import zarr
7
+ from dask.array.core import Array as DaskArray
7
8
  from scipy import sparse
8
9
 
9
10
  from anndata import AnnData
10
11
  from anndata._core.sparse_dataset import sparse_dataset
11
12
  from anndata._io.specs import write_elem
13
+ from anndata.experimental import read_elem_lazy
12
14
 
13
15
 
14
16
  def make_alternating_mask(n):
@@ -37,27 +39,36 @@ class SparseCSRContiguousSlice:
37
39
  # (10_000, 500)
38
40
  ],
39
41
  _slices.keys(),
42
+ [True, False],
40
43
  )
41
- param_names = ("shape", "slice")
44
+ param_names = ("shape", "slice", "use_dask")
42
45
 
43
- def setup(self, shape: tuple[int, int], slice: str):
46
+ def setup(self, shape: tuple[int, int], slice: str, use_dask: bool): # noqa: FBT001
44
47
  X = sparse.random(
45
48
  *shape, density=0.01, format="csr", random_state=np.random.default_rng(42)
46
49
  )
47
50
  self.slice = self._slices[slice]
48
51
  g = zarr.group()
49
52
  write_elem(g, "X", X)
50
- self.x = sparse_dataset(g["X"])
53
+ self.x = read_elem_lazy(g["X"]) if use_dask else sparse_dataset(g["X"])
51
54
  self.adata = AnnData(self.x)
52
55
 
53
56
  def time_getitem(self, *_):
54
- self.x[self.slice]
57
+ res = self.x[self.slice]
58
+ if isinstance(res, DaskArray):
59
+ res.compute()
55
60
 
56
61
  def peakmem_getitem(self, *_):
57
- self.x[self.slice]
62
+ res = self.x[self.slice]
63
+ if isinstance(res, DaskArray):
64
+ res.compute()
58
65
 
59
66
  def time_getitem_adata(self, *_):
60
- self.adata[self.slice]
67
+ res = self.adata[self.slice]
68
+ if isinstance(res, DaskArray):
69
+ res.compute()
61
70
 
62
71
  def peakmem_getitem_adata(self, *_):
63
- self.adata[self.slice]
72
+ res = self.adata[self.slice]
73
+ if isinstance(res, DaskArray):
74
+ res.compute()
@@ -1,9 +1,9 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
2
+ "$schema": "https://biomejs.dev/schemas/2.1.1/schema.json",
3
3
  "formatter": { "useEditorconfig": true },
4
4
  "overrides": [
5
5
  {
6
- "include": ["./.vscode/*.json", "**/*.jsonc", "**/asv.conf.json"],
6
+ "includes": ["./.vscode/*.json", "**/*.jsonc", "**/asv.conf.json"],
7
7
  "json": {
8
8
  "formatter": {
9
9
  "trailingCommas": "all",
@@ -178,9 +178,10 @@ Types used by the former:
178
178
  experimental.ReadCallback
179
179
  experimental.WriteCallback
180
180
  experimental.StorageType
181
- experimental.backed._lazy_arrays.MaskedArray
182
- experimental.backed._lazy_arrays.CategoricalArray
183
- _core.xarray.Dataset2D
181
+ experimental.backed.MaskedArray
182
+ experimental.backed.CategoricalArray
183
+ experimental.backed.Dataset2D
184
+ experimental.Dataset2DIlocIndexer
184
185
  ```
185
186
 
186
187
  (extensions-api)=
@@ -99,23 +99,45 @@ def setup(app: Sphinx):
99
99
  app.add_generic_role("small", partial(nodes.inline, classes=["small"]))
100
100
  app.add_generic_role("smaller", partial(nodes.inline, classes=["smaller"]))
101
101
 
102
+ # TODO: move to scanpydoc
103
+ if TYPE_CHECKING:
104
+ from docutils.nodes import TextElement, reference
105
+ from sphinx.addnodes import pending_xref
106
+ from sphinx.environment import BuildEnvironment
107
+
108
+ def res(
109
+ app: Sphinx, env: BuildEnvironment, node: pending_xref, contnode: TextElement
110
+ ) -> reference | None:
111
+ return env.domains["py"].resolve_xref(
112
+ env,
113
+ node["refdoc"],
114
+ app.builder,
115
+ node["reftype"],
116
+ node["reftarget"],
117
+ node,
118
+ contnode,
119
+ )
120
+
121
+ app.connect("missing-reference", res, priority=502)
122
+
102
123
 
103
124
  intersphinx_mapping = dict(
104
125
  awkward=("https://awkward-array.org/doc/stable", None),
105
126
  cupy=("https://docs.cupy.dev/en/stable", None),
106
127
  dask=("https://docs.dask.org/en/stable", None),
128
+ fsspec=("https://filesystem-spec.readthedocs.io/en/stable/", None),
107
129
  h5py=("https://docs.h5py.org/en/latest", None),
108
130
  hdf5plugin=("https://hdf5plugin.readthedocs.io/en/latest", None),
131
+ kvikio=("https://docs.rapids.ai/api/kvikio/stable/", None),
109
132
  loompy=("https://linnarssonlab.org/loompy", None),
110
133
  numpy=("https://numpy.org/doc/stable", None),
134
+ obstore=("https://developmentseed.org/obstore/latest/", None),
111
135
  pandas=("https://pandas.pydata.org/pandas-docs/stable", None),
112
136
  python=("https://docs.python.org/3", None),
113
137
  scipy=("https://docs.scipy.org/doc/scipy", None),
114
138
  sklearn=("https://scikit-learn.org/stable", None),
115
- zarr=("https://zarr.readthedocs.io/en/stable/", None),
116
139
  xarray=("https://docs.xarray.dev/en/stable", None),
117
- obstore=("https://developmentseed.org/obstore/latest/", None),
118
- kvikio=("https://docs.rapids.ai/api/kvikio/stable/", None),
140
+ zarr=("https://zarr.readthedocs.io/en/stable/", None),
119
141
  zarrs=("https://zarrs-python.readthedocs.io/en/stable/", None),
120
142
  )
121
143
 
@@ -133,6 +155,7 @@ qualname_overrides = {
133
155
  "anndata._types.WriteCallback": "anndata.experimental.WriteCallback",
134
156
  "anndata._types.Read": "anndata.experimental.Read",
135
157
  "anndata._types.Write": "anndata.experimental.Write",
158
+ "anndata._types.Dataset2DIlocIndexer": "anndata.experimental.Dataset2DIlocIndexer",
136
159
  "zarr.core.array.Array": "zarr.Array",
137
160
  "zarr.core.group.Group": "zarr.Group",
138
161
  # Buffer is not yet exported, so the buffer class registry is the closest thing
@@ -142,6 +165,7 @@ qualname_overrides = {
142
165
  "anndata.compat.CupyArray": "cupy.ndarray",
143
166
  "anndata.compat.CupySparseMatrix": "cupyx.scipy.sparse.spmatrix",
144
167
  "anndata.compat.XDataArray": "xarray.DataArray",
168
+ "anndata.compat.XDataset": "xarray.Dataset",
145
169
  "awkward.highlevel.Array": "ak.Array",
146
170
  "numpy.int64": ("py:attr", "numpy.int64"),
147
171
  "pandas.DataFrame.iloc": ("py:attr", "pandas.DataFrame.iloc"),
@@ -0,0 +1,55 @@
1
+ """Extension to skip inherited methods and properties in autosummary."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from traceback import walk_stack
6
+ from typing import TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ from typing import Literal
10
+
11
+ from sphinx.application import Sphinx
12
+ from sphinx.ext.autodoc import Options
13
+
14
+
15
+ def skip_inherited( # noqa: PLR0917
16
+ app: Sphinx,
17
+ what: Literal[
18
+ "module", "class", "exception", "function", "method", "attribute", "property"
19
+ ],
20
+ name: str,
21
+ obj: object,
22
+ skip: bool, # noqa: FBT001
23
+ options: Options | dict[str, object],
24
+ ) -> bool | None:
25
+ """Skip inherited members."""
26
+ # Skip `getdoc` property
27
+ if what == "method" and name == "getdoc":
28
+ return True
29
+
30
+ # find parent class
31
+ for frame, _ in walk_stack(None):
32
+ if frame.f_code.co_name == "_get_members" and frame.f_code.co_filename.endswith(
33
+ "/generate.py"
34
+ ):
35
+ parent = frame.f_locals["obj"]
36
+ if not isinstance(parent, type):
37
+ return None
38
+ break
39
+ else:
40
+ return None
41
+
42
+ # return if it’s a member of the parent class
43
+ typ = parent
44
+ while typ is not type:
45
+ if name in typ.__dict__:
46
+ return None
47
+ typ = type(typ)
48
+
49
+ # skip since we know it’s not a member of the parent class
50
+ return True
51
+
52
+
53
+ def setup(app: Sphinx) -> None:
54
+ """App setup hook."""
55
+ app.connect("autodoc-skip-member", skip_inherited)
@@ -0,0 +1,51 @@
1
+ (v0.12.0)=
2
+ ### 0.12.0 {small}`2025-07-16`
3
+
4
+ - (v0.12.0rc4)=
5
+ {guilabel}`rc4` 2025-06-18
6
+ - (v0.12.0rc3)=
7
+ {guilabel}`rc3` 2025-05-20
8
+ - (v0.12.0rc2)=
9
+ {guilabel}`rc2` 2025-05-15
10
+ - (v0.12.0rc1)=
11
+ {guilabel}`rc1` 2025-04-09
12
+
13
+ #### Breaking changes
14
+
15
+ - {guilabel}`rc1` Remove `anndata.read` {user}`ilan-gold` ({pr}`1766`)
16
+ - {guilabel}`rc1` Tighten usage of {class}`scipy.sparse.spmatrix` for describing sparse matrices in types and instance checks to only {class}`scipy.sparse.csr_matrix` and {class}`scipy.sparse.csc_matrix` {user}`ilan-gold` ({pr}`1768`)
17
+ - {guilabel}`rc1` Disallow declaration of {class}`~anndata.AnnData` with non-`cs{r,c}` sparse data-structures {user}`ilan-gold` ({pr}`1829`)
18
+ - {guilabel}`rc1` Upgrade all `DeprecationWarning`s to `FutureWarning`s {user}`ilan-gold` ({pr}`1874`)
19
+ - {guilabel}`rc4` Lower bound `xarray` by `2025.06.01`. {class}`pandas.arrays.StringArray` was previously used as the in-memory `nullable-string-array` container in `xarray`, but due to {issue}`pydata/xarray#10419` now uses {class}`numpy.ndarray` with an object data type. {user}`ilan-gold` ({pr}`2008`)
20
+
21
+ #### Bug fixes
22
+
23
+ - Fix {func}`anndata.experimental.backed.Dataset2D.reindex` internal setting {user}`ilan-gold` ({pr}`2018`)
24
+ - {guilabel}`rc1` Disallow writing of {class}`~anndata.experimental.backed.Dataset2D` objects {user}`ilan-gold` ({pr}`1887`)
25
+ - {guilabel}`rc1` Upgrade old deprecation warning to a `FutureWarning` on `BaseCompressedSparseDataset.__setitem__`, showing our intent to remove the feature in the next release. {user}`ilan-gold` ({pr}`1928`)
26
+ - {guilabel}`rc1` Don't use {func}`asyncio.run` internally for any operations {user}`ilan-gold` ({pr}`1933`)
27
+ - {guilabel}`rc1` Disallow forward slashes in keys for writing {user}`ilan-gold` ({pr}`1940`)
28
+ - {guilabel}`rc2` Convert 1d {class}`numpy.ndarray` and {class}`cupy.ndarray`s in {attr}`anndata.AnnData.obsm` and {attr}`anndata.AnnData.varm` to 2d {user}`ilan-gold` ({pr}`1962`)
29
+ - {guilabel}`rc3` Update zarr v3 bound to >3.0.8 to prevent corrupted data {issue}`zarr-developers/zarr-python#3061` {user}`ilan-gold` ({pr}`1993`)
30
+
31
+ #### Features
32
+
33
+ - {guilabel}`rc1` {data}`None` values can now be serialized to `.h5ad` and `.zarr`,
34
+ preserving e.g. {attr}`~anndata.AnnData.uns` structure through saving and loading {user}`flying-sheep` ({pr}`999`)
35
+ - {guilabel}`rc1` Add {func}`~anndata.experimental.read_elem_lazy` (in place of `read_elem_as_dask`) to handle backed dataframes, sparse arrays, and dense arrays, as well as a {func}`~anndata.experimental.read_lazy` to handle reading in as much of the on-disk data as possible to produce a {class}`~anndata.AnnData` object {user}`ilan-gold` ({pr}`1247`)
36
+ - {guilabel}`rc1` Support {mod}`zarr` version 3 python package {user}`ilan-gold` ({pr}`1726`)
37
+ - {guilabel}`rc1` Adopt the Scientific Python [deprecation schedule](https://scientific-python.org/specs/spec-0000/) {user}`ilan-gold` ({pr}`1768`)
38
+ - {guilabel}`rc1` Allow {mod}`zarr` v3 writing of data {user}`ilan-gold` ({pr}`1892`)
39
+ - {guilabel}`rc1` {func}`anndata.register_anndata_namespace` functionality for adding custom functionality to an {class}`~anndata.AnnData` object {user}`srivarra` ({pr}`1870`)
40
+ - {guilabel}`rc2` Allow xarray Datasets to be used for obs/var/obsm/varm. {user}`ilia-kats` ({pr}`1966`)
41
+ - {guilabel}`rc4` {class}`anndata.experimental.backed.Dataset2D` now takes a compositional approach to wrapping {class}`xarray.Dataset` which may have breaking changes over the past release versions. {user}`ilan-gold` ({pr}`1997`)
42
+ - {guilabel}`rc4` Use {attr}`numpy.dtypes.StringDType` with `na_object` set to {attr}`pandas.NA` for nullable string data with {class}`anndata.experimental.backed.Dataset2D` {user}`ilan-gold` ({pr}`2011`)
43
+
44
+ #### Performance
45
+
46
+ - {guilabel}`rc2` Load AnnLoader lazily to prevent expensive unnecessary `torch` imports when its available on the system. {user}`Zethson` & {user}`flying-sheep` ({pr}`1950`)
47
+ - {guilabel}`rc4` Improve {func}`~anndata.experimental.read_elem_lazy` performance for `h5ad` files by not caching `indptr`. {user}`ilan-gold` ({pr}`2005`)
48
+
49
+ #### Development
50
+
51
+ - {guilabel}`rc4` Temporarily bound {mod}`zarr` to `<3.1` until {pr}`1995` is merged to handle the new data type structure. {user}`ilan-gold` ({pr}`2013`)
@@ -0,0 +1,10 @@
1
+ (v0.12.1)=
2
+ ### 0.12.1 {small}`2025-07-23`
3
+
4
+ ### Bug fixes
5
+
6
+ - Fix `chunks` argument for {func}`anndata.experimental.read_elem_lazy` so that it uses the on-disk chunking when possible, and allow users to pass this argument through to the reading of {class}`anndata.experimental.backed.Dataset2D` {user}`ilan-gold` ({pr}`2033`)
7
+
8
+ ### Performance
9
+
10
+ - Improve integer indexing performance of `h5` 1d arrays that are opened via {func}`anndata.experimental.read_elem_lazy` {user}`ilan-gold` ({pr}`2035`)
@@ -4,6 +4,23 @@
4
4
  Users should notice a significant performance improvement, especially for cloud data, but also likely for local data as well.
5
5
  Here is a quick guide on some of our learnings so far:
6
6
 
7
+ ## Consolidated Metadata
8
+
9
+ All `zarr` stores are now consolidated by default when written via {func}`anndata.io.write_zarr` or {meth}`anndata.AnnData.write_zarr`. For more information on this topic, please seee {ref}`the zarr docs <zarr:user-guide-consolidated-metadata>`. Practcally, this changes means that once a store has been written, it should be treated as immutable **unless you remove the consolidated metadata and/or rewrite after the mutating operation** i.e., if you wish to use `anndata.io.write_elem` to add a column to `obs`, a `layer` etc. to an existing store. For example, to mutate an existing store on-disk, you may do:
10
+
11
+ ```python
12
+ g = zarr.open_group(orig_path, mode="a", use_consolidated=False)
13
+ ad.io.write_elem(
14
+ g,
15
+ "obs",
16
+ obs,
17
+ dataset_kwargs=dict(chunks=(250,)),
18
+ )
19
+ zarr.consolidate_metadata(g.store)
20
+ ```
21
+
22
+ In this example, the store was opened unconsolidated (trying to open it as a consolidated store would error out), edited, and then reconsolidated. Alternatively, one could simple delete the file containing the consolidated metadata first at the root, `.zmetadata`.
23
+
7
24
  ## Remote data
8
25
 
9
26
  We now provide the {func}`anndata.experimental.read_lazy` feature for reading as much of the {class}`~anndata.AnnData` object as lazily as possible, using `dask` and {mod}`xarray`.
@@ -20,10 +20,14 @@ extra-dependencies = [ "ipykernel" ]
20
20
  env-vars.UV_CONSTRAINT = "ci/constraints.txt"
21
21
  overrides.matrix.deps.env-vars = [
22
22
  { if = [ "pre" ], key = "UV_PRERELEASE", value = "allow" },
23
+ { if = [ "pre" ], key = "UV_CONSTRAINT", value = "ci/pre-deps.txt" },
23
24
  { if = [ "min" ], key = "UV_CONSTRAINT", value = "ci/constraints.txt ci/min-deps.txt" },
24
25
  ]
25
26
  overrides.matrix.deps.pre-install-commands = [
26
27
  { if = [ "min" ], value = "uv run ci/scripts/min-deps.py pyproject.toml --all-extras -o ci/min-deps.txt" },
28
+ # To prevent situations like https://github.com/pydata/xarray/issues/10419 going forward
29
+ { if = [ "pre" ], value = "echo xarray @ git+https://github.com/pydata/xarray.git > ci/pre-deps.txt" },
30
+
27
31
  ]
28
32
  overrides.matrix.deps.python = [
29
33
  { if = [ "min" ], value = "3.11" },