From 259f5ccc35e02c7de955eba00627a16ad5ca2e32 Mon Sep 17 00:00:00 2001 From: Spencer Brown Date: Wed, 11 Sep 2024 15:38:55 +1000 Subject: [PATCH 1/3] Undo towncrier changes when building docs --- docs/source/conf.py | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 3a2b3d5f1..0bf6e49d3 100755 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -19,9 +19,11 @@ from __future__ import annotations import collections.abc +import glob import os import sys import types +from pathlib import Path from typing import TYPE_CHECKING, cast if TYPE_CHECKING: @@ -36,19 +38,39 @@ # Enable reloading with `typing.TYPE_CHECKING` being True os.environ["SPHINX_AUTODOC_RELOAD_MODULES"] = "1" -# https://docs.readthedocs.io/en/stable/builds.html#build-environment -if "READTHEDOCS" in os.environ: - import glob +# Handle writing newsfragments into the history file. +# We want to keep files unchanged when testing locally. +# So immediately revert the contents after running towncrier, +# then substitute when Sphinx wants to read it in. +history_file = Path("history.rst") - if glob.glob("../../newsfragments/*.*.rst"): - print("-- Found newsfragments; running towncrier --", flush=True) - import subprocess +if glob.glob("../../newsfragments/*.*.rst"): + print("-- Found newsfragments; running towncrier --", flush=True) + history_orig = history_file.read_bytes() + import subprocess + try: subprocess.run( - ["towncrier", "--yes", "--date", "not released yet"], + ["towncrier", "--keep", "--date", "not released yet"], cwd="../..", check=True, ) + history_new = history_file.read_text("utf8") + finally: + # Make sure this reverts even if a failure occurred. + history_file.write_bytes(history_orig) + del history_orig # We don't need this any more. +else: + # Leave it as is. + history_new = None + + +def on_read_source(app: Sphinx, docname: str, content: list[str]) -> None: + """Substitute the modified history file.""" + if docname == "history" and history_new is not None: + # This is a 1-item list with the file contents. + content[0] = history_new + # Sphinx is very finicky, and somewhat buggy, so we have several different # methods to help it resolve links. @@ -153,6 +175,7 @@ def setup(app: Sphinx) -> None: app.connect("autodoc-process-signature", autodoc_process_signature) # After Intersphinx runs, add additional mappings. app.connect("builder-inited", add_intersphinx, priority=1000) + app.connect("source-read", on_read_source) # -- General configuration ------------------------------------------------ From 368a90b97daf56f7dcd06c8bf04644582c511daa Mon Sep 17 00:00:00 2001 From: Spencer Brown Date: Wed, 11 Sep 2024 15:39:25 +1000 Subject: [PATCH 2/3] Restore git index after towncrier run --- docs/source/conf.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 0bf6e49d3..60f7bcad0 100755 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -49,6 +49,15 @@ history_orig = history_file.read_bytes() import subprocess + # In case changes were staged, preserve indexed version. + # This grabs the hash of the current staged version. + history_staged = subprocess.run( + ["git", "rev-parse", "--verify", ":docs/source/history.rst"], + check=True, + cwd="../..", + stdout=subprocess.PIPE, + encoding="ascii", + ).stdout.strip() try: subprocess.run( ["towncrier", "--keep", "--date", "not released yet"], @@ -58,6 +67,19 @@ history_new = history_file.read_text("utf8") finally: # Make sure this reverts even if a failure occurred. + # Restore whatever was staged. + print(f"Restoring history.rst = {history_staged}") + subprocess.run( + [ + "git", + "update-index", + "--cacheinfo", + f"100644,{history_staged},docs/source/history.rst", + ], + cwd="../..", + check=False, + ) + # And restore the working copy. history_file.write_bytes(history_orig) del history_orig # We don't need this any more. else: From 1beebbfe9ace83be89beabf461d757f2bb1f9776 Mon Sep 17 00:00:00 2001 From: Spencer Brown Date: Wed, 11 Sep 2024 17:13:06 +1000 Subject: [PATCH 3/3] Add type annotation for history_new --- docs/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 60f7bcad0..ecdbdd470 100755 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -44,6 +44,7 @@ # then substitute when Sphinx wants to read it in. history_file = Path("history.rst") +history_new: str | None if glob.glob("../../newsfragments/*.*.rst"): print("-- Found newsfragments; running towncrier --", flush=True) history_orig = history_file.read_bytes()