1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/docs/moztreedocs/__init__.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,113 @@ 1.4 +# This Source Code Form is subject to the terms of the Mozilla Public 1.5 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 +# file, # You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + 1.8 +from __future__ import unicode_literals 1.9 + 1.10 +import os 1.11 + 1.12 +from mozpack.copier import FileCopier 1.13 +from mozpack.files import FileFinder 1.14 +from mozpack.manifests import InstallManifest 1.15 + 1.16 +import sphinx 1.17 +import sphinx.apidoc 1.18 + 1.19 + 1.20 +class SphinxManager(object): 1.21 + """Manages the generation of Sphinx documentation for the tree.""" 1.22 + 1.23 + def __init__(self, topsrcdir, main_path, output_dir): 1.24 + self._topsrcdir = topsrcdir 1.25 + self._output_dir = output_dir 1.26 + self._conf_py_path = os.path.join(main_path, 'conf.py') 1.27 + self._index_path = os.path.join(main_path, 'index.rst') 1.28 + self._trees = {} 1.29 + self._python_package_dirs = set() 1.30 + 1.31 + def add_tree(self, source_dir, dest_dir): 1.32 + """Add a directory from where docs should be sourced.""" 1.33 + if dest_dir in self._trees: 1.34 + raise Exception('%s has already been registered as a destination.' 1.35 + % dest_dir) 1.36 + 1.37 + self._trees[dest_dir] = source_dir 1.38 + 1.39 + def add_python_package_dir(self, source_dir): 1.40 + """Add a directory containing Python packages. 1.41 + 1.42 + Added directories will have Python API docs generated automatically. 1.43 + """ 1.44 + self._python_package_dirs.add(source_dir) 1.45 + 1.46 + def generate_docs(self, fmt): 1.47 + """Generate documentation using Sphinx.""" 1.48 + self._synchronize_docs() 1.49 + self._generate_python_api_docs() 1.50 + 1.51 + old_env = os.environ.copy() 1.52 + try: 1.53 + os.environ['MOZILLA_DIR'] = self._topsrcdir 1.54 + args = [ 1.55 + 'sphinx', 1.56 + '-b', fmt, 1.57 + os.path.join(self._output_dir, 'staging'), 1.58 + os.path.join(self._output_dir, fmt), 1.59 + ] 1.60 + 1.61 + return sphinx.main(args) 1.62 + finally: 1.63 + os.environ.clear() 1.64 + os.environ.update(old_env) 1.65 + 1.66 + def _generate_python_api_docs(self): 1.67 + """Generate Python API doc files.""" 1.68 + out_dir = os.path.join(self._output_dir, 'staging', 'python') 1.69 + base_args = ['sphinx', '--no-toc', '-o', out_dir] 1.70 + 1.71 + for p in sorted(self._python_package_dirs): 1.72 + full = os.path.join(self._topsrcdir, p) 1.73 + 1.74 + finder = FileFinder(full, find_executables=False) 1.75 + dirs = {os.path.dirname(f[0]) for f in finder.find('**')} 1.76 + 1.77 + excludes = {d for d in dirs if d.endswith('test')} 1.78 + 1.79 + args = list(base_args) 1.80 + args.append(full) 1.81 + args.extend(excludes) 1.82 + 1.83 + sphinx.apidoc.main(args) 1.84 + 1.85 + def _synchronize_docs(self): 1.86 + m = InstallManifest() 1.87 + 1.88 + m.add_symlink(self._conf_py_path, 'conf.py') 1.89 + 1.90 + for dest, source in sorted(self._trees.items()): 1.91 + source_dir = os.path.join(self._topsrcdir, source) 1.92 + for root, dirs, files in os.walk(source_dir): 1.93 + for f in files: 1.94 + source_path = os.path.join(root, f) 1.95 + rel_source = source_path[len(source_dir) + 1:] 1.96 + 1.97 + m.add_symlink(source_path, os.path.join(dest, rel_source)) 1.98 + 1.99 + stage_dir = os.path.join(self._output_dir, 'staging') 1.100 + copier = FileCopier() 1.101 + m.populate_registry(copier) 1.102 + copier.copy(stage_dir) 1.103 + 1.104 + with open(self._index_path, 'rb') as fh: 1.105 + data = fh.read() 1.106 + 1.107 + indexes = ['%s/index' % p for p in sorted(self._trees.keys())] 1.108 + indexes = '\n '.join(indexes) 1.109 + 1.110 + packages = [os.path.basename(p) for p in self._python_package_dirs] 1.111 + packages = ['python/%s' % p for p in packages] 1.112 + packages = '\n '.join(sorted(packages)) 1.113 + data = data.format(indexes=indexes, python_packages=packages) 1.114 + 1.115 + with open(os.path.join(stage_dir, 'index.rst'), 'wb') as fh: 1.116 + fh.write(data)