Source code for pyquickhelper.sphinxext.sphinx_ext_helper

"""
Few helpers for :epkg:`Sphinx`.


:githublink:`%|py|5`
"""
import io
import logging
import os
import pickle
import urllib.parse as urllib_parse
import urllib.request as urllib_request
from urllib.parse import urljoin
from sphinx.util.inventory import InventoryFile


[docs]def info_blocref(app, doctree, fromdocname, class_name, entry_name, class_node, class_node_list): """ Log information with :epkg:`Sphinx`. :param app: application (Sphinx) :param doctree: document tree :param fromdocname: document currently being compiled :param class_name: name of the node :param entry_name: entry name in ``TITLES`` :param class_node: class node (:class:`blocref_node <pyquickhelper.sphinxext.sphinx_blocref_extension.blocref_node>`) :param class_node_list: class node list (:class:`blocreflist <pyquickhelper.sphinxext.sphinx_blocref_extension.blocreflist>`) :githublink:`%|py|27` """ incconf = '%s_include_%ss' % (class_name, class_name) rows2 = [] for node in doctree.traverse(class_node_list): breftag = node.get("breftag", None) rows2.append("tag={0} do={1}".format(breftag, app.config[incconf])) if len(rows2) == 0: return False attr_name = '%s_all_%ss' % (class_name, class_name) env = app.builder.env if hasattr(env, attr_name): bloc_list_env = getattr(env, attr_name) else: bloc_list_env = [] rows = [" [info_blocref]", "len(bloc_list_env)={0}".format(len(bloc_list_env)), ] rows.extend(rows2) rows.extend(["fromdocname='{0}'".format(fromdocname), "entry_name='{0}'".format(entry_name), "class_name='{0}'".format(class_name), "class_node='{0}'".format(class_node), "class_node_list='{0}'".format(class_node_list), "doctree='{0}'".format(type(doctree)), "#doctree={0}".format(len(doctree))]) message = " ".join(rows) logger = logging.getLogger("info_blocref") logger.info(message) return True
[docs]def sphinx_lang(env, default_value='en'): """ Returns the language defined in the configuration file. :param env: environment :param default_value: default value :return: language :githublink:`%|py|66` """ if hasattr(env, "settings"): settings = env.settings if hasattr(settings, "language_code"): lang = env.settings.language_code # pragma: no cover else: lang = "en" else: settings = None # pragma: no cover lang = "en" # pragma: no cover return lang
[docs]class TinyNode: """ Returned by :func:`traverse <pyquickhelper.sphinxext.sphinx_ext_helper.traverse>`. :githublink:`%|py|82` """
[docs] def __init__(self, parent): """ Create a note :param parent: parent node :githublink:`%|py|89` """ self.parent = parent
[docs]class NodeEnter(TinyNode): """ Returned by function :func:`traverse <pyquickhelper.sphinxext.sphinx_ext_helper.traverse>`. :githublink:`%|py|96` """ pass
[docs]class NodeLeave(TinyNode): """ Returned by function :func:`traverse <pyquickhelper.sphinxext.sphinx_ext_helper.traverse>`. :githublink:`%|py|103` """ pass
[docs]class WrappedNode: """ Wraps a docutils node. :githublink:`%|py|110` """
[docs] def __init__(self, node): self.node = node
[docs]def traverse(node, depth=0): """ Enumerates through all children but insert a node whenever digging or leaving the childrens nodes. :param node: node (from doctree) :param depth: current depth :return: enumerate (depth, node) :class:`NodeEnter <pyquickhelper.sphinxext.sphinx_ext_helper.NodeEnter>` and :class:`NodeLeave` are returned whenever entering or leaving nodes. :githublink:`%|py|126` """ if isinstance(node, WrappedNode): node = node.node ne = NodeEnter(node) nl = NodeLeave(node) yield (depth, ne) yield (depth, node) for n in node.children: for r in traverse(n, depth + 1): yield r yield (depth, nl)
[docs]def _get_data(url): """ Loads file ``objects.inv`` generated by extension :epkg:`sphinx.ext.intersphinx`. :param url: url of documentation, example ``https://pandas.pydata.org/docs/`` :return: instance of `InventoryFile` :githublink:`%|py|147` """ url_inv = urljoin(url, "objects.inv") if urllib_parse.urlparse(url_inv).scheme in ('http', 'https'): user_agent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11' # noqa: E501 headers = {'User-Agent': user_agent} req = urllib_request.Request(url_inv, None, headers) resp = urllib_request.urlopen(req) data = resp.read() else: with open(url, 'rb') as fid: data = fid.read() inv = InventoryFile.load(io.BytesIO(data), url, urljoin) return inv
[docs]def get_index(index_url, cache_dir): """ Retrieves documentation data for a specific module. :param url: url of documentation, example ``https://pandas.pydata.org/docs/`` :param cache_dir: restore a cached inventory stored with pickle :return: instance of `InventoryFile` :githublink:`%|py|171` """ if cache_dir is not None: base_file = index_url.replace("/", "_").split(':')[-1] + ".pkl" full_file = os.path.join(cache_dir, base_file) if os.path.exists(full_file): with open(full_file, "rb") as f: return pickle.load(f) index = _get_data(index_url) if cache_dir is not None: with open(full_file, "wb") as f: pickle.dump(index, f) return index