mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #6022 from tk0miya/5196_linkcheck_should_check_remote_image
Close #5196: linkcheck also checks remote images exist
This commit is contained in:
commit
8812131a57
1
CHANGES
1
CHANGES
@ -177,6 +177,7 @@ Features added
|
|||||||
* #6016: HTML search: A placeholder for the search summary prevents search
|
* #6016: HTML search: A placeholder for the search summary prevents search
|
||||||
result links from changing their position when the search terminates. This
|
result links from changing their position when the search terminates. This
|
||||||
makes navigating search results easier.
|
makes navigating search results easier.
|
||||||
|
* #5196: linkcheck also checks remote images exist
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
@ -25,7 +25,7 @@ from sphinx.util import encode_uri, requests, logging
|
|||||||
from sphinx.util.console import ( # type: ignore
|
from sphinx.util.console import ( # type: ignore
|
||||||
purple, red, darkgreen, darkgray, darkred, turquoise
|
purple, red, darkgreen, darkgray, darkred, turquoise
|
||||||
)
|
)
|
||||||
from sphinx.util.nodes import traverse_parent
|
from sphinx.util.nodes import get_node_line
|
||||||
from sphinx.util.requests import is_ssl_error
|
from sphinx.util.requests import is_ssl_error
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@ -271,17 +271,24 @@ class CheckExternalLinksBuilder(Builder):
|
|||||||
# type: (str, nodes.Node) -> None
|
# type: (str, nodes.Node) -> None
|
||||||
logger.info('')
|
logger.info('')
|
||||||
n = 0
|
n = 0
|
||||||
for node in doctree.traverse(nodes.reference):
|
|
||||||
if 'refuri' not in node:
|
# reference nodes
|
||||||
|
for refnode in doctree.traverse(nodes.reference):
|
||||||
|
if 'refuri' not in refnode:
|
||||||
continue
|
continue
|
||||||
uri = node['refuri']
|
uri = refnode['refuri']
|
||||||
lineno = None
|
lineno = get_node_line(refnode)
|
||||||
for parent in traverse_parent(node):
|
|
||||||
if parent.line:
|
|
||||||
lineno = parent.line
|
|
||||||
break
|
|
||||||
self.wqueue.put((uri, docname, lineno), False)
|
self.wqueue.put((uri, docname, lineno), False)
|
||||||
n += 1
|
n += 1
|
||||||
|
|
||||||
|
# image nodes
|
||||||
|
for imgnode in doctree.traverse(nodes.image):
|
||||||
|
uri = imgnode['candidates'].get('?')
|
||||||
|
if uri and '://' in uri:
|
||||||
|
lineno = get_node_line(imgnode)
|
||||||
|
self.wqueue.put((uri, docname, lineno), False)
|
||||||
|
n += 1
|
||||||
|
|
||||||
done = 0
|
done = 0
|
||||||
while done < n:
|
while done < n:
|
||||||
self.process_result(self.rqueue.get())
|
self.process_result(self.rqueue.get())
|
||||||
|
@ -285,6 +285,14 @@ def find_source_node(node):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_node_line(node):
|
||||||
|
# type: (nodes.Element) -> int
|
||||||
|
for pnode in traverse_parent(node):
|
||||||
|
if pnode.line:
|
||||||
|
return pnode.line
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def traverse_parent(node, cls=None):
|
def traverse_parent(node, cls=None):
|
||||||
# type: (nodes.Element, Any) -> Iterable[nodes.Element]
|
# type: (nodes.Element, Any) -> Iterable[nodes.Element]
|
||||||
while node:
|
while node:
|
||||||
|
@ -11,3 +11,6 @@ Some additional anchors to exercise ignore code
|
|||||||
* `Example Bar invalid <http://example.com/#top>`_
|
* `Example Bar invalid <http://example.com/#top>`_
|
||||||
* `Example anchor invalid <http://www.sphinx-doc.org/en/1.7/intro.html#does-not-exist>`_
|
* `Example anchor invalid <http://www.sphinx-doc.org/en/1.7/intro.html#does-not-exist>`_
|
||||||
* `Complete nonsense <https://localhost:7777/doesnotexist>`_
|
* `Complete nonsense <https://localhost:7777/doesnotexist>`_
|
||||||
|
|
||||||
|
.. image:: http://example.com/image.png
|
||||||
|
.. figure:: http://example.com/image2.png
|
||||||
|
@ -24,7 +24,10 @@ def test_defaults(app, status, warning):
|
|||||||
assert "Anchor 'does-not-exist' not found" in content
|
assert "Anchor 'does-not-exist' not found" in content
|
||||||
# looking for non-existent URL should fail
|
# looking for non-existent URL should fail
|
||||||
assert " Max retries exceeded with url: /doesnotexist" in content
|
assert " Max retries exceeded with url: /doesnotexist" in content
|
||||||
assert len(content.splitlines()) == 3
|
# images should fail
|
||||||
|
assert "Not Found for url: http://example.com/image.png" in content
|
||||||
|
assert "Not Found for url: http://example.com/image2.png" in content
|
||||||
|
assert len(content.splitlines()) == 5
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx(
|
@pytest.mark.sphinx(
|
||||||
@ -32,7 +35,9 @@ def test_defaults(app, status, warning):
|
|||||||
confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"],
|
confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"],
|
||||||
'linkcheck_ignore': [
|
'linkcheck_ignore': [
|
||||||
'https://localhost:7777/doesnotexist',
|
'https://localhost:7777/doesnotexist',
|
||||||
'http://www.sphinx-doc.org/en/1.7/intro.html#']
|
'http://www.sphinx-doc.org/en/1.7/intro.html#',
|
||||||
|
'http://example.com/image.png',
|
||||||
|
'http://example.com/image2.png']
|
||||||
})
|
})
|
||||||
def test_anchors_ignored(app, status, warning):
|
def test_anchors_ignored(app, status, warning):
|
||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
Loading…
Reference in New Issue
Block a user