diff options
Diffstat (limited to 'coverage')
-rw-r--r-- | coverage/control.py | 29 | ||||
-rw-r--r-- | coverage/files.py | 92 | ||||
-rw-r--r-- | coverage/python.py | 10 | ||||
-rw-r--r-- | coverage/xmlreport.py | 9 |
4 files changed, 70 insertions, 70 deletions
diff --git a/coverage/control.py b/coverage/control.py index 9256edb2..3cae1d36 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -9,14 +9,14 @@ import socket import sys import traceback -from coverage import env +from coverage import env, files from coverage.annotate import AnnotateReporter from coverage.backward import string_class, iitems from coverage.collector import Collector from coverage.config import CoverageConfig from coverage.data import CoverageData from coverage.debug import DebugControl -from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher +from coverage.files import TreeMatcher, FnmatchMatcher from coverage.files import PathAliases, find_python_files, prep_patterns from coverage.files import ModuleMatcher, abs_file from coverage.html import HtmlReporter @@ -167,7 +167,7 @@ class Coverage(object): # Other instance attributes, set later. self.omit = self.include = self.source = None - self.source_pkgs = self.file_locator = None + self.source_pkgs = None self.data = self.collector = None self.plugins = self.file_tracing_plugins = None self.pylib_dirs = self.cover_dirs = None @@ -214,14 +214,14 @@ class Coverage(object): self._exclude_re = {} self._exclude_regex_stale() - self.file_locator = FileLocator() + files.set_relative_directory() # The source argument can be directories or package names. self.source = [] self.source_pkgs = [] for src in self.config.source or []: if os.path.exists(src): - self.source.append(self.file_locator.canonical_filename(src)) + self.source.append(files.canonical_filename(src)) else: self.source_pkgs.append(src) @@ -468,7 +468,7 @@ class Coverage(object): if filename.endswith("$py.class"): filename = filename[:-9] + ".py" - canonical = self.file_locator.canonical_filename(filename) + canonical = files.canonical_filename(filename) disp.canonical_filename = canonical # Try the plugins, see if they have an opinion about the file. @@ -486,10 +486,9 @@ class Coverage(object): if file_tracer.has_dynamic_source_filename(): disp.has_dynamic_filename = True else: - disp.source_filename = \ - self.file_locator.canonical_filename( - file_tracer.source_filename() - ) + disp.source_filename = files.canonical_filename( + file_tracer.source_filename() + ) break except Exception: self._warn( @@ -740,7 +739,7 @@ class Coverage(object): self._init() aliases = None if self.config.paths: - aliases = PathAliases(self.file_locator) + aliases = PathAliases() for paths in self.config.paths.values(): result = paths[0] for pattern in paths[1:]: @@ -792,7 +791,7 @@ class Coverage(object): # Find files that were never executed at all. for src in self.source: for py_file in find_python_files(src): - py_file = self.file_locator.canonical_filename(py_file) + py_file = files.canonical_filename(py_file) if self.omit_match and self.omit_match.match(py_file): # Turns out this file was omitted, so don't pull it back @@ -872,9 +871,7 @@ class Coverage(object): # The FileReporter can have a name attribute, but if it doesn't, we'll # supply it as the relative path to self.filename. if not hasattr(file_reporter, "name"): - file_reporter.name = self.file_locator.relative_filename( - file_reporter.filename - ) + file_reporter.name = files.relative_filename(file_reporter.filename) return file_reporter @@ -1013,7 +1010,7 @@ class Coverage(object): outfile = open(self.config.xml_output, "w") file_to_close = outfile try: - reporter = XmlReporter(self, self.config, self.file_locator) + reporter = XmlReporter(self, self.config) return reporter.report(morfs, outfile=outfile) except CoverageException: delete_file = True diff --git a/coverage/files.py b/coverage/files.py index a800b7a9..665e2f33 100644 --- a/coverage/files.py +++ b/coverage/files.py @@ -12,55 +12,66 @@ from coverage import env from coverage.misc import CoverageException, join_regex -class FileLocator(object): - """Understand how filenames work.""" +RELATIVE_DIR = None +CANONICAL_FILENAME_CACHE = {} - def __init__(self): - # The absolute path to our current directory. - self.relative_dir = os.path.normcase(abs_file(os.curdir) + os.sep) - # Cache of results of calling the canonical_filename() method, to - # avoid duplicating work. - self.canonical_filename_cache = {} +def set_relative_directory(): + """Set the directory that `relative_filename` will be relative to.""" + global RELATIVE_DIR, CANONICAL_FILENAME_CACHE - def relative_filename(self, filename): - """Return the relative form of `filename`. + # The absolute path to our current directory. + RELATIVE_DIR = os.path.normcase(abs_file(os.curdir) + os.sep) - The filename will be relative to the current directory when the - `FileLocator` was constructed. + # Cache of results of calling the canonical_filename() method, to + # avoid duplicating work. + CANONICAL_FILENAME_CACHE = {} - """ - fnorm = os.path.normcase(filename) - if fnorm.startswith(self.relative_dir): - filename = filename[len(self.relative_dir):] - return filename +def relative_directory(): + """Return the directory that `relative_filename` is relative to.""" + return RELATIVE_DIR - def canonical_filename(self, filename): - """Return a canonical filename for `filename`. +def relative_filename(filename): + """Return the relative form of `filename`. - An absolute path with no redundant components and normalized case. + The filename will be relative to the current directory when the + `set_relative_directory` was called. - """ - if filename not in self.canonical_filename_cache: - if not os.path.isabs(filename): - for path in [os.curdir] + sys.path: - if path is None: - continue - f = os.path.join(path, filename) - if os.path.exists(f): - filename = f - break - cf = abs_file(filename) - self.canonical_filename_cache[filename] = cf - return self.canonical_filename_cache[filename] + """ + fnorm = os.path.normcase(filename) + if fnorm.startswith(RELATIVE_DIR): + filename = filename[len(RELATIVE_DIR):] + return filename + +def canonical_filename(filename): + """Return a canonical filename for `filename`. + + An absolute path with no redundant components and normalized case. + + """ + if filename not in CANONICAL_FILENAME_CACHE: + if not os.path.isabs(filename): + for path in [os.curdir] + sys.path: + if path is None: + continue + f = os.path.join(path, filename) + if os.path.exists(f): + filename = f + break + cf = abs_file(filename) + CANONICAL_FILENAME_CACHE[filename] = cf + return CANONICAL_FILENAME_CACHE[filename] if env.WINDOWS: + _ACTUAL_PATH_CACHE = {} + _ACTUAL_PATH_LIST_CACHE = {} + def actual_path(path): """Get the actual path of `path`, including the correct case.""" - if path in actual_path.cache: - return actual_path.cache[path] + if path in _ACTUAL_PATH_CACHE: + return _ACTUAL_PATH_CACHE[path] head, tail = os.path.split(path) if not tail: @@ -70,26 +81,23 @@ if env.WINDOWS: actpath = tail else: head = actual_path(head) - if head in actual_path.list_cache: - files = actual_path.list_cache[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 + _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 + _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/coverage/python.py b/coverage/python.py index 69823da7..8dc163df 100644 --- a/coverage/python.py +++ b/coverage/python.py @@ -3,8 +3,7 @@ import os.path import zipimport -from coverage import env -from coverage.files import FileLocator +from coverage import env, files from coverage.misc import contract, NoSource, join_regex from coverage.parser import PythonParser from coverage.phystokens import source_token_lines, source_encoding @@ -85,7 +84,6 @@ class PythonFileReporter(FileReporter): def __init__(self, morf, coverage=None): self.coverage = coverage - file_locator = coverage.file_locator if coverage else FileLocator() if hasattr(morf, '__file__'): filename = morf.__file__ @@ -98,15 +96,13 @@ class PythonFileReporter(FileReporter): elif filename.endswith('$py.class'): # Jython filename = filename[:-9] + ".py" - super(PythonFileReporter, self).__init__( - file_locator.canonical_filename(filename) - ) + super(PythonFileReporter, self).__init__(files.canonical_filename(filename)) if hasattr(morf, '__name__'): name = morf.__name__ name = name.replace(".", os.sep) + ".py" else: - name = file_locator.relative_filename(filename) + name = files.relative_filename(filename) self.name = name self._source = None diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py index 996f19a2..49b73122 100644 --- a/coverage/xmlreport.py +++ b/coverage/xmlreport.py @@ -5,7 +5,7 @@ import sys import time import xml.dom.minidom -from coverage import __url__, __version__ +from coverage import __url__, __version__, files from coverage.report import Reporter @@ -20,10 +20,9 @@ def rate(hit, num): class XmlReporter(Reporter): """A reporter for writing Cobertura-style XML coverage results.""" - def __init__(self, coverage, config, file_locator): + def __init__(self, coverage, config): super(XmlReporter, self).__init__(coverage, config) - self.file_locator = file_locator self.source_paths = set() self.packages = {} self.xml_out = None @@ -122,7 +121,7 @@ class XmlReporter(Reporter): # Create the 'lines' and 'package' XML elements, which # are populated later. Note that a package == a directory. - filename = self.file_locator.relative_filename(fr.filename) + filename = files.relative_filename(fr.filename) filename = filename.replace("\\", "/") dirname = os.path.dirname(filename) or "." parts = dirname.split("/") @@ -130,7 +129,7 @@ class XmlReporter(Reporter): package_name = dirname.replace("/", ".") className = fr.name - self.source_paths.add(self.file_locator.relative_dir.rstrip('/')) + self.source_paths.add(files.relative_directory().rstrip('/')) package = self.packages.setdefault(package_name, [{}, 0, 0, 0, 0]) xclass = self.xml_out.createElement("class") |