diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2016-11-05 08:50:36 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2016-11-05 08:50:36 -0400 |
commit | 1752d7e0ddefb87021812d982ec998eefaed5d0f (patch) | |
tree | 0b1ef3c81014f7cd7d39cc1b121197d6015a80ef | |
parent | b3f1198035da5576416f2096ca5e0fa19ca5ccab (diff) | |
download | python-coveragepy-git-1752d7e0ddefb87021812d982ec998eefaed5d0f.tar.gz |
A fix for coding declarations, bug #529
-rw-r--r-- | CHANGES.rst | 4 | ||||
-rw-r--r-- | coverage/phystokens.py | 6 | ||||
-rw-r--r-- | tests/test_phystokens.py | 58 |
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.""" |