diff options
-rw-r--r-- | CHANGES.rst | 6 | ||||
-rw-r--r-- | CONTRIBUTORS.txt | 1 | ||||
-rw-r--r-- | coverage/files.py | 10 | ||||
-rw-r--r-- | tests/test_files.py | 24 |
4 files changed, 37 insertions, 4 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index 97a7247e..51a0019d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -13,7 +13,13 @@ Unreleased See :ref:`api_plugin` for details. This solves the complex configuration problem described in `issue 563`_. +- On Windows, the HTML report could fail when source trees are deeply nested, + due to attempting to create HTML filenames longer than the 250-character + maximum. Now filenames will never exceed 200 characters, fixing `issue + 627`_. Thanks to Alex Sandro for helping with the fix. + .. _issue 563: https://bitbucket.org/ned/coveragepy/issues/563/platform-specific-configuration +.. _issue 627: https://bitbucket.org/ned/coveragepy/issues/627/failure-generating-html-reports-when-the .. _changes_442: diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index b6d78890..6c6bcd0b 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -7,6 +7,7 @@ useful bug reports, have been made by: Adi Roiban Alex Gaynor Alex Groce +Alex Sandro Alexander Todorov Andrew Hoos Anthony Sottile diff --git a/coverage/files.py b/coverage/files.py index 04ce9cb1..12b89e8f 100644 --- a/coverage/files.py +++ b/coverage/files.py @@ -3,6 +3,7 @@ """File wrangling.""" +import hashlib import fnmatch import ntpath import os @@ -75,6 +76,9 @@ def canonical_filename(filename): return CANONICAL_FILENAME_CACHE[filename] +MAX_FLAT = 200 + +@contract(filename='unicode', returns='unicode') def flat_rootname(filename): """A base for a flat file name to correspond to this file. @@ -86,7 +90,11 @@ def flat_rootname(filename): """ name = ntpath.splitdrive(filename)[1] - return re.sub(r"[\\/.:]", "_", name) + name = re.sub(r"[\\/.:]", "_", name) + if len(name) > MAX_FLAT: + h = hashlib.sha1(name.encode('UTF-8')).hexdigest() + name = name[-(MAX_FLAT-len(h)-1):] + '_' + h + return name if env.WINDOWS: diff --git a/tests/test_files.py b/tests/test_files.py index c76dbafe..84d84a4e 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -1,3 +1,4 @@ +# coding: utf-8 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt @@ -6,6 +7,8 @@ import os import os.path +import pytest + from coverage import files from coverage.files import ( TreeMatcher, FnmatchMatcher, ModuleMatcher, PathAliases, @@ -54,9 +57,24 @@ class FilesTest(CoverageTest): rel = os.path.join('sub', trick, 'file1.py') self.assertEqual(files.relative_filename(abs_file(rel)), rel) - def test_flat_rootname(self): - self.assertEqual(flat_rootname("a/b/c.py"), "a_b_c_py") - self.assertEqual(flat_rootname(r"c:\foo\bar.html"), "_foo_bar_html") + +@pytest.mark.parametrize("original, flat", [ + (u"a/b/c.py", u"a_b_c_py"), + (u"c:\\foo\\bar.html", u"_foo_bar_html"), + (u"Montréal/☺/conf.py", u"Montréal_☺_conf_py"), + ( # original: + u"c:\\lorem\\ipsum\\quia\\dolor\\sit\\amet\\consectetur\\adipisci\\velit\\sed\\quia\\non" + u"\\numquam\\eius\\modi\\tempora\\incidunt\\ut\\labore\\et\\dolore\\magnam\\aliquam" + u"\\quaerat\\voluptatem\\ut\\enim\\ad\\minima\\veniam\\quis\\nostrum\\exercitationem" + u"\\ullam\\corporis\\suscipit\\laboriosam\\Montréal\\☺\\my_program.py", + # flat: + u"re_et_dolore_magnam_aliquam_quaerat_voluptatem_ut_enim_ad_minima_veniam_quis_" + u"nostrum_exercitationem_ullam_corporis_suscipit_laboriosam_Montréal_☺_my_program_py_" + u"97eaca41b860faaa1a21349b1f3009bb061cf0a8" + ), +]) +def test_flat_rootname(original, flat): + assert flat_rootname(original) == flat class MatcherTest(CoverageTest): |