Skip to content

Commit 82a2231

Browse files
authored
Merge branch 'main' into add-reload-test
2 parents 87d1e32 + fd726c5 commit 82a2231

File tree

13 files changed

+174
-91
lines changed

13 files changed

+174
-91
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
- "3.11"
2626
- "3.12"
2727
- "3.13"
28+
- "3.14"
2829
steps:
2930
- uses: actions/checkout@v4
3031
- uses: actions/setup-python@v5

.pre-commit-config.yaml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: v0.6.3
3+
rev: v0.12.10
44
hooks:
5-
- id: ruff
5+
- id: ruff-check
66
- id: ruff-format
77

88
- repo: https://github.com/pre-commit/pre-commit-hooks
9-
rev: v4.6.0
9+
rev: v6.0.0
1010
hooks:
1111
- id: check-builtin-literals
1212
- id: check-added-large-files
@@ -18,12 +18,7 @@ repos:
1818
- id: forbid-new-submodules
1919
- id: trailing-whitespace
2020

21-
- repo: https://github.com/tox-dev/pyproject-fmt
22-
rev: 2.2.1
23-
hooks:
24-
- id: pyproject-fmt
25-
2621
- repo: https://github.com/abravalheri/validate-pyproject
27-
rev: v0.19
22+
rev: v0.24.1
2823
hooks:
2924
- id: validate-pyproject

CONTRIBUTING.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ The tests can be run using:
5050

5151
.. code-block:: bash
5252
53-
nox -s tests
53+
nox -s test
5454
5555
This will run tests against all supported version of Python that are installed.
5656

NEWS.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@ Changelog
44
unreleased
55
----------
66

7+
2025.08.25 - 2025-08-25
8+
-----------------------
9+
710
* Drop support for Python 3.9-3.10 to match Sphinx.
11+
* Declare support for Python 3.14.
12+
* Add an optional ``--post-build`` flag to run additional commands
13+
after building the documentation.
14+
* Add support for the ``SPHINX_AUTOBUILD_DEBUG`` environment variable
15+
to help with debugging.
816

917
2024.10.03 - 2024-10-03
1018
-----------------------

README.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ which can seen by running ``sphinx-autobuild --help``:
6767
--delay DELAY how long to wait before opening the browser
6868
--watch DIR additional directories to watch
6969
--pre-build COMMAND additional command(s) to run prior to building the documentation
70+
--post-build COMMAND additional command(s) to run after building the documentation
7071
7172
Using with Makefile
7273
-------------------
@@ -140,6 +141,19 @@ to avoid needing to manually manage ports and opening browser windows
140141
sphinx-autobuild --port=0 --open-browser pikachu/docs pikachu/docs/_build/html &
141142
sphinx-autobuild --port=0 --open-browser magikarp/docs magickarp/docs/_build/html &
142143
144+
Notifications for build cycles
145+
------------------------------
146+
147+
As an example of using the ``--pre-build`` and ``--post-build`` arguments,
148+
the command below uses `notify-send` to send a notification when a build
149+
starts and finishes.
150+
151+
.. code-block:: bash
152+
153+
sphinx-autobuild docs docs/_build/html/ \
154+
--pre-build 'notify-send "sphinx-autobuild: build start"' \
155+
--post-build 'notify-send "sphinx-autobuild: build end"'
156+
143157
Relevant Sphinx Bugs
144158
====================
145159

@@ -153,6 +167,15 @@ or passing relevant ``filenames`` in addition to source and output directory in
153167

154168
__ https://github.com/sphinx-doc/sphinx-autobuild/issues/34
155169

170+
Debugging
171+
=========
172+
173+
If the ``SPHINX_AUTOBUILD_DEBUG`` environment variable is present,
174+
is not ``""`` (the empty string) or ``0``,
175+
and a file change is detected,
176+
its path and the currently active ignore expressions are printed.
177+
This is to help setting up the ignore expressions correctly.
178+
156179
Acknowledgements
157180
================
158181

noxfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def lint(session):
99
session.run("pre-commit", "run", "--all-files", *session.posargs)
1010

1111

12-
@nox.session(python=["3.11", "3.12", "3.13"])
12+
@nox.session(python=["3.11", "3.12", "3.13", "3.14"])
1313
def test(session):
1414
session.install("-e", ".[test]", silent=True)
1515
session.run("pytest", *session.posargs)

pyproject.toml

Lines changed: 62 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,80 @@
11
[build-system]
2+
requires = ["flit-core>=3.7"]
23
build-backend = "flit_core.buildapi"
3-
requires = [
4-
"flit-core>=3.7",
5-
]
64

5+
# project metadata
76
[project]
87
name = "sphinx-autobuild"
98
description = "Rebuild Sphinx documentation on changes, with hot reloading in the browser."
109
readme = "README.rst"
10+
urls.Changelog = "https://github.com/sphinx-doc/sphinx-autobuild/blob/main/NEWS.rst"
11+
urls.Documentation = "https://github.com/sphinx-doc/sphinx-autobuild#readme"
12+
urls.Download = "https://pypi.org/project/sphinx-autobuild/"
13+
urls."Issue tracker" = "https://github.com/sphinx-doc/sphinx-autobuild/issues"
14+
urls.Source = "https://github.com/sphinx-doc/sphinx-autobuild"
1115
license.text = "MIT"
12-
authors = [
13-
{ name = "Adam Turner" },
14-
{ name = "Jonathan Stoppani", email = "[email protected]" },
15-
]
1616
requires-python = ">=3.11"
17+
18+
# Classifiers list: https://pypi.org/classifiers/
1719
classifiers = [
18-
"Development Status :: 5 - Production/Stable",
19-
"Environment :: Console",
20-
"Environment :: Web Environment",
21-
"Framework :: Sphinx",
22-
"Intended Audience :: Developers",
23-
"License :: OSI Approved :: MIT License",
24-
"Operating System :: OS Independent",
25-
"Programming Language :: Python",
26-
"Programming Language :: Python :: 3 :: Only",
27-
"Programming Language :: Python :: 3.11",
28-
"Programming Language :: Python :: 3.12",
29-
"Programming Language :: Python :: 3.13",
30-
"Programming Language :: Python :: Implementation :: CPython",
31-
"Programming Language :: Python :: Implementation :: PyPy",
32-
"Topic :: Documentation",
33-
"Topic :: Documentation :: Sphinx",
34-
"Topic :: Software Development",
35-
"Topic :: Software Development :: Documentation",
36-
"Topic :: Software Development :: Libraries :: Python Modules",
37-
"Topic :: Utilities",
38-
]
39-
dynamic = [
40-
"version",
20+
"Development Status :: 5 - Production/Stable",
21+
"Environment :: Console",
22+
"Environment :: Web Environment",
23+
"Framework :: Sphinx",
24+
"Intended Audience :: Developers",
25+
"License :: OSI Approved :: MIT License",
26+
"Operating System :: OS Independent",
27+
"Programming Language :: Python",
28+
"Programming Language :: Python :: 3",
29+
"Programming Language :: Python :: 3 :: Only",
30+
"Programming Language :: Python :: 3.11",
31+
"Programming Language :: Python :: 3.12",
32+
"Programming Language :: Python :: 3.13",
33+
"Programming Language :: Python :: 3.14",
34+
"Programming Language :: Python :: Implementation :: CPython",
35+
"Programming Language :: Python :: Implementation :: PyPy",
36+
"Topic :: Documentation",
37+
"Topic :: Documentation :: Sphinx",
38+
"Topic :: Software Development",
39+
"Topic :: Software Development :: Documentation",
40+
"Topic :: Software Development :: Libraries :: Python Modules",
41+
"Topic :: Utilities",
4142
]
4243
dependencies = [
43-
"colorama>=0.4.6",
44-
"sphinx",
45-
"starlette>=0.35",
46-
"uvicorn>=0.25",
47-
"watchfiles>=0.20",
48-
"websockets>=11",
49-
]
50-
optional-dependencies.docs = [
44+
"colorama>=0.4.6",
45+
"Sphinx",
46+
"starlette>=0.35",
47+
"uvicorn>=0.25",
48+
"watchfiles>=0.20",
49+
"websockets>=11",
5150
]
52-
optional-dependencies.test = [
53-
"asgi-lifespan",
54-
"httpx",
55-
"httpx-ws",
56-
"pytest>=6",
51+
dynamic = ["version"]
52+
53+
[project.optional-dependencies]
54+
docs = []
55+
test = [
56+
"asgi-lifespan",
57+
"httpx",
58+
"httpx-ws",
59+
"pytest>=6",
5760
]
58-
urls.Changelog = "https://github.com/sphinx-doc/sphinx-autobuild/blob/main/NEWS.rst"
59-
urls.Documentation = "https://github.com/sphinx-doc/sphinx-autobuild#readme"
60-
urls.Download = "https://pypi.org/project/sphinx-autobuild/"
61-
urls."Issue tracker" = "https://github.com/sphinx-doc/sphinx-autobuild/issues"
62-
urls.Source = "https://github.com/sphinx-doc/sphinx-autobuild"
63-
scripts.sphinx-autobuild = "sphinx_autobuild.__main__:main"
61+
62+
[[project.authors]]
63+
name = "Adam Turner"
64+
65+
[[project.authors]]
66+
name = "Jonathan Stoppani"
67+
68+
69+
[project.scripts]
70+
sphinx-autobuild = "sphinx_autobuild.__main__:main"
6471

6572
[tool.flit.sdist]
6673
include = [
67-
"AUTHORS.rst",
68-
"LICENSE.rst",
69-
"NEWS.rst",
70-
# Tests
71-
"tests/",
72-
"noxfile.py",
74+
"AUTHORS.rst",
75+
"LICENSE.rst",
76+
"NEWS.rst",
77+
# Tests
78+
"tests/",
79+
"noxfile.py",
7380
]
74-
75-
[tool.pyproject-fmt]
76-
max_supported_python = "3.13"

sphinx_autobuild/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Rebuild Sphinx documentation on changes, with hot reloading in the browser."""
22

3-
__version__ = "2024.10.03"
3+
__version__ = "2025.08.25"

sphinx_autobuild/__main__.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@ def main(argv=()):
4949
url_host = f"{host_name}:{port_num}"
5050

5151
pre_build_commands = list(map(shlex.split, args.pre_build))
52-
52+
post_build_commands = list(map(shlex.split, args.post_build))
5353
builder = Builder(
5454
build_args,
5555
url_host=url_host,
5656
pre_build_commands=pre_build_commands,
57+
post_build_commands=post_build_commands,
5758
)
5859

5960
watch_dirs = [src_dir] + args.additional_watched_dirs
@@ -146,6 +147,10 @@ def _get_sphinx_build_parser():
146147
sphinx_build_parser.description = None
147148
sphinx_build_parser.epilog = None
148149
sphinx_build_parser.prog = "sphinx-autobuild"
150+
for action in sphinx_build_parser._actions:
151+
if hasattr(action, "help"):
152+
# Replace _TranslationProxy objects with strings
153+
action.help = str(action.help)
149154
for action in sphinx_build_parser._actions:
150155
if hasattr(action, "version"):
151156
# Fix the version
@@ -233,6 +238,13 @@ def _add_autobuild_arguments(parser):
233238
default=[],
234239
help="additional command(s) to run prior to building the documentation",
235240
)
241+
group.add_argument(
242+
"--post-build",
243+
action="append",
244+
metavar="COMMAND",
245+
default=[],
246+
help="additional command(s) to run after building the documentation",
247+
)
236248
return group
237249

238250

sphinx_autobuild/build.py

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515

1616

1717
class Builder:
18-
def __init__(self, sphinx_args, *, url_host, pre_build_commands):
18+
def __init__(
19+
self, sphinx_args, *, url_host, pre_build_commands, post_build_commands
20+
):
1921
self.sphinx_args = sphinx_args
2022
self.pre_build_commands = pre_build_commands
23+
self.post_build_commands = post_build_commands
2124
self.uri = f"http://{url_host}"
2225

2326
def __call__(self, *, changed_paths: Sequence[Path]):
@@ -35,24 +38,7 @@ def __call__(self, *, changed_paths: Sequence[Path]):
3538
show_message(f"Detected changes ({', '.join(rel_paths)})")
3639
show_message("Rebuilding...")
3740

38-
try:
39-
for command in self.pre_build_commands:
40-
show_message("pre-build")
41-
show_command(command)
42-
subprocess.run(command, check=True)
43-
except subprocess.CalledProcessError as e:
44-
print(f"Pre-build command exited with exit code: {e.returncode}")
45-
print(
46-
"Please fix the cause of the error above or press Ctrl+C to stop the "
47-
"server."
48-
)
49-
print(
50-
"The server will continue serving the build folder, but the contents "
51-
"being served are no longer in sync with the documentation sources. "
52-
"Please fix the cause of the error above or press Ctrl+C to stop the "
53-
"server."
54-
)
55-
traceback.print_exception(e)
41+
if self._run_commands(self.pre_build_commands, "pre-build") != 0:
5642
return
5743

5844
if sphinx.version_info[:3] >= (7, 2, 3):
@@ -70,5 +56,33 @@ def __call__(self, *, changed_paths: Sequence[Path]):
7056
"Please fix the cause of the error above or press Ctrl+C to stop the "
7157
"server."
7258
)
59+
else:
60+
# Run the post-build commands only if the build was successful
61+
self._run_commands(self.post_build_commands, "post-build")
62+
7363
# Remind the user of the server URL for convenience.
7464
show_message(f"Serving on {self.uri}")
65+
66+
def _run_commands(self, commands, log_context):
67+
try:
68+
for command in commands:
69+
show_message(log_context)
70+
show_command(command)
71+
subprocess.run(command, check=True)
72+
except subprocess.CalledProcessError as e:
73+
print(
74+
f"{log_context.title()} command exited with exit code: {e.returncode}"
75+
)
76+
print(
77+
"Please fix the cause of the error above or press Ctrl+C to stop the "
78+
"server."
79+
)
80+
print(
81+
"The server will continue serving the build folder, but the contents "
82+
"being served are no longer in sync with the documentation sources. "
83+
"Please fix the cause of the error above or press Ctrl+C to stop the "
84+
"server."
85+
)
86+
traceback.print_exception(e)
87+
return e.returncode
88+
return 0

0 commit comments

Comments
 (0)