source: sasview/docs/sphinx-docs/build_sphinx.py @ ffbf35ee

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

doc build linting

  • Property mode set to 100755
File size: 9.3 KB
RevLine 
[9bf64f6]1#!/usr/bin/env python
[35bf493]2"""
3Functions for building sphinx docs.
4
5For more information on the invocation of sphinx see:
6http://sphinx-doc.org/invocation.html
7"""
[01f1e17]8from __future__ import print_function
9
[153b75a]10import sys
[35bf493]11import os
[3bd677b]12from os.path import join as joinpath, abspath, dirname, isdir, exists, relpath
[35bf493]13import shutil
[153b75a]14import subprocess
[296f290]15import imp
[21bba86]16from glob import glob
[35bf493]17from distutils.dir_util import copy_tree
18from distutils.util import get_platform
[1573220]19from distutils.spawn import find_executable
20
[153b75a]21PLATFORM = '.%s-%s'%(get_platform(), sys.version[:3])
[35bf493]22
[3bd677b]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")
[153b75a]32SASVIEW_BUILD = abspath(joinpath(SASVIEW_ROOT, "build", "lib"+PLATFORM))
[3bd677b]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'))
[296f290]59run.prepare()
60
[bb0c836]61def inplace_change(filename, old_string, new_string):
[153b75a]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()))
[bb0c836]71
[35bf493]72def _remove_dir(dir_path):
73    """Removes the given directory."""
[3bd677b]74    if isdir(dir_path):
[21bba86]75        print("Removing \"%s\"... " % dir_path)
[35bf493]76        shutil.rmtree(dir_path)
77
78def clean():
79    """
80    Clean the sphinx build directory.
81    """
[f4d571b]82    print("=== Cleaning Sphinx Build ===")
[3bd677b]83    _remove_dir(SASVIEW_DOC_TARGET)
[35bf493]84    _remove_dir(SPHINX_BUILD)
[5dd7499]85    _remove_dir(SPHINX_SOURCE)
[35bf493]86
[5dd7499]87def setup_source_temp():
88    """
89    Copy the source toctrees to new folder for assembling the sphinx-docs
90    """
[f4d571b]91    print("=== Copying Source toctrees ===")
[3bd677b]92    shutil.copytree(SASVIEW_DOCS, SPHINX_SOURCE)
[354524d]93
[35bf493]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    """
[f4d571b]110    print("=== Retrieve User Docs ===")
[35bf493]111
[3bd677b]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
[6a9c0e5a]137
[c22c5e3]138def retrieve_bumps_docs():
139    """
140    Copies select files from the bumps documentation into fitting perspective
141    """
[3bd677b]142    if exists(BUMPS_SOURCE):
[f4d571b]143        print("=== Retrieve BUMPS Docs ===")
[3bd677b]144        filenames = [joinpath(BUMPS_SOURCE, "optimizer.rst")]
145        filenames += glob(joinpath(BUMPS_SOURCE, "dream-*.png"))
146        filenames += glob(joinpath(BUMPS_SOURCE, "fit-*.png"))
[c22c5e3]147        for f in filenames:
[f4d571b]148            print("Copying file", f)
[c22c5e3]149            shutil.copy(f, BUMPS_TARGET)
150    else:
[f4d571b]151        print("""
[01f1e17]152======= Error =======
153missing directory %s
[c22c5e3]154The documentation will not include the optimizer selection section.
155Checkout the bumps source tree and rebuild the docs.
[f4d571b]156""" % BUMPS_DOCS)
[c22c5e3]157
[35bf493]158def apidoc():
159    """
160    Runs sphinx-apidoc to generate .rst files from the docstrings in .py files
161    in the SasView build directory.
162    """
[f4d571b]163    print("=== Generate API Rest Files ===")
[35bf493]164
165    # Clean directory before generating a new version.
[3bd677b]166    #_remove_dir(SASVIEW_API_TARGET)
[35bf493]167
168    subprocess.call(["sphinx-apidoc",
[3bd677b]169                     "-o", SASVIEW_API_TARGET, # Output dir.
[35bf493]170                     "-d", "8", # Max depth of TOC.
[3bd677b]171                     "-H", "SasView", # Package header
[35bf493]172                     SASVIEW_BUILD])
173
[3bd677b]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
[3194371]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.
[3bd677b]189                     "-d", joinpath(SPHINX_BUILD, "doctrees"),
[3194371]190                     SPHINX_SOURCE,
[3bd677b]191                     joinpath(SPHINX_BUILD, "latex")])
[3194371]192
[3bd677b]193    LATEXDIR = joinpath(SPHINX_BUILD, "latex")
[1573220]194    #TODO: Does it need to be done so many time?
[3194371]195    def pdflatex():
[6e546f8]196        subprocess.call(["pdflatex", "SasView.tex"], cwd=LATEXDIR)
[3194371]197    pdflatex()
198    pdflatex()
199    pdflatex()
[6e546f8]200    subprocess.call(["makeindex", "-s", "python.ist", "SasView.idx"], cwd=LATEXDIR)
[3194371]201    pdflatex()
202    pdflatex()
203
204    print("=== Copy PDF to HTML Directory ===")
[3bd677b]205    source = joinpath(LATEXDIR, "SasView.pdf")
206    target = joinpath(SASVIEW_DOC_TARGET, "SasView.pdf")
[3194371]207    shutil.copyfile(source, target)
208
[35bf493]209def build():
210    """
211    Runs sphinx-build.  Reads in all .rst files and spits out the final html.
212    """
[3194371]213    print("=== Build HTML Docs from ReST Files ===")
[35bf493]214    subprocess.call(["sphinx-build",
215                     "-b", "html", # Builder name. TODO: accept as arg to setup.py.
[3bd677b]216                     "-d", joinpath(SPHINX_BUILD, "doctrees"),
[35bf493]217                     SPHINX_SOURCE,
[3bd677b]218                     joinpath(SPHINX_BUILD, "html")])
[35bf493]219
[f4d571b]220    print("=== Copy HTML Docs to Build Directory ===")
[3bd677b]221    html = joinpath(SPHINX_BUILD, "html")
222    copy_tree(html, SASVIEW_DOC_TARGET)
[35bf493]223
[f4771596]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
[3bd677b]229    if not exists(cache_path):
[f4771596]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()
[153b75a]236    with ZipFile(cache_path) as archive:
237        archive.extractall(destination)
[f4771596]238
[3194371]239def convert_katex():
240    print("=== Preprocess HTML, converting latex to html ===")
[3bd677b]241    subprocess.call(["node", "convertKaTex.js", SASVIEW_DOC_TARGET])
[3194371]242
[f4771596]243def convert_mathjax():
244    print("=== Preprocess HTML, converting latex to html ===")
[3bd677b]245    subprocess.call(["node", "convertMathJax.js", SASVIEW_DOC_TARGET])
[f4771596]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
[c2ee2b1]251def rebuild():
[35bf493]252    clean()
[5dd7499]253    setup_source_temp()
[35bf493]254    retrieve_user_docs()
[c22c5e3]255    retrieve_bumps_docs()
[f4771596]256    #fetch_katex(version=KATEX_VERSION, destination=KATEX_PARENT)
257    #fetch_mathjax()
[35bf493]258    apidoc()
259    build()
[3d37fe9]260    if find_executable('latex'):
[df72475]261        build_pdf()
[3194371]262    #convert_katex()
[f4771596]263    #convert_mathjax()
[c2ee2b1]264
[f4d571b]265    print("=== Done ===")
[c2ee2b1]266
267if __name__ == "__main__":
[9bf64f6]268    rebuild()
Note: See TracBrowser for help on using the repository browser.