Proposal: add new builder that checks if hardcoded URLs can be replaced with crossrefs#9626
Proposal: add new builder that checks if hardcoded URLs can be replaced with crossrefs#9626hoefling wants to merge 23 commits intosphinx-doc:masterfrom
Conversation
|
The original proposal was made in pytest-dev/pytest#9082, where it was suggested to add the builder to Sphinx instead, so it can be reused in multiple projects. Please note that this PR isn't ready to be merged yet (e.g. missing tests and proper documentation). Its purpose is merely to propose the builder first and check whether @tk0miya would approve the general idea. |
|
Agreed. This must be worthy. So +1 for merging this into the core. But I'm not sure this should be added as a standalone builder or an additional feature of linkcheck builder. Is there any reason to make this standalone? |
|
This is pretty cool. Implementation-wise I'm wondering if it is possible to have a bit more indirection such that this doesn't access the intersphinx inventory directly, but asks the intersphinx extension to lookup an URL and return the necessary information. |
I would prefer a standalone |
|
Since the changes are added to Sphinx itself, the builder might not be necessary at all, depending on how deeply those warnings should be integrated. E.g. I could add a |
58ae250 to
241a390
Compare
|
That would be fantastic for all my use-cases! |
|
follow-up idea - for linkcheck identify links that are in locations where a intersphinx ref could be used or added (for links to other docs that use sphinx but are not declared as intersphinx |
4ee525c to
602f1d0
Compare
|
@tk0miya gentle ping for a review. |
4273745 to
e03424f
Compare
4026ad1 to
f2f07a3
Compare
f13bbb9 to
6dead54
Compare
|
@tk0miya gentle ping. Maybe it's still not too late for this to become part of 4.4? |
aeafef9 to
48f8b2b
Compare
48f8b2b to
327f381
Compare
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
…e in docstring Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: Oleg Hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
9423340 to
2d50d64
Compare
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
Signed-off-by: oleg.hoefling <oleg.hoefling@gmail.com>
|
@AA-Turner done 😎 |
| * #9075: autodoc: Add a config variable :confval:`autodoc_typehints_format` | ||
| to suppress the leading module names of typehints of function signatures (ex. | ||
| ``io.StringIO`` -> ``StringIO``) | ||
| * #9626: intersphinx: Emit warning if a hardcoded link is replaceable |
There was a problem hiding this comment.
This should be moved to the latest version now!
doc/conf.py
Outdated
|
|
||
| intersphinx_mapping = { | ||
| 'python': ('https://docs.python.org/3/', None), | ||
| 'requests': ('https://requests.readthedocs.io/en/latest/', None), |
There was a problem hiding this comment.
Let's minimize the changes (unless there is a reason to change this)
| import time | ||
| from os import path | ||
| from typing import TYPE_CHECKING, cast | ||
| from typing import IO, TYPE_CHECKING, Any, cast |
There was a problem hiding this comment.
Where do you need IO and Any as runtime types?
| # Project: foo | ||
| # Version: 2.0 | ||
| # The remainder of this file is compressed with zlib. | ||
| ''' + zlib.compress(b'') |
There was a problem hiding this comment.
Hardcode the value of zlib.compress(..) and put a comment.
Other suggestion: make these constants private or create a class testing find_replacements so that the logic is "contained" (with a class-based approach you could put the setup of your test in a method).
| normalize_intersphinx_mapping(app, app.config) | ||
| load_mappings(app) | ||
|
|
||
| assert next(find_replacements(app, 'https://example.com'), None) is None |
| load_mappings(app) | ||
|
|
||
| uri = 'https://example.com/foo.html#module-module1' | ||
| replacement = next(find_replacements(app, uri), None) |
| load_mappings(app) | ||
|
|
||
| uri = 'https://docs.python.org/foo.html#module-module1' | ||
| replacement = next(find_replacements(app, uri)) |
There was a problem hiding this comment.
replacements = list(...)
assert len(replacements) == ...
assert replacements[0] == ...
...or
assert list(...) == [...]
Subject: (copied from pytest-dev/pytest#9082)
This PR adds a new no-op Sphinx builder named
crossrefcheckthat checks whether a hardcoded URL in the text can be replaced with a crossreference from one of the inventories configured inintersphinx_mapping.Feature or Bugfix
Purpose
If a hardcoded link can be replaced with a crossref,
crossrefcheckwill emit a warning like this:If a replacement suggestion is printed, the hardcoded URL can be safely replaced with that suggestion.
Usage
Caveats
The builder is not able to catch the URLs for the internal docs. This is because no information is known about the URL the docs will be hosted at. Thus, if e.g. links to
https://docs.pytest.orgshould be checked as well in the docs for thepytestproject, it is best to extendintersphinx_mapping. Example:If a URL is reported without a suggestion, it usually indicates that either:
Example output from running over
Sphinxrepository