From e84ba7f78aa0e09750c12e38963d5f43ca599c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Chaves?= Date: Tue, 14 May 2019 14:48:52 +0200 Subject: [PATCH] Support coverage_ignore_pyobjects in the coverage builder --- AUTHORS | 1 + CHANGES | 1 + doc/usage/extensions/coverage.rst | 12 ++++++++++ sphinx/ext/coverage.py | 17 +++++++++++--- tests/roots/test-ext-coverage/conf.py | 12 ++++++++++ .../test-ext-coverage/coverage_ignored.py | 22 +++++++++++++++++++ .../test-ext-coverage/coverage_not_ignored.py | 22 +++++++++++++++++++ tests/roots/test-ext-coverage/index.rst | 6 +++++ tests/test_ext_coverage.py | 19 ++++++++++++++++ 9 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 tests/roots/test-ext-coverage/conf.py create mode 100644 tests/roots/test-ext-coverage/coverage_ignored.py create mode 100644 tests/roots/test-ext-coverage/coverage_not_ignored.py create mode 100644 tests/roots/test-ext-coverage/index.rst diff --git a/AUTHORS b/AUTHORS index aef4410be..27c51d150 100644 --- a/AUTHORS +++ b/AUTHORS @@ -82,6 +82,7 @@ Other contributors, listed alphabetically, are: * Stephen Finucane -- setup command improvements and documentation * Daniel Pizetta -- inheritance diagram improvements * KINEBUCHI Tomohiko -- typing Sphinx as well as docutils +* Adrián Chaves (Gallaecio) -- coverage builder improvements Many thanks for all contributions! diff --git a/CHANGES b/CHANGES index 1319812cf..ddcdaf654 100644 --- a/CHANGES +++ b/CHANGES @@ -99,6 +99,7 @@ Features added * #6306: html: Add a label to search form for accessability purposes * #6358: The ``rawsource`` property of ``production`` nodes now contains the full production rule +* Support a new ``coverage_ignore_pyobjects`` option in the coverage builder Bugs fixed ---------- diff --git a/doc/usage/extensions/coverage.rst b/doc/usage/extensions/coverage.rst index 1fb9b1850..46d31053c 100644 --- a/doc/usage/extensions/coverage.rst +++ b/doc/usage/extensions/coverage.rst @@ -22,6 +22,16 @@ should check: .. confval:: coverage_ignore_classes +.. confval:: coverage_ignore_pyobjects + + List of `Python regular expressions`_. + + If any of these regular expressions matches any part of the full import path + of a Python object, that Python object is excluded from the documentation + coverage report. + + .. versionadded:: 2.1 + .. confval:: coverage_c_path .. confval:: coverage_c_regexes @@ -40,3 +50,5 @@ should check: ``False`` by default. .. versionadded:: 1.1 + +.. _Python regular expressions: https://docs.python.org/library/re \ No newline at end of file diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py index 63beecd61..6c9489046 100644 --- a/sphinx/ext/coverage.py +++ b/sphinx/ext/coverage.py @@ -79,6 +79,8 @@ class CoverageBuilder(Builder): self.config.coverage_ignore_classes) self.fun_ignorexps = compile_regex_list('coverage_ignore_functions', self.config.coverage_ignore_functions) + self.py_ignorexps = compile_regex_list('coverage_ignore_pyobjects', + self.config.coverage_ignore_pyobjects) def get_outdated_docs(self): # type: () -> str @@ -130,6 +132,12 @@ class CoverageBuilder(Builder): op.write(' * %-50s [%9s]\n' % (name, typ)) op.write('\n') + def ignore_pyobj(self, full_name): + for exp in self.py_ignorexps: + if exp.search(full_name): + return True + return False + def build_py_coverage(self): # type: () -> None objects = self.env.domaindata['py']['objects'] @@ -143,7 +151,7 @@ class CoverageBuilder(Builder): if exp.match(mod_name): ignore = True break - if ignore: + if ignore or self.ignore_pyobj(mod_name): continue try: @@ -169,6 +177,8 @@ class CoverageBuilder(Builder): continue full_name = '%s.%s' % (mod_name, name) + if self.ignore_pyobj(full_name): + continue if inspect.isfunction(obj): if full_name not in objects: @@ -209,11 +219,11 @@ class CoverageBuilder(Builder): if skip_undoc and not attr.__doc__: # skip methods without docstring if wished continue - full_attr_name = '%s.%s' % (full_name, attr_name) + if self.ignore_pyobj(full_attr_name): + continue if full_attr_name not in objects: attrs.append(attr_name) - if attrs: # some attributes are undocumented classes[name] = attrs @@ -270,6 +280,7 @@ def setup(app): app.add_config_value('coverage_ignore_modules', [], False) app.add_config_value('coverage_ignore_functions', [], False) app.add_config_value('coverage_ignore_classes', [], False) + app.add_config_value('coverage_ignore_pyobjects', [], False) app.add_config_value('coverage_c_path', [], False) app.add_config_value('coverage_c_regexes', {}, False) app.add_config_value('coverage_ignore_c_items', {}, False) diff --git a/tests/roots/test-ext-coverage/conf.py b/tests/roots/test-ext-coverage/conf.py new file mode 100644 index 000000000..d3ec6e87f --- /dev/null +++ b/tests/roots/test-ext-coverage/conf.py @@ -0,0 +1,12 @@ +import os +import sys + +sys.path.insert(0, os.path.abspath('.')) + +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage'] + +coverage_ignore_pyobjects = [ + r'^coverage_ignored(\..*)?$', + r'\.Ignored$', + r'\.Documented\.ignored\d$', +] diff --git a/tests/roots/test-ext-coverage/coverage_ignored.py b/tests/roots/test-ext-coverage/coverage_ignored.py new file mode 100644 index 000000000..b76295501 --- /dev/null +++ b/tests/roots/test-ext-coverage/coverage_ignored.py @@ -0,0 +1,22 @@ +class Documented: + """Documented""" + + def ignored1(self): + pass + + def ignored2(self): + pass + + def not_ignored1(self): + pass + + def not_ignored2(self): + pass + + +class Ignored: + pass + + +class NotIgnored: + pass diff --git a/tests/roots/test-ext-coverage/coverage_not_ignored.py b/tests/roots/test-ext-coverage/coverage_not_ignored.py new file mode 100644 index 000000000..b76295501 --- /dev/null +++ b/tests/roots/test-ext-coverage/coverage_not_ignored.py @@ -0,0 +1,22 @@ +class Documented: + """Documented""" + + def ignored1(self): + pass + + def ignored2(self): + pass + + def not_ignored1(self): + pass + + def not_ignored2(self): + pass + + +class Ignored: + pass + + +class NotIgnored: + pass diff --git a/tests/roots/test-ext-coverage/index.rst b/tests/roots/test-ext-coverage/index.rst new file mode 100644 index 000000000..b8468987e --- /dev/null +++ b/tests/roots/test-ext-coverage/index.rst @@ -0,0 +1,6 @@ +.. automodule:: coverage_ignored + :members: + + +.. automodule:: coverage_not_ignored + :members: diff --git a/tests/test_ext_coverage.py b/tests/test_ext_coverage.py index 73181909d..8209820a0 100644 --- a/tests/test_ext_coverage.py +++ b/tests/test_ext_coverage.py @@ -45,3 +45,22 @@ def test_build(app, status, warning): assert 'classes' in undoc_py['autodoc_target'] assert 'Class' in undoc_py['autodoc_target']['classes'] assert 'undocmeth' in undoc_py['autodoc_target']['classes']['Class'] + + +@pytest.mark.sphinx('coverage', testroot='ext-coverage') +def test_coverage_ignore_pyobjects(app, status, warning): + app.builder.build_all() + actual = (app.outdir / 'python.txt').text() + expected = '''Undocumented Python objects +=========================== +coverage_not_ignored +-------------------- +Classes: + * Documented -- missing methods: + + - not_ignored1 + - not_ignored2 + * NotIgnored + +''' + assert actual == expected