From acad72bbd6b13c7633504e16bf15f55938d55ecf Mon Sep 17 00:00:00 2001 From: Ashley Whetter Date: Sat, 20 Jul 2024 10:31:03 -0700 Subject: [PATCH] Gracefully handle no objects being rendered Closes #448 --- autoapi/_mapper.py | 10 +++++++++ autoapi/extension.py | 3 +++ docs/changes/448.bugfix | 1 + docs/reference/config.rst | 20 +++++++++++------ tests/python/pynorender/conf.py | 22 ++++++++++++++++++ tests/python/pynorender/example/_example.py | 7 ++++++ tests/python/pynorender/index.rst | 25 +++++++++++++++++++++ tests/python/test_pyintegration.py | 7 ++++++ tox.ini | 1 + 9 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 docs/changes/448.bugfix create mode 100644 tests/python/pynorender/conf.py create mode 100644 tests/python/pynorender/example/_example.py create mode 100644 tests/python/pynorender/index.rst diff --git a/autoapi/_mapper.py b/autoapi/_mapper.py index 48bd2c7f..7c7dc71d 100644 --- a/autoapi/_mapper.py +++ b/autoapi/_mapper.py @@ -359,6 +359,16 @@ def _output_top_rst(self): # Render Top Index top_level_index = os.path.join(self.dir_root, "index.rst") pages = [obj for obj in self.objects_to_render.values() if obj.display] + if not pages: + msg = ( + "No modules were rendered. " + "Do you need to set autoapi_options to render additional objects?" + ) + LOGGER.warning( + msg, type="autoapi", subtype="nothing_rendered" + ) + return + with open(top_level_index, "wb") as top_level_file: content = self.jinja_env.get_template("index.rst") top_level_file.write(content.render(pages=pages).encode("utf-8")) diff --git a/autoapi/extension.py b/autoapi/extension.py index c974e771..609c09b0 100644 --- a/autoapi/extension.py +++ b/autoapi/extension.py @@ -124,6 +124,9 @@ def build_finished(app, exception): normalized_root = os.path.normpath( os.path.join(app.srcdir, app.config.autoapi_root) ) + if not os.path.exists(normalized_root): + return + if app.verbosity > 1: LOGGER.info( colorize("bold", "[AutoAPI] ") diff --git a/docs/changes/448.bugfix b/docs/changes/448.bugfix new file mode 100644 index 00000000..b7446d84 --- /dev/null +++ b/docs/changes/448.bugfix @@ -0,0 +1 @@ +Gracefully handle no objects being rendered \ No newline at end of file diff --git a/docs/reference/config.rst b/docs/reference/config.rst index 08eed5eb..082ded45 100644 --- a/docs/reference/config.rst +++ b/docs/reference/config.rst @@ -273,13 +273,19 @@ Suppressing Warnings If narrower suppression is wanted, the available subtypes for AutoAPI are: - * python_import_resolution - Used if resolving references to objects in an imported module failed. Potential reasons - include cyclical imports and missing (parent) modules. - * not_readable - Emitted if processing (opening, parsing, ...) an input file failed. - * toc_reference - Used if a reference to an entry in a table of content cannot be resolved. + * ``python_import_resolution``: + Emitted if resolving references to objects in an imported module failed. + Potential reasons include cyclical imports and missing (parent) modules. + * ``not_readable``: + Emitted if processing (opening, parsing, ...) an input file failed. + * ``toc_reference``: + Emitted if a reference to an entry in a table of content cannot be resolved. + * ``nothing_rendered``: + Emitted if nothing was found to be documented. + Potential reasons include no files being found in :confval:`autoapi_dirs` + that match :confval:`autoapi_file_patterns`, + or all discovered modules and objects being excluded from rendering due to + :confval:`autoapi_options` or :ref:`other rendering exclusions `. So if all AutoAPI warnings concerning unreadable sources and failing Python imports should be filtered, but all other warnings should not, the option would be diff --git a/tests/python/pynorender/conf.py b/tests/python/pynorender/conf.py new file mode 100644 index 00000000..e195ce72 --- /dev/null +++ b/tests/python/pynorender/conf.py @@ -0,0 +1,22 @@ +templates_path = ["_templates"] +source_suffix = ".rst" +master_doc = "index" +project = "pyexample" +copyright = "2015, readthedocs" +author = "readthedocs" +version = "0.1" +release = "0.1" +language = "en" +exclude_patterns = ["_build"] +pygments_style = "sphinx" +todo_include_todos = False +html_theme = "alabaster" +htmlhelp_basename = "pyexampledoc" +extensions = ["sphinx.ext.autodoc", "autoapi.extension"] +autoapi_dirs = ["example"] +autoapi_python_class_content = "both" +autoapi_options = [ + "members", + "imported-members", + "inherited-members", +] diff --git a/tests/python/pynorender/example/_example.py b/tests/python/pynorender/example/_example.py new file mode 100644 index 00000000..db52e8d3 --- /dev/null +++ b/tests/python/pynorender/example/_example.py @@ -0,0 +1,7 @@ +def func() -> int: + """Returns five.""" + return 5 + + +class Foo: + """This is a class.""" \ No newline at end of file diff --git a/tests/python/pynorender/index.rst b/tests/python/pynorender/index.rst new file mode 100644 index 00000000..5d8a591e --- /dev/null +++ b/tests/python/pynorender/index.rst @@ -0,0 +1,25 @@ +.. pyexample documentation master file, created by + sphinx-quickstart on Fri May 29 13:34:37 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to pyexample's documentation! +===================================== + +.. toctree:: + + autoapi/index + +Contents: + +.. toctree:: + :maxdepth: 2 + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/tests/python/test_pyintegration.py b/tests/python/test_pyintegration.py index b0d54858..1377089f 100644 --- a/tests/python/test_pyintegration.py +++ b/tests/python/test_pyintegration.py @@ -1195,3 +1195,10 @@ def test_line_number_order(self, parse): method_sphinx_docs = example_file.find(id="example.Foo.method_sphinx_docs") assert method_tricky.sourceline < method_sphinx_docs.sourceline + + +def test_nothing_to_render_raises_warning(builder): + with pytest.raises(sphinx.errors.SphinxWarning) as exc_info: + builder("pynorender", warningiserror=True) + + assert "No modules were rendered" in str(exc_info.value) \ No newline at end of file diff --git a/tox.ini b/tox.ini index 4984790a..1d1dd08e 100644 --- a/tox.ini +++ b/tox.ini @@ -19,6 +19,7 @@ python = 3.13: py313 [testenv] +usedevelop = True deps = beautifulsoup4 pytest