diff options
Diffstat (limited to 'tasks/docs.py')
-rw-r--r-- | tasks/docs.py | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/tasks/docs.py b/tasks/docs.py new file mode 100644 index 0000000..3360279 --- /dev/null +++ b/tasks/docs.py @@ -0,0 +1,198 @@ +# -*- coding: UTF-8 -*- +""" +Provides tasks to build documentation with sphinx, etc. +""" + +from __future__ import absolute_import, print_function +import os +import sys +from invoke import task, Collection +from invoke.util import cd +from path import Path + +# -- TASK-LIBRARY: +from ._tasklet_cleanup import cleanup_tasks, cleanup_dirs + + +# ----------------------------------------------------------------------------- +# CONSTANTS: +# ----------------------------------------------------------------------------- +SPHINX_LANGUAGE_DEFAULT = os.environ.get("SPHINX_LANGUAGE", "en") + + +# ----------------------------------------------------------------------------- +# UTILTITIES: +# ----------------------------------------------------------------------------- +def _sphinxdoc_get_language(ctx, language=None): + language = language or ctx.config.sphinx.language or SPHINX_LANGUAGE_DEFAULT + return language + + +def _sphinxdoc_get_destdir(ctx, builder, language=None): + if builder == "gettext": + # -- CASE: not LANGUAGE-SPECIFIC + destdir = Path(ctx.config.sphinx.destdir or "build")/builder + else: + # -- CASE: LANGUAGE-SPECIFIC: + language = _sphinxdoc_get_language(ctx, language) + destdir = Path(ctx.config.sphinx.destdir or "build")/builder/language + return destdir + + +# ----------------------------------------------------------------------------- +# TASKS: +# ----------------------------------------------------------------------------- +@task +def clean(ctx, dry_run=False): + """Cleanup generated document artifacts.""" + basedir = ctx.sphinx.destdir or "build/docs" + cleanup_dirs([basedir], dry_run=dry_run) + + +@task(help={ + "builder": "Builder to use (html, ...)", + "language": "Language to use (en, ...)", + "options": "Additional options for sphinx-build", +}) +def build(ctx, builder="html", language=None, options=""): + """Build docs with sphinx-build""" + language = _sphinxdoc_get_language(ctx, language) + sourcedir = ctx.config.sphinx.sourcedir + destdir = _sphinxdoc_get_destdir(ctx, builder, language=language) + destdir = destdir.abspath() + with cd(sourcedir): + destdir_relative = Path(".").relpathto(destdir) + command = "sphinx-build {opts} -b {builder} -D language={language} {sourcedir} {destdir}" \ + .format(builder=builder, sourcedir=".", + destdir=destdir_relative, + language=language, + opts=options) + ctx.run(command) + +@task(help={ + "builder": "Builder to use (html, ...)", + "language": "Language to use (en, ...)", + "options": "Additional options for sphinx-build", +}) +def rebuild(ctx, builder="html", language=None, options=""): + """Rebuilds the docs. + Perform the steps: clean, build + """ + clean(ctx) + build(ctx, builder=builder, language=None, options=options) + +@task +def linkcheck(ctx): + """Check if all links are corect.""" + build(ctx, builder="linkcheck") + +@task(help={"language": "Language to use (en, ...)"}) +def browse(ctx, language=None): + """Open documentation in web browser.""" + output_dir = _sphinxdoc_get_destdir(ctx, "html", language=language) + page_html = Path(output_dir)/"index.html" + if not page_html.exists(): + build(ctx, builder="html") + assert page_html.exists() + open_cmd = "open" # -- WORKS ON: MACOSX + if sys.platform.startswith("win"): + open_cmd = "start" + ctx.run("{open} {page_html}".format(open=open_cmd, page_html=page_html)) + # ctx.run('python -m webbrowser -t {page_html}'.format(page_html=page_html)) + # -- DISABLED: + # import webbrowser + # print("Starting webbrowser with page=%s" % page_html) + # webbrowser.open(str(page_html)) + + +@task(help={ + "dest": "Destination directory to save docs", + "format": "Format/Builder to use (html, ...)", + "language": "Language to use (en, ...)", +}) +# pylint: disable=redefined-builtin +def save(ctx, dest="docs.html", format="html", language=None): + """Save/update docs under destination directory.""" + print("STEP: Generate docs in HTML format") + build(ctx, builder=format, language=language) + + print("STEP: Save docs under %s/" % dest) + source_dir = Path(_sphinxdoc_get_destdir(ctx, format, language=language)) + Path(dest).rmtree_p() + source_dir.copytree(dest) + + # -- POST-PROCESSING: Polish up. + for part in [".buildinfo", ".doctrees"]: + partpath = Path(dest)/part + if partpath.isdir(): + partpath.rmtree_p() + elif partpath.exists(): + partpath.remove_p() + + +@task(help={ + "language": 'Language to use, like "en" (default: "all" to build all).', +}) +def update_translation(ctx, language="all"): + """Update sphinx-doc translation(s) messages from the "English" docs. + + * Generates gettext *.po files in "build/docs/gettext/" directory + * Updates/generates gettext *.po per language in "docs/LOCALE/{language}/" + + .. note:: Afterwards, the missing message translations can be filled in. + + :param language: Indicate which language messages to update (or "all"). + + REQUIRES: + + * sphinx + * sphinx-intl >= 0.9 + + .. seealso:: https://github.com/sphinx-doc/sphinx-intl + """ + if language == "all": + # -- CASE: Process/update all support languages (translations). + DEFAULT_LANGUAGES = os.environ.get("SPHINXINTL_LANGUAGE", None) + if DEFAULT_LANGUAGES: + # -- EXAMPLE: SPHINXINTL_LANGUAGE="de,ja" + DEFAULT_LANGUAGES = DEFAULT_LANGUAGES.split(",") + languages = ctx.config.sphinx.languages or DEFAULT_LANGUAGES + else: + # -- CASE: Process only one language (translation use case). + languages = [language] + + # -- STEP: Generate *.po/*.pot files w/ sphinx-build -b gettext + build(ctx, builder="gettext") + + # -- STEP: Update *.po/*.pot files w/ sphinx-intl + if languages: + gettext_build_dir = _sphinxdoc_get_destdir(ctx, "gettext").abspath() + docs_sourcedir = ctx.config.sphinx.sourcedir + languages_opts = "-l "+ " -l ".join(languages) + with ctx.cd(docs_sourcedir): + ctx.run("sphinx-intl update -p {gettext_dir} {languages}".format( + gettext_dir=gettext_build_dir.relpath(docs_sourcedir), + languages=languages_opts)) + else: + print("OOPS: No languages specified (use: SPHINXINTL_LANGUAGE=...)") + + +# ----------------------------------------------------------------------------- +# TASK CONFIGURATION: +# ----------------------------------------------------------------------------- +namespace = Collection(clean, rebuild, linkcheck, browse, save, update_translation) +namespace.add_task(build, default=True) +namespace.configure({ + "sphinx": { + # -- FOR TASKS: docs.build, docs.rebuild, docs.clean, ... + "language": SPHINX_LANGUAGE_DEFAULT, + "sourcedir": "docs", + "destdir": "build/docs", + # -- FOR TASK: docs.update_translation + "languages": None, # -- List of language translations, like: de, ja, ... + } +}) + +# -- ADD CLEANUP TASK: +cleanup_tasks.add_task(clean, "clean_docs") +cleanup_tasks.configure(namespace.configuration()) |