summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.rst8
-rw-r--r--coverage/disposition.py2
-rw-r--r--coverage/inorout.py3
-rw-r--r--tests/test_oddball.py22
4 files changed, 32 insertions, 3 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 49f5dc9a..966a56b3 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -30,6 +30,12 @@ Unreleased
- Feature: The HTML report pages for Python source files now have a sticky
header so the file name and controls are always visible.
+- Fix: more generated code is now excluded from measurement. Code such as
+ `attrs`_ boilerplate, or doctest code, was being measured though the
+ synthetic line numbers meant they were never reported. Once Cython was
+ involved though, the generated .so files were parsed as Python, raising
+ syntax errors, as reported in `issue 1160`_. This is now fixed.
+
- Fix: When sorting human-readable names, numeric components are sorted
correctly: file10.py will appear after file9.py. This applies to file names,
module names, environment variables, and test contexts.
@@ -41,6 +47,8 @@ Unreleased
.. _issue 553: https://github.com/nedbat/coveragepy/issues/553
.. _issue 840: https://github.com/nedbat/coveragepy/issues/840
+.. _issue 1160: https://github.com/nedbat/coveragepy/issues/1160
+.. _attrs: https://www.attrs.org/
.. _changes_602:
diff --git a/coverage/disposition.py b/coverage/disposition.py
index dfcc6def..1c39a9c1 100644
--- a/coverage/disposition.py
+++ b/coverage/disposition.py
@@ -30,6 +30,8 @@ def disposition_debug_msg(disp):
"""Make a nice debug message of what the FileDisposition is doing."""
if disp.trace:
msg = f"Tracing {disp.original_filename!r}"
+ if disp.original_filename != disp.source_filename:
+ msg += f" as {disp.source_filename!r}"
if disp.file_tracer:
msg += ": will be traced by %r" % disp.file_tracer
else:
diff --git a/coverage/inorout.py b/coverage/inorout.py
index 6bdac06e..3bc7e54e 100644
--- a/coverage/inorout.py
+++ b/coverage/inorout.py
@@ -317,6 +317,9 @@ class InOrOut:
disp.reason = reason
return disp
+ if original_filename.startswith('<'):
+ return nope(disp, "not a real original file name")
+
if frame is not None:
# Compiled Python files have two file names: frame.f_code.co_filename is
# the file name at the time the .pyc was compiled. The second name is
diff --git a/tests/test_oddball.py b/tests/test_oddball.py
index c3082abb..b59e6395 100644
--- a/tests/test_oddball.py
+++ b/tests/test_oddball.py
@@ -393,7 +393,13 @@ class DoctestTest(CoverageTest):
"""Tests invoked with doctest should measure properly."""
def test_doctest(self):
- self.check_coverage('''\
+ # Doctests used to be traced, with their line numbers credited to the
+ # file they were in. Below, one of the doctests has four lines (1-4),
+ # which would incorrectly claim that lines 1-4 of the file were
+ # executed. In this file, line 2 is not executed.
+ self.make_file("the_doctest.py", '''\
+ if "x" in "abc":
+ print("hello")
def return_arg_or_void(arg):
"""If <arg> is None, return "Void"; otherwise return <arg>
@@ -403,6 +409,11 @@ class DoctestTest(CoverageTest):
'arg'
>>> return_arg_or_void("None")
'None'
+ >>> if "x" in "xyz": # line 1
+ ... if "a" in "aswed": # line 2
+ ... if "a" in "abc": # line 3
+ ... return_arg_or_void(12) # line 4
+ 12
"""
if arg is None:
return "Void"
@@ -411,8 +422,13 @@ class DoctestTest(CoverageTest):
import doctest, sys
doctest.testmod(sys.modules[__name__]) # we're not __main__ :(
- ''',
- [1, 11, 12, 14, 16, 17], "")
+ ''')
+ cov = coverage.Coverage()
+ self.start_import_stop(cov, "the_doctest")
+ data = cov.get_data()
+ assert len(data.measured_files()) == 1
+ lines = data.lines(data.measured_files().pop())
+ assert lines == [1, 3, 18, 19, 21, 23, 24]
class GettraceTest(CoverageTest):