Source code for make

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Expedite documentation builds.

.. module:: make
    :synopsis: Expedite documentation builds.

We attempt to automate documentation builds with this module.

Still need to add an option to recursively move the html files out of the
currently git-ignored directory `_build/html/` into this directory.

Update the options you can give to the parser:

#) remove python path
#) Add open in browser as an option
#) Fix the output for the `commands` argument when this is run with :data:`sys.argv` == 0

"""
import argparse
import logging
import os
import shutil
import subprocess
import sys
import webbrowser

from pyutil.__about__ import __version__

DOC_PATH = os.path.dirname(os.path.abspath(__file__))
BUILD_PATH = os.path.join(DOC_PATH, '_build')
LOGGER = logging.getLogger(name=__name__)


[docs]def _parse_arguments(cmds=None): """Parse user arguments. Parameters ---------- cmd : str Arguments provided by the user. Returns ------- user_args : :class:`argparse.NameSpace` Argumemts as they've been interpreted by :mod:`argparse`. See Also -------- :mod:`docutils.core` Shows a few good methods on how to programatically publish docs. """ cmds = [method for method in dir(DocBuilder) if not method.startswith('_')] parser = argparse.ArgumentParser(description="Pyutil doc builder.", epilog="Commands: {}".format( ','.join(cmds))) parser.add_argument('builder', nargs='?', default='html', metavar='builder: (html or latex)', help='command to run: {}'.format(', '.join(cmds))) parser.add_argument('-j', '--num-jobs', metavar='num-jobs', dest='jobs', type=int, default=os.cpu_count(), help='Number of parallel jobs used by `sphinx-build`.') parser.add_argument('-s', '--single', metavar='FILENAME', type=str, default=None, help=('filename of section or method name to build.')) parser.add_argument('-p', '--python-path', type=str, default=os.path.dirname(DOC_PATH), help='path') parser.add_argument('-l', '--log', default=sys.stdout, type=argparse.FileType('w'), help='File to write logging messages to.') parser.add_argument('-ll', '--log-level', dest='log_level', default='INFO', help='Log level. Defaults to INFO. Implies logging.') parser.add_argument( '-V', '--verbose', default=False, help='Enable verbose logging and increase level to `debug`.') parser.add_argument('--version', action='version', version=__version__) user_args = parser.parse_args() if len(sys.argv[1:]) == 0: parser.print_help() sys.exit() # from ipdb import set_trace # set_trace() return user_args
[docs]class DocBuilder: """Class to wrap the different commands of this script. All public methods of this class can be called as parameters of the script. Attributes ----------- builder : str The filetype :command:`make` invokes :command:`sphinx-build` to create. """ def __init__(self, num_jobs=1, verbosity=0, warnings_are_errors=False): self.num_jobs = num_jobs self.verbosity = verbosity self.warnings_are_errors = warnings_are_errors
[docs] def sphinx_build(self, kind='html'): """Build docs. Parameters ---------- kind : {'html', 'latex'} Kind of docs to build. Examples -------- >>> DocBuilder(num_jobs=4).sphinx_build('html') """ if kind not in ('html', 'latex'): raise ValueError('kind must be html or latex, ' 'not {}'.format(kind)) cmd = ['sphinx-build', '-b', kind, '-c', '.'] if self.num_jobs: cmd += ['-j', str(self.num_jobs)] if self.warnings_are_errors: cmd += ['-W', '--keep-going'] if self.verbosity: cmd.append('-{}'.format('v' * self.verbosity)) cmd += [ '-d', os.path.join(BUILD_PATH, 'doctrees'), DOC_PATH, os.path.join(BUILD_PATH, kind) ] return subprocess.call(cmd)
[docs] def _open_browser(self, single_doc_html): """Open a browser tab showing the single doc html option.""" url = os.path.join('file://', DOC_PATH, 'build', 'html', single_doc_html) webbrowser.open(url, new=2)
[docs]def termux_hack(): """Android permissions don't allow viewing files in app specific files.""" try: shutil.copytree( '_build/html/', '/data/data/com.termux/files/home/storage/downloads/html') except FileExistsError: shutil.rmtree( '/data/data/com.termux/files/home/storage/downloads/html') shutil.copytree( '_build/html/', '/data/data/com.termux/files/home/storage/downloads/html') except FileNotFoundError: logging.error("The build directory currently doesn't exist. Exiting.")
[docs]def main(): """Set everything up.""" args = _parse_arguments() try: log_level = args.log_level.upper() except AttributeError: logging.basicConfig(level=logging.WARNING) else: logging.basicConfig(level=log_level) jobs = args.jobs # there's a default for the argument so no need for try/ excepts try: verbosity = args.verbosity except AttributeError: verbosity = None builder = args.builder DocBuilder(num_jobs=jobs, verbosity=verbosity).sphinx_build(kind=builder) if os.environ.get('ANDROID_ROOT'): termux_hack()
if __name__ == "__main__": main()