source: sasview/docs/sphinx-docs/build_sphinx.py @ 0e0c645

ticket-1243
Last change on this file since 0e0c645 was 153b75a, checked in by Paul Kienzle <pkienzle@…>, 6 years ago

doc build linting

  • Property mode set to 100755
File size: 9.3 KB
Line 
1#!/usr/bin/env python
2"""
3Functions for building sphinx docs.
4
5For more information on the invocation of sphinx see:
6http://sphinx-doc.org/invocation.html
7"""
8from __future__ import print_function
9
10import sys
11import os
12from os.path import join as joinpath, abspath, dirname, isdir, exists, relpath
13import shutil
14import subprocess
15import imp
16from glob import glob
17from distutils.dir_util import copy_tree
18from distutils.util import get_platform
19from distutils.spawn import find_executable
20
21PLATFORM = '.%s-%s'%(get_platform(), sys.version[:3])
22
23# sphinx paths
24SPHINX_ROOT = dirname(abspath(__file__))
25SPHINX_BUILD = joinpath(SPHINX_ROOT, "build")
26SPHINX_SOURCE = joinpath(SPHINX_ROOT, "source-temp")
27SPHINX_PERSPECTIVES = joinpath(SPHINX_SOURCE, "user", "sasgui", "perspectives")
28
29# sasview paths
30SASVIEW_ROOT = joinpath(SPHINX_ROOT, '..', '..')
31SASVIEW_DOCS = joinpath(SPHINX_ROOT, "source")
32SASVIEW_BUILD = abspath(joinpath(SASVIEW_ROOT, "build", "lib"+PLATFORM))
33SASVIEW_MEDIA_SOURCE = joinpath(SASVIEW_ROOT, "src", "sas")
34SASVIEW_DOC_TARGET = joinpath(SASVIEW_BUILD, "doc")
35SASVIEW_API_TARGET = joinpath(SPHINX_SOURCE, "dev", "sasview-api")
36
37# sasmodels paths
38SASMODELS_ROOT = joinpath(SASVIEW_ROOT, "..", "sasmodels")
39SASMODELS_DOCS = joinpath(SASMODELS_ROOT, "doc")
40SASMODELS_BUILD = joinpath(SASMODELS_ROOT, "build", "lib")
41SASMODELS_MODEL_SOURCE = joinpath(SASMODELS_DOCS, "model")
42SASMODELS_MODEL_TARGET = joinpath(SPHINX_SOURCE, "user", "models")
43#SASMODELS_API_SOURCE = joinpath(SASMODELS_DOCS, "api")
44SASMODELS_API_TARGET = joinpath(SPHINX_SOURCE, "dev", "sasmodels-api")
45SASMODELS_DEV_SOURCE = joinpath(SASMODELS_DOCS, "developer")
46SASMODELS_DEV_TARGET = joinpath(SPHINX_SOURCE, "dev", "sasmodels-dev")
47SASMODELS_GUIDE_SOURCE = joinpath(SASMODELS_DOCS, "guide")
48SASMODELS_GUIDE_TARGET = joinpath(SPHINX_PERSPECTIVES, "fitting")
49SASMODELS_GUIDE_EXCLUDE = [
50    "index.rst", "install.rst", "intro.rst",
51]
52
53# bumps paths
54BUMPS_DOCS = joinpath(SASVIEW_ROOT, "..", "bumps", "doc")
55BUMPS_SOURCE = joinpath(BUMPS_DOCS, "guide")
56BUMPS_TARGET = joinpath(SPHINX_PERSPECTIVES, "fitting")
57
58run = imp.load_source('run', joinpath(SASVIEW_ROOT, 'run.py'))
59run.prepare()
60
61def inplace_change(filename, old_string, new_string):
62    # Thanks to http://stackoverflow.com/questions/4128144/replace-string-within-file-contents
63    s = open(filename).read()
64    if old_string in s:
65        print('Changing "{old_string}" to "{new_string}"'.format(**locals()))
66        s = s.replace(old_string, new_string)
67        with open(filename, 'w') as f:
68            f.write(s)
69    else:
70        print('No occurences of "{old_string}" found.'.format(**locals()))
71
72def _remove_dir(dir_path):
73    """Removes the given directory."""
74    if isdir(dir_path):
75        print("Removing \"%s\"... " % dir_path)
76        shutil.rmtree(dir_path)
77
78def clean():
79    """
80    Clean the sphinx build directory.
81    """
82    print("=== Cleaning Sphinx Build ===")
83    _remove_dir(SASVIEW_DOC_TARGET)
84    _remove_dir(SPHINX_BUILD)
85    _remove_dir(SPHINX_SOURCE)
86
87def setup_source_temp():
88    """
89    Copy the source toctrees to new folder for assembling the sphinx-docs
90    """
91    print("=== Copying Source toctrees ===")
92    shutil.copytree(SASVIEW_DOCS, SPHINX_SOURCE)
93
94def retrieve_user_docs():
95    """
96    Copies across the contents of any media/ directories in src/, and puts them
97    in an appropriately named directory of docs/sphinx-docs/source/. For
98    example:
99
100        sas/../[MODULE]/media/dir/A.rst
101        sas/../[MODULE]/media/B.rst
102
103    gets copied to a new location:
104
105        docs/sphinx-docs/source/user/[MODULE]/dir/A.rst
106        docs/sphinx-docs/source/user/[MODULE]/B.rst
107
108    so that Sphinx may pick it up when generating the documentation.
109    """
110    print("=== Retrieve User Docs ===")
111
112    # Copy documentation files from sas/.../media to the sphinx directory
113    for root, dirs, _ in os.walk(SASVIEW_MEDIA_SOURCE):
114        if 'media' in dirs:
115            source_dir = abspath(joinpath(root, "media"))
116            relative = dirname(relpath(source_dir, SASVIEW_MEDIA_SOURCE))
117            dest_dir = joinpath(SPHINX_SOURCE, "user", relative)
118
119            print("Found sasview docs folder at \"%s\"." % relative)
120            copy_tree(source_dir, dest_dir)
121
122    print("=== Sasmodels Docs ===")
123    shutil.copy(joinpath(SASMODELS_DOCS, "rst_prolog"), SPHINX_SOURCE)
124    copy_tree(SASMODELS_MODEL_SOURCE, SASMODELS_MODEL_TARGET)
125    #copy_tree(SASMODELS_API_SOURCE, SASMODELS_API_TARGET)
126    copy_tree(SASMODELS_DEV_SOURCE, SASMODELS_DEV_TARGET)
127    copy_tree(SASMODELS_GUIDE_SOURCE, SASMODELS_GUIDE_TARGET)
128    for filename in SASMODELS_GUIDE_EXCLUDE:
129        os.unlink(joinpath(SASMODELS_GUIDE_TARGET, filename))
130
131    # Model category files reference the model as ../../model/name.rst.  Since
132    # we are rearranging the tree, we need to update each of these links.
133    catdir = joinpath(SASMODELS_GUIDE_TARGET, "models")
134    for filename in os.listdir(catdir):
135        inplace_change(joinpath(catdir, filename), "../../model/", "/user/models/")
136
137
138def retrieve_bumps_docs():
139    """
140    Copies select files from the bumps documentation into fitting perspective
141    """
142    if exists(BUMPS_SOURCE):
143        print("=== Retrieve BUMPS Docs ===")
144        filenames = [joinpath(BUMPS_SOURCE, "optimizer.rst")]
145        filenames += glob(joinpath(BUMPS_SOURCE, "dream-*.png"))
146        filenames += glob(joinpath(BUMPS_SOURCE, "fit-*.png"))
147        for f in filenames:
148            print("Copying file", f)
149            shutil.copy(f, BUMPS_TARGET)
150    else:
151        print("""
152======= Error =======
153missing directory %s
154The documentation will not include the optimizer selection section.
155Checkout the bumps source tree and rebuild the docs.
156""" % BUMPS_DOCS)
157
158def apidoc():
159    """
160    Runs sphinx-apidoc to generate .rst files from the docstrings in .py files
161    in the SasView build directory.
162    """
163    print("=== Generate API Rest Files ===")
164
165    # Clean directory before generating a new version.
166    #_remove_dir(SASVIEW_API_TARGET)
167
168    subprocess.call(["sphinx-apidoc",
169                     "-o", SASVIEW_API_TARGET, # Output dir.
170                     "-d", "8", # Max depth of TOC.
171                     "-H", "SasView", # Package header
172                     SASVIEW_BUILD])
173
174    subprocess.call(["sphinx-apidoc",
175                     "-o", SASMODELS_API_TARGET, # Output dir.
176                     "-d", "8", # Max depth of TOC.
177                     "-H", "sasmodels", # Package header
178                     SASMODELS_BUILD,
179                     joinpath(SASMODELS_BUILD, "sasmodels", "models"), # exclude
180                     ])
181
182def build_pdf():
183    """
184    Runs sphinx-build for pdf.  Reads in all .rst files and spits out the final html.
185    """
186    print("=== Build PDF Docs from ReST Files ===")
187    subprocess.call(["sphinx-build",
188                     "-b", "latex", # Builder name. TODO: accept as arg to setup.py.
189                     "-d", joinpath(SPHINX_BUILD, "doctrees"),
190                     SPHINX_SOURCE,
191                     joinpath(SPHINX_BUILD, "latex")])
192
193    LATEXDIR = joinpath(SPHINX_BUILD, "latex")
194    #TODO: Does it need to be done so many time?
195    def pdflatex():
196        subprocess.call(["pdflatex", "SasView.tex"], cwd=LATEXDIR)
197    pdflatex()
198    pdflatex()
199    pdflatex()
200    subprocess.call(["makeindex", "-s", "python.ist", "SasView.idx"], cwd=LATEXDIR)
201    pdflatex()
202    pdflatex()
203
204    print("=== Copy PDF to HTML Directory ===")
205    source = joinpath(LATEXDIR, "SasView.pdf")
206    target = joinpath(SASVIEW_DOC_TARGET, "SasView.pdf")
207    shutil.copyfile(source, target)
208
209def build():
210    """
211    Runs sphinx-build.  Reads in all .rst files and spits out the final html.
212    """
213    print("=== Build HTML Docs from ReST Files ===")
214    subprocess.call(["sphinx-build",
215                     "-b", "html", # Builder name. TODO: accept as arg to setup.py.
216                     "-d", joinpath(SPHINX_BUILD, "doctrees"),
217                     SPHINX_SOURCE,
218                     joinpath(SPHINX_BUILD, "html")])
219
220    print("=== Copy HTML Docs to Build Directory ===")
221    html = joinpath(SPHINX_BUILD, "html")
222    copy_tree(html, SASVIEW_DOC_TARGET)
223
224def fetch_katex(version, destination="_static"):
225    from zipfile import ZipFile
226    import urllib2
227    url = "https://github.com/Khan/KaTeX/releases/download/%s/katex.zip" % version
228    cache_path = "katex_%s.zip" % version
229    if not exists(cache_path):
230        try:
231            fd_in = urllib2.urlopen(url)
232            with open(cache_path, "wb") as fd_out:
233                fd_out.write(fd_in.read())
234        finally:
235            fd_in.close()
236    with ZipFile(cache_path) as archive:
237        archive.extractall(destination)
238
239def convert_katex():
240    print("=== Preprocess HTML, converting latex to html ===")
241    subprocess.call(["node", "convertKaTex.js", SASVIEW_DOC_TARGET])
242
243def convert_mathjax():
244    print("=== Preprocess HTML, converting latex to html ===")
245    subprocess.call(["node", "convertMathJax.js", SASVIEW_DOC_TARGET])
246
247def fetch_mathjax():
248    subprocess.call(["npm", "install", "mathjax-node-page"])
249    # TODO: copy fonts from node_modules/mathjax/fonts/HTML-CSS/Tex into static
250
251def rebuild():
252    clean()
253    setup_source_temp()
254    retrieve_user_docs()
255    retrieve_bumps_docs()
256    #fetch_katex(version=KATEX_VERSION, destination=KATEX_PARENT)
257    #fetch_mathjax()
258    apidoc()
259    build()
260    if find_executable('latex'):
261        build_pdf()
262    #convert_katex()
263    #convert_mathjax()
264
265    print("=== Done ===")
266
267if __name__ == "__main__":
268    rebuild()
Note: See TracBrowser for help on using the repository browser.