Source code for pyquickhelper.sphinxext.sphinx_downloadlink_extension

# -*- coding: utf-8 -*-
"""
Defines a :epkg:`sphinx` extension to show a link instead of downloading it.
This extension does not work for :epkg:`Sphinx` < 1.8.

.. versionadded:: 1.8


:githublink:`%|py|9`
"""
import os
import sphinx
from docutils import nodes
from sphinx import addnodes
from sphinx.environment.collectors import EnvironmentCollector
from sphinx.util import status_iterator, relative_path, ensuredir, copyfile
from sphinx.util import logging
from sphinx.locale import __

try:
    from sphinx.util import DownloadFiles
except ImportError:
    # Sphinx < 1.8
    class DownloadFiles(dict):
        def purge_doc(self, *args, **kwargs):
            pass

        def merge_other(self, *args, **kwargs):
            pass

        def add_file(self, docname, ref_filename):
            self[docname] = (docname, ref_filename)






































[docs]class DownloadLinkFileCollector(EnvironmentCollector): """ Download files collector for *sphinx.environment*. :githublink:`%|py|221` """ def check_attr(self, env): if not hasattr(env, 'dllinkfiles'): env.dllinkfiles = DownloadFiles()
[docs] def clear_doc(self, app, env, docname): self.check_attr(env) if env.dllinkfiles and len(env.dllinkfiles) > 0: env.dllinkfiles.purge_doc(docname)
[docs] def merge_other(self, app, env, docnames, other): logger = logging.getLogger("downloadlink") logger.info("[downloadlink] merge") self.check_attr(env) env.dllinkfiles.merge_other(docnames, other.dllinkfiles)
[docs] def process_doc(self, app, doctree): # type: (Sphinx, nodes.Node) -> None """Process downloadable file paths. """ self.check_attr(app.env) nb = 0 for node in doctree.traverse(downloadlink_node): format = node["format"] if format and format != app.builder.format: continue nb += 1 dest = os.path.split(app.env.docname)[0] name = node["filename"] rel_filename = os.path.join(dest, name) app.env.dependencies[app.env.docname].add(rel_filename) node['dest'] = app.env.dllinkfiles.add_file( app.env.docname, rel_filename) if nb > 0: logger = logging.getLogger("downloadlink") logger.info("[downloadlink] processed {0}".format(nb))
[docs]def copy_download_files(app, exc): """ Copies all files mentioned with role *downloadlink*. :githublink:`%|py|262` """ if exc: builder = app.builder logger = logging.getLogger("downloadlink") mes = "Builder format '{0}'-'{1}', unable to copy file due to {2}".format( builder.format, builder.__class__.__name__, exc) logger.warning(mes) return def to_relpath(f): # type: (unicode) -> unicode return relative_path(app.srcdir, f) # copy downloadable files builder = app.builder if builder.env.dllinkfiles: logger = logging.getLogger("downloadlink") logger.info("[downloadlink] copy_download_files") for src in status_iterator(builder.env.dllinkfiles, __('copying downloadable(link) files... '), "brown", len( builder.env.dllinkfiles), builder.app.verbosity, stringify_func=to_relpath): docname, dest = builder.env.dllinkfiles[src] relpath = set(os.path.dirname(dn) for dn in docname) for rel in relpath: dest = os.path.join(builder.outdir, rel) ensuredir(os.path.dirname(dest)) shortname = os.path.split(src)[-1] dest = os.path.join(dest, shortname) name = os.path.join(builder.srcdir, src) try: copyfile(name, dest) logger.info( "[downloadlink] copy '{0}' to '{1}'".format(name, dest)) except FileNotFoundError: mes = "Builder format '{0}'-'{3}', unable to copy file '{1}' into {2}'".format( builder.format, name, dest, builder.__class__.__name__) logger.warning( "[downloadlink] cannot copy '{0}' to '{1}'".format(name, dest))
[docs]def setup(app): """ setup for ``bigger`` (sphinx) :githublink:`%|py|305` """ app.add_env_collector(DownloadLinkFileCollector) if hasattr(app, "add_mapping"): app.add_mapping('downloadlink', downloadlink_node) app.connect('build-finished', copy_download_files) app.add_node(downloadlink_node, html=(visit_downloadlink_node_html, depart_downloadlink_node_html), epub=(visit_downloadlink_node_html, depart_downloadlink_node_html), latex=(visit_downloadlink_node_latex, depart_downloadlink_node_latex), elatex=(visit_downloadlink_node_latex, depart_downloadlink_node_latex), text=(visit_downloadlink_node_text, depart_downloadlink_node_text), md=(visit_downloadlink_node_md, depart_downloadlink_node_md), rst=(visit_downloadlink_node_rst, depart_downloadlink_node_rst)) app.add_role('downloadlink', process_downloadlink_role) return {'version': sphinx.__display_version__, 'parallel_read_safe': True}