diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2012-11-11 23:00:07 -0500 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2012-11-11 23:00:07 -0500 |
commit | b5ad7d3f30ad817a0e126cdad1be3ae0df6910c6 (patch) | |
tree | 920162e204c9589406ea99c535d6fdd8c2baab93 | |
parent | 7fda5e935bb78af2fbc2ff01731d2adb8f6af848 (diff) | |
download | python-coveragepy-git-b5ad7d3f30ad817a0e126cdad1be3ae0df6910c6.tar.gz |
A faster way to get the actual path of Windows files, especially when operating on lots of files in the same directory.
-rw-r--r-- | coverage/files.py | 59 | ||||
-rw-r--r-- | test/test_process.py | 4 |
2 files changed, 32 insertions, 31 deletions
diff --git a/coverage/files.py b/coverage/files.py index 8d2a2a7b..40af7bf7 100644 --- a/coverage/files.py +++ b/coverage/files.py @@ -2,7 +2,7 @@ from coverage.backward import to_string from coverage.misc import CoverageException -import fnmatch, os, re, sys +import fnmatch, os, os.path, re, sys class FileLocator(object): """Understand how filenames work.""" @@ -76,38 +76,39 @@ class FileLocator(object): if sys.platform == 'win32': - import ctypes - - def getLongPathName(path): - """Call Windows' GetLongPathNameW, unicode to unicode.""" - buf = ctypes.create_unicode_buffer(260) - rv = ctypes.windll.kernel32.GetLongPathNameW(path, buf, 260) - if rv == 0 or rv > 260: - return path - else: - return buf.value - - def getShortPathName(path): - """Call Windows' GetShortPathNameW, unicode to unicode.""" - buf = ctypes.create_unicode_buffer(260) - rv = ctypes.windll.kernel32.GetShortPathNameW(path, buf, 260) - if rv == 0 or rv > 260: - return path - else: - return buf.value def actual_path(path): """Get the actual path of `path`, including the correct case.""" - if sys.version_info >= (3,0): - path = path.encode('utf-16') - else: - path = path.decode('utf8') - actual = getLongPathName(getShortPathName(path)) - if sys.version_info >= (3,0): - actual = actual.decode('utf-16') + if path in actual_path.cache: + return actual_path.cache[path] + + head, tail = os.path.split(path) + if not tail: + actpath = head + elif not head: + actpath = tail else: - actual = actual.encode('utf8') - return actual + head = actual_path(head) + if head in actual_path.list_cache: + files = actual_path.list_cache[head] + else: + try: + files = os.listdir(head) + except OSError: + files = [] + actual_path.list_cache[head] = files + normtail = os.path.normcase(tail) + for f in files: + if os.path.normcase(f) == normtail: + tail = f + break + actpath = os.path.join(head, tail) + actual_path.cache[path] = actpath + return actpath + + actual_path.cache = {} + actual_path.list_cache = {} + else: def actual_path(filename): """The actual path for non-Windows platforms.""" diff --git a/test/test_process.py b/test/test_process.py index 259bf259..a67a9c2d 100644 --- a/test/test_process.py +++ b/test/test_process.py @@ -175,8 +175,8 @@ class ProcessTest(CoverageTest): data.read_file(".coverage") summary = data.summary(fullpath=True) self.assertEqual(len(summary), 1) - actual = os.path.abspath(list(summary.keys())[0]) - expected = os.path.abspath('src/x.py') + actual = os.path.normcase(os.path.abspath(list(summary.keys())[0])) + expected = os.path.normcase(os.path.abspath('src/x.py')) self.assertEqual(actual, expected) self.assertEqual(list(summary.values())[0], 6) |