Skip to content

Commit

Permalink
Fix #8268: make linkcheck report HTTP errors
Browse files Browse the repository at this point in the history
  • Loading branch information
francoisfreitag committed Oct 3, 2020
1 parent 9175da4 commit 822ca17
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 2 deletions.
5 changes: 3 additions & 2 deletions CHANGES
Expand Up @@ -41,6 +41,7 @@ Bugs fixed
* #8093: The highlight warning has wrong location in some builders (LaTeX,
singlehtml and so on)
* #8239: Failed to refer a token in productionlist if it is indented
* #8268: linkcheck: Report HTTP errors when ``linkcheck_anchors`` is ``True``

Testing
--------
Expand Down Expand Up @@ -171,7 +172,7 @@ Bugs fixed
contains a hyperlink target
* #7469: autosummary: "Module attributes" header is not translatable
* #7940: apidoc: An extra newline is generated at the end of the rst file if a
module has submodules
module has submodules
* #4258: napoleon: decorated special methods are not shown
* #7799: napoleon: parameters are not escaped for combined params in numpydoc
* #7780: napoleon: multiple paramaters declaration in numpydoc was wrongly
Expand Down Expand Up @@ -338,7 +339,7 @@ Features added
* #7543: html theme: Add top and bottom margins to tables
* #7695: html theme: Add viewport meta tag for basic theme
* #7721: html theme: classic: default codetextcolor/codebgcolor doesn't override
Pygments
Pygments
* C and C++: allow semicolon in the end of declarations.
* C++, parse parameterized noexcept specifiers.
* #7294: C++, parse expressions with user-defined literals.
Expand Down
1 change: 1 addition & 0 deletions sphinx/builders/linkcheck.py
Expand Up @@ -166,6 +166,7 @@ def check_uri() -> Tuple[str, str, int]:
# Read the whole document and see if #anchor exists
response = requests.get(req_url, stream=True, config=self.app.config,
auth=auth_info, **kwargs)
response.raise_for_status()
found = check_anchor(response, unquote(anchor))

if not found:
Expand Down
2 changes: 2 additions & 0 deletions tests/roots/test-linkcheck-localserver/conf.py
@@ -0,0 +1,2 @@
exclude_patterns = ['_build']
linkcheck_anchors = True
1 change: 1 addition & 0 deletions tests/roots/test-linkcheck-localserver/index.rst
@@ -0,0 +1 @@
`local server <http://localhost:7777/#anchor>`_
36 changes: 36 additions & 0 deletions tests/test_build_linkcheck.py
Expand Up @@ -8,8 +8,10 @@
:license: BSD, see LICENSE for details.
"""

import http.server
import json
import re
import threading
from unittest import mock
import pytest

Expand Down Expand Up @@ -106,6 +108,21 @@ def test_anchors_ignored(app, status, warning):
# expect all ok when excluding #top
assert not content

@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver', freshenv=True)
def test_raises_for_invalid_status(app, status, warning):
server_thread = HttpServerThread(InternalServerErrorHandler, daemon=True)
server_thread.start()
try:
app.builder.build_all()
finally:
server_thread.terminate()
content = (app.outdir / 'output.txt').read_text()
assert content == (
"index.rst:1: [broken] http://localhost:7777/#anchor: "
"500 Server Error: Internal Server Error "
"for url: http://localhost:7777/\n"
)


@pytest.mark.sphinx(
'linkcheck', testroot='linkcheck', freshenv=True,
Expand Down Expand Up @@ -160,3 +177,22 @@ def test_linkcheck_request_headers(app, status, warning):
assert headers["X-Secret"] == "open sesami"
else:
assert headers["Accept"] == "text/html,application/xhtml+xml;q=0.9,*/*;q=0.8"


class HttpServerThread(threading.Thread):
def __init__(self, handler, *args, **kwargs):
super().__init__(*args, **kwargs)
self.server = http.server.HTTPServer(("localhost", 7777), handler)

def run(self):
self.server.serve_forever(poll_interval=0.01)

def terminate(self):
self.server.shutdown()
self.server.server_close()
self.join()


class InternalServerErrorHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
self.send_error(500, "Internal Server Error")

0 comments on commit 822ca17

Please sign in to comment.