-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: add new builder that checks if hardcoded URLs can be replaced with crossrefs #9626
base: master
Are you sure you want to change the base?
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>
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 😎 |
@@ -1063,6 +1063,8 @@ Features added | |||
* #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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be moved to the latest version now!
@@ -116,8 +116,8 @@ | |||
|
|||
intersphinx_mapping = { | |||
'python': ('https://docs.python.org/3/', None), | |||
'requests': ('https://requests.readthedocs.io/en/latest/', None), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's minimize the changes (unless there is a reason to change this)
@@ -25,7 +25,7 @@ | |||
import sys | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert not list(...)
load_mappings(app) | ||
|
||
uri = 'https://example.com/foo.html#module-module1' | ||
replacement = next(find_replacements(app, uri), None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert not list(...)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
crossrefcheck
that 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,
crossrefcheck
will 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.org
should be checked as well in the docs for thepytest
project, 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
Sphinx
repository