def test_yosys_script(self): TEST_NAME = "test_compat" TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) TEST_FILES = ["test_compat/test_compat.rst", "code/verilog/adder.v"] TEST_JINJA_DICT = { "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), "master_doc": "'test_compat'", "custom_variables": """ extensions = [ 'sphinxcontrib_verilog_diagrams', ]""" } self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) # Run the Sphinx sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) with docutils_namespace(): app = Sphinx(buildername="html", warningiserror=True, **sphinx_dirs) app.build(force_all=True)
def test_yosys_path(self): TEST_NAME = "test_yosys_path" TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) TEST_FILES = [ "test_yosys_type/test_yosys_path.rst", "code/verilog/adder.v" ] yosys_path = shutil.which("yosys") TEST_JINJA_DICT = { "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), "master_doc": "'test_yosys_path'", "custom_variables": "hdl_diagram_yosys = '{}'".format(yosys_path) } self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) # Run the Sphinx sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) with docutils_namespace(): app = Sphinx(buildername="html", warningiserror=True, **sphinx_dirs) app.build(force_all=True)
def test_netlistsvg_diagram(self): TEST_NAME = "test_skins" TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) TEST_FILES = [ "test_skins/test_skins.rst", "test_skins/skin-purple.svg", "test_skins/skin-yellow.svg", "code/verilog/adder.v" ] TEST_JINJA_DICT = { "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), "master_doc": "'test_skins'", "custom_variables": "hdl_diagram_skin = os.path.realpath('skin-purple.svg')" } self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) # Run the Sphinx sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) with docutils_namespace(): app = Sphinx(buildername="html", warningiserror=True, **sphinx_dirs) app.build(force_all=True)
def build_sphinx(src_dir, output_dir, files=None, config={}): doctrees_dir = join(output_dir, '.doctrees') filenames = [] force_all = True default_config = { 'extensions': ['sphinxcontrib.restbuilder'], 'master_doc': 'index', } default_config.update(config) config = default_config if files: force_all = False filenames = [join(src_dir, file + '.rst') for file in files] config['master_doc'] = files[0] with docutils_namespace(): app = Sphinx( src_dir, None, output_dir, doctrees_dir, 'rst', confoverrides=config, verbosity=0, ) app.build(force_all=force_all, filenames=filenames)
def render_sphinx_project(name, project_dir, template_cfg=None, stylesheet=None): project_path = TEST_DIR / project_dir out_path = OUTPUT_DIR / name confoverrides = {} if template_cfg: confoverrides['rinoh_template'] = str(TEST_DIR / template_cfg) if stylesheet: confoverrides['rinoh_stylesheet'] = str(TEST_DIR / stylesheet) with docutils_namespace(): sphinx = Sphinx(srcdir=str(project_path), confdir=str(project_path), outdir=str(out_path / 'rinoh'), doctreedir=str(out_path / 'doctrees'), buildername='rinoh', confoverrides=confoverrides) sphinx.build() out_filename = '{}.pdf'.format(name) with in_directory(out_path): if not diff_pdf(TEST_DIR / 'reference' / out_filename, out_path / 'rinoh' / out_filename): pytest.fail( 'The generated PDF is different from the reference ' 'PDF.\nGenerated files can be found in {}'.format(out_path))
def sphinx_app(tmpdir_factory, req_mpl, req_pil): temp_dir = (tmpdir_factory.getbasetemp() / 'root').strpath src_dir = op.join(op.dirname(__file__), 'tinybuild') def ignore(src, names): return ('_build', 'gen_modules', 'auto_examples') shutil.copytree(src_dir, temp_dir, ignore=ignore) # For testing iteration, you can get similar behavior just doing `make` # inside the tinybuild directory src_dir = temp_dir conf_dir = temp_dir out_dir = op.join(temp_dir, '_build', 'html') toctrees_dir = op.join(temp_dir, '_build', 'toctrees') # Avoid warnings about re-registration, see: # https://github.com/sphinx-doc/sphinx/issues/5038 with docutils_namespace(): app = Sphinx(src_dir, conf_dir, out_dir, toctrees_dir, buildername='html', status=StringIO(), warning=StringIO()) # need to build within the context manager # for automodule and backrefs to work app.build(False, []) return app
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 sphinx_app(tmpdir_factory): temp_dir = (tmpdir_factory.getbasetemp() / "root").strpath src_dir = op.join(op.dirname(__file__), "tinybuild") def ignore(src, names): return ("_build", "generated") shutil.copytree(src_dir, temp_dir, ignore=ignore) # For testing iteration, you can get similar behavior just doing `make` # inside the tinybuild directory src_dir = temp_dir conf_dir = temp_dir out_dir = op.join(temp_dir, "_build", "html") toctrees_dir = op.join(temp_dir, "_build", "toctrees") # Set behavior across different Sphinx versions kwargs = dict() if LooseVersion(sphinx.__version__) >= LooseVersion("1.8"): kwargs.update(warningiserror=True, keep_going=True) # Avoid warnings about re-registration, see: # https://github.com/sphinx-doc/sphinx/issues/5038 with docutils_namespace(): app = Sphinx( src_dir, conf_dir, out_dir, toctrees_dir, buildername="html", **kwargs ) # need to build within the context manager # for automodule and backrefs to work app.build(False, []) return app
def gen_pdf(isRebuild=False): """make latexpdf """ if isRebuild: clear_all_api() srcDir = os.path.join(DIR, "docs") confDir = os.path.join(docDir, "source") outDir = op.join(docDir, '_build', 'latex') toctreesDir = op.join(docDir, '_build', 'toctrees-pdf') # Avoid warnings about re-registration, see: https://github.com/sphinx-doc/sphinx/issues/5038 with docutils_namespace(): app = Sphinx(srcDir, confDir, outDir, toctreesDir, buildername='latex') # latex 只有 tex 文件 # need to build within the context manager for automodule and backrefs to work app.build(force_all=isRebuild, filenames=[]) # 构建 pdf ERROR 不行,有异常,还是手动编译算了 isBuildPdf = False if isBuildPdf: cmd = "pdflatex {texFile} -output-directory={pdfDir}".format( texFile=os.path.join(outDir, "dataset.tex"), pdfDir=outDir) ret = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) if ret.returncode != 0: print("子程序错误!\n {err}".format(err=ret.stderr.decode("utf-8"))) code = 1 else: code = 0 return code
def sphinx_app(tmpdir_factory): if LooseVersion(sphinx.__version__) < LooseVersion('1.8'): # Previous versions throw an error trying to pickle the scraper pytest.skip('Sphinx 1.8+ required') temp_dir = (tmpdir_factory.getbasetemp() / 'root').strpath src_dir = op.join(op.dirname(__file__), 'tinybuild') def ignore(src, names): return ('_build', 'gen_modules', 'auto_examples') shutil.copytree(src_dir, temp_dir, ignore=ignore) # For testing iteration, you can get similar behavior just doing `make` # inside the tinybuild directory src_dir = temp_dir conf_dir = temp_dir out_dir = op.join(temp_dir, '_build', 'html') toctrees_dir = op.join(temp_dir, '_build', 'toctrees') # Avoid warnings about re-registration, see: # https://github.com/sphinx-doc/sphinx/issues/5038 with docutils_namespace(): app = Sphinx(src_dir, conf_dir, out_dir, toctrees_dir, buildername='html', status=MixedEncodingStringIO()) # need to build within the context manager # for automodule and backrefs to work app.build(False, []) return app
def build_sphinx(src_dir, files=None): out_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'output') shutil.rmtree(out_dir, ignore_errors=True) doctrees_dir = os.path.join(out_dir, '.doctrees') filenames = [] force_all = True config = {'extensions': ['sphinxcontrib.restbuilder']} if files: force_all = False filenames = [os.path.join(src_dir, file + '.rst') for file in files] config['master_doc'] = files[0] with docutils_namespace(): app = Sphinx( src_dir, None, out_dir, doctrees_dir, 'rst', confoverrides=config, verbosity=0, ) app.build(force_all=force_all, filenames=filenames) return out_dir
def build(self): """Build the documentation. Places the data into the `outdir` directory. Use it like this:: support = WebSupport(srcdir, builddir, search='xapian') support.build() This will read reStructured text files from `srcdir`. Then it will build the pickles and search index, placing them into `builddir`. It will also save node data to the database. """ if not self.srcdir: raise RuntimeError('No srcdir associated with WebSupport object') with docutils_namespace(): from sphinx.application import Sphinx app = Sphinx(self.srcdir, self.srcdir, self.outdir, self.doctreedir, self.buildername, self.confoverrides, status=self.status, warning=self.warning) app.builder.set_webinfo( self.staticdir, self.staticroot, # type: ignore self.search, self.storage) self.storage.pre_build() app.build() self.storage.post_build()
def prepareSphinx(src_dir, out_dir, doctree_dir, config=None, relax=False): """ prepare a sphinx application instance Return a prepared Sphinx application instance [1] ready for execution. [1]: https://github.com/sphinx-doc/sphinx/blob/master/sphinx/application.py """ # Enable coloring of warning and other messages. Note that this can # cause sys.stderr to be mocked which is why we pass the new value # explicitly on the call to Sphinx() below. if not color_terminal(): nocolor() sts = ConfluenceTestUtil.default_sphinx_status conf = dict(config) if config else None conf_dir = src_dir if not conf else None warnerr = not relax with docutils_namespace(): app = Sphinx( src_dir, # output for document sources conf_dir, # ignore configuration directory out_dir, # output for generated documents doctree_dir, # output for doctree files ConfluenceBuilder.name, # use this extension's builder confoverrides=conf, # load provided configuration (volatile) status=sts, # status output warning=sys.stderr, # warnings output warningiserror=warnerr) # treat warnings as errors yield app
def run_setup( setup_func: _setup_func_type ) -> RunSetupOutput: # , buildername: str = "html" """ Function for running an extension's ``setup()`` function for testing. :param setup_func: The ``setup()`` function under test. :returns: 5-element namedtuple """ app = Sphinx() # buildername app.add_domain(PythonDomain) try: _additional_nodes = copy.copy(docutils.additional_nodes) docutils.additional_nodes = set() with docutils.docutils_namespace(): setup_ret = setup_func(app) # type: ignore directives = copy.copy( docutils.directives._directives) # type: ignore roles = copy.copy(docutils.roles._roles) # type: ignore additional_nodes = copy.copy(docutils.additional_nodes) finally: docutils.additional_nodes = _additional_nodes return RunSetupOutput(setup_ret, directives, roles, additional_nodes, app)
def build_main(args_parser): """ build mainline The mainline for the 'build' action. Args: args_parser: the argument parser to use for argument processing Returns: the exit code """ args_parser.add_argument('-D', action='append', default=[], dest='define') args_parser.add_argument('--output-dir', '-o') known_args = sys.argv[1:] args, unknown_args = args_parser.parse_known_args(known_args) if unknown_args: logger.warn('unknown arguments: {}'.format(' '.join(unknown_args))) defines = {} for val in args.define: try: key, val = val.split('=', 1) defines[key] = val except ValueError: logger.error('invalid define provided in command line') return 1 work_dir = args.work_dir if args.work_dir else os.getcwd() if args.output_dir: output_dir = args.output_dir else: output_dir = os.path.join(work_dir, '_build', 'confluence') doctrees_dir = os.path.join(output_dir, '.doctrees') builder = args.action if args.action else DEFAULT_BUILDER verbosity = 0 if args.verbose: try: verbosity = int(args.verbose) except ValueError: pass # run sphinx engine with docutils_namespace(): app = Sphinx( work_dir, # document sources work_dir, # directory with configuration output_dir, # output for generated documents doctrees_dir, # output for doctree files builder, # builder to execute confoverrides=defines, # configuration overload freshenv=True, # fresh environment verbosity=verbosity) # verbosity app.build(force_all=True) return 0
def create_sphinx_app(self): # Avoid warnings about re-registration, see: # https://github.com/sphinx-doc/sphinx/issues/5038 with docutils_namespace(): app = Sphinx(self.srcdir, self.confdir, self.outdir, self.doctreedir, self.buildername, **self.kwargs) sphinx_compatibility._app = app return app
def run(self) -> None: warnings.warn('setup.py build_sphinx is deprecated.', RemovedInSphinx70Warning, stacklevel=2) if not color_terminal(): nocolor() if not self.verbose: # type: ignore status_stream = StringIO() else: status_stream = sys.stdout # type: ignore confoverrides: Dict[str, Any] = {} if self.project: confoverrides['project'] = self.project if self.version: confoverrides['version'] = self.version if self.release: confoverrides['release'] = self.release if self.today: confoverrides['today'] = self.today if self.copyright: confoverrides['copyright'] = self.copyright if self.nitpicky: confoverrides['nitpicky'] = self.nitpicky for builder, builder_target_dir in self.builder_target_dirs: app = None try: confdir = self.config_dir or self.source_dir with patch_docutils(confdir), docutils_namespace(): app = Sphinx(self.source_dir, self.config_dir, builder_target_dir, self.doctree_dir, builder, confoverrides, status_stream, freshenv=self.fresh_env, warningiserror=self.warning_is_error, verbosity=self.verbosity, keep_going=self.keep_going) app.build(force_all=self.all_files) if app.statuscode: raise DistutilsExecError('caused by %s builder.' % app.builder.name) except Exception as exc: handle_exception(app, self, exc, sys.stderr) if not self.pdb: raise SystemExit(1) from exc if not self.link_index: continue src = app.config.root_doc + app.builder.out_suffix # type: ignore dst = app.builder.get_outfilename('index') # type: ignore os.symlink(src, dst)
def render_sphinx(content): with tempfile.TemporaryDirectory() as tmp_dir: src_path = pathlib.Path(tmp_dir, "src/contents.rst") src_path.parent.mkdir() with src_path.open("w") as src: src.write(content) build_path = pathlib.Path(tmp_dir, "build/contents.fjson") source_dir = str(src_path.parent) doctree_dir = os.path.join(source_dir, ".doctrees") confoverrides = { "extensions": ["zuul_sphinx"], "master_doc": "contents" } status_log = io.StringIO() # NOTE (fschmidt): This part needs to be in sync with the used version # of Sphinx. Current version is: # https://github.com/sphinx-doc/sphinx/blob/v1.8.1/sphinx/cmd/build.py#L299 with patch_docutils(source_dir), docutils_namespace(): # Remove the color from the Sphinx' console output. Otherwise # the lines cannot be parsed properly as some \n are not set properly. nocolor() app = Sphinx( srcdir=source_dir, confdir=None, outdir=str(build_path.parent), doctreedir=doctree_dir, buildername="json", confoverrides=confoverrides, status=status_log, warning=sys.stderr, ) # Add the mocked SupportedOS directive to get the os information # without rendering it into the resulting HTML page app.add_directive("supported_os", SupportedOS) # Start the Sphinx build app.build(force_all=True, filenames=[]) if app.statuscode: raise SphinxBuildError # Extract the platforms from the logger output platforms = [] status_log.seek(0) for line in status_log.readlines(): prefix, _, platform = line.partition(":") if prefix == SUPPORTED_OS_LOG_PREFIX: platforms.append(platform.strip().lower()) with build_path.open() as build: html_parts = json.load(build) return {"html": html_parts["body"], "platforms": platforms}
def runsphinx(_outdir, _srcdir, text, builder, confoverrides): f = open(os.path.join(_srcdir, 'index.rst'), 'w') try: f.write(text) finally: f.close() with docutils_namespace(): app = Sphinx(_srcdir, _fixturedir, _outdir, _outdir, builder, confoverrides) app.build()
def prepareSphinx(src_dir, out_dir, doctree_dir, config=None, extra_config=None, builder=None, relax=False): """ prepare a sphinx application instance Return a prepared Sphinx application instance [1] ready for execution. [1]: https://github.com/sphinx-doc/sphinx/blob/master/sphinx/application.py """ # Enable coloring of warning and other messages. Note that this can # cause sys.stderr to be mocked which is why we pass the new value # explicitly on the call to Sphinx() below. if not color_terminal(): nocolor() conf = dict(config) if config else {} if extra_config: conf.update(extra_config) conf_dir = src_dir if config is None else None warnerr = not relax sts = None if 'SPHINX_STATUS' in os.environ: sts = sys.stdout verbosity = 0 if 'SPHINX_VERBOSITY' in os.environ: try: verbosity = int(os.environ['SPHINX_VERBOSITY']) except ValueError: pass # default to using this extension's builder if not builder: builder = 'confluence' with docutils_namespace(): app = Sphinx( src_dir, # output for document sources conf_dir, # configuration directory out_dir, # output for generated documents doctree_dir, # output for doctree files builder, # builder to execute confoverrides=conf, # load provided configuration (volatile) status=sts, # status output warning=sys.stderr, # warnings output warningiserror=warnerr, # treat warnings as errors verbosity=verbosity) # verbosity yield app
def test_sphinx_build(buildername: str, tmp_path: pathlib.Path) -> None: """Test :meth:`sphinx.application.Sphinx.build`.""" doctreedir = tmp_path / "doctrees" with docutils_namespace(): app = Sphinx("docs", "docs", tmp_path, doctreedir, buildername=buildername, warningiserror=True) app.build(force_all=True)
def run(self): # type: () -> None if not color_terminal(): nocolor() if not self.verbose: # type: ignore status_stream = StringIO() else: status_stream = sys.stdout # type: ignore confoverrides = {} if self.project: confoverrides['project'] = self.project if self.version: confoverrides['version'] = self.version if self.release: confoverrides['release'] = self.release if self.today: confoverrides['today'] = self.today if self.copyright: confoverrides['copyright'] = self.copyright for builder, builder_target_dir in self.builder_target_dirs: app = None try: confdir = self.config_dir or self.source_dir with patch_docutils(confdir), docutils_namespace(): app = Sphinx(self.source_dir, self.config_dir, builder_target_dir, self.doctree_dir, builder, confoverrides, status_stream, freshenv=self.fresh_env, warningiserror=self.warning_is_error) app.build(force_all=self.all_files) if app.statuscode: raise DistutilsExecError('caused by %s builder.' % app.builder.name) except Exception as exc: handle_exception(app, self, exc, sys.stderr) if not self.pdb: raise SystemExit(1) if not self.link_index: continue src = app.config.master_doc + app.builder.out_suffix # type: ignore dst = app.builder.get_outfilename('index') # type: ignore os.symlink(src, dst)
def create_sphinx_app(tmp_path, all_docs=('index', ), **confoverrides): with docutils_namespace(): confdir = tmp_path / 'confdir' confdir.mkdir() conf_py = confdir / 'conf.py' conf_py.touch() app = Sphinx(srcdir=str(tmp_path), confdir=str(confdir), outdir=str(tmp_path / 'output'), doctreedir=str(tmp_path / 'doctrees'), buildername='rinoh', confoverrides=confoverrides) app.env.all_docs.update({doc: 0 for doc in all_docs}) return app
def test(test_name): rst_path = RST_PATH / (test_name + '.rst') test_output_dir = OUTPUT_DIR / test_name if test_name.startswith('sphinx_'): with docutils_namespace(): out_dir = str(test_output_dir) Sphinx(srcdir=str(RST_PATH), confdir=None, outdir=out_dir, doctreedir=out_dir, buildername='dummy', status=None) render_rst_file(rst_path, test_name, RST_PATH) else: render_rst_file(rst_path, test_name, RST_PATH)
def run(self): # type: () -> None if not color_terminal(): nocolor() if not self.verbose: # type: ignore status_stream = StringIO() else: status_stream = sys.stdout # type: ignore confoverrides = {} # type: Dict[str, Any] if self.project: confoverrides['project'] = self.project if self.version: confoverrides['version'] = self.version if self.release: confoverrides['release'] = self.release if self.today: confoverrides['today'] = self.today if self.copyright: confoverrides['copyright'] = self.copyright if self.nitpicky: confoverrides['nitpicky'] = self.nitpicky for builder, builder_target_dir in self.builder_target_dirs: app = None try: confdir = self.config_dir or self.source_dir with patch_docutils(confdir), docutils_namespace(): app = Sphinx(self.source_dir, self.config_dir, builder_target_dir, self.doctree_dir, builder, confoverrides, status_stream, freshenv=self.fresh_env, warningiserror=self.warning_is_error) app.build(force_all=self.all_files) if app.statuscode: raise DistutilsExecError( 'caused by %s builder.' % app.builder.name) except Exception as exc: handle_exception(app, self, exc, sys.stderr) if not self.pdb: raise SystemExit(1) if not self.link_index: continue src = app.config.master_doc + app.builder.out_suffix # type: ignore dst = app.builder.get_outfilename('index') # type: ignore os.symlink(src, dst)
def test_junit(sphinx_app, tmpdir): out_dir = sphinx_app.outdir junit_file = op.join(out_dir, 'sphinx-gallery', 'junit-results.xml') assert op.isfile(junit_file) with codecs.open(junit_file, 'r', 'utf-8') as fid: contents = fid.read() assert contents.startswith('<?xml') assert 'errors="0" failures="0"' in contents assert 'tests="5"' in contents assert 'local_module' not in contents # it's not actually run as an ex assert 'expected example failure' in contents assert '<failure message' not in contents src_dir = sphinx_app.srcdir new_src_dir = op.join(str(tmpdir), 'src') shutil.copytree(src_dir, new_src_dir) del src_dir new_out_dir = op.join(new_src_dir, '_build', 'html') new_toctree_dir = op.join(new_src_dir, '_build', 'toctrees') passing_fname = op.join(new_src_dir, 'examples', 'plot_numpy_matplotlib.py') failing_fname = op.join(new_src_dir, 'examples', 'plot_future_imports_broken.py') shutil.move(passing_fname, passing_fname + '.temp') shutil.move(failing_fname, passing_fname) shutil.move(passing_fname + '.temp', failing_fname) with docutils_namespace(): app = Sphinx(new_src_dir, new_src_dir, new_out_dir, new_toctree_dir, buildername='html', status=MixedEncodingStringIO()) # need to build within the context manager # for automodule and backrefs to work with pytest.raises(ValueError, match='Here is a summary of the '): app.build(False, []) junit_file = op.join(new_out_dir, 'sphinx-gallery', 'junit-results.xml') assert op.isfile(junit_file) with codecs.open(junit_file, 'r', 'utf-8') as fid: contents = fid.read() assert 'errors="0" failures="2"' in contents assert 'tests="2"' in contents # this time we only ran the two stale files if LooseVersion(sys.version) >= LooseVersion('3'): assert '<failure message="RuntimeError: Forcing' in contents else: assert '<failure message="SyntaxError: invalid' in contents assert 'Passed even though it was marked to fail' in contents
def test_register_node(): class custom_node(nodes.Element): pass with docutils_namespace(): register_node(custom_node) # check registered assert hasattr(nodes.GenericNodeVisitor, 'visit_custom_node') assert hasattr(nodes.GenericNodeVisitor, 'depart_custom_node') assert hasattr(nodes.SparseNodeVisitor, 'visit_custom_node') assert hasattr(nodes.SparseNodeVisitor, 'depart_custom_node') # check unregistered outside namespace assert not hasattr(nodes.GenericNodeVisitor, 'visit_custom_node') assert not hasattr(nodes.GenericNodeVisitor, 'depart_custom_node') assert not hasattr(nodes.SparseNodeVisitor, 'visit_custom_node') assert not hasattr(nodes.SparseNodeVisitor, 'depart_custom_node')
def run(self): if not color_terminal(): nocolor() if not self.verbose: status_stream = StringIO() else: status_stream = sys.stdout confoverrides = {} if self.project: confoverrides["project"] = self.project if self.version: confoverrides["version"] = self.version if self.release: confoverrides["release"] = self.release if self.today: confoverrides["today"] = self.today if self.copyright: confoverrides["copyright"] = self.copyright try: with docutils_namespace(): app = Sphinx( self.source_dir, self.config_dir, self.builder_target_dir, self.doctree_dir, self.builder, confoverrides, status_stream, freshenv=self.fresh_env, warningiserror=self.warning_is_error, ) app.build(force_all=self.all_files) if app.statuscode: raise DistutilsExecError("caused by %s builder." % app.builder.name) except Exception as exc: handle_exception(app, self, exc, sys.stderr) if not self.pdb: raise SystemExit(1) if self.link_index: src = app.config.master_doc + app.builder.out_suffix dst = app.builder.get_outfilename("index") os.symlink(src, dst)
def gen_html(isRebuild=False): """ make html """ if isRebuild: clear_all_api() srcDir = os.path.join(DIR, "docs") # Directory containing source confDir = os.path.join(docDir, "source") # Directory containing ``conf.py`` outDir = op.join(docDir, '_build', 'html') # Directory for storing build documents. toctreesDir = op.join(docDir, '_build', 'toctrees') # Directory for storing pickled doctrees # Avoid warnings about re-registration, see: https://github.com/sphinx-doc/sphinx/issues/5038 with docutils_namespace(): app = Sphinx(srcDir, confDir, outDir, toctreesDir, buildername='html') # need to build within the context manager for automodule and backrefs to work app.build(force_all=isRebuild, filenames=[]) return app
def test_yosys_script(self): TEST_NAME = "test_rtlil" TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) TEST_FILES = [ "test_rtlil/test_rtlil.rst", "code/rtlil/counter.il" ] TEST_JINJA_DICT = { "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), "master_doc": "'test_rtlil'", "custom_variables": "''" } self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) # Run the Sphinx sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) with docutils_namespace(): app = Sphinx(buildername="html", warningiserror=True, **sphinx_dirs) app.build(force_all=True)
def render_sphinx_rst_file(rst_path, out_filename, reference_path, test_output_dir): with docutils_namespace(): out_dir = str(test_output_dir) app = Sphinx(srcdir=str(rst_path.parent), confdir=None, outdir=out_dir, doctreedir=out_dir, buildername='dummy', status=None) with open(rst_path) as rst_file: contents = rst_file.read() sphinx_doctree = sphinx_parse(app, contents) doctree = from_doctree(sphinx_doctree) docinfo = sphinx_doctree.settings.env.metadata['index'] return _render_rst(rst_path, doctree, out_filename, reference_path, warnings=docinfo.get('warnings', '').splitlines())
def _build_documentation(self, builder, out_dir, doctree_dir, config=None): conf = dict(config) if config else {} conf['master_doc'] = 'index' # force index for legacy sphinx conf['html_theme'] = 'sphinx_alice_theme' conf['html_theme_path'] = self.root_dir if 'extensions' not in conf: conf['extensions'] = [] conf['extensions'].append('sphinx.ext.autodoc') with docutils_namespace(): app = Sphinx( self.doc_dir, # documentation to process None, # default configuration out_dir, # output for generated documents doctree_dir, # output for doctree files builder, # builder to execute confoverrides=conf, # load provided configuration (volatile) warning=sys.stderr, # warnings output warningiserror=True) # treat warnings as errors app.build(force_all=True)
def sphinx_app(tmpdir_factory): temp_dir = (tmpdir_factory.getbasetemp() / 'root').strpath src_dir = op.join(op.dirname(__file__), 'tinybuild') def ignore(src, names): return ('_build', 'gen_modules', 'auto_examples') shutil.copytree(src_dir, temp_dir, ignore=ignore) # For testing iteration, you can get similar behavior just doing `make` # inside the tinybuild directory src_dir = temp_dir conf_dir = temp_dir out_dir = op.join(temp_dir, '_build', 'html') toctrees_dir = op.join(temp_dir, '_build', 'toctrees') # Avoid warnings about re-registration, see: # https://github.com/sphinx-doc/sphinx/issues/5038 with docutils_namespace(): app = Sphinx(src_dir, conf_dir, out_dir, toctrees_dir, buildername='html') # need to build within the context manager # for automodule and backrefs to work app.build(False, []) return app
def build_main(argv=sys.argv[1:]): # type: (List[str]) -> int """Sphinx build "main" command-line entry.""" parser = get_parser() args = parser.parse_args(argv) if args.noconfig: args.confdir = None elif not args.confdir: args.confdir = args.sourcedir if not args.doctreedir: args.doctreedir = os.path.join(args.outputdir, '.doctrees') # handle remaining filename arguments filenames = args.filenames missing_files = [] for filename in filenames: if not os.path.isfile(filename): missing_files.append(filename) if missing_files: parser.error(__('cannot find files %r') % missing_files) if args.force_all and filenames: parser.error(__('cannot combine -a option and filenames')) if args.color == 'no' or (args.color == 'auto' and not color_terminal()): nocolor() status = sys.stdout warning = sys.stderr error = sys.stderr if args.quiet: status = None if args.really_quiet: status = warning = None if warning and args.warnfile: try: warnfp = open(args.warnfile, 'w') except Exception as exc: parser.error(__('cannot open warning file %r: %s') % ( args.warnfile, exc)) warning = Tee(warning, warnfp) # type: ignore error = warning confoverrides = {} for val in args.define: try: key, val = val.split('=', 1) except ValueError: parser.error(__('-D option argument must be in the form name=value')) confoverrides[key] = val for val in args.htmldefine: try: key, val = val.split('=') except ValueError: parser.error(__('-A option argument must be in the form name=value')) try: val = int(val) except ValueError: pass confoverrides['html_context.%s' % key] = val if args.nitpicky: confoverrides['nitpicky'] = True app = None try: confdir = args.confdir or args.sourcedir with patch_docutils(confdir), docutils_namespace(): app = Sphinx(args.sourcedir, args.confdir, args.outputdir, args.doctreedir, args.builder, confoverrides, status, warning, args.freshenv, args.warningiserror, args.tags, args.verbosity, args.jobs, args.keep_going) app.build(args.force_all, filenames) return app.statuscode except (Exception, KeyboardInterrupt) as exc: handle_exception(app, args, exc, error) return 2
def main(argv): # type: (List[unicode]) -> int parser = optparse.OptionParser(USAGE, epilog=EPILOG, formatter=MyFormatter()) parser.add_option('--version', action='store_true', dest='version', help='show version information and exit') group = parser.add_option_group('General options') group.add_option('-b', metavar='BUILDER', dest='builder', default='html', help='builder to use; default is html') group.add_option('-a', action='store_true', dest='force_all', help='write all files; default is to only write new and ' 'changed files') group.add_option('-E', action='store_true', dest='freshenv', help='don\'t use a saved environment, always read ' 'all files') group.add_option('-d', metavar='PATH', default=None, dest='doctreedir', help='path for the cached environment and doctree files ' '(default: outdir/.doctrees)') group.add_option('-j', metavar='N', default=1, type='int', dest='jobs', help='build in parallel with N processes where possible') # this option never gets through to this point (it is intercepted earlier) # group.add_option('-M', metavar='BUILDER', dest='make_mode', # help='"make" mode -- as used by Makefile, like ' # '"sphinx-build -M html"') group = parser.add_option_group('Build configuration options') group.add_option('-c', metavar='PATH', dest='confdir', help='path where configuration file (conf.py) is located ' '(default: same as sourcedir)') group.add_option('-C', action='store_true', dest='noconfig', help='use no config file at all, only -D options') group.add_option('-D', metavar='setting=value', action='append', dest='define', default=[], help='override a setting in configuration file') group.add_option('-A', metavar='name=value', action='append', dest='htmldefine', default=[], help='pass a value into HTML templates') group.add_option('-t', metavar='TAG', action='append', dest='tags', default=[], help='define tag: include "only" blocks with TAG') group.add_option('-n', action='store_true', dest='nitpicky', help='nit-picky mode, warn about all missing references') group = parser.add_option_group('Console output options') group.add_option('-v', action='count', dest='verbosity', default=0, help='increase verbosity (can be repeated)') group.add_option('-q', action='store_true', dest='quiet', help='no output on stdout, just warnings on stderr') group.add_option('-Q', action='store_true', dest='really_quiet', help='no output at all, not even warnings') group.add_option('--color', dest='color', action='store_const', const='yes', default='auto', help='Do emit colored output (default: auto-detect)') group.add_option('-N', '--no-color', dest='color', action='store_const', const='no', help='Do not emit colored output (default: auot-detect)') group.add_option('-w', metavar='FILE', dest='warnfile', help='write warnings (and errors) to given file') group.add_option('-W', action='store_true', dest='warningiserror', help='turn warnings into errors') group.add_option('-T', action='store_true', dest='traceback', help='show full traceback on exception') group.add_option('-P', action='store_true', dest='pdb', help='run Pdb on exception') # parse options try: opts, args = parser.parse_args(list(argv[1:])) except SystemExit as err: return err.code # handle basic options if opts.version: print('Sphinx (sphinx-build) %s' % __display_version__) return 0 # get paths (first and second positional argument) try: srcdir = abspath(args[0]) confdir = abspath(opts.confdir or srcdir) if opts.noconfig: confdir = None if not path.isdir(srcdir): print('Error: Cannot find source directory `%s\'.' % srcdir, file=sys.stderr) return 1 if not opts.noconfig and not path.isfile(path.join(confdir, 'conf.py')): print('Error: Config directory doesn\'t contain a conf.py file.', file=sys.stderr) return 1 outdir = abspath(args[1]) if srcdir == outdir: print('Error: source directory and destination directory are same.', file=sys.stderr) return 1 except IndexError: parser.print_help() return 1 except UnicodeError: print( 'Error: Multibyte filename not supported on this filesystem ' 'encoding (%r).' % fs_encoding, file=sys.stderr) return 1 # handle remaining filename arguments filenames = args[2:] errored = False for filename in filenames: if not path.isfile(filename): print('Error: Cannot find file %r.' % filename, file=sys.stderr) errored = True if errored: return 1 # likely encoding used for command-line arguments try: locale = __import__('locale') # due to submodule of the same name likely_encoding = locale.getpreferredencoding() except Exception: likely_encoding = None if opts.force_all and filenames: print('Error: Cannot combine -a option and filenames.', file=sys.stderr) return 1 if opts.color == 'no' or (opts.color == 'auto' and not color_terminal()): nocolor() doctreedir = abspath(opts.doctreedir or path.join(outdir, '.doctrees')) status = sys.stdout warning = sys.stderr error = sys.stderr if opts.quiet: status = None if opts.really_quiet: status = warning = None if warning and opts.warnfile: try: warnfp = open(opts.warnfile, 'w') except Exception as exc: print('Error: Cannot open warning file %r: %s' % (opts.warnfile, exc), file=sys.stderr) sys.exit(1) warning = Tee(warning, warnfp) # type: ignore error = warning confoverrides = {} for val in opts.define: try: key, val = val.split('=', 1) except ValueError: print('Error: -D option argument must be in the form name=value.', file=sys.stderr) return 1 if likely_encoding and isinstance(val, binary_type): try: val = val.decode(likely_encoding) except UnicodeError: pass confoverrides[key] = val for val in opts.htmldefine: try: key, val = val.split('=') except ValueError: print('Error: -A option argument must be in the form name=value.', file=sys.stderr) return 1 try: val = int(val) except ValueError: if likely_encoding and isinstance(val, binary_type): try: val = val.decode(likely_encoding) except UnicodeError: pass confoverrides['html_context.%s' % key] = val if opts.nitpicky: confoverrides['nitpicky'] = True app = None try: with docutils_namespace(): app = Sphinx(srcdir, confdir, outdir, doctreedir, opts.builder, confoverrides, status, warning, opts.freshenv, opts.warningiserror, opts.tags, opts.verbosity, opts.jobs) app.build(opts.force_all, filenames) return app.statuscode except (Exception, KeyboardInterrupt) as exc: handle_exception(app, opts, exc, error) return 1
def test_rebuild(tmpdir_factory, sphinx_app): # Make sure that examples that haven't been changed aren't run twice. # # First run completes in the fixture. # status = sphinx_app._status.getvalue() want = '.*%s added, 0 changed, 0 removed$.*' % (N_RST,) assert re.match(want, status, re.MULTILINE | re.DOTALL) is not None assert re.match('.*targets for 1 source files that are out of date$.*', status, re.MULTILINE | re.DOTALL) is not None want = ('.*executed %d out of %d.*after excluding 0 files.*based on MD5.*' % (N_GOOD, N_TOT)) assert re.match(want, status, re.MULTILINE | re.DOTALL) is not None old_src_dir = (tmpdir_factory.getbasetemp() / 'root_old').strpath shutil.copytree(sphinx_app.srcdir, old_src_dir) generated_modules_0 = sorted( op.join(old_src_dir, 'gen_modules', f) for f in os.listdir(op.join(old_src_dir, 'gen_modules')) if op.isfile(op.join(old_src_dir, 'gen_modules', f))) generated_backrefs_0 = sorted( op.join(old_src_dir, 'gen_modules', 'backreferences', f) for f in os.listdir(op.join(old_src_dir, 'gen_modules', 'backreferences'))) generated_rst_0 = sorted( op.join(old_src_dir, 'auto_examples', f) for f in os.listdir(op.join(old_src_dir, 'auto_examples')) if f.endswith('.rst')) generated_pickle_0 = sorted( op.join(old_src_dir, 'auto_examples', f) for f in os.listdir(op.join(old_src_dir, 'auto_examples')) if f.endswith('.pickle')) copied_py_0 = sorted( op.join(old_src_dir, 'auto_examples', f) for f in os.listdir(op.join(old_src_dir, 'auto_examples')) if f.endswith('.py')) copied_ipy_0 = sorted( op.join(old_src_dir, 'auto_examples', f) for f in os.listdir(op.join(old_src_dir, 'auto_examples')) if f.endswith('.ipynb')) assert len(generated_modules_0) > 0 assert len(generated_backrefs_0) > 0 assert len(generated_rst_0) > 0 assert len(generated_pickle_0) > 0 assert len(copied_py_0) > 0 assert len(copied_ipy_0) > 0 assert len(sphinx_app.config.sphinx_gallery_conf['stale_examples']) == 0 assert op.isfile(op.join(sphinx_app.outdir, '_images', 'sphx_glr_plot_numpy_matplotlib_001.png')) # # run a second time, no files should be updated # src_dir = sphinx_app.srcdir del sphinx_app # don't accidentally use it below conf_dir = src_dir out_dir = op.join(src_dir, '_build', 'html') toctrees_dir = op.join(src_dir, '_build', 'toctrees') time.sleep(0.1) with docutils_namespace(): new_app = Sphinx(src_dir, conf_dir, out_dir, toctrees_dir, buildername='html', status=MixedEncodingStringIO()) new_app.build(False, []) status = new_app._status.getvalue() lines = [line for line in status.split('\n') if '0 removed' in line] assert re.match('.*0 added, [2|3|6|7|8] changed, 0 removed$.*', status, re.MULTILINE | re.DOTALL) is not None, lines want = ('.*executed 0 out of 1.*after excluding %s files.*based on MD5.*' % (N_GOOD,)) assert re.match(want, status, re.MULTILINE | re.DOTALL) is not None n_stale = len(new_app.config.sphinx_gallery_conf['stale_examples']) assert n_stale == N_GOOD assert op.isfile(op.join(new_app.outdir, '_images', 'sphx_glr_plot_numpy_matplotlib_001.png')) generated_modules_1 = sorted( op.join(new_app.srcdir, 'gen_modules', f) for f in os.listdir(op.join(new_app.srcdir, 'gen_modules')) if op.isfile(op.join(new_app.srcdir, 'gen_modules', f))) generated_backrefs_1 = sorted( op.join(new_app.srcdir, 'gen_modules', 'backreferences', f) for f in os.listdir(op.join(new_app.srcdir, 'gen_modules', 'backreferences'))) generated_rst_1 = sorted( op.join(new_app.srcdir, 'auto_examples', f) for f in os.listdir(op.join(new_app.srcdir, 'auto_examples')) if f.endswith('.rst')) generated_pickle_1 = sorted( op.join(new_app.srcdir, 'auto_examples', f) for f in os.listdir(op.join(new_app.srcdir, 'auto_examples')) if f.endswith('.pickle')) copied_py_1 = sorted( op.join(new_app.srcdir, 'auto_examples', f) for f in os.listdir(op.join(new_app.srcdir, 'auto_examples')) if f.endswith('.py')) copied_ipy_1 = sorted( op.join(new_app.srcdir, 'auto_examples', f) for f in os.listdir(op.join(new_app.srcdir, 'auto_examples')) if f.endswith('.ipynb')) # mtimes for modules _assert_mtimes(generated_modules_0, generated_modules_1) # mtimes for backrefs (gh-394) _assert_mtimes(generated_backrefs_0, generated_backrefs_1) # generated RST files ignore = ( # these two should almost always be different, but in case we # get extremely unlucky and have identical run times # on the one script that gets re-run (because it's a fail)... 'sg_execution_times.rst', 'plot_future_imports_broken.rst', ) _assert_mtimes(generated_rst_0, generated_rst_1, ignore=ignore) # mtimes for pickles _assert_mtimes(generated_pickle_0, generated_pickle_1) # mtimes for .py files (gh-395) _assert_mtimes(copied_py_0, copied_py_1) # mtimes for .ipynb files _assert_mtimes(copied_ipy_0, copied_ipy_1) # # run a third time, changing one file # time.sleep(0.1) fname = op.join(src_dir, 'examples', 'plot_numpy_matplotlib.py') with codecs.open(fname, 'r', 'utf-8') as fid: lines = fid.readlines() with codecs.open(fname, 'w', 'utf-8') as fid: for line in lines: if line.startswith('FYI this'): line = 'A ' + line fid.write(line) with docutils_namespace(): new_app = Sphinx(src_dir, conf_dir, out_dir, toctrees_dir, buildername='html', status=MixedEncodingStringIO()) new_app.build(False, []) status = new_app._status.getvalue() if LooseVersion(sphinx.__version__) <= LooseVersion('1.6'): n = N_RST else: n = '[2|3]' lines = [line for line in status.split('\n') if 'source files tha' in line] want = '.*targets for %s source files that are out of date$.*' % n assert re.match(want, status, re.MULTILINE | re.DOTALL) is not None, lines want = ('.*executed 1 out of 2.*after excluding %s files.*based on MD5.*' % (N_GOOD - 1,)) assert re.match(want, status, re.MULTILINE | re.DOTALL) is not None n_stale = len(new_app.config.sphinx_gallery_conf['stale_examples']) assert n_stale == N_GOOD - 1 assert op.isfile(op.join(new_app.outdir, '_images', 'sphx_glr_plot_numpy_matplotlib_001.png')) generated_modules_1 = sorted( op.join(new_app.srcdir, 'gen_modules', f) for f in os.listdir(op.join(new_app.srcdir, 'gen_modules')) if op.isfile(op.join(new_app.srcdir, 'gen_modules', f))) generated_backrefs_1 = sorted( op.join(new_app.srcdir, 'gen_modules', 'backreferences', f) for f in os.listdir(op.join(new_app.srcdir, 'gen_modules', 'backreferences'))) generated_rst_1 = sorted( op.join(new_app.srcdir, 'auto_examples', f) for f in os.listdir(op.join(new_app.srcdir, 'auto_examples')) if f.endswith('.rst')) generated_pickle_1 = sorted( op.join(new_app.srcdir, 'auto_examples', f) for f in os.listdir(op.join(new_app.srcdir, 'auto_examples')) if f.endswith('.pickle')) copied_py_1 = sorted( op.join(new_app.srcdir, 'auto_examples', f) for f in os.listdir(op.join(new_app.srcdir, 'auto_examples')) if f.endswith('.py')) copied_ipy_1 = sorted( op.join(new_app.srcdir, 'auto_examples', f) for f in os.listdir(op.join(new_app.srcdir, 'auto_examples')) if f.endswith('.ipynb')) # mtimes for modules _assert_mtimes(generated_modules_0, generated_modules_1) # mtimes for backrefs (gh-394) _assert_mtimes(generated_backrefs_0, generated_backrefs_1) # generated RST files different = ( # this one should get rewritten as we retried it 'plot_future_imports_broken.rst', 'plot_numpy_matplotlib.rst', ) ignore = ( # this one should almost always be different, but in case we # get extremely unlucky and have identical run times # on the one script above that changes... 'sg_execution_times.rst', ) _assert_mtimes(generated_rst_0, generated_rst_1, different, ignore) # mtimes for pickles _assert_mtimes(generated_pickle_0, generated_pickle_1, different=('plot_numpy_matplotlib.codeobj.pickle')) # mtimes for .py files (gh-395) _assert_mtimes(copied_py_0, copied_py_1, different=('plot_numpy_matplotlib.py')) # mtimes for .ipynb files _assert_mtimes(copied_ipy_0, copied_ipy_1, different=('plot_numpy_matplotlib.ipynb'))
def create_sphinx_app_context(self): with docutils_namespace(): app = Sphinx(self.srcdir, self.confdir, self.outdir, self.doctreedir, self.buildername, **self.kwargs) sphinx_compatibility._app = app yield app
def main(argv=sys.argv[1:]): # type: ignore # type: (List[unicode]) -> int parser = get_parser() # parse options try: args = parser.parse_args(argv) except SystemExit as err: return err.code # get paths (first and second positional argument) try: srcdir = abspath(args.sourcedir) confdir = abspath(args.confdir or srcdir) if args.noconfig: confdir = None if not path.isdir(srcdir): print('Error: Cannot find source directory `%s\'.' % srcdir, file=sys.stderr) return 1 if not args.noconfig and not path.isfile(path.join(confdir, 'conf.py')): print('Error: Config directory doesn\'t contain a conf.py file.', file=sys.stderr) return 1 outdir = abspath(args.outputdir) if srcdir == outdir: print('Error: source directory and destination directory are same.', file=sys.stderr) return 1 except UnicodeError: print( 'Error: Multibyte filename not supported on this filesystem ' 'encoding (%r).' % fs_encoding, file=sys.stderr) return 1 # handle remaining filename arguments filenames = args.filenames errored = False for filename in filenames: if not path.isfile(filename): print('Error: Cannot find file %r.' % filename, file=sys.stderr) errored = True if errored: return 1 # likely encoding used for command-line arguments try: locale = __import__('locale') # due to submodule of the same name likely_encoding = locale.getpreferredencoding() except Exception: likely_encoding = None if args.force_all and filenames: print('Error: Cannot combine -a option and filenames.', file=sys.stderr) return 1 if args.color == 'no' or (args.color == 'auto' and not color_terminal()): nocolor() doctreedir = abspath(args.doctreedir or path.join(outdir, '.doctrees')) status = sys.stdout warning = sys.stderr error = sys.stderr if args.quiet: status = None if args.really_quiet: status = warning = None if warning and args.warnfile: try: warnfp = open(args.warnfile, 'w') except Exception as exc: print('Error: Cannot open warning file %r: %s' % (args.warnfile, exc), file=sys.stderr) sys.exit(1) warning = Tee(warning, warnfp) # type: ignore error = warning confoverrides = {} for val in args.define: try: key, val = val.split('=', 1) except ValueError: print('Error: -D option argument must be in the form name=value.', file=sys.stderr) return 1 if likely_encoding and isinstance(val, binary_type): try: val = val.decode(likely_encoding) except UnicodeError: pass confoverrides[key] = val for val in args.htmldefine: try: key, val = val.split('=') except ValueError: print('Error: -A option argument must be in the form name=value.', file=sys.stderr) return 1 try: val = int(val) except ValueError: if likely_encoding and isinstance(val, binary_type): try: val = val.decode(likely_encoding) except UnicodeError: pass confoverrides['html_context.%s' % key] = val if args.nitpicky: confoverrides['nitpicky'] = True app = None try: with patch_docutils(), docutils_namespace(): app = Sphinx(srcdir, confdir, outdir, doctreedir, args.builder, confoverrides, status, warning, args.freshenv, args.warningiserror, args.tags, args.verbosity, args.jobs) app.build(args.force_all, filenames) return app.statuscode except (Exception, KeyboardInterrupt) as exc: handle_exception(app, args, exc, error) return 1
def main(argv): if not color_terminal(): nocolor() parser = optparse.OptionParser(USAGE, epilog=EPILOG, formatter=MyFormatter()) parser.add_option("--version", action="store_true", dest="version", help="show version information and exit") group = parser.add_option_group("General options") group.add_option("-b", metavar="BUILDER", dest="builder", default="html", help="builder to use; default is html") group.add_option( "-a", action="store_true", dest="force_all", help="write all files; default is to only write new and " "changed files", ) group.add_option( "-E", action="store_true", dest="freshenv", help="don't use a saved environment, always read " "all files" ) group.add_option( "-d", metavar="PATH", default=None, dest="doctreedir", help="path for the cached environment and doctree files " "(default: outdir/.doctrees)", ) group.add_option( "-j", metavar="N", default=1, type="int", dest="jobs", help="build in parallel with N processes where possible" ) # this option never gets through to this point (it is intercepted earlier) # group.add_option('-M', metavar='BUILDER', dest='make_mode', # help='"make" mode -- as used by Makefile, like ' # '"sphinx-build -M html"') group = parser.add_option_group("Build configuration options") group.add_option( "-c", metavar="PATH", dest="confdir", help="path where configuration file (conf.py) is located " "(default: same as sourcedir)", ) group.add_option("-C", action="store_true", dest="noconfig", help="use no config file at all, only -D options") group.add_option( "-D", metavar="setting=value", action="append", dest="define", default=[], help="override a setting in configuration file", ) group.add_option( "-A", metavar="name=value", action="append", dest="htmldefine", default=[], help="pass a value into HTML templates", ) group.add_option( "-t", metavar="TAG", action="append", dest="tags", default=[], help='define tag: include "only" blocks with TAG' ) group.add_option( "-n", action="store_true", dest="nitpicky", help="nit-picky mode, warn about all missing references" ) group = parser.add_option_group("Console output options") group.add_option("-v", action="count", dest="verbosity", default=0, help="increase verbosity (can be repeated)") group.add_option("-q", action="store_true", dest="quiet", help="no output on stdout, just warnings on stderr") group.add_option("-Q", action="store_true", dest="really_quiet", help="no output at all, not even warnings") group.add_option("-N", action="store_true", dest="nocolor", help="do not emit colored output") group.add_option("-w", metavar="FILE", dest="warnfile", help="write warnings (and errors) to given file") group.add_option("-W", action="store_true", dest="warningiserror", help="turn warnings into errors") group.add_option("-T", action="store_true", dest="traceback", help="show full traceback on exception") group.add_option("-P", action="store_true", dest="pdb", help="run Pdb on exception") # parse options try: opts, args = parser.parse_args(list(argv[1:])) except SystemExit as err: return err.code # handle basic options if opts.version: print("Sphinx (sphinx-build) %s" % __display_version__) return 0 # get paths (first and second positional argument) try: srcdir = abspath(args[0]) confdir = abspath(opts.confdir or srcdir) if opts.noconfig: confdir = None if not path.isdir(srcdir): print("Error: Cannot find source directory `%s'." % srcdir, file=sys.stderr) return 1 if not opts.noconfig and not path.isfile(path.join(confdir, "conf.py")): print("Error: Config directory doesn't contain a conf.py file.", file=sys.stderr) return 1 outdir = abspath(args[1]) if srcdir == outdir: print("Error: source directory and destination directory are same.", file=sys.stderr) return 1 except IndexError: parser.print_help() return 1 except UnicodeError: print( "Error: Multibyte filename not supported on this filesystem " "encoding (%r)." % fs_encoding, file=sys.stderr, ) return 1 # handle remaining filename arguments filenames = args[2:] err = 0 for filename in filenames: if not path.isfile(filename): print("Error: Cannot find file %r." % filename, file=sys.stderr) err = 1 if err: return 1 # likely encoding used for command-line arguments try: locale = __import__("locale") # due to submodule of the same name likely_encoding = locale.getpreferredencoding() except Exception: likely_encoding = None if opts.force_all and filenames: print("Error: Cannot combine -a option and filenames.", file=sys.stderr) return 1 if opts.nocolor: nocolor() doctreedir = abspath(opts.doctreedir or path.join(outdir, ".doctrees")) status = sys.stdout warning = sys.stderr error = sys.stderr if opts.quiet: status = None if opts.really_quiet: status = warning = None if warning and opts.warnfile: try: warnfp = open(opts.warnfile, "w") except Exception as exc: print("Error: Cannot open warning file %r: %s" % (opts.warnfile, exc), file=sys.stderr) sys.exit(1) warning = Tee(warning, warnfp) error = warning confoverrides = {} for val in opts.define: try: key, val = val.split("=") except ValueError: print("Error: -D option argument must be in the form name=value.", file=sys.stderr) return 1 if likely_encoding and isinstance(val, binary_type): try: val = val.decode(likely_encoding) except UnicodeError: pass confoverrides[key] = val for val in opts.htmldefine: try: key, val = val.split("=") except ValueError: print("Error: -A option argument must be in the form name=value.", file=sys.stderr) return 1 try: val = int(val) except ValueError: if likely_encoding and isinstance(val, binary_type): try: val = val.decode(likely_encoding) except UnicodeError: pass confoverrides["html_context.%s" % key] = val if opts.nitpicky: confoverrides["nitpicky"] = True app = None try: with docutils_namespace(): app = Sphinx( srcdir, confdir, outdir, doctreedir, opts.builder, confoverrides, status, warning, opts.freshenv, opts.warningiserror, opts.tags, opts.verbosity, opts.jobs, ) app.build(opts.force_all, filenames) return app.statuscode except (Exception, KeyboardInterrupt) as exc: handle_exception(app, opts, exc, error) return 1