Created
March 3, 2020 03:52
-
-
Save dzhu/4477338e34620d141bc71f4dc214ea47 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Sphinx is hardcoded to interpret links to downloadable files relative to the root of the docs | |
source tree. However, the downloadable files we want to use are themselves generated at build time, | |
and we would therefore like them to be separate from the source. This module is a Sphinx plugin that | |
replaces the normal interpretation of links, causing Sphinx to look for downloads relative to a | |
different directory (which is set in `conf.py`). | |
""" | |
import logging | |
import os | |
import types | |
from typing import Any, Dict | |
from docutils import nodes | |
from sphinx import addnodes, application | |
from sphinx.environment.collectors import asset | |
from sphinx.locale import __ | |
logger = logging.getLogger(__name__) | |
class DownloadExternalFileCollector(asset.DownloadFileCollector): | |
def process_doc( | |
self: asset.DownloadFileCollector, app: application.Sphinx, doctree: nodes.document | |
) -> None: | |
""" | |
This function is different from the original method only in doing some surgery on the paths | |
it finds when a separate root directory is configured. | |
Compare to the original at https://github.com/sphinx-doc/sphinx/blob/cdc7cc6fb3e2ade64149a5bed9b3b5be0132ce47/sphinx/environment/collectors/asset.py#L122 | |
""" | |
for node in doctree.traverse(addnodes.download_reference): | |
targetname = node["reftarget"] | |
if "://" in targetname: | |
node["refuri"] = targetname | |
else: | |
rel_filename, filename = app.env.relfn2path(targetname, app.env.docname) | |
if app.config.downloads_root: | |
filename = os.path.abspath( | |
os.path.join(app.config.downloads_root, rel_filename) | |
) | |
rel_filename = os.path.relpath(filename, app.env.srcdir) | |
app.env.dependencies[app.env.docname].add(rel_filename) | |
if not os.access(filename, os.R_OK): | |
logger.warning( | |
__("download file not readable: %s") % filename, | |
location=node, | |
type="download", | |
subtype="not_readable", | |
) | |
continue | |
node["filename"] = app.env.dlfiles.add_file(app.env.docname, rel_filename) | |
def setup(app: application.Sphinx) -> Dict[str, Any]: | |
app.add_config_value("downloads_root", None, "html") | |
# Disable the old instance of DownloadFileCollector and replace it with ours. | |
for event in app.events.listeners.values(): | |
for listener_id, callback in list(event.items()): | |
if isinstance(callback, types.MethodType) and isinstance( | |
callback.__self__, asset.DownloadFileCollector | |
): | |
del event[listener_id] | |
app.add_env_collector(DownloadExternalFileCollector) | |
return { | |
"version": "0", | |
"parallel_read_safe": True, | |
"parallel_write_safe": True, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment