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 read_doc(self, docname: str) -> None: """Parse a file and add/update inventory entries for the doctree.""" self.env.prepare_settings(docname) # Add confdir/docutils.conf to dependencies list if exists docutilsconf = path.join(self.confdir, 'docutils.conf') if path.isfile(docutilsconf): self.env.note_dependency(docutilsconf) with sphinx_domains(self.env), rst.default_role( docname, self.config.default_role): doctree = read_doc(self.app, self.env, self.env.doc2path(docname)) # store time of reading, for outdated files detection # (Some filesystems have coarse timestamp resolution; # therefore time.time() can be older than filesystem's timestamp. # For example, FAT32 has 2sec timestamp resolution.) self.env.all_docs[docname] = max( time.time(), path.getmtime(self.env.doc2path(docname))) # cleanup self.env.temp_data.clear() self.env.ref_context.clear() self.write_doctree(docname, doctree)
def read_doc(self, docname, app=None): # type: (unicode, Sphinx) -> None """Parse a file and add/update inventory entries for the doctree.""" self.prepare_settings(docname) docutilsconf = path.join(self.srcdir, 'docutils.conf') # read docutils.conf from source dir, not from current dir OptionParser.standard_config_files[1] = docutilsconf if path.isfile(docutilsconf): self.note_dependency(docutilsconf) with sphinx_domains(self), rst.default_role(docname, self.config.default_role): doctree = read_doc(self.app, self, self.doc2path(docname)) # store time of reading, for outdated files detection # (Some filesystems have coarse timestamp resolution; # therefore time.time() can be older than filesystem's timestamp. # For example, FAT32 has 2sec timestamp resolution.) self.all_docs[docname] = max(time.time(), path.getmtime(self.doc2path(docname))) # cleanup self.temp_data.clear() self.ref_context.clear() self.write_doctree(docname, doctree)
def sphinx_env(app_env: SphinxAppEnv): """This context enters the standard sphinx contexts, then registers the roles, directives and nodes saved in the app_env. The standard sphinx contexts: - Patch docutils.languages.get_language(), to suppress reporter warnings - Temporarily sets `os.environ['DOCUTILSCONFIG']` to the sphinx confdir - Saves copies of roles._roles and directives._directives & resets them on exit - Un-registers additional nodes (set via `register_node`) on exit (by deleting `GenericNodeVisitor` visit/depart methods) - Patches roles.roles and directives.directives functions to also look in domains """ with patch_docutils( app_env.app.confdir), docutils_namespace(), sphinx_domains( app_env.app.env): from docutils.parsers.rst import directives, roles from sphinx.util.docutils import register_node if app_env.roles: roles._roles.update(app_env.roles) if app_env.directives: directives._directives.update(app_env.directives) for node in app_env.additional_nodes: register_node(node) # TODO how to make `unregister_node` thread safe yield
def make_html(self, docstring): with Timer('make_html'): with open(self.doc_file, 'w') as f: f.write(docstring) app = self.app docname = 'index' with sphinx_domains(app.builder.env), rst.default_role( docname, app.builder.env.config.default_role): doctree = read_doc(app.builder.env.app, app.builder.env, app.builder.env.doc2path(docname)) for domain in app.builder.env.domains.values(): domain.process_doc(app.builder.env, docname, doctree) app.emit('doctree-read', doctree) app.builder.prepare_writing({docname}) doctree = app.builder.env.get_and_resolve_doctree( docname, app.builder, doctree) app.builder.write_doc_serialized(docname, doctree) doctree.settings = app.builder.docsettings app.builder.secnumbers = app.builder.env.toc_secnumbers.get( docname, {}) app.builder.fignumbers = app.builder.env.toc_fignumbers.get( docname, {}) app.builder.imgpath = relative_uri( app.builder.get_target_uri(docname), '_images') app.builder.dlpath = relative_uri( app.builder.get_target_uri(docname), '_downloads') app.builder.current_docname = docname app.builder.docwriter.write(doctree, self.destination) app.builder.docwriter.assemble_parts() body = app.builder.docwriter.parts['fragment'] return body
def read_doc(self, docname): # type: (unicode) -> None """Parse a file and add/update inventory entries for the doctree.""" self.env.prepare_settings(docname) # Add confdir/docutils.conf to dependencies list if exists docutilsconf = path.join(self.confdir, 'docutils.conf') if path.isfile(docutilsconf): self.env.note_dependency(docutilsconf) with sphinx_domains(self.env), rst.default_role(docname, self.config.default_role): doctree = read_doc(self.app, self.env, self.env.doc2path(docname)) # store time of reading, for outdated files detection # (Some filesystems have coarse timestamp resolution; # therefore time.time() can be older than filesystem's timestamp. # For example, FAT32 has 2sec timestamp resolution.) self.env.all_docs[docname] = max(time.time(), path.getmtime(self.env.doc2path(docname))) # cleanup self.env.temp_data.clear() self.env.ref_context.clear() self.write_doctree(docname, doctree)
def read_doc(self, docname: str) -> None: """Parse a file and add/update inventory entries for the doctree.""" self.env.prepare_settings(docname) # Add confdir/docutils.conf to dependencies list if exists docutilsconf = path.join(self.confdir, 'docutils.conf') if path.isfile(docutilsconf): self.env.note_dependency(docutilsconf) filename = self.env.doc2path(docname) filetype = get_filetype(self.app.config.source_suffix, filename) publisher = self.app.registry.get_publisher(self.app, filetype) with sphinx_domains(self.env), rst.default_role(docname, self.config.default_role): # set up error_handler for the target document codecs.register_error('sphinx', UnicodeDecodeErrorHandler(docname)) # type: ignore publisher.set_source(source_path=filename) publisher.publish() doctree = publisher.document # store time of reading, for outdated files detection # (Some filesystems have coarse timestamp resolution; # therefore time.time() can be older than filesystem's timestamp. # For example, FAT32 has 2sec timestamp resolution.) self.env.all_docs[docname] = max(time.time(), path.getmtime(self.env.doc2path(docname))) # cleanup self.env.temp_data.clear() self.env.ref_context.clear() self.write_doctree(docname, doctree)
def _parse(app: Sphinx, code: str) -> document: with NamedTemporaryFile("w+", suffix=".rst", dir=app.env.srcdir) as f: f.write(code) f.flush() app.env.prepare_settings(f.name) with sphinx_domains(app.env), rst.default_role( f.name, app.config.default_role): return read_doc(app, app.env, f.name)
def find_autoasdf_directives(env, filename): docname = env.path2doc(filename) env.prepare_settings(docname) with sphinx_domains(env), rst.default_role(docname, env.config.default_role): doctree = read_doc(env.app, env, env.doc2path(docname)) return doctree.traverse(schema_def)
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 settings(app): texescape.init() # otherwise done by the latex builder optparser = frontend.OptionParser(components=(RstParser, HTMLWriter, LaTeXWriter)) settings = optparser.get_default_values() settings.env = app.builder.env settings.env.temp_data['docname'] = 'dummy' domain_context = sphinx_domains(settings.env) domain_context.enable() yield settings domain_context.disable()
def settings(app): texescape.init() # otherwise done by the latex builder optparser = frontend.OptionParser( components=(RstParser, HTMLWriter, LaTeXWriter)) settings = optparser.get_default_values() settings.env = app.builder.env settings.env.temp_data['docname'] = 'dummy' domain_context = sphinx_domains(settings.env) domain_context.enable() yield settings domain_context.disable()
def setup_module(): global app, settings, parser, domain_context texescape.init() # otherwise done by the latex builder app = TestApp() optparser = frontend.OptionParser( components=(rst.Parser, HTMLWriter, LaTeXWriter)) settings = optparser.get_default_values() settings.env = app.builder.env settings.env.temp_data['docname'] = 'dummy' parser = rst.Parser() domain_context = sphinx_domains(settings.env) domain_context.enable()
def _get_doctree(docstring: str): docname = "_docstring" builder = _get_builder() env = builder.env env.prepare_settings(docname) with sphinx_domains(env), rst.default_role(docname, builder.config.default_role): document = publish_doctree(docstring, settings_overrides=env.settings) env.apply_post_transforms(document, docname) return document
def sphinx_state(local_app): """ Fixture which will provide a sphinx state for use in testing sphinx directives. Yields: :class:`docutils.parsers.rst.states.State`: A state for use in testing directive functionality. """ # Get the environment and decorate it with what sphinx may need for the # parsing. env = local_app.env env.temp_data["docname"] = "test" # A fake document name # Create a document and inliner object, to be perfectly honest not sure # exactly what these are or do, but needed to get the directive to run. document = new_document(__file__) document.settings.pep_references = 1 document.settings.rfc_references = 1 document.settings.env = env document.settings.tab_width = 4 inliner = Inliner() inliner.init_customizations(document.settings) # Create a state machine so that we can get a state to pass back. statemachine = RSTStateMachine(state_classes=state_classes, initial_state="Body") statemachine.input_lines = StringList([""] * 40) state = statemachine.get_state() state.document = document state.memo = Struct( inliner=inliner, language=en, title_styles=[], reporter=document.reporter, document=document, section_level=0, section_bubble_up_kludge=False, ) state.memo.reporter.get_source_and_line = statemachine.get_source_and_line # The environemnt isn't normally available on the state in sphinx, but it's # done here to make testing easier. state.env = env # Sphinx monkeypatches docutils when run. This is how it get's # monkeypatched so that the python directives and roles can be found with sphinx_domains(env): # Provide the state back to the test. yield state
def settings(app): texescape.init() # otherwise done by the latex builder optparser = frontend.OptionParser(components=(RstParser, HTMLWriter, LaTeXWriter)) settings = optparser.get_default_values() settings.smart_quotes = True settings.env = app.builder.env settings.env.temp_data['docname'] = 'dummy' settings.contentsname = 'dummy' settings.rfc_base_url = 'http://tools.ietf.org/html/' domain_context = sphinx_domains(settings.env) domain_context.enable() yield settings domain_context.disable()
def parse(app, text, docname='index'): # type: (Sphinx, str, str) -> nodes.document """Parse a string as reStructuredText with Sphinx application.""" try: app.env.temp_data['docname'] = docname parser = RSTParser() parser.set_application(app) with sphinx_domains(app.env): return publish_doctree(text, path.join(app.srcdir, docname + '.rst'), reader=SphinxStandaloneReader(app), parser=parser, settings_overrides={'env': app.env, 'gettext_compact': True}) finally: app.env.temp_data.pop('docname', None)
def parse(app: Sphinx, text: str, docname: str = "index") -> nodes.document: """Parse a string as MystMarkdown with Sphinx application.""" app.env.temp_data["docname"] = docname app.env.all_docs[docname] = time.time() reader = SphinxStandaloneReader() reader.setup(app) parser = MystParser() parser.set_application(app) with sphinx_domains(app.env): return publish_doctree( text, path.join(app.srcdir, docname + ".md"), reader=reader, parser=parser, parser_name="markdown", settings_overrides={"env": app.env, "gettext_compact": True}, )
def settings(app): texescape.init() # otherwise done by the latex builder with warnings.catch_warnings(): warnings.filterwarnings('ignore', category=DeprecationWarning) # DeprecationWarning: The frontend.OptionParser class will be replaced # by a subclass of argparse.ArgumentParser in Docutils 0.21 or later. optparser = frontend.OptionParser(components=(RstParser, HTMLWriter, LaTeXWriter), defaults=default_settings) settings = optparser.get_default_values() settings.smart_quotes = True settings.env = app.builder.env settings.env.temp_data['docname'] = 'dummy' settings.contentsname = 'dummy' domain_context = sphinx_domains(settings.env) domain_context.enable() yield settings domain_context.disable()
def read_doc(self, docname, app=None): # type: (unicode, Sphinx) -> None """Parse a file and add/update inventory entries for the doctree.""" self.prepare_settings(docname) docutilsconf = path.join(self.srcdir, 'docutils.conf') # read docutils.conf from source dir, not from current dir OptionParser.standard_config_files[1] = docutilsconf if path.isfile(docutilsconf): self.note_dependency(docutilsconf) with sphinx_domains(self), rst.default_role(docname, self.config.default_role): doctree = read_doc(self.app, self, self.doc2path(docname)) # post-processing for domain in itervalues(self.domains): domain.process_doc(self, docname, doctree) # allow extension-specific post-processing if app: app.emit('doctree-read', doctree) # store time of reading, for outdated files detection # (Some filesystems have coarse timestamp resolution; # therefore time.time() can be older than filesystem's timestamp. # For example, FAT32 has 2sec timestamp resolution.) self.all_docs[docname] = max( time.time(), path.getmtime(self.doc2path(docname))) if self.versioning_condition: # add uids for versioning versioning.prepare(doctree) # cleanup self.temp_data.clear() self.ref_context.clear() self.write_doctree(docname, doctree)
def __enter__(self): """If `load_sphinx_env=True`, we set up an environment, to parse sphinx roles/directives, outside of a `sphinx-build`. This primarily copies the code in `sphinx.util.docutils.docutils_namespace` and `sphinx.util.docutils.sphinx_domains`. """ if not self.load_sphinx_env: return super().__enter__() # store currently loaded roles/directives, so we can revert on exit self._directives = copy.copy(directives._directives) self._roles = copy.copy(roles._roles) # Monkey-patch directive and role dispatch, # so that sphinx domain-specific markup takes precedence. self._env = self.mock_sphinx_env( configuration=self.sphinx_conf, sourcedir=self.sphinx_srcdir ).env from sphinx.util.docutils import sphinx_domains self._sphinx_domains = sphinx_domains(self._env) self._sphinx_domains.enable() return super().__enter__()
start_time = time() # app.builder.env._read_serial(docnames, app.builder.env.app) for docname in docnames: print('docname', docname) app.emit('env-purge-doc', app.builder.env, docname) app.builder.env.clear_doc(docname) # app.builder.env.read_doc(docname, app) app.builder.env.prepare_settings(docname) docutilsconf = path.join(app.builder.env.srcdir, 'docutils.conf') # read docutils.conf from source dir, not from current dir OptionParser.standard_config_files[1] = docutilsconf if path.isfile(docutilsconf): app.builder.env.note_dependency(docutilsconf) with sphinx_domains(app.builder.env), rst.default_role(docname, app.builder.env.config.default_role): doctree = read_doc(app.builder.env.app, app.builder.env, app.builder.env.doc2path(docname)) # post-processing for domain in app.builder.env.domains.values(): domain.process_doc(app.builder.env, docname, doctree) # allow extension-specific post-processing if app: app.emit('doctree-read', doctree) print('docnames', docnames) updated_docnames = set(docnames) print('updated_docnames:', updated_docnames)
def get_doctree(path, **kwargs): """ Obtain a Sphinx doctree from the RST file at ``path``. Performs no Releases-specific processing; this code would, ideally, be in Sphinx itself, but things there are pretty tightly coupled. So we wrote this. Any additional kwargs are passed unmodified into an internal `make_app` call. :param str path: A relative or absolute file path string. :returns: A two-tuple of the generated ``sphinx.application.Sphinx`` app and the doctree (a ``docutils.document`` object). .. versionchanged:: 1.6 Added support for passing kwargs to `make_app`. """ root, filename = os.path.split(path) docname, _ = os.path.splitext(filename) # TODO: this only works for top level changelog files (i.e. ones where # their dirname is the project/doc root) app = make_app(srcdir=root, **kwargs) # Create & init a BuildEnvironment. Mm, tasty side effects. app._init_env(freshenv=True) env = app.env # More arity/API changes: Sphinx 1.3/1.4-ish require one to pass in the app # obj in BuildEnvironment.update(); modern Sphinx performs that inside # Application._init_env() (which we just called above) and so that kwarg is # removed from update(). EAFP. kwargs = dict( config=app.config, srcdir=root, doctreedir=app.doctreedir, app=app, ) try: env.update(**kwargs) except TypeError: # Assume newer Sphinx w/o an app= kwarg del kwargs["app"] env.update(**kwargs) # Code taken from sphinx.environment.read_doc; easier to manually call # it with a working Environment object, instead of doing more random crap # to trick the higher up build system into thinking our single changelog # document was "updated". env.temp_data["docname"] = docname env.app = app # NOTE: SphinxStandaloneReader API changed in 1.4 :( reader_kwargs = { "app": app, "parsers": env.config.source_parsers, } if sphinx.version_info[:2] < (1, 4): del reader_kwargs["app"] # This monkeypatches (!!!) docutils to 'inject' all registered Sphinx # domains' roles & so forth. Without this, rendering the doctree lacks # almost all Sphinx magic, including things like :ref: and :doc:! with sphinx_domains(env): try: reader = SphinxStandaloneReader(**reader_kwargs) except TypeError: # If we import from io, this happens automagically, not in API del reader_kwargs["parsers"] reader = SphinxStandaloneReader(**reader_kwargs) pub = Publisher( reader=reader, writer=SphinxDummyWriter(), destination_class=NullOutput ) pub.set_components(None, "restructuredtext", None) pub.process_programmatic_settings(None, env.settings, None) # NOTE: docname derived higher up, from our given path src_path = env.doc2path(docname) source = SphinxFileInput( app, env, source=None, source_path=src_path, encoding=env.config.source_encoding, ) pub.source = source pub.settings._source = src_path pub.set_destination(None, None) pub.publish() return app, pub.document
def read_doc(self, docname, app=None): # type: (unicode, Sphinx) -> None """Parse a file and add/update inventory entries for the doctree.""" self.temp_data['docname'] = docname # defaults to the global default, but can be re-set in a document self.temp_data['default_domain'] = \ self.domains.get(self.config.primary_domain) self.settings['input_encoding'] = self.config.source_encoding self.settings['trim_footnote_reference_space'] = \ self.config.trim_footnote_reference_space self.settings['gettext_compact'] = self.config.gettext_compact docutilsconf = path.join(self.srcdir, 'docutils.conf') # read docutils.conf from source dir, not from current dir OptionParser.standard_config_files[1] = docutilsconf if path.isfile(docutilsconf): self.note_dependency(docutilsconf) with sphinx_domains(self): if self.config.default_role: role_fn, messages = roles.role(self.config.default_role, english, 0, dummy_reporter) if role_fn: roles._roles[''] = role_fn else: logger.warning('default role %s not found', self.config.default_role, location=docname) codecs.register_error('sphinx', self.warn_and_replace) # type: ignore # publish manually reader = SphinxStandaloneReader(self.app, parsers=self.config.source_parsers) pub = Publisher(reader=reader, writer=SphinxDummyWriter(), destination_class=NullOutput) pub.set_components(None, 'restructuredtext', None) pub.process_programmatic_settings(None, self.settings, None) src_path = self.doc2path(docname) source = SphinxFileInput(app, self, source=None, source_path=src_path, encoding=self.config.source_encoding) pub.source = source pub.settings._source = src_path pub.set_destination(None, None) pub.publish() doctree = pub.document # post-processing for domain in itervalues(self.domains): domain.process_doc(self, docname, doctree) # allow extension-specific post-processing if app: app.emit('doctree-read', doctree) # store time of reading, for outdated files detection # (Some filesystems have coarse timestamp resolution; # therefore time.time() can be older than filesystem's timestamp. # For example, FAT32 has 2sec timestamp resolution.) self.all_docs[docname] = max( time.time(), path.getmtime(self.doc2path(docname))) if self.versioning_condition: old_doctree = None if self.versioning_compare: # get old doctree try: with open(self.doc2path(docname, self.doctreedir, '.doctree'), 'rb') as f: old_doctree = pickle.load(f) except EnvironmentError: pass # add uids for versioning if not self.versioning_compare or old_doctree is None: list(add_uids(doctree, self.versioning_condition)) else: list(merge_doctrees( old_doctree, doctree, self.versioning_condition)) # make it picklable doctree.reporter = None doctree.transformer = None doctree.settings.warning_stream = None doctree.settings.env = None doctree.settings.record_dependencies = None # cleanup self.temp_data.clear() self.ref_context.clear() roles._roles.pop('', None) # if a document has set a local default role # save the parsed doctree doctree_filename = self.doc2path(docname, self.doctreedir, '.doctree') ensuredir(path.dirname(doctree_filename)) with open(doctree_filename, 'wb') as f: pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
def get_doctree(path, **kwargs): """ Obtain a Sphinx doctree from the RST file at ``path``. Performs no Releases-specific processing; this code would, ideally, be in Sphinx itself, but things there are pretty tightly coupled. So we wrote this. Any additional kwargs are passed unmodified into an internal `make_app` call. :param str path: A relative or absolute file path string. :returns: A two-tuple of the generated ``sphinx.application.Sphinx`` app and the doctree (a ``docutils.document`` object). .. versionchanged:: 1.6 Added support for passing kwargs to `make_app`. """ root, filename = os.path.split(path) docname, _ = os.path.splitext(filename) # TODO: this only works for top level changelog files (i.e. ones where # their dirname is the project/doc root) app = make_app(srcdir=root, **kwargs) # Create & init a BuildEnvironment. Mm, tasty side effects. app._init_env(freshenv=True) env = app.env # More arity/API changes: Sphinx 1.3/1.4-ish require one to pass in the app # obj in BuildEnvironment.update(); modern Sphinx performs that inside # Application._init_env() (which we just called above) and so that kwarg is # removed from update(). EAFP. kwargs = dict( config=app.config, srcdir=root, doctreedir=app.doctreedir, app=app, ) try: env.update(**kwargs) except TypeError: # Assume newer Sphinx w/o an app= kwarg del kwargs['app'] env.update(**kwargs) # Code taken from sphinx.environment.read_doc; easier to manually call # it with a working Environment object, instead of doing more random crap # to trick the higher up build system into thinking our single changelog # document was "updated". env.temp_data['docname'] = docname env.app = app # NOTE: SphinxStandaloneReader API changed in 1.4 :( reader_kwargs = { 'app': app, 'parsers': env.config.source_parsers, } if sphinx.version_info[:2] < (1, 4): del reader_kwargs['app'] # This monkeypatches (!!!) docutils to 'inject' all registered Sphinx # domains' roles & so forth. Without this, rendering the doctree lacks # almost all Sphinx magic, including things like :ref: and :doc:! with sphinx_domains(env): reader = SphinxStandaloneReader(**reader_kwargs) pub = Publisher(reader=reader, writer=SphinxDummyWriter(), destination_class=NullOutput) pub.set_components(None, 'restructuredtext', None) pub.process_programmatic_settings(None, env.settings, None) # NOTE: docname derived higher up, from our given path src_path = env.doc2path(docname) source = SphinxFileInput( app, env, source=None, source_path=src_path, encoding=env.config.source_encoding, ) pub.source = source pub.settings._source = src_path pub.set_destination(None, None) pub.publish() return app, pub.document
def mock_document(tmp_path) -> nodes.document: settings = OptionParser(components=(RSTParser, )).get_default_values() document = new_document("notset", settings=settings) document.settings.env = MockEnv(tmp_path) with sphinx_domains(document.settings.env): yield document