[9bf64f6] | 1 | #!/usr/bin/env python |
---|
[35bf493] | 2 | """ |
---|
| 3 | Functions for building sphinx docs. |
---|
| 4 | |
---|
| 5 | For more information on the invocation of sphinx see: |
---|
| 6 | http://sphinx-doc.org/invocation.html |
---|
| 7 | """ |
---|
[01f1e17] | 8 | from __future__ import print_function |
---|
| 9 | |
---|
[153b75a] | 10 | import sys |
---|
[35bf493] | 11 | import os |
---|
[3bd677b] | 12 | from os.path import join as joinpath, abspath, dirname, isdir, exists, relpath |
---|
[35bf493] | 13 | import shutil |
---|
[153b75a] | 14 | import subprocess |
---|
[296f290] | 15 | import imp |
---|
[21bba86] | 16 | from glob import glob |
---|
[35bf493] | 17 | from distutils.dir_util import copy_tree |
---|
| 18 | from distutils.util import get_platform |
---|
[1573220] | 19 | from distutils.spawn import find_executable |
---|
| 20 | |
---|
[153b75a] | 21 | PLATFORM = '.%s-%s'%(get_platform(), sys.version[:3]) |
---|
[35bf493] | 22 | |
---|
[3bd677b] | 23 | # sphinx paths |
---|
| 24 | SPHINX_ROOT = dirname(abspath(__file__)) |
---|
| 25 | SPHINX_BUILD = joinpath(SPHINX_ROOT, "build") |
---|
| 26 | SPHINX_SOURCE = joinpath(SPHINX_ROOT, "source-temp") |
---|
| 27 | SPHINX_PERSPECTIVES = joinpath(SPHINX_SOURCE, "user", "sasgui", "perspectives") |
---|
| 28 | |
---|
| 29 | # sasview paths |
---|
| 30 | SASVIEW_ROOT = joinpath(SPHINX_ROOT, '..', '..') |
---|
| 31 | SASVIEW_DOCS = joinpath(SPHINX_ROOT, "source") |
---|
[153b75a] | 32 | SASVIEW_BUILD = abspath(joinpath(SASVIEW_ROOT, "build", "lib"+PLATFORM)) |
---|
[3bd677b] | 33 | SASVIEW_MEDIA_SOURCE = joinpath(SASVIEW_ROOT, "src", "sas") |
---|
| 34 | SASVIEW_DOC_TARGET = joinpath(SASVIEW_BUILD, "doc") |
---|
| 35 | SASVIEW_API_TARGET = joinpath(SPHINX_SOURCE, "dev", "sasview-api") |
---|
| 36 | |
---|
| 37 | # sasmodels paths |
---|
| 38 | SASMODELS_ROOT = joinpath(SASVIEW_ROOT, "..", "sasmodels") |
---|
| 39 | SASMODELS_DOCS = joinpath(SASMODELS_ROOT, "doc") |
---|
| 40 | SASMODELS_BUILD = joinpath(SASMODELS_ROOT, "build", "lib") |
---|
| 41 | SASMODELS_MODEL_SOURCE = joinpath(SASMODELS_DOCS, "model") |
---|
| 42 | SASMODELS_MODEL_TARGET = joinpath(SPHINX_SOURCE, "user", "models") |
---|
| 43 | #SASMODELS_API_SOURCE = joinpath(SASMODELS_DOCS, "api") |
---|
| 44 | SASMODELS_API_TARGET = joinpath(SPHINX_SOURCE, "dev", "sasmodels-api") |
---|
| 45 | SASMODELS_DEV_SOURCE = joinpath(SASMODELS_DOCS, "developer") |
---|
| 46 | SASMODELS_DEV_TARGET = joinpath(SPHINX_SOURCE, "dev", "sasmodels-dev") |
---|
| 47 | SASMODELS_GUIDE_SOURCE = joinpath(SASMODELS_DOCS, "guide") |
---|
| 48 | SASMODELS_GUIDE_TARGET = joinpath(SPHINX_PERSPECTIVES, "fitting") |
---|
| 49 | SASMODELS_GUIDE_EXCLUDE = [ |
---|
| 50 | "index.rst", "install.rst", "intro.rst", |
---|
| 51 | ] |
---|
| 52 | |
---|
| 53 | # bumps paths |
---|
| 54 | BUMPS_DOCS = joinpath(SASVIEW_ROOT, "..", "bumps", "doc") |
---|
| 55 | BUMPS_SOURCE = joinpath(BUMPS_DOCS, "guide") |
---|
| 56 | BUMPS_TARGET = joinpath(SPHINX_PERSPECTIVES, "fitting") |
---|
| 57 | |
---|
| 58 | run = imp.load_source('run', joinpath(SASVIEW_ROOT, 'run.py')) |
---|
[296f290] | 59 | run.prepare() |
---|
| 60 | |
---|
[bb0c836] | 61 | def 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] | 72 | def _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 | |
---|
| 78 | def 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] | 87 | def 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] | 94 | def 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] | 138 | def 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 ======= |
---|
| 153 | missing directory %s |
---|
[c22c5e3] | 154 | The documentation will not include the optimizer selection section. |
---|
| 155 | Checkout the bumps source tree and rebuild the docs. |
---|
[f4d571b] | 156 | """ % BUMPS_DOCS) |
---|
[c22c5e3] | 157 | |
---|
[35bf493] | 158 | def 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] | 182 | def 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] | 209 | def 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] | 224 | def 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] | 239 | def convert_katex(): |
---|
| 240 | print("=== Preprocess HTML, converting latex to html ===") |
---|
[3bd677b] | 241 | subprocess.call(["node", "convertKaTex.js", SASVIEW_DOC_TARGET]) |
---|
[3194371] | 242 | |
---|
[f4771596] | 243 | def convert_mathjax(): |
---|
| 244 | print("=== Preprocess HTML, converting latex to html ===") |
---|
[3bd677b] | 245 | subprocess.call(["node", "convertMathJax.js", SASVIEW_DOC_TARGET]) |
---|
[f4771596] | 246 | |
---|
| 247 | def 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] | 251 | def 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 | |
---|
| 267 | if __name__ == "__main__": |
---|
[9bf64f6] | 268 | rebuild() |
---|