diff --git a/tools/docs/mach_commands.py b/tools/docs/mach_commands.py index afd7f3ead54..825e5ec38aa 100644 --- a/tools/docs/mach_commands.py +++ b/tools/docs/mach_commands.py @@ -2,16 +2,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, # You can obtain one at http://mozilla.org/MPL/2.0/. -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals import os +import sys from mach.decorators import ( + Command, CommandArgument, CommandProvider, - Command, ) +import mozhttpd + from mozbuild.base import MachCommandBase @@ -21,15 +24,17 @@ class Documentation(MachCommandBase): @Command('doc', category='devenv', description='Generate and display documentation from the tree.') - @CommandArgument('what', default=None, nargs='*', + @CommandArgument('what', nargs='*', metavar='DIRECTORY [, DIRECTORY]', help='Path(s) to documentation to build and display.') @CommandArgument('--format', default='html', help='Documentation format to write.') - @CommandArgument('--outdir', default=None, + @CommandArgument('--outdir', default=None, metavar='DESTINATION', help='Where to write output.') @CommandArgument('--no-open', dest='auto_open', default=True, action='store_false', - help='Don\'t automatically open HTML docs in a browser.') - def build_docs(self, what=None, format=None, outdir=None, auto_open=True): + help="Don't automatically open HTML docs in a browser.") + @CommandArgument('--http', const=':6666', metavar='ADDRESS', nargs='?', + help='Serve documentation on an HTTP server, e.g. ":6666".') + def build_docs(self, what=None, format=None, outdir=None, auto_open=True, http=None): self._activate_virtualenv() self.virtualenv_manager.install_pip_package('sphinx_rtd_theme==0.1.6') @@ -38,9 +43,9 @@ class Documentation(MachCommandBase): if not outdir: outdir = os.path.join(self.topobjdir, 'docs') - if not what: what = [os.path.join(self.topsrcdir, 'tools')] + outdir = os.path.join(outdir, format) generated = [] failed = [] @@ -54,7 +59,7 @@ class Documentation(MachCommandBase): # find project name to use as a namespace within `outdir` project = self._find_project_name(docdir) - savedir = os.path.join(outdir, format, project) + savedir = os.path.join(outdir, project) args = [ 'sphinx', @@ -68,18 +73,26 @@ class Documentation(MachCommandBase): else: generated.append(savedir) - # attempt to open html docs in a browser index_path = os.path.join(savedir, 'index.html') - if auto_open and os.path.isfile(index_path): + if not http and auto_open and os.path.isfile(index_path): webbrowser.open(index_path) if generated: - print("\nGenerated documentation:\n%s\n" % '\n'.join(generated)) + print('\nGenerated documentation:\n%s\n' % '\n'.join(generated)) if failed: - failed = ['%s - %s' % (f[0], f[1]) for f in failed] - print("ERROR failed to generate documentation:\n%s" % '\n'.join(failed)) - return 1 + failed = ['%s: %s' % (f[0], f[1]) for f in failed] + return die('failed to generate documentation:\n%s' % '\n'.join(failed)) + + if http is not None: + host, port = http.split(':', 1) + addr = (host, int(port)) + if len(addr) != 2: + return die('invalid address: %s' % http) + + httpd = mozhttpd.MozHttpd(host=addr[0], port=addr[1], docroot=outdir) + print('listening on %s:%d' % addr) + httpd.start(block=True) def _find_project_name(self, path): import imp @@ -96,3 +109,9 @@ class Documentation(MachCommandBase): p = os.path.join(path, d) if os.path.isfile(os.path.join(p, 'conf.py')): return p + + +def die(msg, exit_code=1): + msg = '%s: %s' % (sys.argv[0], msg) + print(msg, file=sys.stderr) + return exit_code