From b2cdd6f3d53b1430a8540989202c72427bce5a7c Mon Sep 17 00:00:00 2001 From: AC Date: Thu, 15 Oct 2026 13:02:59 +0800 Subject: [PATCH] Register the routing table label before parallel reading --- CHANGELOG.rst | 2 ++ src/sphinxcontrib/httpdomain/__init__.py | 10 +++--- tests/routingtable_test.py | 46 ++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 tests/routingtable_test.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9fcbfde..8478b57 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -18,6 +18,8 @@ Major changes Minor changes ............. +- Fixed references to the HTTP routing table on clean parallel builds. [:issue:`58`] + Version 2.2.1 ````````````` diff --git a/src/sphinxcontrib/httpdomain/__init__.py b/src/sphinxcontrib/httpdomain/__init__.py index da0f5c9..4e8c41e 100644 --- a/src/sphinxcontrib/httpdomain/__init__.py +++ b/src/sphinxcontrib/httpdomain/__init__.py @@ -800,17 +800,19 @@ def content_callback(self, match): } -def register_routingtable_as_label(app, document): - labels = app.env.domaindata['std']['labels'] +def register_routingtable_as_label(app, env, docnames): + # Register in the main environment: parallel readers only merge labels + # belonging to source documents, not generated index pages. + labels = env.domaindata['std']['labels'] labels['routingtable'] = 'http-routingtable', '', _('HTTP Routing Table') - anonlabels = app.env.domaindata['std']['anonlabels'] + anonlabels = env.domaindata['std']['anonlabels'] anonlabels['routingtable'] = 'http-routingtable', '' def setup(app): app.add_domain(HTTPDomain) app.add_domain(WebSocketDomain) - app.connect('doctree-read', register_routingtable_as_label) + app.connect('env-before-read-docs', register_routingtable_as_label) package_dir = os.path.abspath(os.path.dirname(__file__)) locale_dir = os.path.join(package_dir, 'locale') diff --git a/tests/routingtable_test.py b/tests/routingtable_test.py new file mode 100644 index 0000000..b2404e6 --- /dev/null +++ b/tests/routingtable_test.py @@ -0,0 +1,46 @@ +import pytest + +from websocket_test import build, inventory_uri, load_inventory, write_project + + +@pytest.mark.parametrize('jobs', [1, 2]) +def test_routingtable_reference_on_clean_and_incremental_build(tmp_path, jobs): + sources = { + 'index.rst': ''' + API + === + + .. toctree:: + + routes + references + ''', + 'routes.rst': ''' + Routes + ====== + + .. http:get:: /health + ''', + 'references.rst': ''' + References + ========== + + :ref:`routingtable` + + :ref:`All routes ` + ''', + } + source = write_project(tmp_path, sources) + for stage in ('clean', 'incremental', 'unchanged'): + if stage == 'incremental': + with (source / 'references.rst').open('a', encoding='utf-8') as page: + page.write('\nUpdated reference: :ref:`routingtable`\n') + result, output = build(source, tmp_path, jobs=jobs) + assert result.returncode == 0, result.stdout + result.stderr + page = (output / 'references.html').read_text(encoding='utf-8') + assert 'href="http-routingtable.html"' in page + assert 'HTTP Routing Table' in page + assert 'All routes' in page + assert (output / 'http-routingtable.html').exists() + inventory = load_inventory(output) + assert inventory_uri(inventory['std:label']['routingtable']) == 'http-routingtable.html'