# Copyright 2018 Virgil Dupras # # This software is licensed under the "GPLv3" License as described in the "LICENSE" file, # which should be included with this package. The terms are also available at # http://www.gnu.org/licenses/gpl-3.0.html import os.path as op import re from distutils.version import LooseVersion from pkg_resources import load_entry_point, get_distribution from .build import read_changelog_file, filereplace CHANGELOG_FORMAT = """ {version} ({date}) ---------------------- {description} """ def tixgen(tixurl): """This is a filter *generator*. tixurl is a url pattern for the tix with a {0} placeholder for the tix # """ urlpattern = tixurl.format('\\1') # will be replaced buy the content of the first group in re R = re.compile(r'#(\d+)') repl = '`#\\1 <{}>`__'.format(urlpattern) return lambda text: R.sub(repl, text) def gen(basepath, destpath, changelogpath, tixurl, confrepl=None, confpath=None, changelogtmpl=None): """Generate sphinx docs with all bells and whistles. basepath: The base sphinx source path. destpath: The final path of html files changelogpath: The path to the changelog file to insert in changelog.rst. tixurl: The URL (with one formattable argument for the tix number) to the ticket system. confrepl: Dictionary containing replacements that have to be made in conf.py. {name: replacement} """ if confrepl is None: confrepl = {} if confpath is None: confpath = op.join(basepath, 'conf.tmpl') if changelogtmpl is None: changelogtmpl = op.join(basepath, 'changelog.tmpl') changelog = read_changelog_file(changelogpath) tix = tixgen(tixurl) rendered_logs = [] for log in changelog: description = tix(log['description']) # The format of the changelog descriptions is in markdown, but since we only use bulled list # and links, it's not worth depending on the markdown package. A simple regexp suffice. description = re.sub(r'\[(.*?)\]\((.*?)\)', '`\\1 <\\2>`__', description) rendered = CHANGELOG_FORMAT.format(version=log['version'], date=log['date_str'], description=description) rendered_logs.append(rendered) confrepl['version'] = changelog[0]['version'] changelog_out = op.join(basepath, 'changelog.rst') filereplace(changelogtmpl, changelog_out, changelog='\n'.join(rendered_logs)) if op.exists(confpath): conf_out = op.join(basepath, 'conf.py') filereplace(confpath, conf_out, **confrepl) if LooseVersion(get_distribution("sphinx").version) >= LooseVersion("1.7.0"): from sphinx.cmd.build import build_main as sphinx_build # Call the sphinx_build function, which is the same as doing sphinx-build from cli try: sphinx_build([basepath, destpath]) except SystemExit: print("Sphinx called sys.exit(), but we're cancelling it because we don't actually want to exit") else: # We used to call sphinx-build with print_and_do(), but the problem was that the virtualenv # of the calling python wasn't correctly considered and caused problems with documentation # relying on autodoc (which tries to import the module to auto-document, but fail because of # missing dependencies which are in the virtualenv). Here, we do exactly what is done when # calling the command from bash. cmd = load_entry_point('Sphinx', 'console_scripts', 'sphinx-build') try: cmd(['sphinx-build', basepath, destpath]) except SystemExit: print("Sphinx called sys.exit(), but we're cancelling it because we don't actually want to exit")