Skip to content

Commit 6a745d8

Browse files
datapythonistaTomAugspurger
authored andcommitted
DOC: Implementing redirect system, and adding user_guide redirects (#24715)
* DOC: Implementing redirect system, and adding user_guide redirects * Using relative urls for the redirect * Validating that no file is overwritten by a redirect * Adding redirects for getting started and development sections
1 parent 4b937ff commit 6a745d8

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed

doc/make.py

+77-1
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@
1515
import sys
1616
import os
1717
import shutil
18+
import csv
1819
import subprocess
1920
import argparse
2021
import webbrowser
22+
import docutils
23+
import docutils.parsers.rst
2124

2225

2326
DOC_PATH = os.path.dirname(os.path.abspath(__file__))
2427
SOURCE_PATH = os.path.join(DOC_PATH, 'source')
2528
BUILD_PATH = os.path.join(DOC_PATH, 'build')
26-
BUILD_DIRS = ['doctrees', 'html', 'latex', 'plots', '_static', '_templates']
29+
REDIRECTS_FILE = os.path.join(DOC_PATH, 'redirects.csv')
2730

2831

2932
class DocBuilder:
@@ -139,6 +142,77 @@ def _open_browser(self, single_doc_html):
139142
single_doc_html)
140143
webbrowser.open(url, new=2)
141144

145+
def _get_page_title(self, page):
146+
"""
147+
Open the rst file `page` and extract its title.
148+
"""
149+
fname = os.path.join(SOURCE_PATH, '{}.rst'.format(page))
150+
option_parser = docutils.frontend.OptionParser(
151+
components=(docutils.parsers.rst.Parser,))
152+
doc = docutils.utils.new_document(
153+
'<doc>',
154+
option_parser.get_default_values())
155+
with open(fname) as f:
156+
data = f.read()
157+
158+
parser = docutils.parsers.rst.Parser()
159+
# do not generate any warning when parsing the rst
160+
with open(os.devnull, 'a') as f:
161+
doc.reporter.stream = f
162+
parser.parse(data, doc)
163+
164+
section = next(node for node in doc.children
165+
if isinstance(node, docutils.nodes.section))
166+
title = next(node for node in section.children
167+
if isinstance(node, docutils.nodes.title))
168+
169+
return title.astext()
170+
171+
def _add_redirects(self):
172+
"""
173+
Create in the build directory an html file with a redirect,
174+
for every row in REDIRECTS_FILE.
175+
"""
176+
html = '''
177+
<html>
178+
<head>
179+
<meta http-equiv="refresh" content="0;URL={url}"/>
180+
</head>
181+
<body>
182+
<p>
183+
The page has been moved to <a href="{url}">{title}</a>
184+
</p>
185+
</body>
186+
<html>
187+
'''
188+
with open(REDIRECTS_FILE) as mapping_fd:
189+
reader = csv.reader(mapping_fd)
190+
for row in reader:
191+
if not row or row[0].strip().startswith('#'):
192+
continue
193+
194+
path = os.path.join(BUILD_PATH,
195+
'html',
196+
*row[0].split('/')) + '.html'
197+
198+
try:
199+
title = self._get_page_title(row[1])
200+
except Exception:
201+
# the file can be an ipynb and not an rst, or docutils
202+
# may not be able to read the rst because it has some
203+
# sphinx specific stuff
204+
title = 'this page'
205+
206+
if os.path.exists(path):
207+
raise RuntimeError((
208+
'Redirection would overwrite an existing file: '
209+
'{}').format(path))
210+
211+
with open(path, 'w') as moved_page_fd:
212+
moved_page_fd.write(
213+
html.format(url='{}.html'.format(row[1]),
214+
title=title))
215+
142216
def html(self):
143217
"""
144218
Build HTML documentation.
@@ -150,6 +224,8 @@ def html(self):
150224

151225
if self.single_doc_html is not None:
152226
self._open_browser(self.single_doc_html)
227+
else:
228+
self._add_redirects()
153229
return ret_code
154230

155231
def latex(self, force=False):

doc/redirects.csv

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# This file should contain all the redirects in the documentation
2+
# in the format `<old_path>,<new_path>`
3+
4+
# getting started
5+
10min,getting_started/10min
6+
basics,getting_started/basics
7+
dsintro,getting_started/dsintro
8+
overview,getting_started/overview
9+
tutorials,getting_started/tutorials
10+
11+
# user guide
12+
advanced,user_guide/advanced
13+
categorical,user_guide/categorical
14+
computation,user_guide/computation
15+
enhancingperf,user_guide/enhancingperf
16+
gotchas,user_guide/gotchas
17+
groupby,user_guide/groupby
18+
indexing,user_guide/indexing
19+
integer_na,user_guide/integer_na
20+
io,user_guide/io
21+
merging,user_guide/merging
22+
missing_data,user_guide/missing_data
23+
options,user_guide/options
24+
reshaping,user_guide/reshaping
25+
sparse,user_guide/sparse
26+
style,user_guide/style
27+
text,user_guide/text
28+
timedeltas,user_guide/timedeltas
29+
timeseries,user_guide/timeseries
30+
visualization,user_guide/visualization
31+
32+
# development
33+
contributing,development/contributing
34+
contributing_docstring,development/contributing_docstring
35+
developer,development/developer
36+
extending,development/extending
37+
internals,development/internals

0 commit comments

Comments
 (0)