Skip to content

Commit

Permalink
Merge pull request #8579 from francoisfreitag/fix-queue
Browse files Browse the repository at this point in the history
Ensure linkcheck items are comparable
  • Loading branch information
tk0miya authored Dec 23, 2020
2 parents 955d655 + a1b8b1f commit 46eaa5d
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Bugs fixed
annotations
* #8568: autodoc: TypeError is raised on checking slots attribute
* #8567: autodoc: Instance attributes are incorrectly added to Parent class
* #8565: linkcheck: Fix PriorityQueue crash when link tuples are not
comparable

Testing
--------
Expand Down
14 changes: 11 additions & 3 deletions sphinx/builders/linkcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from urllib.parse import unquote, urlparse

from docutils import nodes
from docutils.nodes import Node
from docutils.nodes import Element, Node
from requests import Response
from requests.exceptions import HTTPError, TooManyRedirects

Expand All @@ -47,6 +47,14 @@
DEFAULT_DELAY = 60.0


def node_line_or_0(node: Element) -> int:
"""
PriorityQueue items must be comparable. The line number is part of the
tuple used by the PriorityQueue, keep an homogeneous type for comparison.
"""
return get_node_line(node) or 0


class AnchorCheckParser(HTMLParser):
"""Specialized HTML parser that looks for a specific anchor."""

Expand Down Expand Up @@ -406,7 +414,7 @@ def write_doc(self, docname: str, doctree: Node) -> None:
if 'refuri' not in refnode:
continue
uri = refnode['refuri']
lineno = get_node_line(refnode)
lineno = node_line_or_0(refnode)
uri_info = (CHECK_IMMEDIATELY, uri, docname, lineno)
self.wqueue.put(uri_info, False)
n += 1
Expand All @@ -415,7 +423,7 @@ def write_doc(self, docname: str, doctree: Node) -> None:
for imgnode in doctree.traverse(nodes.image):
uri = imgnode['candidates'].get('?')
if uri and '://' in uri:
lineno = get_node_line(imgnode)
lineno = node_line_or_0(imgnode)
uri_info = (CHECK_IMMEDIATELY, uri, docname, lineno)
self.wqueue.put(uri_info, False)
n += 1
Expand Down
1 change: 1 addition & 0 deletions tests/roots/test-linkcheck-localserver-two-links/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exclude_patterns = ['_build']
6 changes: 6 additions & 0 deletions tests/roots/test-linkcheck-localserver-two-links/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. image:: http://localhost:7777/
:target: http://localhost:7777/

`weblate.org`_

.. _weblate.org: http://localhost:7777/
37 changes: 37 additions & 0 deletions tests/test_build_linkcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,3 +573,40 @@ def test_limit_rate_bails_out_after_waiting_max_time(app):
checker.rate_limits = {"localhost": RateLimit(90.0, 0.0)}
next_check = checker.limit_rate(FakeResponse())
assert next_check is None


@pytest.mark.sphinx(
'linkcheck', testroot='linkcheck-localserver-two-links', freshenv=True,
)
def test_priorityqueue_items_are_comparable(app):
with http_server(OKHandler):
app.builder.build_all()
content = (app.outdir / 'output.json').read_text()
rows = [json.loads(x) for x in sorted(content.splitlines())]
assert rows == [
{
'filename': 'index.rst',
# Should not be None.
'lineno': 0,
'status': 'working',
'code': 0,
'uri': 'http://localhost:7777/',
'info': '',
},
{
'filename': 'index.rst',
'lineno': 0,
'status': 'working',
'code': 0,
'uri': 'http://localhost:7777/',
'info': '',
},
{
'filename': 'index.rst',
'lineno': 4,
'status': 'working',
'code': 0,
'uri': 'http://localhost:7777/',
'info': '',
}
]

0 comments on commit 46eaa5d

Please sign in to comment.