diff --git a/coverage/misc.py b/coverage/misc.py index c484d61e5..c16b6b4aa 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -107,44 +107,6 @@ def nice_pair(pair): return "%d-%d" % (start, end) -def format_lines(statements, lines): - """Nicely format a list of line numbers. - - Format a list of line numbers for printing by coalescing groups of lines as - long as the lines represent consecutive statements. This will coalesce - even if there are gaps between statements. - - For example, if `statements` is [1,2,3,4,5,10,11,12,13,14] and - `lines` is [1,2,5,10,11,13,14] then the result will be "1-2, 5-11, 13-14". - - Both `lines` and `statements` can be any iterable. All of the elements of - `lines` must be in `statements`, and all of the values must be positive - integers. - - """ - statements = sorted(statements) - lines = sorted(lines) - - pairs = [] - start = None - lidx = 0 - for stmt in statements: - if lidx >= len(lines): - break - if stmt == lines[lidx]: - lidx += 1 - if not start: - start = stmt - end = stmt - elif start: - pairs.append((start, end)) - start = None - if start: - pairs.append((start, end)) - ret = ', '.join(map(nice_pair, pairs)) - return ret - - def expensive(fn): """A decorator to indicate that a method shouldn't be called more than once. diff --git a/coverage/results.py b/coverage/results.py index ecd50ae94..f7e0ae565 100644 --- a/coverage/results.py +++ b/coverage/results.py @@ -7,7 +7,7 @@ from coverage.backward import iitems from coverage.debug import SimpleReprMixin -from coverage.misc import contract, format_lines, CoverageException +from coverage.misc import contract, CoverageException, nice_pair class Analysis(object): @@ -272,6 +272,44 @@ def __radd__(self, other): return NotImplemented +def format_lines(statements, lines): + """Nicely format a list of line numbers. + + Format a list of line numbers for printing by coalescing groups of lines as + long as the lines represent consecutive statements. This will coalesce + even if there are gaps between statements. + + For example, if `statements` is [1,2,3,4,5,10,11,12,13,14] and + `lines` is [1,2,5,10,11,13,14] then the result will be "1-2, 5-11, 13-14". + + Both `lines` and `statements` can be any iterable. All of the elements of + `lines` must be in `statements`, and all of the values must be positive + integers. + + """ + statements = sorted(statements) + lines = sorted(lines) + + pairs = [] + start = None + lidx = 0 + for stmt in statements: + if lidx >= len(lines): + break + if stmt == lines[lidx]: + lidx += 1 + if not start: + start = stmt + end = stmt + elif start: + pairs.append((start, end)) + start = None + if start: + pairs.append((start, end)) + ret = ', '.join(map(nice_pair, pairs)) + return ret + + @contract(total='number', fail_under='number', precision=int, returns=bool) def should_fail_under(total, fail_under, precision): """Determine if a total should fail due to fail-under. diff --git a/tests/test_misc.py b/tests/test_misc.py index c8c2c9e49..e288c4f2e 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -6,7 +6,7 @@ import pytest from coverage.misc import contract, dummy_decorator_with_args, file_be_gone -from coverage.misc import format_lines, Hasher, one_of, substitute_variables +from coverage.misc import Hasher, one_of, substitute_variables from coverage.misc import CoverageException from tests.coveragetest import CoverageTest @@ -125,19 +125,6 @@ def undecorated(a=None, b=None): # pylint: disable=missing-docstr assert undecorated(b=42, a=3) == (3, 42) -@pytest.mark.parametrize("statements, lines, result", [ - (set([1,2,3,4,5,10,11,12,13,14]), set([1,2,5,10,11,13,14]), "1-2, 5-11, 13-14"), - ([1,2,3,4,5,10,11,12,13,14,98,99], [1,2,5,10,11,13,14,99], "1-2, 5-11, 13-14, 99"), - ([1,2,3,4,98,99,100,101,102,103,104], [1,2,99,102,103,104], "1-2, 99, 102-104"), - ([17], [17], "17"), - ([90,91,92,93,94,95], [90,91,92,93,94,95], "90-95"), - ([1, 2, 3, 4, 5], [], ""), - ([1, 2, 3, 4, 5], [4], "4"), -]) -def test_format_lines(statements, lines, result): - assert format_lines(statements, lines) == result - - VARS = { 'FOO': 'fooey', 'BAR': 'xyzzy', diff --git a/tests/test_results.py b/tests/test_results.py index ec6301db8..8acbcaeca 100644 --- a/tests/test_results.py +++ b/tests/test_results.py @@ -6,7 +6,7 @@ import pytest from coverage.misc import CoverageException -from coverage.results import Numbers, should_fail_under +from coverage.results import format_lines, Numbers, should_fail_under from tests.coveragetest import CoverageTest @@ -111,3 +111,16 @@ def test_should_fail_under(total, fail_under, precision, result): def test_should_fail_under_invalid_value(): with pytest.raises(CoverageException, match=r"fail_under=101"): should_fail_under(100.0, 101, 0) + + +@pytest.mark.parametrize("statements, lines, result", [ + (set([1,2,3,4,5,10,11,12,13,14]), set([1,2,5,10,11,13,14]), "1-2, 5-11, 13-14"), + ([1,2,3,4,5,10,11,12,13,14,98,99], [1,2,5,10,11,13,14,99], "1-2, 5-11, 13-14, 99"), + ([1,2,3,4,98,99,100,101,102,103,104], [1,2,99,102,103,104], "1-2, 99, 102-104"), + ([17], [17], "17"), + ([90,91,92,93,94,95], [90,91,92,93,94,95], "90-95"), + ([1, 2, 3, 4, 5], [], ""), + ([1, 2, 3, 4, 5], [4], "4"), +]) +def test_format_lines(statements, lines, result): + assert format_lines(statements, lines) == result