Created
January 7, 2021 19:03
-
-
Save Cilyan/f6d3e5ba1c446ac765d349ad4167936b to your computer and use it in GitHub Desktop.
Modification of sphinx.ext.ifconfig to run as a Transform as early as possible. By processing the conditions early and removing the nodes that will not go to the final doctree, the goal is to reduce the amount of unexpected errors and warnings that later transforms may face when processing nodes that are not going to be included anyway.
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
""" | |
sphinxcontrib.ifearly | |
~~~~~~~~~~~~~~~~~~~~~ | |
Provides the ``ifearly`` directive that allows to write documentation | |
that is included depending on configuration variables. | |
Usage:: | |
.. ifearly:: releaselevel in ('alpha', 'beta', 'rc') | |
This stuff is only included in the built docs for unstable versions. | |
The argument for ``ifearly`` is a plain Python expression, evaluated in the | |
namespace of the project configuration (that is, all variables from | |
``conf.py`` are available.) | |
The difference with the ``ifconfig`` directive, is that ``ifearly`` is | |
evaluated early in the transform process, so that content that is not | |
included in the final documentation is not evaluated. On the contrary, | |
the ``ifconfig`` directive is evaluated late. Content is always evaluated, | |
possibly raising errors and side-effect, but finally removed just before the | |
resulting document is written. | |
Original code from ``sphinx.ext.ifconfig`` | |
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. | |
:license: BSD, see LICENSE for details. | |
""" | |
from typing import Any, Dict, List | |
from docutils import nodes | |
from docutils.nodes import Node | |
import sphinx | |
from sphinx.application import Sphinx | |
from sphinx.transforms import SphinxTransform | |
from sphinx.util.docutils import SphinxDirective | |
from sphinx.util.nodes import nested_parse_with_titles | |
class ifearly(nodes.Element): | |
pass | |
class IfEarly(SphinxDirective): | |
has_content = True | |
required_arguments = 1 | |
optional_arguments = 0 | |
final_argument_whitespace = True | |
option_spec = {} # type: Dict | |
def run(self) -> List[Node]: | |
node = ifearly() | |
node.document = self.state.document | |
self.set_source_info(node) | |
node['expr'] = self.arguments[0] | |
nested_parse_with_titles(self.state, self.content, node) | |
return [node] | |
class IfEarlyTransform(SphinxTransform): | |
# run as early as possible | |
default_priority = 5 | |
def apply(self) -> None: | |
ns = {confval.name: confval.value for confval in self.app.config} | |
ns.update(self.app.config.__dict__.copy()) | |
ns['builder'] = self.app.builder.name | |
for node in self.document.traverse(ifearly): | |
try: | |
res = eval(node['expr'], ns) | |
except Exception as err: | |
# handle exceptions in a clean fashion | |
from traceback import format_exception_only | |
msg = ''.join(format_exception_only(err.__class__, err)) | |
newnode = self.document.doctree.reporter.error( | |
'Exception occurred in ifearly expression: \n%s' % msg, | |
base_node=node | |
) | |
node.replace_self(newnode) | |
else: | |
if not res: | |
node.replace_self([]) | |
else: | |
node.replace_self(node.children) | |
def setup(app: Sphinx) -> Dict[str, Any]: | |
app.add_node(ifearly) | |
app.add_directive('ifearly', IfEarly) | |
app.add_transform(IfEarlyTransform) | |
return {'version': '0.1.0', 'parallel_read_safe': True} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment