From 88a5e45468cbd0be92845e72d9f40356ae750839 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Wed, 21 Aug 2024 15:35:52 -0400 Subject: [PATCH 01/21] (feat): add `hatch.toml` for building the docs --- .gitignore | 1 - hatch.toml | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 hatch.toml diff --git a/.gitignore b/.gitignore index 51533016e..8124b9450 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ __pycache__/ /src/anndata/_version.py /requirements*.lock /.python-version -/hatch.toml # Test results (nunit/junit) and coverage /test-data/ diff --git a/hatch.toml b/hatch.toml new file mode 100644 index 000000000..3888aff48 --- /dev/null +++ b/hatch.toml @@ -0,0 +1,8 @@ +[envs.docs] +installer = "uv" +features = ["doc"] +dependencies = ["setuptools"] # https://bitbucket.org/pybtex-devs/pybtex/issues/169 + +[envs.docs.scripts] +build = "sphinx-build -M html docs docs/_build -W --keep-going {args}" +clean = "git clean -fX -- docs" From 1cfa318a9296885c9b8966525c7f1d732785a2e8 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Wed, 21 Aug 2024 16:01:23 -0400 Subject: [PATCH 02/21] (chore): start using `towncrier` for next release by preparing it --- docs/release-notes/0.10.9.md | 20 -------------------- docs/release-notes/1147.bugfix.md | 1 + docs/release-notes/1501.bugfix.md | 1 + docs/release-notes/1504.performance.md | 1 + docs/release-notes/1516.bugfix.md | 1 + docs/release-notes/1532.bugfix.md | 1 + docs/release-notes/1540.bugfix.md | 1 + docs/release-notes/1557.doc.md | 1 + docs/release-notes/1580.bugfix.md | 1 + docs/release-notes/1586.bugfix.md | 1 + pyproject.toml | 16 ++++++++++++++++ 11 files changed, 25 insertions(+), 20 deletions(-) delete mode 100644 docs/release-notes/0.10.9.md create mode 100644 docs/release-notes/1147.bugfix.md create mode 100644 docs/release-notes/1501.bugfix.md create mode 100644 docs/release-notes/1504.performance.md create mode 100644 docs/release-notes/1516.bugfix.md create mode 100644 docs/release-notes/1532.bugfix.md create mode 100644 docs/release-notes/1540.bugfix.md create mode 100644 docs/release-notes/1557.doc.md create mode 100644 docs/release-notes/1580.bugfix.md create mode 100644 docs/release-notes/1586.bugfix.md diff --git a/docs/release-notes/0.10.9.md b/docs/release-notes/0.10.9.md deleted file mode 100644 index 6245978f8..000000000 --- a/docs/release-notes/0.10.9.md +++ /dev/null @@ -1,20 +0,0 @@ -(0.10.9)= -### 0.10.9 {small}`the future` - -#### Bugfix - -* Add warning for setting `X` on a view with repeated indices {pr}`1501` {user}`ilan-gold` -* Coerce {class}`numpy.matrix` classes to arrays when trying to store them in `AnnData` {pr}`1516` {user}`flying-sheep` -* Fix for setting a dense `X` view with a sparse matrix {pr}`1532` {user}`ilan-gold` -* Upper bound {mod}`numpy` for `gpu` installation on account of {issue}`cupy/cupy#8391` {pr}`1540` {user}`ilan-gold` -* Fix writing large number of columns for `h5` files {pr}`1147` {user}`ilan-gold` {user}`selmanozleyen` -* Upper bound dask on account of {issue}`1579` {pr}`1580` {user}`ilan-gold` -* Ensure setting {attr}`pandas.DataFrame.index` on a view of a {class}`~anndata.AnnData` instantiates the {class}`~pandas.DataFrame` from the view {pr}`1586` {user}`ilan-gold` - -#### Documentation - -* add `callback` typing for {func}`~anndata.experimental.read_dispatched` and {func}`~anndata.experimental.write_dispatched` {pr}`1557` {user}`ilan-gold` - -#### Performance - -* Support for `concat_on_disk` outer join {pr}`1504` {user}`ilan-gold` diff --git a/docs/release-notes/1147.bugfix.md b/docs/release-notes/1147.bugfix.md new file mode 100644 index 000000000..e08caed2e --- /dev/null +++ b/docs/release-notes/1147.bugfix.md @@ -0,0 +1 @@ +Fix writing large number of columns for `h5` files {pr}`1147` {user}`ilan-gold` {user}`selmanozleyen` diff --git a/docs/release-notes/1501.bugfix.md b/docs/release-notes/1501.bugfix.md new file mode 100644 index 000000000..653c5f133 --- /dev/null +++ b/docs/release-notes/1501.bugfix.md @@ -0,0 +1 @@ +Add warning for setting `X` on a view with repeated indices {pr}`1501` {user}`ilan-gold` diff --git a/docs/release-notes/1504.performance.md b/docs/release-notes/1504.performance.md new file mode 100644 index 000000000..4f65574f7 --- /dev/null +++ b/docs/release-notes/1504.performance.md @@ -0,0 +1 @@ +Support for `concat_on_disk` outer join {pr}`1504` {user}`ilan-gold` diff --git a/docs/release-notes/1516.bugfix.md b/docs/release-notes/1516.bugfix.md new file mode 100644 index 000000000..aeabf0fcf --- /dev/null +++ b/docs/release-notes/1516.bugfix.md @@ -0,0 +1 @@ +Coerce {class}`numpy.matrix` classes to arrays when trying to store them in `AnnData` {pr}`1516` {user}`flying-sheep` diff --git a/docs/release-notes/1532.bugfix.md b/docs/release-notes/1532.bugfix.md new file mode 100644 index 000000000..62a10c97e --- /dev/null +++ b/docs/release-notes/1532.bugfix.md @@ -0,0 +1 @@ +Fix for setting a dense `X` view with a sparse matrix {pr}`1532` {user}`ilan-gold` diff --git a/docs/release-notes/1540.bugfix.md b/docs/release-notes/1540.bugfix.md new file mode 100644 index 000000000..7e4fa3ed2 --- /dev/null +++ b/docs/release-notes/1540.bugfix.md @@ -0,0 +1 @@ +Upper bound {mod}`numpy` for `gpu` installation on account of {issue}`cupy/cupy#8391` {pr}`1540` {user}`ilan-gold` diff --git a/docs/release-notes/1557.doc.md b/docs/release-notes/1557.doc.md new file mode 100644 index 000000000..558479049 --- /dev/null +++ b/docs/release-notes/1557.doc.md @@ -0,0 +1 @@ +add `callback` typing for {func}`~anndata.experimental.read_dispatched` and {func}`~anndata.experimental.write_dispatched` {pr}`1557` {user}`ilan-gold` diff --git a/docs/release-notes/1580.bugfix.md b/docs/release-notes/1580.bugfix.md new file mode 100644 index 000000000..3d1d0a4b5 --- /dev/null +++ b/docs/release-notes/1580.bugfix.md @@ -0,0 +1 @@ +Upper bound dask on account of {issue}`1579` {pr}`1580` {user}`ilan-gold` diff --git a/docs/release-notes/1586.bugfix.md b/docs/release-notes/1586.bugfix.md new file mode 100644 index 000000000..40b6b880f --- /dev/null +++ b/docs/release-notes/1586.bugfix.md @@ -0,0 +1 @@ +Ensure setting {attr}`pandas.DataFrame.index` on a view of a {class}`~anndata.AnnData` instantiates the {class}`~pandas.DataFrame` from the view {pr}`1586` {user}`ilan-gold` diff --git a/pyproject.toml b/pyproject.toml index a36f06af6..73551515b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,6 +64,7 @@ dev = [ "setuptools_scm", # test speedups "pytest-xdist", + "towncrier", ] doc = [ "sphinx>=7.4.6", @@ -192,3 +193,18 @@ strict = true [tool.codespell] skip = ".git,*.pdf,*.svg" ignore-words-list = "theis,coo,homogenous" + +[tool.towncrier] +package = "anndata" +directory = "docs/release-notes" +filename = "{version}.md" +single_file = false +package_dir = "src" + +[tool.towncrier.fragment.bugfix] +[tool.towncrier.fragment.doc] +[tool.towncrier.fragment.feature] +[tool.towncrier.fragment.misc] + +[tool.towncrier.fragment.performance] +name = "Performance" From de447942b456005223012a4b18cedeca518bf6e2 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Wed, 21 Aug 2024 16:44:09 -0400 Subject: [PATCH 03/21] (fix): release notes locale --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 73551515b..fc5d0132e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -197,7 +197,7 @@ ignore-words-list = "theis,coo,homogenous" [tool.towncrier] package = "anndata" directory = "docs/release-notes" -filename = "{version}.md" +filename = "docs/release-notes/{version}.md" single_file = false package_dir = "src" From 0daf18d9f76c07977c222cce62a9f6cf7fa21d0b Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Wed, 21 Aug 2024 16:51:07 -0400 Subject: [PATCH 04/21] (chore): `venv` ignored --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8124b9450..710b149e0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ __pycache__/ /*cache/ /node_modules/ /data/ +/venv/ # Distribution / packaging /dist/ From 272b67ddfd4513dd4252444aecd56321d59a605b Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Wed, 21 Aug 2024 17:04:13 -0400 Subject: [PATCH 05/21] (fix): add issue formatter --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index fc5d0132e..5f2a54bbc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -200,6 +200,7 @@ directory = "docs/release-notes" filename = "docs/release-notes/{version}.md" single_file = false package_dir = "src" +issue_format = "[#{issue}](https://github.com/scverse/anndata/pull/{issue})" [tool.towncrier.fragment.bugfix] [tool.towncrier.fragment.doc] From 8e4b939b4313d72656985d0edb5ff5209b636c09 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Thu, 22 Aug 2024 11:10:36 -0400 Subject: [PATCH 06/21] (chore): add correct header --- pyproject.toml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5f2a54bbc..bb2626a10 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,8 @@ dev = [ "setuptools_scm", # test speedups "pytest-xdist", - "towncrier", + # until https://github.com/twisted/towncrier/pull/651 is released + "towncrier @ git+https://github.com/twisted/towncrier", ] doc = [ "sphinx>=7.4.6", @@ -112,6 +113,8 @@ source = "vcs" version-file = "src/anndata/_version.py" [tool.hatch.build.targets.wheel] packages = ["src/anndata", "src/testing"] +[tool.hatch.metadata] +allow-direct-references = true [tool.coverage.run] source_pkgs = ["anndata"] @@ -201,7 +204,7 @@ filename = "docs/release-notes/{version}.md" single_file = false package_dir = "src" issue_format = "[#{issue}](https://github.com/scverse/anndata/pull/{issue})" - +title_format = "({version})=\n### {version} `{project_date}`" [tool.towncrier.fragment.bugfix] [tool.towncrier.fragment.doc] [tool.towncrier.fragment.feature] From a4937de37db411141f9b98cf782b3872305eebae Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Thu, 22 Aug 2024 11:29:38 -0400 Subject: [PATCH 07/21] (chore): reignore `hatch.toml` --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 710b149e0..51533016e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,13 +7,13 @@ __pycache__/ /*cache/ /node_modules/ /data/ -/venv/ # Distribution / packaging /dist/ /src/anndata/_version.py /requirements*.lock /.python-version +/hatch.toml # Test results (nunit/junit) and coverage /test-data/ From 1eedf30724a234267b29d819cf5d9fe66260e43c Mon Sep 17 00:00:00 2001 From: Ilan Gold Date: Fri, 23 Aug 2024 08:58:52 -0400 Subject: [PATCH 08/21] Update pyproject.toml Co-authored-by: Philipp A. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bb2626a10..e0ef42c6b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -204,7 +204,7 @@ filename = "docs/release-notes/{version}.md" single_file = false package_dir = "src" issue_format = "[#{issue}](https://github.com/scverse/anndata/pull/{issue})" -title_format = "({version})=\n### {version} `{project_date}`" +title_format = "(v{version})=\n### {version} `{project_date}`" [tool.towncrier.fragment.bugfix] [tool.towncrier.fragment.doc] [tool.towncrier.fragment.feature] From eefafad90d6ef3ee9656d8e5815af2f92496ffbd Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Fri, 23 Aug 2024 15:45:46 +0200 Subject: [PATCH 09/21] Rely on prerelease version --- hatch.toml | 5 ++++- pyproject.toml | 5 +---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hatch.toml b/hatch.toml index 3888aff48..ad888c3bb 100644 --- a/hatch.toml +++ b/hatch.toml @@ -1,5 +1,8 @@ -[envs.docs] +[envs.default] installer = "uv" +features = ["dev"] + +[envs.docs] features = ["doc"] dependencies = ["setuptools"] # https://bitbucket.org/pybtex-devs/pybtex/issues/169 diff --git a/pyproject.toml b/pyproject.toml index e0ef42c6b..919ee93ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,8 +64,7 @@ dev = [ "setuptools_scm", # test speedups "pytest-xdist", - # until https://github.com/twisted/towncrier/pull/651 is released - "towncrier @ git+https://github.com/twisted/towncrier", + "towncrier>=24.8.0rc1", ] doc = [ "sphinx>=7.4.6", @@ -113,8 +112,6 @@ source = "vcs" version-file = "src/anndata/_version.py" [tool.hatch.build.targets.wheel] packages = ["src/anndata", "src/testing"] -[tool.hatch.metadata] -allow-direct-references = true [tool.coverage.run] source_pkgs = ["anndata"] From d1e83c06218b2aa0376fd919660cb446b2daf5ac Mon Sep 17 00:00:00 2001 From: Ilan Gold Date: Fri, 23 Aug 2024 09:49:52 -0400 Subject: [PATCH 10/21] Update pyproject.toml Co-authored-by: Philipp A. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 919ee93ae..1b7756417 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -200,7 +200,7 @@ directory = "docs/release-notes" filename = "docs/release-notes/{version}.md" single_file = false package_dir = "src" -issue_format = "[#{issue}](https://github.com/scverse/anndata/pull/{issue})" +issue_format = "{{issue}}`{issue}`" title_format = "(v{version})=\n### {version} `{project_date}`" [tool.towncrier.fragment.bugfix] [tool.towncrier.fragment.doc] From 51453026c90614de9c79411adace940d1e9ef527 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Fri, 23 Aug 2024 12:18:17 -0400 Subject: [PATCH 11/21] (fix): remove `hatch.toml` from `.gitignore` --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 51533016e..8124b9450 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ __pycache__/ /src/anndata/_version.py /requirements*.lock /.python-version -/hatch.toml # Test results (nunit/junit) and coverage /test-data/ From 249030e3f643926a4e139003c6e99d2705297609 Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Sun, 25 Aug 2024 19:41:35 +0200 Subject: [PATCH 12/21] Sketch for bump CI --- ci/scripts/min-deps.py | 2 +- ci/scripts/release-notes.py | 89 +++++++++++++++++++++++++++++++++++++ docs/release-notes/index.md | 9 +--- pyproject.toml | 1 + 4 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 ci/scripts/release-notes.py diff --git a/ci/scripts/min-deps.py b/ci/scripts/min-deps.py index a7482e70e..1e9cf3126 100755 --- a/ci/scripts/min-deps.py +++ b/ci/scripts/min-deps.py @@ -27,7 +27,7 @@ def min_dep(req: Requirement) -> Requirement: ------- >>> min_dep(Requirement("numpy>=1.0")) - "numpy==1.0" + "numpy==1.0.*" """ req_name = req.name if req.extras: diff --git a/ci/scripts/release-notes.py b/ci/scripts/release-notes.py new file mode 100644 index 000000000..37a847c24 --- /dev/null +++ b/ci/scripts/release-notes.py @@ -0,0 +1,89 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from typing import TypeAlias + + Version: TypeAlias = tuple[int, int] | tuple[int, int, int] + +MARKER_F = "" +MARKER_P = "" + +# A new minor release needs a new header +TEMPLATE_F = f"""\ +{MARKER_F} + +(v{{version}})= +## Version {{version}} + +{MARKER_P}\ +""" + +# A new patch release needs just an include directive +TEMPLATE_P = f"""\ +{MARKER_P} + +```{{{{include}}}} /release-notes/{{version}}.md +```\ +""" + + +def checked_replace(rel_notes: str, marker: str, replacement: str) -> str: + if marker not in rel_notes: + msg = rf"Missing {marker!r} in release notes index!" + raise RuntimeError(msg) + return rel_notes.replace(marker, replacement) + + +def insert_patch(rel_notes: str, version: Version) -> str: + r"""Insert a new patch version into `rel_notes`. + + >>> rel_notes = f"START\n\n{MARKER_P}\n\nEND" + >>> print(insert_patch(rel_notes, version=(1, 0, 1))) + START + + + + ```{include} /release-notes/1.0.1.md + ``` + + END + """ + assert len(version) == 3 + return checked_replace( + rel_notes, MARKER_P, TEMPLATE_P.format(version=".".join(map(str, version))) + ) + + +def insert_feature(rel_notes: str, version: Version) -> str: + r"""Insert a new feature version into `rel_notes`. + + >>> rel_notes = f"START\n\n{MARKER_F}\n\nOLD:\n\n{MARKER_P}\n\nEND" + >>> print(insert_feature(rel_notes, version=(1, 1))) + START + + + + (v1.1)= + ## Version 1.1 + + + + ```{include} /release-notes/1.1.0.md + ``` + + OLD: + + END + """ + assert len(version) == 2 + # delete old patch marker + rel_notes = checked_replace(rel_notes, f"{MARKER_P}\n\n", "") + # replace feature marker with header and new patch marker + rel_notes = checked_replace( + rel_notes, MARKER_F, TEMPLATE_F.format(version=".".join(map(str, version))) + ) + # insert include for new .0 patch version + rel_notes = insert_patch(rel_notes, (*version, 0)) + return rel_notes diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md index c0a802f23..d37986f8e 100644 --- a/docs/release-notes/index.md +++ b/docs/release-notes/index.md @@ -1,16 +1,11 @@ # Release notes -(v0.11)= -## Version 0.11 - -```{include} /release-notes/0.11.0.md -``` + (v0.10)= ## Version 0.10 -```{include} /release-notes/0.10.9.md -``` + ```{include} /release-notes/0.10.8.md ``` diff --git a/pyproject.toml b/pyproject.toml index 1b7756417..cadfc7d0c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,6 +148,7 @@ python_files = "test_*.py" testpaths = [ "anndata", # docstrings (module name due to --pyargs) "./tests", # unit tests + "./ci/scripts", # CI script tests "./docs/concatenation.rst", # further doctests ] # For some reason this effects how logging is shown when tests are run From 236637d04391030f2d2fb4b83d10d85cbd106a37 Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Sun, 25 Aug 2024 19:57:11 +0200 Subject: [PATCH 13/21] Add CLI --- ci/scripts/release-notes.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/ci/scripts/release-notes.py b/ci/scripts/release-notes.py index 37a847c24..90af6cde0 100644 --- a/ci/scripts/release-notes.py +++ b/ci/scripts/release-notes.py @@ -1,12 +1,18 @@ from __future__ import annotations +import sys +from pathlib import Path from typing import TYPE_CHECKING if TYPE_CHECKING: + from collections.abc import Sequence from typing import TypeAlias Version: TypeAlias = tuple[int, int] | tuple[int, int, int] + +HERE = Path(__file__).parent + MARKER_F = "" MARKER_P = "" @@ -87,3 +93,27 @@ def insert_feature(rel_notes: str, version: Version) -> str: # insert include for new .0 patch version rel_notes = insert_patch(rel_notes, (*version, 0)) return rel_notes + + +def main(args: Sequence[str] | None = None) -> str | None: + if args is None: + args = sys.argv[1:] + + if len(args) != 1: + return "Usage: python release-notes.py " + + version = tuple(map(int, args[0].split("."))) + + index_path = HERE.parent.parent / "docs" / "release-notes" / "index.md" + index = index_path.read_text() + if len(version) == 2: + index = insert_feature(index, version) + elif len(version) == 3: + index = insert_patch(index, version) + else: + return f"Invalid version: {version!r}" + index_path.write_text(index) + + +if __name__ == "__main__": + sys.exit(main()) From ef8ac8fe2d6f0fd8f5d37e9764074d6ad76f10b1 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Mon, 26 Aug 2024 11:13:55 +0200 Subject: [PATCH 14/21] (fix): broken `v0.11` link --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 61d759ab1..06aacaed6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,7 +5,7 @@ See {doc}`/release-notes/index`, particularly {ref}`v0.10` for the current release, -and {ref}`v0.11` for the upcoming release, +and [the `.feature` fragments](https://github.com/scverse/anndata/tree/main/docs) for the upcoming release, ```{toctree} :hidden: true From 1ebcd2037cb720b2de5492733e1098a3af7974e6 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Mon, 26 Aug 2024 11:19:24 +0200 Subject: [PATCH 15/21] (chore): move `towncrier` to full release --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index cadfc7d0c..536689ed6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,7 @@ dev = [ "setuptools_scm", # test speedups "pytest-xdist", - "towncrier>=24.8.0rc1", + "towncrier>=24.8.0", ] doc = [ "sphinx>=7.4.6", From 67ca1f85ef0e4fbb77d4fdde878208b0c22d4f4d Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Mon, 26 Aug 2024 11:45:17 +0200 Subject: [PATCH 16/21] (fix): use `repr` --- ci/scripts/min-deps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/scripts/min-deps.py b/ci/scripts/min-deps.py index 1e9cf3126..d0cf41a52 100755 --- a/ci/scripts/min-deps.py +++ b/ci/scripts/min-deps.py @@ -27,7 +27,7 @@ def min_dep(req: Requirement) -> Requirement: ------- >>> min_dep(Requirement("numpy>=1.0")) - "numpy==1.0.*" + "" """ req_name = req.name if req.extras: From 271353f8c414f84af35de07b7e648db293581114 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Mon, 26 Aug 2024 12:04:37 +0200 Subject: [PATCH 17/21] (fix): remove quotes --- ci/scripts/min-deps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/scripts/min-deps.py b/ci/scripts/min-deps.py index d0cf41a52..b5b0b980e 100755 --- a/ci/scripts/min-deps.py +++ b/ci/scripts/min-deps.py @@ -27,7 +27,7 @@ def min_dep(req: Requirement) -> Requirement: ------- >>> min_dep(Requirement("numpy>=1.0")) - "" + """ req_name = req.name if req.extras: From 78577c69df19f3775141b470d614a1bfb552f2f8 Mon Sep 17 00:00:00 2001 From: Phil Schaf Date: Mon, 26 Aug 2024 15:42:17 +0200 Subject: [PATCH 18/21] directive --- ci/scripts/release-notes.py | 119 ------------------------------- docs/conf.py | 4 +- docs/extensions/release_notes.py | 111 ++++++++++++++++++++++++++++ docs/release-notes/index.md | 99 +------------------------ 4 files changed, 115 insertions(+), 218 deletions(-) delete mode 100644 ci/scripts/release-notes.py create mode 100644 docs/extensions/release_notes.py diff --git a/ci/scripts/release-notes.py b/ci/scripts/release-notes.py deleted file mode 100644 index 90af6cde0..000000000 --- a/ci/scripts/release-notes.py +++ /dev/null @@ -1,119 +0,0 @@ -from __future__ import annotations - -import sys -from pathlib import Path -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from collections.abc import Sequence - from typing import TypeAlias - - Version: TypeAlias = tuple[int, int] | tuple[int, int, int] - - -HERE = Path(__file__).parent - -MARKER_F = "" -MARKER_P = "" - -# A new minor release needs a new header -TEMPLATE_F = f"""\ -{MARKER_F} - -(v{{version}})= -## Version {{version}} - -{MARKER_P}\ -""" - -# A new patch release needs just an include directive -TEMPLATE_P = f"""\ -{MARKER_P} - -```{{{{include}}}} /release-notes/{{version}}.md -```\ -""" - - -def checked_replace(rel_notes: str, marker: str, replacement: str) -> str: - if marker not in rel_notes: - msg = rf"Missing {marker!r} in release notes index!" - raise RuntimeError(msg) - return rel_notes.replace(marker, replacement) - - -def insert_patch(rel_notes: str, version: Version) -> str: - r"""Insert a new patch version into `rel_notes`. - - >>> rel_notes = f"START\n\n{MARKER_P}\n\nEND" - >>> print(insert_patch(rel_notes, version=(1, 0, 1))) - START - - - - ```{include} /release-notes/1.0.1.md - ``` - - END - """ - assert len(version) == 3 - return checked_replace( - rel_notes, MARKER_P, TEMPLATE_P.format(version=".".join(map(str, version))) - ) - - -def insert_feature(rel_notes: str, version: Version) -> str: - r"""Insert a new feature version into `rel_notes`. - - >>> rel_notes = f"START\n\n{MARKER_F}\n\nOLD:\n\n{MARKER_P}\n\nEND" - >>> print(insert_feature(rel_notes, version=(1, 1))) - START - - - - (v1.1)= - ## Version 1.1 - - - - ```{include} /release-notes/1.1.0.md - ``` - - OLD: - - END - """ - assert len(version) == 2 - # delete old patch marker - rel_notes = checked_replace(rel_notes, f"{MARKER_P}\n\n", "") - # replace feature marker with header and new patch marker - rel_notes = checked_replace( - rel_notes, MARKER_F, TEMPLATE_F.format(version=".".join(map(str, version))) - ) - # insert include for new .0 patch version - rel_notes = insert_patch(rel_notes, (*version, 0)) - return rel_notes - - -def main(args: Sequence[str] | None = None) -> str | None: - if args is None: - args = sys.argv[1:] - - if len(args) != 1: - return "Usage: python release-notes.py " - - version = tuple(map(int, args[0].split("."))) - - index_path = HERE.parent.parent / "docs" / "release-notes" / "index.md" - index = index_path.read_text() - if len(version) == 2: - index = insert_feature(index, version) - elif len(version) == 3: - index = insert_patch(index, version) - else: - return f"Invalid version: {version!r}" - index_path.write_text(index) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/docs/conf.py b/docs/conf.py index a0e338006..6a0006a70 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -61,9 +61,11 @@ "sphinx.ext.linkcode", "nbsphinx", "IPython.sphinxext.ipython_console_highlighting", - "patch_sphinx_toolbox_autoprotocol", + "patch_sphinx_toolbox_autoprotocol", # internal extension "sphinx_toolbox.more_autodoc.autoprotocol", + # other internal extensions "patch_myst_cite", + "release_notes", ] myst_enable_extensions = [ "html_image", # So README.md can be used on github and sphinx docs diff --git a/docs/extensions/release_notes.py b/docs/extensions/release_notes.py new file mode 100644 index 000000000..bb28453a7 --- /dev/null +++ b/docs/extensions/release_notes.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +import itertools +import re +from pathlib import Path +from typing import TYPE_CHECKING + +from docutils import nodes +from packaging.version import Version +from sphinx.util.docutils import SphinxDirective + +if TYPE_CHECKING: + from collections.abc import Iterable, Sequence + from typing import ClassVar + + from myst_parser.mdit_to_docutils.base import DocutilsRenderer + from sphinx.application import Sphinx + + +FULL_VERSION_RE = re.compile(r"^(\d+)\.(\d+)\.(\d+)$") + + +class ReleaseNotes(SphinxDirective): + required_arguments: ClassVar = 1 + + def run(self) -> Sequence[nodes.Node]: + dir_ = Path(self.arguments[0]) + # resolve relative dir + if not dir_.is_absolute(): + src_file = Path(self.get_source_info()[0]) + if not src_file.is_file(): + msg = f"Cannot find relative path to: {src_file}" + raise self.error(msg) + dir_ = src_file.parent / self.arguments[0] + if not dir_.is_dir(): + msg = f"Not a directory: {dir_}" + raise self.error(msg) + + versions = sorted( + ( + (Version(f.stem), f) + for f in dir_.iterdir() + if FULL_VERSION_RE.match(f.stem) + ), + reverse=True, # descending + ) + version_groups = itertools.groupby( + versions, key=lambda vf: (vf[0].major, vf[0].minor) + ) + for (major, minor), versions in version_groups: + self.render_version_group(major, minor, versions) + return [] + + def render_version_group( + self, major: int, minor: int, versions: Iterable[tuple[Version, Path]] + ) -> None: + target = nodes.target( + ids=[f"v{major}-{minor}"], + names=[f"v{major}.{minor}"], + ) + section = nodes.section( + "", + nodes.title("", f"Version {major}.{minor}"), + ids=[], + names=[f"version {major}.{minor}"], + ) + self.state.document.note_implicit_target(section) + self.state.document.note_explicit_target(target) + # append target and section to parent + self.renderer.current_node.append(target) + self.renderer.update_section_level_state(section, 2) + # append children to section + with self.renderer.current_node_context(section): + for _, p in versions: + self.render_include(p) + + def render_include(self, path: Path) -> None: + # hacky solution because of https://github.com/executablebooks/MyST-Parser/issues/967 + from docutils.parsers.rst.directives.misc import Include + from myst_parser.mocking import MockIncludeDirective + + srcfile, lineno = self.get_source_info() + parent_dir = Path(srcfile).parent + + d = MockIncludeDirective( + renderer=self.renderer, + name=type(self).__name__, + klass=Include, # type: ignore # wrong type hint + arguments=[str(path.relative_to(parent_dir))], + options={}, + body=[], + lineno=lineno, + ) + d.run() + + # TODO: replace the above with this once the above mentioned bug is fixed + # from sphinx.util.parsing import nested_parse_to_nodes + # return nested_parse_to_nodes( + # self.state, + # path.read_text(), + # source=str(path), + # offset=self.content_offset, + # ) + + @property + def renderer(self) -> DocutilsRenderer: + return self.state._renderer + + +def setup(app: Sphinx) -> None: + app.add_directive("release-notes", ReleaseNotes) diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md index d37986f8e..60b7a352b 100644 --- a/docs/release-notes/index.md +++ b/docs/release-notes/index.md @@ -1,101 +1,4 @@ # Release notes - - -(v0.10)= -## Version 0.10 - - - -```{include} /release-notes/0.10.8.md -``` - -```{include} /release-notes/0.10.7.md -``` - -```{include} /release-notes/0.10.6.md -``` - -```{include} /release-notes/0.10.5.md -``` - -```{include} /release-notes/0.10.4.md -``` - -```{include} /release-notes/0.10.3.md -``` - -```{include} /release-notes/0.10.2.md -``` - -```{include} /release-notes/0.10.1.md -``` - -```{include} /release-notes/0.10.0.md -``` - -(v0.9)= -## Version 0.9 - -```{include} /release-notes/0.9.2.md -``` - -```{include} /release-notes/0.9.1.md -``` - -```{include} /release-notes/0.9.0.md -``` - -(v0.8)= -## Version 0.8 - -```{include} /release-notes/0.8.0.md -``` - -(v0.7)= -## Version 0.7 - -```{include} /release-notes/0.7.8.md -``` - -```{include} /release-notes/0.7.7.md -``` - -```{include} /release-notes/0.7.6.md -``` - -```{include} /release-notes/0.7.5.md -``` - -```{include} /release-notes/0.7.4.md -``` - -```{include} /release-notes/0.7.3.md -``` - -```{include} /release-notes/0.7.2.md -``` - -```{include} /release-notes/0.7.0.md -``` - -(v0.6)= -## Version 0.6 - -```{include} /release-notes/0.6.x.md -``` - -```{include} /release-notes/0.6.0.md -``` - -(v0.5)= -## Version 0.5 - -```{include} /release-notes/0.5.0.md -``` - -(v0.4)= -## Version 0.4 - -```{include} /release-notes/0.4.0.md +```{release-notes} . ``` From 1d2a8d0e1181a105bb585fce1d73081df41de004 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Tue, 27 Aug 2024 11:03:46 +0200 Subject: [PATCH 19/21] (fix): remove extra issue number --- docs/release-notes/1147.bugfix.md | 2 +- docs/release-notes/1501.bugfix.md | 2 +- docs/release-notes/1504.performance.md | 2 +- docs/release-notes/1516.bugfix.md | 2 +- docs/release-notes/1532.bugfix.md | 2 +- docs/release-notes/1540.bugfix.md | 2 +- docs/release-notes/1557.doc.md | 2 +- docs/release-notes/1580.bugfix.md | 2 +- docs/release-notes/1586.bugfix.md | 2 +- docs/release-notes/1589.bugfix.md | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/release-notes/1147.bugfix.md b/docs/release-notes/1147.bugfix.md index e08caed2e..c02530f58 100644 --- a/docs/release-notes/1147.bugfix.md +++ b/docs/release-notes/1147.bugfix.md @@ -1 +1 @@ -Fix writing large number of columns for `h5` files {pr}`1147` {user}`ilan-gold` {user}`selmanozleyen` +Fix writing large number of columns for `h5` files {user}`ilan-gold` {user}`selmanozleyen` diff --git a/docs/release-notes/1501.bugfix.md b/docs/release-notes/1501.bugfix.md index 653c5f133..d08e6fe82 100644 --- a/docs/release-notes/1501.bugfix.md +++ b/docs/release-notes/1501.bugfix.md @@ -1 +1 @@ -Add warning for setting `X` on a view with repeated indices {pr}`1501` {user}`ilan-gold` +Add warning for setting `X` on a view with repeated indices {user}`ilan-gold` diff --git a/docs/release-notes/1504.performance.md b/docs/release-notes/1504.performance.md index 4f65574f7..b50436d9d 100644 --- a/docs/release-notes/1504.performance.md +++ b/docs/release-notes/1504.performance.md @@ -1 +1 @@ -Support for `concat_on_disk` outer join {pr}`1504` {user}`ilan-gold` +Support for `concat_on_disk` outer join {user}`ilan-gold` diff --git a/docs/release-notes/1516.bugfix.md b/docs/release-notes/1516.bugfix.md index aeabf0fcf..71fbf1de8 100644 --- a/docs/release-notes/1516.bugfix.md +++ b/docs/release-notes/1516.bugfix.md @@ -1 +1 @@ -Coerce {class}`numpy.matrix` classes to arrays when trying to store them in `AnnData` {pr}`1516` {user}`flying-sheep` +Coerce {class}`numpy.matrix` classes to arrays when trying to store them in `AnnData` {user}`flying-sheep` diff --git a/docs/release-notes/1532.bugfix.md b/docs/release-notes/1532.bugfix.md index 62a10c97e..6df5a7a22 100644 --- a/docs/release-notes/1532.bugfix.md +++ b/docs/release-notes/1532.bugfix.md @@ -1 +1 @@ -Fix for setting a dense `X` view with a sparse matrix {pr}`1532` {user}`ilan-gold` +Fix for setting a dense `X` view with a sparse matrix {user}`ilan-gold` diff --git a/docs/release-notes/1540.bugfix.md b/docs/release-notes/1540.bugfix.md index 7e4fa3ed2..4a03c72c9 100644 --- a/docs/release-notes/1540.bugfix.md +++ b/docs/release-notes/1540.bugfix.md @@ -1 +1 @@ -Upper bound {mod}`numpy` for `gpu` installation on account of {issue}`cupy/cupy#8391` {pr}`1540` {user}`ilan-gold` +Upper bound {mod}`numpy` for `gpu` installation on account of {issue}`cupy/cupy#8391`{user}`ilan-gold` diff --git a/docs/release-notes/1557.doc.md b/docs/release-notes/1557.doc.md index 558479049..39e85410e 100644 --- a/docs/release-notes/1557.doc.md +++ b/docs/release-notes/1557.doc.md @@ -1 +1 @@ -add `callback` typing for {func}`~anndata.experimental.read_dispatched` and {func}`~anndata.experimental.write_dispatched` {pr}`1557` {user}`ilan-gold` +add `callback` typing for {func}`~anndata.experimental.read_dispatched` and {func}`~anndata.experimental.write_dispatched` {user}`ilan-gold` diff --git a/docs/release-notes/1580.bugfix.md b/docs/release-notes/1580.bugfix.md index 3d1d0a4b5..96fcede1f 100644 --- a/docs/release-notes/1580.bugfix.md +++ b/docs/release-notes/1580.bugfix.md @@ -1 +1 @@ -Upper bound dask on account of {issue}`1579` {pr}`1580` {user}`ilan-gold` +Upper bound dask on account of {issue}`1579` {user}`ilan-gold` diff --git a/docs/release-notes/1586.bugfix.md b/docs/release-notes/1586.bugfix.md index 40b6b880f..d09374415 100644 --- a/docs/release-notes/1586.bugfix.md +++ b/docs/release-notes/1586.bugfix.md @@ -1 +1 @@ -Ensure setting {attr}`pandas.DataFrame.index` on a view of a {class}`~anndata.AnnData` instantiates the {class}`~pandas.DataFrame` from the view {pr}`1586` {user}`ilan-gold` +Ensure setting {attr}`pandas.DataFrame.index` on a view of a {class}`~anndata.AnnData` instantiates the {class}`~pandas.DataFrame` from the view {user}`ilan-gold` diff --git a/docs/release-notes/1589.bugfix.md b/docs/release-notes/1589.bugfix.md index 1f14535b9..9413aaa1e 100644 --- a/docs/release-notes/1589.bugfix.md +++ b/docs/release-notes/1589.bugfix.md @@ -1 +1 @@ -Disallow using {class}`~pandas.DataFrame`s with multi-index columns {pr}`1589` {user}`ilan-gold` +Disallow using {class}`~pandas.DataFrame`s with multi-index columns {user}`ilan-gold` From c08ccf5620c39bd9ad1a7a2d8aabf1dcd57b98d5 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Tue, 27 Aug 2024 11:22:33 +0200 Subject: [PATCH 20/21] (fix): date in title --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 536689ed6..6749bff76 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -202,7 +202,7 @@ filename = "docs/release-notes/{version}.md" single_file = false package_dir = "src" issue_format = "{{issue}}`{issue}`" -title_format = "(v{version})=\n### {version} `{project_date}`" +title_format = "(v{version})=\n### {version} {{small}}`{project_date}`" [tool.towncrier.fragment.bugfix] [tool.towncrier.fragment.doc] [tool.towncrier.fragment.feature] From dac333b3d12d46161bc74de2f09230c8d9520dd8 Mon Sep 17 00:00:00 2001 From: Ilan Gold Date: Tue, 27 Aug 2024 16:16:32 +0200 Subject: [PATCH 21/21] Update pyproject.toml Co-authored-by: Philipp A. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6749bff76..2931d7ff6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -201,7 +201,7 @@ directory = "docs/release-notes" filename = "docs/release-notes/{version}.md" single_file = false package_dir = "src" -issue_format = "{{issue}}`{issue}`" +issue_format = "{{pr}}`{issue}`" title_format = "(v{version})=\n### {version} {{small}}`{project_date}`" [tool.towncrier.fragment.bugfix] [tool.towncrier.fragment.doc]