Skip to content

Commit eb46343

Browse files
authored
Merge pull request #19580 from meeseeksmachine/auto-backport-of-pr-19456-on-v3.4.x
Backport PR #19456 on branch v3.4.x (Doc implement reredirects)
2 parents a89d28b + 3bcb006 commit eb46343

File tree

7 files changed

+135
-0
lines changed

7 files changed

+135
-0
lines changed

doc/api/backend_gtk3_api.rst

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
**NOTE** These backends are not documented here, to avoid adding a dependency
22
to building the docs.
33

4+
.. redirect-from:: /api/backend_gtk3agg_api
5+
.. redirect-from:: /api/backend_gtk3cairo_api
6+
7+
48
:mod:`matplotlib.backends.backend_gtk3agg`
59
==========================================
610

doc/api/backend_qt_api.rst

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
**NOTE** These backends are not documented here, to avoid adding a dependency
22
to building the docs.
33

4+
.. redirect-from:: /api/backend_qt4agg_api
5+
.. redirect-from:: /api/backend_qt4cairo_api
6+
.. redirect-from:: /api/backend_qt5agg_api
7+
.. redirect-from:: /api/backend_qt5cairo_api
8+
49
:mod:`matplotlib.backends.backend_qt4agg`
510
=========================================
611

doc/api/backend_wx_api.rst

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
**NOTE** These backends are not documented here, to avoid adding a dependency
22
to building the docs.
33

4+
.. redirect-from:: /api/backend_wxagg_api
5+
46
:mod:`matplotlib.backends.backend_wxagg`
57
========================================
68

doc/conf.py

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
'sphinxext.missing_references',
6464
'sphinxext.mock_gui_toolkits',
6565
'sphinxext.skip_deprecated',
66+
'sphinxext.redirect_from',
6667
'sphinx_copybutton',
6768
]
6869

doc/devel/documenting_mpl.rst

+34
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,40 @@ should ideally be named similar to :file:`imshow_mynewexample.py`.
889889
Miscellaneous
890890
=============
891891

892+
Moving documentation
893+
--------------------
894+
895+
Sometimes it is desirable to move or consolidate documentation. With no
896+
action this will lead to links either going dead (404) or pointing to old
897+
versions of the documentation. Preferable is to replace the old page
898+
with an html refresh that immediately redirects the viewer to the new
899+
page. So, for example we move ``/doc/topic/old_info.rst`` to
900+
``/doc/topic/new_info.rst``. We remove ``/doc/topic/old_info.rst`` and
901+
in ``/doc/topic/new_info.rst`` we insert a ``redirect-from`` directive that
902+
tells sphinx to still make the old file with the html refresh/redirect in it
903+
(probably near the top of the file to make it noticeable)
904+
905+
.. code-block:: rst
906+
907+
.. redirect-from:: /topic/old_info
908+
909+
In the built docs this will yield an html file
910+
``/build/html/topic/old_info.html`` that has a refresh to ``new_info.html``.
911+
If the two files are in different subdirectories:
912+
913+
.. code-block:: rst
914+
915+
.. redirect-from:: /old_topic/old_info2
916+
917+
will yield an html file ``/build/html/old_topic/old_info2.html`` that has a
918+
(relative) refresh to ``../topic/new_info.html``.
919+
920+
Use the full path for this directive, relative to the doc root at
921+
``http://matplotlib.org/stable/``. So ``/old_topic/old_info2`` would be
922+
found by users at ``http://matplotlib.org/stable/old_topic/old_info2``.
923+
For clarity, do not use relative links.
924+
925+
892926
Adding animations
893927
-----------------
894928

doc/sphinxext/redirect_from.py

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"""
2+
Redirecting old docs to new location
3+
====================================
4+
5+
If an rst file is moved or its content subsumed in a different file, it
6+
is desireable to redirect the old file to the new or existing file. This
7+
extension enables this with a simple html refresh.
8+
9+
For example suppose ``doc/topic/old-page.rst`` is removed and its content
10+
included in ``doc/topic/new-page.rst``. We use the ``redirect-from``
11+
directive in ``doc/topic/new-page.rst``::
12+
13+
.. redirect-from:: /topic/old-page
14+
15+
This creates in the build directory a file ``build/html/topic/old-page.html``
16+
that contains a relative refresh::
17+
18+
<html>
19+
<head>
20+
<meta http-equiv="refresh" content="0; url=new-page.html">
21+
</head>
22+
</html>
23+
24+
If you need to redirect across subdirectory trees, that works as well. For
25+
instance if ``doc/topic/subdir1/old-page.rst`` is now found at
26+
``doc/topic/subdir2/new-page.rst`` then ``new-page.rst`` just lists the
27+
full path::
28+
29+
.. redirect-from:: /topic/subdir1/old-page.rst
30+
31+
"""
32+
33+
from pathlib import Path
34+
from docutils.parsers.rst import Directive
35+
from sphinx.util import logging
36+
37+
logger = logging.getLogger(__name__)
38+
39+
40+
HTML_TEMPLATE = """<html>
41+
<head>
42+
<meta http-equiv="refresh" content="0; url={v}">
43+
</head>
44+
</html>
45+
"""
46+
47+
48+
def setup(app):
49+
RedirectFrom.app = app
50+
app.add_directive("redirect-from", RedirectFrom)
51+
app.connect("build-finished", _generate_redirects)
52+
53+
54+
class RedirectFrom(Directive):
55+
required_arguments = 1
56+
redirects = {}
57+
58+
def run(self):
59+
redirected_doc, = self.arguments
60+
env = self.app.env
61+
builder = self.app.builder
62+
current_doc = env.path2doc(self.state.document.current_source)
63+
redirected_reldoc, _ = env.relfn2path(redirected_doc, current_doc)
64+
if redirected_reldoc in self.redirects:
65+
raise ValueError(
66+
f"{redirected_reldoc} is already noted as redirecting to "
67+
f"{self.redirects[redirected_reldoc]}")
68+
self.redirects[redirected_reldoc] = builder.get_relative_uri(
69+
redirected_reldoc, current_doc)
70+
return []
71+
72+
73+
def _generate_redirects(app, exception):
74+
builder = app.builder
75+
if builder.name != "html" or exception:
76+
return
77+
for k, v in RedirectFrom.redirects.items():
78+
p = Path(app.outdir, k + builder.out_suffix)
79+
if p.is_file():
80+
logger.warning(f'A redirect-from directive is trying to create '
81+
f'{p}, but that file already exists (perhaps '
82+
f'you need to run "make clean")')
83+
else:
84+
p.parent.mkdir(parents=True, exist_ok=True)
85+
with p.open("x") as file:
86+
logger.info(f'making refresh html file: {k} redirect to {v}')
87+
file.write(HTML_TEMPLATE.format(v=v))

tutorials/introductory/customizing.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"""
2+
.. redirect-from:: /users/customizing
3+
24
Customizing Matplotlib with style sheets and rcParams
35
=====================================================
46

0 commit comments

Comments
 (0)