From 532ad0306e0ec540f7fd206328c27c2e6aa30dd9 Mon Sep 17 00:00:00 2001 From: James Addison <55152140+jayaddison@users.noreply.github.com> Date: Fri, 12 Apr 2024 23:18:22 +0100 Subject: [PATCH] linkcheck: Make the new 'timeout' status opt-in (#12023) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- CHANGES.rst | 2 ++ doc/usage/configuration.rst | 15 +++++++++++++++ sphinx/builders/linkcheck.py | 17 ++++++++++++++++- tests/test_builders/test_build_linkcheck.py | 9 +++++++-- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index d791357ea..14ab7dc5b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -108,6 +108,8 @@ Bugs fixed responses as broken. Patch by James Addison. * #11868: linkcheck: added a distinct ``timeout`` reporting status code. + This can be enabled by setting :confval:`linkcheck_report_timeouts_as_broken` + to ``False``. Patch by James Addison. * #11869: Refresh the documentation for the ``linkcheck_timeout`` setting. Patch by James Addison. diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index 3cee32b2d..32dfecc72 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -2971,6 +2971,21 @@ Options for the linkcheck builder .. versionadded:: 7.3 +.. confval:: linkcheck_report_timeouts_as_broken + + When an HTTP response is not received from a webserver before the configured + :confval:`linkcheck_timeout` expires, + the current default behaviour of Sphinx is to treat the link as 'broken'. + To report timeouts using a distinct report code of ``timeout``, + set :confval:`linkcheck_report_timeouts_as_broken` to ``False``. + + From Sphinx 8.0 onwards, timeouts that occur while checking hyperlinks + will be reported using the new 'timeout' status code. + + .. xref RemovedInSphinx80Warning + + .. versionadded:: 7.3 + Options for the XML builder --------------------------- diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index 3cec33fe3..9178458b1 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -75,6 +75,16 @@ class CheckExternalLinksBuilder(DummyBuilder): ) warnings.warn(deprecation_msg, RemovedInSphinx80Warning, stacklevel=1) + if self.config.linkcheck_report_timeouts_as_broken: + deprecation_msg = ( + "The default value for 'linkcheck_report_timeouts_as_broken' will change " + 'to False in Sphinx 8, meaning that request timeouts ' + "will be reported with a new 'timeout' status, instead of as 'broken'. " + 'This is intended to provide more detail as to the failure mode. ' + 'See https://github.com/sphinx-doc/sphinx/issues/11868 for details.' + ) + warnings.warn(deprecation_msg, RemovedInSphinx80Warning, stacklevel=1) + def finish(self) -> None: checker = HyperlinkAvailabilityChecker(self.config) logger.info('') @@ -302,6 +312,10 @@ class HyperlinkAvailabilityCheckWorker(Thread): self.retries: int = config.linkcheck_retries self.rate_limit_timeout = config.linkcheck_rate_limit_timeout self._allow_unauthorized = config.linkcheck_allow_unauthorized + if config.linkcheck_report_timeouts_as_broken: + self._timeout_status = 'broken' + else: + self._timeout_status = 'timeout' self.user_agent = config.user_agent self.tls_verify = config.tls_verify @@ -444,7 +458,7 @@ class HyperlinkAvailabilityCheckWorker(Thread): break except RequestTimeout as err: - return 'timeout', str(err), 0 + return self._timeout_status, str(err), 0 except SSLError as err: # SSL failure; report that the link is broken. @@ -669,6 +683,7 @@ def setup(app: Sphinx) -> ExtensionMetadata: app.add_config_value('linkcheck_anchors_ignore_for_url', (), '', (tuple, list)) app.add_config_value('linkcheck_rate_limit_timeout', 300.0, '') app.add_config_value('linkcheck_allow_unauthorized', True, '') + app.add_config_value('linkcheck_report_timeouts_as_broken', True, '', bool) app.add_event('linkcheck-process-uri') diff --git a/tests/test_builders/test_build_linkcheck.py b/tests/test_builders/test_build_linkcheck.py index f986caa23..c8d8515af 100644 --- a/tests/test_builders/test_build_linkcheck.py +++ b/tests/test_builders/test_build_linkcheck.py @@ -856,7 +856,13 @@ def test_too_many_requests_retry_after_without_header(app, capsys): ) -@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver', freshenv=True) +@pytest.mark.sphinx( + 'linkcheck', testroot='linkcheck-localserver', freshenv=True, + confoverrides={ + 'linkcheck_report_timeouts_as_broken': False, + 'linkcheck_timeout': 0.01, + } +) def test_requests_timeout(app): class DelayedResponseHandler(BaseHTTPRequestHandler): protocol_version = "HTTP/1.1" @@ -867,7 +873,6 @@ def test_requests_timeout(app): self.send_header("Content-Length", "0") self.end_headers() - app.config.linkcheck_timeout = 0.01 with serve_application(app, DelayedResponseHandler): app.build()