summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2016-11-05 08:50:36 -0400
committerNed Batchelder <ned@nedbatchelder.com>2016-11-05 08:50:36 -0400
commit1752d7e0ddefb87021812d982ec998eefaed5d0f (patch)
tree0b1ef3c81014f7cd7d39cc1b121197d6015a80ef
parentb3f1198035da5576416f2096ca5e0fa19ca5ccab (diff)
downloadpython-coveragepy-git-1752d7e0ddefb87021812d982ec998eefaed5d0f.tar.gz
A fix for coding declarations, bug #529
-rw-r--r--CHANGES.rst4
-rw-r--r--coverage/phystokens.py6
-rw-r--r--tests/test_phystokens.py58
3 files changed, 67 insertions, 1 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 431fa19b..637537ec 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -40,6 +40,9 @@ Unreleased
call stack printed for every line in the multi-line config output. This is
now fixed.
+- Fixed an unusual bug involving multiple coding declarations affecting code
+ containing code in multi-line strings: `issue 529`_.
+
- Corrected the name of the jquery.ba-throttle-debounce.js library. Thanks,
Ben Finney. Closes `issue 505`_.
@@ -51,6 +54,7 @@ Unreleased
.. _issue 511: https://bitbucket.org/ned/coveragepy/issues/511/version-42-coverage-combine-empties
.. _issue 516: https://bitbucket.org/ned/coveragepy/issues/516/running-coverage-combine-twice-deletes-all
.. _issue 525: https://bitbucket.org/ned/coveragepy/issues/525/coverage-combine-when-not-in-parallel-mode
+.. _issue 529: https://bitbucket.org/ned/coveragepy/issues/529/encoding-marker-may-only-appear-on-the
Version 4.2 --- 2016-07-26
diff --git a/coverage/phystokens.py b/coverage/phystokens.py
index 5e80ed54..9a697b60 100644
--- a/coverage/phystokens.py
+++ b/coverage/phystokens.py
@@ -290,5 +290,9 @@ def compile_unicode(source, filename, mode):
@contract(source='unicode', returns='unicode')
def neuter_encoding_declaration(source):
"""Return `source`, with any encoding declaration neutered."""
- source = COOKIE_RE.sub("# (deleted declaration)", source, count=2)
+ if COOKIE_RE.search(source):
+ source_lines = source.splitlines(True)
+ for lineno in range(min(2, len(source_lines))):
+ source_lines[lineno] = COOKIE_RE.sub("# (deleted declaration)", source_lines[lineno])
+ source = "".join(source_lines)
return source
diff --git a/tests/test_phystokens.py b/tests/test_phystokens.py
index ccbe01b0..68456b5b 100644
--- a/tests/test_phystokens.py
+++ b/tests/test_phystokens.py
@@ -5,6 +5,7 @@
import os.path
import re
+import textwrap
from coverage import env
from coverage.phystokens import source_token_lines, source_encoding
@@ -177,6 +178,63 @@ class NeuterEncodingDeclarationTest(CoverageTest):
"Wrong encoding in %r" % neutered
)
+ def test_two_encoding_declarations(self):
+ input_src = textwrap.dedent(u"""\
+ # -*- coding: ascii -*-
+ # -*- coding: utf-8 -*-
+ # -*- coding: utf-16 -*-
+ """)
+ expected_src = textwrap.dedent(u"""\
+ # (deleted declaration) -*-
+ # (deleted declaration) -*-
+ # -*- coding: utf-16 -*-
+ """)
+ output_src = neuter_encoding_declaration(input_src)
+ self.assertEqual(expected_src, output_src)
+
+ def test_one_encoding_declaration(self):
+ input_src = textwrap.dedent(u"""\
+ # -*- coding: utf-16 -*-
+ # Just a comment.
+ # -*- coding: ascii -*-
+ """)
+ expected_src = textwrap.dedent(u"""\
+ # (deleted declaration) -*-
+ # Just a comment.
+ # -*- coding: ascii -*-
+ """)
+ output_src = neuter_encoding_declaration(input_src)
+ self.assertEqual(expected_src, output_src)
+
+
+class Bug529Test(CoverageTest):
+ """Test of bug 529"""
+
+ def test_bug_529(self):
+ self.make_file("the_test.py", '''\
+ # -*- coding: utf-8 -*-
+ import unittest
+ class FailsUnderCoverageTest(unittest.TestCase):
+ def test_fails_under_coverage(self):
+ src1 = u"""\\
+ # -*- coding: utf-8 -*-
+ # Just a comment.
+ """
+ src2 = u"""\\
+ # -*- coding: utf-8 -*-
+ # Just a comment.
+ """
+ self.assertEqual(src1, src2)
+
+ if __name__ == "__main__":
+ unittest.main()
+ ''')
+ status, out = self.run_command_status("coverage run the_test.py")
+ self.assertEqual(status, 0)
+ self.assertIn("OK", out)
+ # If this test fails, the output will be super-confusing, because it
+ # has a failing unit test contained within the failing unit test.
+
class CompileUnicodeTest(CoverageTest):
"""Tests of compiling Unicode strings."""