mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #7985 from tk0miya/5208_linkcheck_for_localfiles
Close #5208: linkcheck: Support checks for local links
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -27,6 +27,7 @@ Features added
|
|||||||
* #7902: html theme: Add a new option :confval:`globaltoc_maxdepth` to control
|
* #7902: html theme: Add a new option :confval:`globaltoc_maxdepth` to control
|
||||||
the behavior of globaltoc in sidebar
|
the behavior of globaltoc in sidebar
|
||||||
* #7840: i18n: Optimize the dependencies check on bootstrap
|
* #7840: i18n: Optimize the dependencies check on bootstrap
|
||||||
|
* #5208: linkcheck: Support checks for local links
|
||||||
* #7052: add ``:noindexentry:`` to the Python, C, C++, and Javascript domains.
|
* #7052: add ``:noindexentry:`` to the Python, C, C++, and Javascript domains.
|
||||||
Update the documentation to better reflect the relationship between this option
|
Update the documentation to better reflect the relationship between this option
|
||||||
and the ``:noindex:`` option.
|
and the ``:noindex:`` option.
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ from sphinx.util.requests import is_ssl_error
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
uri_re = re.compile('[a-z]+://')
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_REQUEST_HEADERS = {
|
DEFAULT_REQUEST_HEADERS = {
|
||||||
'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8',
|
'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8',
|
||||||
@@ -210,10 +212,21 @@ class CheckExternalLinksBuilder(Builder):
|
|||||||
|
|
||||||
def check() -> Tuple[str, str, int]:
|
def check() -> Tuple[str, str, int]:
|
||||||
# check for various conditions without bothering the network
|
# check for various conditions without bothering the network
|
||||||
if len(uri) == 0 or uri.startswith(('#', 'mailto:', 'ftp:')):
|
if len(uri) == 0 or uri.startswith(('#', 'mailto:')):
|
||||||
return 'unchecked', '', 0
|
return 'unchecked', '', 0
|
||||||
elif not uri.startswith(('http:', 'https:')):
|
elif not uri.startswith(('http:', 'https:')):
|
||||||
return 'local', '', 0
|
if uri_re.match(uri):
|
||||||
|
# non supported URI schemes (ex. ftp)
|
||||||
|
return 'unchecked', '', 0
|
||||||
|
else:
|
||||||
|
if path.exists(path.join(self.srcdir, uri)):
|
||||||
|
return 'working', '', 0
|
||||||
|
else:
|
||||||
|
for rex in self.to_ignore:
|
||||||
|
if rex.match(uri):
|
||||||
|
return 'ignored', '', 0
|
||||||
|
else:
|
||||||
|
return 'broken', '', 0
|
||||||
elif uri in self.good:
|
elif uri in self.good:
|
||||||
return 'working', 'old', 0
|
return 'working', 'old', 0
|
||||||
elif uri in self.broken:
|
elif uri in self.broken:
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ Some additional anchors to exercise ignore code
|
|||||||
* `Example Bar invalid <https://www.google.com/#top>`_
|
* `Example Bar invalid <https://www.google.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>`_
|
||||||
|
* `Example valid local file <conf.py>`_
|
||||||
|
* `Example invalid local file <path/to/notfound>`_
|
||||||
|
|
||||||
.. image:: https://www.google.com/image.png
|
.. image:: https://www.google.com/image.png
|
||||||
.. figure:: https://www.google.com/image2.png
|
.. figure:: https://www.google.com/image2.png
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ def test_defaults(app, status, warning):
|
|||||||
# images should fail
|
# images should fail
|
||||||
assert "Not Found for url: https://www.google.com/image.png" in content
|
assert "Not Found for url: https://www.google.com/image.png" in content
|
||||||
assert "Not Found for url: https://www.google.com/image2.png" in content
|
assert "Not Found for url: https://www.google.com/image2.png" in content
|
||||||
assert len(content.splitlines()) == 5
|
# looking for local file should fail
|
||||||
|
assert "[broken] path/to/notfound" in content
|
||||||
|
assert len(content.splitlines()) == 6
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('linkcheck', testroot='linkcheck', freshenv=True)
|
@pytest.mark.sphinx('linkcheck', testroot='linkcheck', freshenv=True)
|
||||||
@@ -47,8 +49,8 @@ def test_defaults_json(app, status, warning):
|
|||||||
"info"]:
|
"info"]:
|
||||||
assert attr in row
|
assert attr in row
|
||||||
|
|
||||||
assert len(content.splitlines()) == 8
|
assert len(content.splitlines()) == 10
|
||||||
assert len(rows) == 8
|
assert len(rows) == 10
|
||||||
# the output order of the rows is not stable
|
# the output order of the rows is not stable
|
||||||
# due to possible variance in network latency
|
# due to possible variance in network latency
|
||||||
rowsby = {row["uri"]:row for row in rows}
|
rowsby = {row["uri"]:row for row in rows}
|
||||||
@@ -69,7 +71,7 @@ def test_defaults_json(app, status, warning):
|
|||||||
assert dnerow['uri'] == 'https://localhost:7777/doesnotexist'
|
assert dnerow['uri'] == 'https://localhost:7777/doesnotexist'
|
||||||
assert rowsby['https://www.google.com/image2.png'] == {
|
assert rowsby['https://www.google.com/image2.png'] == {
|
||||||
'filename': 'links.txt',
|
'filename': 'links.txt',
|
||||||
'lineno': 16,
|
'lineno': 18,
|
||||||
'status': 'broken',
|
'status': 'broken',
|
||||||
'code': 0,
|
'code': 0,
|
||||||
'uri': 'https://www.google.com/image2.png',
|
'uri': 'https://www.google.com/image2.png',
|
||||||
@@ -92,7 +94,8 @@ def test_defaults_json(app, status, warning):
|
|||||||
'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#',
|
||||||
'https://www.google.com/image.png',
|
'https://www.google.com/image.png',
|
||||||
'https://www.google.com/image2.png']
|
'https://www.google.com/image2.png',
|
||||||
|
'path/to/notfound']
|
||||||
})
|
})
|
||||||
def test_anchors_ignored(app, status, warning):
|
def test_anchors_ignored(app, status, warning):
|
||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
|||||||
Reference in New Issue
Block a user