summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2019-07-01 23:14:15 -0400
committerNed Batchelder <ned@nedbatchelder.com>2019-07-01 23:14:15 -0400
commit25aff80d444a6b1fa87173ffd8026f69be7ae0d0 (patch)
treebce9981e83cf7374098fc9e299574b93b089c744
parent262c06921db064a85f442b19cbf0980bb3cd786d (diff)
downloadpython-coveragepy-git-25aff80d444a6b1fa87173ffd8026f69be7ae0d0.tar.gz
Clean up and test filtering contexts for reporting
-rw-r--r--coverage/cmdline.py2
-rw-r--r--coverage/config.py3
-rw-r--r--coverage/control.py8
-rw-r--r--coverage/html.py5
-rw-r--r--coverage/sqldata.py17
-rw-r--r--coverage/summary.py2
-rw-r--r--tests/test_html.py21
7 files changed, 37 insertions, 21 deletions
diff --git a/coverage/cmdline.py b/coverage/cmdline.py
index cf97bb01..354ae8c2 100644
--- a/coverage/cmdline.py
+++ b/coverage/cmdline.py
@@ -109,7 +109,7 @@ class Opts(object):
'', '--contexts', action='store',
metavar="PAT1,PAT2,...",
help=(
- "Only count the lines covered in given contexts. "
+ "Only display data from lines covered in the given contexts. "
"Accepts shell-style wildcards, which must be quoted."
),
)
diff --git a/coverage/config.py b/coverage/config.py
index d5d89d1f..4bb60eb3 100644
--- a/coverage/config.py
+++ b/coverage/config.py
@@ -179,7 +179,6 @@ class CoverageConfig(object):
self.command_line = None
self.concurrency = None
self.context = None
- self.query_contexts = None
self.cover_pylib = False
self.data_file = ".coverage"
self.debug = []
@@ -202,6 +201,7 @@ class CoverageConfig(object):
self.partial_always_list = DEFAULT_PARTIAL_ALWAYS[:]
self.partial_list = DEFAULT_PARTIAL[:]
self.precision = 0
+ self.report_contexts = None
self.show_missing = False
self.skip_covered = False
@@ -347,6 +347,7 @@ class CoverageConfig(object):
('partial_always_list', 'report:partial_branches_always', 'regexlist'),
('partial_list', 'report:partial_branches', 'regexlist'),
('precision', 'report:precision', 'int'),
+ ('report_contexts', 'report:contexts', 'list'),
('report_include', 'report:include', 'list'),
('report_omit', 'report:omit', 'list'),
('show_missing', 'report:show_missing', 'boolean'),
diff --git a/coverage/control.py b/coverage/control.py
index a8e9d15c..a4e21295 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -781,7 +781,7 @@ class Coverage(object):
self.config.from_args(
ignore_errors=ignore_errors, report_omit=omit, report_include=include,
show_missing=show_missing, skip_covered=skip_covered,
- query_contexts=contexts,
+ report_contexts=contexts,
)
reporter = SummaryReporter(self)
return reporter.report(morfs, outfile=file)
@@ -802,7 +802,7 @@ class Coverage(object):
"""
self.config.from_args(
ignore_errors=ignore_errors, report_omit=omit,
- report_include=include, query_contexts=contexts,
+ report_include=include, report_contexts=contexts,
)
reporter = AnnotateReporter(self)
reporter.report(morfs, directory=directory)
@@ -836,7 +836,7 @@ class Coverage(object):
self.config.from_args(
ignore_errors=ignore_errors, report_omit=omit, report_include=include,
html_dir=directory, extra_css=extra_css, html_title=title,
- skip_covered=skip_covered, show_contexts=show_contexts, query_contexts=contexts,
+ skip_covered=skip_covered, show_contexts=show_contexts, report_contexts=contexts,
)
reporter = HtmlReporter(self)
return reporter.report(morfs)
@@ -859,7 +859,7 @@ class Coverage(object):
"""
self.config.from_args(
ignore_errors=ignore_errors, report_omit=omit, report_include=include,
- xml_output=outfile, query_contexts=contexts,
+ xml_output=outfile, report_contexts=contexts,
)
file_to_close = None
delete_file = False
diff --git a/coverage/html.py b/coverage/html.py
index cff2419d..fc3bb364 100644
--- a/coverage/html.py
+++ b/coverage/html.py
@@ -80,7 +80,9 @@ class HtmlDataGeneration(object):
def __init__(self, cov):
self.coverage = cov
self.config = self.coverage.config
- self.has_arcs = self.coverage.get_data().has_arcs()
+ data = self.coverage.get_data()
+ self.has_arcs = data.has_arcs()
+ data.set_query_contexts(self.config.report_contexts)
def data_for_file(self, fr, analysis):
"""Produce the data needed for one file's report."""
@@ -218,7 +220,6 @@ class HtmlReporter(object):
self.incr.check_global_data(self.config, self.pyfile_html_source)
# Process all the files.
- self.coverage.get_data().set_query_contexts(self.config.query_contexts)
for fr, analysis in get_analysis_to_report(self.coverage, morfs):
self.html_file(fr, analysis)
diff --git a/coverage/sqldata.py b/coverage/sqldata.py
index 1cc64f24..03a352ba 100644
--- a/coverage/sqldata.py
+++ b/coverage/sqldata.py
@@ -558,10 +558,12 @@ class CoverageSqliteData(SimpleReprMixin):
return "" # File was measured, but no tracer associated.
- def set_query_contexts(self, contexts=None):
+ def set_query_contexts(self, contexts):
"""Set query contexts for future `lines`, `arcs` etc. calls."""
- self._query_context_ids = self._get_query_context_ids(contexts) \
- if contexts is not None else None
+ if contexts:
+ self._query_context_ids = self._get_query_context_ids(contexts)
+ else:
+ self._query_context_ids = None
self._query_contexts = contexts
def _get_query_context_ids(self, contexts=None):
@@ -570,13 +572,10 @@ class CoverageSqliteData(SimpleReprMixin):
return None
self._start_using()
with self._connect() as con:
- # Context entries can be globs, so convert '*' with '%'.
- context_selectors = [context.replace('*', '%') for context in contexts]
- context_clause = ' or '.join(['context like ?']*len(contexts))
- cur = con.execute(
- "select id from context where " + context_clause, context_selectors)
+ context_clause = ' or '.join(['context glob ?'] * len(contexts))
+ cur = con.execute("select id from context where " + context_clause, contexts)
return [row[0] for row in cur.fetchall()]
- elif self._query_contexts is not None:
+ elif self._query_contexts:
return self._query_context_ids
return None
diff --git a/coverage/summary.py b/coverage/summary.py
index 419051b0..72d21033 100644
--- a/coverage/summary.py
+++ b/coverage/summary.py
@@ -40,7 +40,7 @@ class SummaryReporter(object):
"""
self.outfile = outfile or sys.stdout
- self.coverage.get_data().set_query_contexts(self.config.query_contexts)
+ self.coverage.get_data().set_query_contexts(self.config.report_contexts)
for fr, analysis in get_analysis_to_report(self.coverage, morfs):
self.report_one_file(fr, analysis)
diff --git a/tests/test_html.py b/tests/test_html.py
index 37862f6d..4509e52f 100644
--- a/tests/test_html.py
+++ b/tests/test_html.py
@@ -1037,10 +1037,10 @@ assert len(math) == 18
def html_data_from_cov(cov, morf):
"""Get HTML report data from a `Coverage` object for a morf."""
- reporter = coverage.html.HtmlDataGeneration(cov)
+ datagen = coverage.html.HtmlDataGeneration(cov)
for fr, analysis in get_analysis_to_report(cov, [morf]):
# This will only loop once, so it's fine to return inside the loop.
- file_data = reporter.data_for_file(fr, analysis)
+ file_data = datagen.data_for_file(fr, analysis)
return file_data
@@ -1081,7 +1081,7 @@ class HtmlWithContextsTest(HtmlTestHelpers, CoverageTest):
TEST_ONE_LINES = [5, 6, 2]
TEST_TWO_LINES = [9, 10, 11, 13, 14, 15, 2]
- def test_dynamic_alone(self):
+ def test_dynamic_contexts(self):
self.make_file("two_tests.py", self.SOURCE)
cov = coverage.Coverage(source=["."])
cov.set_option("run:dynamic_context", "test_function")
@@ -1094,3 +1094,18 @@ class HtmlWithContextsTest(HtmlTestHelpers, CoverageTest):
for label, expected in zip(context_labels, expected_lines):
actual = [ld.number for ld in d.lines if label in (ld.contexts or ())]
assert sorted(expected) == sorted(actual)
+
+ def test_filtered_dynamic_contexts(self):
+ self.make_file("two_tests.py", self.SOURCE)
+ cov = coverage.Coverage(source=["."])
+ cov.set_option("run:dynamic_context", "test_function")
+ cov.set_option("html:show_contexts", True)
+ cov.set_option("report:contexts", ["*test_one*"])
+ mod = self.start_import_stop(cov, "two_tests")
+ d = html_data_from_cov(cov, mod)
+
+ context_labels = ['(empty)', 'two_tests.test_one', 'two_tests.test_two']
+ expected_lines = [[], self.TEST_ONE_LINES, []]
+ for label, expected in zip(context_labels, expected_lines):
+ actual = [ld.number for ld in d.lines if label in (ld.contexts or ())]
+ assert sorted(expected) == sorted(actual)