summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--CHANGES1
-rw-r--r--doc/usage/extensions/coverage.rst12
-rw-r--r--sphinx/ext/coverage.py17
-rw-r--r--tests/roots/test-ext-coverage/conf.py12
-rw-r--r--tests/roots/test-ext-coverage/coverage_ignored.py22
-rw-r--r--tests/roots/test-ext-coverage/coverage_not_ignored.py22
-rw-r--r--tests/roots/test-ext-coverage/index.rst6
-rw-r--r--tests/test_ext_coverage.py19
9 files changed, 109 insertions, 3 deletions
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