From fb2c6262c4964eba2d90a1ddd999fe5bc49827b4 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Tue, 9 Jul 2019 14:23:38 -0400 Subject: Make Analysis a context manager to properly close sqlite files --- coverage/control.py | 16 +++++------ coverage/results.py | 6 ++++ tests/coveragetest.py | 78 +++++++++++++++++++++++++-------------------------- tests/test_api.py | 3 +- tests/test_arcs.py | 3 +- tests/test_plugins.py | 13 ++++----- 6 files changed, 63 insertions(+), 56 deletions(-) diff --git a/coverage/control.py b/coverage/control.py index fbf4455c..9ee6e4b4 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -683,14 +683,14 @@ class Coverage(object): coverage data. """ - analysis = self._analyze(morf) - return ( - analysis.filename, - sorted(analysis.statements), - sorted(analysis.excluded), - sorted(analysis.missing), - analysis.missing_formatted(), - ) + with self._analyze(morf) as analysis: + return ( + analysis.filename, + sorted(analysis.statements), + sorted(analysis.excluded), + sorted(analysis.missing), + analysis.missing_formatted(), + ) def _analyze(self, it): """Analyze a single morf or code unit. diff --git a/coverage/results.py b/coverage/results.py index ba335209..83cdbdf9 100644 --- a/coverage/results.py +++ b/coverage/results.py @@ -49,6 +49,12 @@ class Analysis(object): n_missing_branches=n_missing_branches, ) + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.data.close() + def missing_formatted(self, branches=False): """The missing line numbers, formatted nicely. diff --git a/tests/coveragetest.py b/tests/coveragetest.py index b06db896..c79cab4d 100644 --- a/tests/coveragetest.py +++ b/tests/coveragetest.py @@ -196,48 +196,48 @@ class CoverageTest( del sys.modules[modname] # Get the analysis results, and check that they are right. - analysis = cov._analyze(mod) - statements = sorted(analysis.statements) - if lines is not None: - if isinstance(lines[0], int): - # lines is just a list of numbers, it must match the statements - # found in the code. - self.assertEqual(statements, lines) - else: - # lines is a list of possible line number lists, one of them - # must match. - for line_list in lines: - if statements == line_list: - break + with cov._analyze(mod) as analysis: + statements = sorted(analysis.statements) + if lines is not None: + if isinstance(lines[0], int): + # lines is just a list of numbers, it must match the statements + # found in the code. + self.assertEqual(statements, lines) else: - self.fail("None of the lines choices matched %r" % statements) + # lines is a list of possible line number lists, one of them + # must match. + for line_list in lines: + if statements == line_list: + break + else: + self.fail("None of the lines choices matched %r" % statements) - missing_formatted = analysis.missing_formatted() - if isinstance(missing, string_class): - self.assertEqual(missing_formatted, missing) - else: - for missing_list in missing: - if missing_formatted == missing_list: - break + missing_formatted = analysis.missing_formatted() + if isinstance(missing, string_class): + self.assertEqual(missing_formatted, missing) else: - self.fail("None of the missing choices matched %r" % missing_formatted) - - if arcs is not None: - with self.delayed_assertions(): - self.assert_equal_arcs( - arcs, analysis.arc_possibilities(), - "Possible arcs differ: minus is expected, plus is actual" - ) - - self.assert_equal_arcs( - arcs_missing, analysis.arcs_missing(), - "Missing arcs differ: minus is expected, plus is actual" - ) - - self.assert_equal_arcs( - arcs_unpredicted, analysis.arcs_unpredicted(), - "Unpredicted arcs differ: minus is expected, plus is actual" - ) + for missing_list in missing: + if missing_formatted == missing_list: + break + else: + self.fail("None of the missing choices matched %r" % missing_formatted) + + if arcs is not None: + with self.delayed_assertions(): + self.assert_equal_arcs( + arcs, analysis.arc_possibilities(), + "Possible arcs differ: minus is expected, plus is actual" + ) + + self.assert_equal_arcs( + arcs_missing, analysis.arcs_missing(), + "Missing arcs differ: minus is expected, plus is actual" + ) + + self.assert_equal_arcs( + arcs_unpredicted, analysis.arcs_unpredicted(), + "Unpredicted arcs differ: minus is expected, plus is actual" + ) if report: frep = StringIO() diff --git a/tests/test_api.py b/tests/test_api.py index 301257dc..c69a3010 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -834,7 +834,8 @@ class AnalysisTest(CoverageTest): # Import the Python file, executing it. self.start_import_stop(cov, "missing") - nums = cov._analyze("missing.py").numbers + with cov._analyze("missing.py") as analysis: + nums = analysis.numbers self.assertEqual(nums.n_files, 1) self.assertEqual(nums.n_statements, 7) self.assertEqual(nums.n_excluded, 1) diff --git a/tests/test_arcs.py b/tests/test_arcs.py index 638478ab..79a9b184 100644 --- a/tests/test_arcs.py +++ b/tests/test_arcs.py @@ -1315,7 +1315,8 @@ class MiscArcTest(CoverageTest): # ugh, unexposed methods?? filename = self.last_module_name + ".py" fr = cov._get_file_reporter(filename) - arcs_executed = cov._analyze(filename).arcs_executed() + with cov._analyze(filename) as analysis: + arcs_executed = analysis.arcs_executed() self.assertEqual( fr.missing_arc_description(3, -3, arcs_executed), "line 3 didn't finish the generator expression on line 3" diff --git a/tests/test_plugins.py b/tests/test_plugins.py index a4c7a5ee..9afe83da 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -399,13 +399,12 @@ class GoodFileTracerTest(FileTracerTest): # The way plugin2 works, a file named foo_7.html will be claimed to # have 7 lines in it. If render() was called with line number 4, # then the plugin will claim that lines 4 and 5 were executed. - analysis = cov._analyze("foo_7.html") - self.assertEqual(analysis.statements, set([1, 2, 3, 4, 5, 6, 7])) - # Plugins don't do branch coverage yet. - self.assertEqual(analysis.has_arcs(), True) - self.assertEqual(analysis.arc_possibilities(), []) - - self.assertEqual(analysis.missing, set([1, 2, 3, 6, 7])) + with cov._analyze("foo_7.html") as analysis: + self.assertEqual(analysis.statements, set([1, 2, 3, 4, 5, 6, 7])) + # Plugins don't do branch coverage yet. + self.assertEqual(analysis.has_arcs(), True) + self.assertEqual(analysis.arc_possibilities(), []) + self.assertEqual(analysis.missing, set([1, 2, 3, 6, 7])) def test_plugin2_with_text_report(self): self.make_render_and_caller() -- cgit v1.2.1