def mock_sphinx_env(conf=None, srcdir=None, document=None): """Set up an environment, to parse sphinx roles/directives, outside of a `sphinx-build`. :param conf: a dictionary representation of the sphinx `conf.py` :param srcdir: a path to a source directory (for example, can be used for `include` statements) This primarily copies the code in `sphinx.util.docutils.docutils_namespace` and `sphinx.util.docutils.sphinx_domains`. """ # store currently loaded roles/directives, so we can revert on exit _directives = copy.copy(directives._directives) _roles = copy.copy(roles._roles) # Monkey-patch directive and role dispatch, # so that sphinx domain-specific markup takes precedence. app = minimal_sphinx_app(configuration=conf, sourcedir=srcdir) _sphinx_domains = sphinx_domains(app.env) _sphinx_domains.enable() if document is not None: document.settings.env = app.env try: yield app finally: # revert loaded roles/directives directives._directives = _directives roles._roles = _roles # TODO unregister nodes (see `sphinx.util.docutils.docutils_namespace`) for node in list(additional_nodes): unregister_node(node) additional_nodes.discard(node) # revert directive/role function (see `sphinx.util.docutils.sphinx_domains`) _sphinx_domains.disable()
def mock_sphinx_env_compat( conf=None, srcdir=None, document=None, with_builder=False, raise_on_warning=False, ): """Set up an environment, to parse sphinx roles/directives, outside of a `sphinx-build`. :param conf: a dictionary representation of the sphinx `conf.py` :param srcdir: a path to a source directory (for example, can be used for `include` statements) This primarily copies the code in `sphinx.util.docutils.docutils_namespace` and `sphinx.util.docutils.sphinx_domains`. """ with tempfile.TemporaryDirectory() as tempdir: # store currently loaded roles/directives, so we can revert on exit _directives = copy.copy(directives._directives) _roles = copy.copy(roles._roles) # creating a builder attempts to make the doctreedir app = Sphinx( srcdir=srcdir, confdir=None, outdir=tempdir, doctreedir=tempdir, confoverrides=conf, buildername=with_builder, warningiserror=raise_on_warning, keep_going=True, ) _sphinx_domains = sphinx_domains(app.env) _sphinx_domains.enable() if document is not None: document.settings.env = app.env try: yield app finally: # NOTE: the following cleanup is to avoid warnings while creating a Sphinx # Application multiple times # revert loaded roles/directives directives._directives = _directives roles._roles = _roles for node in list(additional_nodes): unregister_node(node) additional_nodes.discard(node) # revert directive/role function (ee # `sphinx.util.docutils.sphinx_domains`) _sphinx_domains.disable()
def __exit__(self, exception_type, exception_val, traceback): if not self.load_sphinx_env: return super().__exit__(exception_type, exception_val, traceback) # revert loaded roles/directives directives._directives = self._directives roles._roles = self._roles self._directives = None self._roles = None # unregister nodes (see `sphinx.util.docutils.docutils_namespace`) from sphinx.util.docutils import additional_nodes, unregister_node for node in list(additional_nodes): unregister_node(node) additional_nodes.discard(node) # revert directive/role function (see `sphinx.util.docutils.sphinx_domains`) self._sphinx_domains.disable() self._sphinx_domains = None self._env = None return super().__exit__(exception_type, exception_val, traceback)