Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Unified Diff: sky/tools/webkitpy/thirdparty/coverage/control.py

Issue 946753002: Delete a bunch of dead python code. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sky/tools/webkitpy/thirdparty/coverage/config.py ('k') | sky/tools/webkitpy/thirdparty/coverage/data.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/tools/webkitpy/thirdparty/coverage/control.py
diff --git a/sky/tools/webkitpy/thirdparty/coverage/control.py b/sky/tools/webkitpy/thirdparty/coverage/control.py
deleted file mode 100644
index b617f486abda8071f504a3638b2439cf14d8418a..0000000000000000000000000000000000000000
--- a/sky/tools/webkitpy/thirdparty/coverage/control.py
+++ /dev/null
@@ -1,688 +0,0 @@
-"""Core control stuff for Coverage."""
-
-import atexit, os, random, socket, sys
-
-from coverage.annotate import AnnotateReporter
-from coverage.backward import string_class
-from coverage.codeunit import code_unit_factory, CodeUnit
-from coverage.collector import Collector
-from coverage.config import CoverageConfig
-from coverage.data import CoverageData
-from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher
-from coverage.files import PathAliases, find_python_files
-from coverage.html import HtmlReporter
-from coverage.misc import CoverageException, bool_or_none, join_regex
-from coverage.results import Analysis, Numbers
-from coverage.summary import SummaryReporter
-from coverage.xmlreport import XmlReporter
-
-class coverage(object):
- """Programmatic access to Coverage.
-
- To use::
-
- from coverage import coverage
-
- cov = coverage()
- cov.start()
- #.. blah blah (run your code) blah blah ..
- cov.stop()
- cov.html_report(directory='covhtml')
-
- """
- def __init__(self, data_file=None, data_suffix=None, cover_pylib=None,
- auto_data=False, timid=None, branch=None, config_file=True,
- source=None, omit=None, include=None):
- """
- `data_file` is the base name of the data file to use, defaulting to
- ".coverage". `data_suffix` is appended (with a dot) to `data_file` to
- create the final file name. If `data_suffix` is simply True, then a
- suffix is created with the machine and process identity included.
-
- `cover_pylib` is a boolean determining whether Python code installed
- with the Python interpreter is measured. This includes the Python
- standard library and any packages installed with the interpreter.
-
- If `auto_data` is true, then any existing data file will be read when
- coverage measurement starts, and data will be saved automatically when
- measurement stops.
-
- If `timid` is true, then a slower and simpler trace function will be
- used. This is important for some environments where manipulation of
- tracing functions breaks the faster trace function.
-
- If `branch` is true, then branch coverage will be measured in addition
- to the usual statement coverage.
-
- `config_file` determines what config file to read. If it is a string,
- it is the name of the config file to read. If it is True, then a
- standard file is read (".coveragerc"). If it is False, then no file is
- read.
-
- `source` is a list of file paths or package names. Only code located
- in the trees indicated by the file paths or package names will be
- measured.
-
- `include` and `omit` are lists of filename patterns. Files that match
- `include` will be measured, files that match `omit` will not. Each
- will also accept a single string argument.
-
- """
- from coverage import __version__
-
- # A record of all the warnings that have been issued.
- self._warnings = []
-
- # Build our configuration from a number of sources:
- # 1: defaults:
- self.config = CoverageConfig()
-
- # 2: from the coveragerc file:
- if config_file:
- if config_file is True:
- config_file = ".coveragerc"
- try:
- self.config.from_file(config_file)
- except ValueError:
- _, err, _ = sys.exc_info()
- raise CoverageException(
- "Couldn't read config file %s: %s" % (config_file, err)
- )
-
- # 3: from environment variables:
- self.config.from_environment('COVERAGE_OPTIONS')
- env_data_file = os.environ.get('COVERAGE_FILE')
- if env_data_file:
- self.config.data_file = env_data_file
-
- # 4: from constructor arguments:
- if isinstance(omit, string_class):
- omit = [omit]
- if isinstance(include, string_class):
- include = [include]
- self.config.from_args(
- data_file=data_file, cover_pylib=cover_pylib, timid=timid,
- branch=branch, parallel=bool_or_none(data_suffix),
- source=source, omit=omit, include=include
- )
-
- self.auto_data = auto_data
- self.atexit_registered = False
-
- # _exclude_re is a dict mapping exclusion list names to compiled
- # regexes.
- self._exclude_re = {}
- self._exclude_regex_stale()
-
- self.file_locator = FileLocator()
-
- # 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))
- else:
- self.source_pkgs.append(src)
-
- self.omit = self._prep_patterns(self.config.omit)
- self.include = self._prep_patterns(self.config.include)
-
- self.collector = Collector(
- self._should_trace, timid=self.config.timid,
- branch=self.config.branch, warn=self._warn
- )
-
- # Suffixes are a bit tricky. We want to use the data suffix only when
- # collecting data, not when combining data. So we save it as
- # `self.run_suffix` now, and promote it to `self.data_suffix` if we
- # find that we are collecting data later.
- if data_suffix or self.config.parallel:
- if not isinstance(data_suffix, string_class):
- # if data_suffix=True, use .machinename.pid.random
- data_suffix = True
- else:
- data_suffix = None
- self.data_suffix = None
- self.run_suffix = data_suffix
-
- # Create the data file. We do this at construction time so that the
- # data file will be written into the directory where the process
- # started rather than wherever the process eventually chdir'd to.
- self.data = CoverageData(
- basename=self.config.data_file,
- collector="coverage v%s" % __version__
- )
-
- # The dirs for files considered "installed with the interpreter".
- self.pylib_dirs = []
- if not self.config.cover_pylib:
- # Look at where some standard modules are located. That's the
- # indication for "installed with the interpreter". In some
- # environments (virtualenv, for example), these modules may be
- # spread across a few locations. Look at all the candidate modules
- # we've imported, and take all the different ones.
- for m in (atexit, os, random, socket):
- if hasattr(m, "__file__"):
- m_dir = self._canonical_dir(m.__file__)
- if m_dir not in self.pylib_dirs:
- self.pylib_dirs.append(m_dir)
-
- # To avoid tracing the coverage code itself, we skip anything located
- # where we are.
- self.cover_dir = self._canonical_dir(__file__)
-
- # The matchers for _should_trace, created when tracing starts.
- self.source_match = None
- self.pylib_match = self.cover_match = None
- self.include_match = self.omit_match = None
-
- # Only _harvest_data once per measurement cycle.
- self._harvested = False
-
- # Set the reporting precision.
- Numbers.set_precision(self.config.precision)
-
- # When tearing down the coverage object, modules can become None.
- # Saving the modules as object attributes avoids problems, but it is
- # quite ad-hoc which modules need to be saved and which references
- # need to use the object attributes.
- self.socket = socket
- self.os = os
- self.random = random
-
- def _canonical_dir(self, f):
- """Return the canonical directory of the file `f`."""
- return os.path.split(self.file_locator.canonical_filename(f))[0]
-
- def _source_for_file(self, filename):
- """Return the source file for `filename`."""
- if not filename.endswith(".py"):
- if filename[-4:-1] == ".py":
- filename = filename[:-1]
- return filename
-
- def _should_trace(self, filename, frame):
- """Decide whether to trace execution in `filename`
-
- This function is called from the trace function. As each new file name
- is encountered, this function determines whether it is traced or not.
-
- Returns a canonicalized filename if it should be traced, False if it
- should not.
-
- """
- if os is None:
- return False
-
- if filename.startswith('<'):
- # Lots of non-file execution is represented with artificial
- # filenames like "<string>", "<doctest readme.txt[0]>", or
- # "<exec_function>". Don't ever trace these executions, since we
- # can't do anything with the data later anyway.
- return False
-
- if filename.endswith(".html"):
- # Jinja and maybe other templating systems compile templates into
- # Python code, but use the template filename as the filename in
- # the compiled code. Of course, those filenames are useless later
- # so don't bother collecting. TODO: How should we really separate
- # out good file extensions from bad?
- return False
-
- self._check_for_packages()
-
- # Compiled Python files have two filenames: frame.f_code.co_filename is
- # the filename at the time the .pyc was compiled. The second name is
- # __file__, which is where the .pyc was actually loaded from. Since
- # .pyc files can be moved after compilation (for example, by being
- # installed), we look for __file__ in the frame and prefer it to the
- # co_filename value.
- dunder_file = frame.f_globals.get('__file__')
- if dunder_file:
- filename = self._source_for_file(dunder_file)
-
- # Jython reports the .class file to the tracer, use the source file.
- if filename.endswith("$py.class"):
- filename = filename[:-9] + ".py"
-
- canonical = self.file_locator.canonical_filename(filename)
-
- # If the user specified source or include, then that's authoritative
- # about the outer bound of what to measure and we don't have to apply
- # any canned exclusions. If they didn't, then we have to exclude the
- # stdlib and coverage.py directories.
- if self.source_match:
- if not self.source_match.match(canonical):
- return False
- elif self.include_match:
- if not self.include_match.match(canonical):
- return False
- else:
- # If we aren't supposed to trace installed code, then check if this
- # is near the Python standard library and skip it if so.
- if self.pylib_match and self.pylib_match.match(canonical):
- return False
-
- # We exclude the coverage code itself, since a little of it will be
- # measured otherwise.
- if self.cover_match and self.cover_match.match(canonical):
- return False
-
- # Check the file against the omit pattern.
- if self.omit_match and self.omit_match.match(canonical):
- return False
-
- return canonical
-
- # To log what should_trace returns, change this to "if 1:"
- if 0:
- _real_should_trace = _should_trace
- def _should_trace(self, filename, frame): # pylint: disable=E0102
- """A logging decorator around the real _should_trace function."""
- ret = self._real_should_trace(filename, frame)
- print("should_trace: %r -> %r" % (filename, ret))
- return ret
-
- def _warn(self, msg):
- """Use `msg` as a warning."""
- self._warnings.append(msg)
- sys.stderr.write("Coverage.py warning: %s\n" % msg)
-
- def _prep_patterns(self, patterns):
- """Prepare the file patterns for use in a `FnmatchMatcher`.
-
- If a pattern starts with a wildcard, it is used as a pattern
- as-is. If it does not start with a wildcard, then it is made
- absolute with the current directory.
-
- If `patterns` is None, an empty list is returned.
-
- """
- patterns = patterns or []
- prepped = []
- for p in patterns or []:
- if p.startswith("*") or p.startswith("?"):
- prepped.append(p)
- else:
- prepped.append(self.file_locator.abs_file(p))
- return prepped
-
- def _check_for_packages(self):
- """Update the source_match matcher with latest imported packages."""
- # Our self.source_pkgs attribute is a list of package names we want to
- # measure. Each time through here, we see if we've imported any of
- # them yet. If so, we add its file to source_match, and we don't have
- # to look for that package any more.
- if self.source_pkgs:
- found = []
- for pkg in self.source_pkgs:
- try:
- mod = sys.modules[pkg]
- except KeyError:
- continue
-
- found.append(pkg)
-
- try:
- pkg_file = mod.__file__
- except AttributeError:
- self._warn("Module %s has no Python source." % pkg)
- else:
- d, f = os.path.split(pkg_file)
- if f.startswith('__init__.'):
- # This is actually a package, return the directory.
- pkg_file = d
- else:
- pkg_file = self._source_for_file(pkg_file)
- pkg_file = self.file_locator.canonical_filename(pkg_file)
- self.source.append(pkg_file)
- self.source_match.add(pkg_file)
-
- for pkg in found:
- self.source_pkgs.remove(pkg)
-
- def use_cache(self, usecache):
- """Control the use of a data file (incorrectly called a cache).
-
- `usecache` is true or false, whether to read and write data on disk.
-
- """
- self.data.usefile(usecache)
-
- def load(self):
- """Load previously-collected coverage data from the data file."""
- self.collector.reset()
- self.data.read()
-
- def start(self):
- """Start measuring code coverage."""
- if self.run_suffix:
- # Calling start() means we're running code, so use the run_suffix
- # as the data_suffix when we eventually save the data.
- self.data_suffix = self.run_suffix
- if self.auto_data:
- self.load()
- # Save coverage data when Python exits.
- if not self.atexit_registered:
- atexit.register(self.save)
- self.atexit_registered = True
-
- # Create the matchers we need for _should_trace
- if self.source or self.source_pkgs:
- self.source_match = TreeMatcher(self.source)
- else:
- if self.cover_dir:
- self.cover_match = TreeMatcher([self.cover_dir])
- if self.pylib_dirs:
- self.pylib_match = TreeMatcher(self.pylib_dirs)
- if self.include:
- self.include_match = FnmatchMatcher(self.include)
- if self.omit:
- self.omit_match = FnmatchMatcher(self.omit)
-
- self._harvested = False
- self.collector.start()
-
- def stop(self):
- """Stop measuring code coverage."""
- self.collector.stop()
- self._harvest_data()
-
- def erase(self):
- """Erase previously-collected coverage data.
-
- This removes the in-memory data collected in this session as well as
- discarding the data file.
-
- """
- self.collector.reset()
- self.data.erase()
-
- def clear_exclude(self, which='exclude'):
- """Clear the exclude list."""
- setattr(self.config, which + "_list", [])
- self._exclude_regex_stale()
-
- def exclude(self, regex, which='exclude'):
- """Exclude source lines from execution consideration.
-
- A number of lists of regular expressions are maintained. Each list
- selects lines that are treated differently during reporting.
-
- `which` determines which list is modified. The "exclude" list selects
- lines that are not considered executable at all. The "partial" list
- indicates lines with branches that are not taken.
-
- `regex` is a regular expression. The regex is added to the specified
- list. If any of the regexes in the list is found in a line, the line
- is marked for special treatment during reporting.
-
- """
- excl_list = getattr(self.config, which + "_list")
- excl_list.append(regex)
- self._exclude_regex_stale()
-
- def _exclude_regex_stale(self):
- """Drop all the compiled exclusion regexes, a list was modified."""
- self._exclude_re.clear()
-
- def _exclude_regex(self, which):
- """Return a compiled regex for the given exclusion list."""
- if which not in self._exclude_re:
- excl_list = getattr(self.config, which + "_list")
- self._exclude_re[which] = join_regex(excl_list)
- return self._exclude_re[which]
-
- def get_exclude_list(self, which='exclude'):
- """Return a list of excluded regex patterns.
-
- `which` indicates which list is desired. See `exclude` for the lists
- that are available, and their meaning.
-
- """
- return getattr(self.config, which + "_list")
-
- def save(self):
- """Save the collected coverage data to the data file."""
- data_suffix = self.data_suffix
- if data_suffix is True:
- # If data_suffix was a simple true value, then make a suffix with
- # plenty of distinguishing information. We do this here in
- # `save()` at the last minute so that the pid will be correct even
- # if the process forks.
- data_suffix = "%s.%s.%06d" % (
- self.socket.gethostname(), self.os.getpid(),
- self.random.randint(0, 99999)
- )
-
- self._harvest_data()
- self.data.write(suffix=data_suffix)
-
- def combine(self):
- """Combine together a number of similarly-named coverage data files.
-
- All coverage data files whose name starts with `data_file` (from the
- coverage() constructor) will be read, and combined together into the
- current measurements.
-
- """
- aliases = None
- if self.config.paths:
- aliases = PathAliases(self.file_locator)
- for paths in self.config.paths.values():
- result = paths[0]
- for pattern in paths[1:]:
- aliases.add(pattern, result)
- self.data.combine_parallel_data(aliases=aliases)
-
- def _harvest_data(self):
- """Get the collected data and reset the collector.
-
- Also warn about various problems collecting data.
-
- """
- if not self._harvested:
- self.data.add_line_data(self.collector.get_line_data())
- self.data.add_arc_data(self.collector.get_arc_data())
- self.collector.reset()
-
- # If there are still entries in the source_pkgs list, then we never
- # encountered those packages.
- for pkg in self.source_pkgs:
- self._warn("Module %s was never imported." % pkg)
-
- # Find out if we got any data.
- summary = self.data.summary()
- if not summary:
- self._warn("No data was collected.")
-
- # Find files that were never executed at all.
- for src in self.source:
- for py_file in find_python_files(src):
- self.data.touch_file(py_file)
-
- self._harvested = True
-
- # Backward compatibility with version 1.
- def analysis(self, morf):
- """Like `analysis2` but doesn't return excluded line numbers."""
- f, s, _, m, mf = self.analysis2(morf)
- return f, s, m, mf
-
- def analysis2(self, morf):
- """Analyze a module.
-
- `morf` is a module or a filename. It will be analyzed to determine
- its coverage statistics. The return value is a 5-tuple:
-
- * The filename for the module.
- * A list of line numbers of executable statements.
- * A list of line numbers of excluded statements.
- * A list of line numbers of statements not run (missing from
- execution).
- * A readable formatted string of the missing line numbers.
-
- The analysis uses the source file itself and the current measured
- coverage data.
-
- """
- analysis = self._analyze(morf)
- return (
- analysis.filename, analysis.statements, analysis.excluded,
- analysis.missing, analysis.missing_formatted()
- )
-
- def _analyze(self, it):
- """Analyze a single morf or code unit.
-
- Returns an `Analysis` object.
-
- """
- if not isinstance(it, CodeUnit):
- it = code_unit_factory(it, self.file_locator)[0]
-
- return Analysis(self, it)
-
- def report(self, morfs=None, show_missing=True, ignore_errors=None,
- file=None, # pylint: disable=W0622
- omit=None, include=None
- ):
- """Write a summary report to `file`.
-
- Each module in `morfs` is listed, with counts of statements, executed
- statements, missing statements, and a list of lines missed.
-
- `include` is a list of filename patterns. Modules whose filenames
- match those patterns will be included in the report. Modules matching
- `omit` will not be included in the report.
-
- """
- self.config.from_args(
- ignore_errors=ignore_errors, omit=omit, include=include
- )
- reporter = SummaryReporter(
- self, show_missing, self.config.ignore_errors
- )
- reporter.report(morfs, outfile=file, config=self.config)
-
- def annotate(self, morfs=None, directory=None, ignore_errors=None,
- omit=None, include=None):
- """Annotate a list of modules.
-
- Each module in `morfs` is annotated. The source is written to a new
- file, named with a ",cover" suffix, with each line prefixed with a
- marker to indicate the coverage of the line. Covered lines have ">",
- excluded lines have "-", and missing lines have "!".
-
- See `coverage.report()` for other arguments.
-
- """
- self.config.from_args(
- ignore_errors=ignore_errors, omit=omit, include=include
- )
- reporter = AnnotateReporter(self, self.config.ignore_errors)
- reporter.report(morfs, config=self.config, directory=directory)
-
- def html_report(self, morfs=None, directory=None, ignore_errors=None,
- omit=None, include=None):
- """Generate an HTML report.
-
- See `coverage.report()` for other arguments.
-
- """
- self.config.from_args(
- ignore_errors=ignore_errors, omit=omit, include=include,
- html_dir=directory,
- )
- reporter = HtmlReporter(self, self.config.ignore_errors)
- reporter.report(morfs, config=self.config)
-
- def xml_report(self, morfs=None, outfile=None, ignore_errors=None,
- omit=None, include=None):
- """Generate an XML report of coverage results.
-
- The report is compatible with Cobertura reports.
-
- Each module in `morfs` is included in the report. `outfile` is the
- path to write the file to, "-" will write to stdout.
-
- See `coverage.report()` for other arguments.
-
- """
- self.config.from_args(
- ignore_errors=ignore_errors, omit=omit, include=include,
- xml_output=outfile,
- )
- file_to_close = None
- if self.config.xml_output:
- if self.config.xml_output == '-':
- outfile = sys.stdout
- else:
- outfile = open(self.config.xml_output, "w")
- file_to_close = outfile
- try:
- reporter = XmlReporter(self, self.config.ignore_errors)
- reporter.report(morfs, outfile=outfile, config=self.config)
- finally:
- if file_to_close:
- file_to_close.close()
-
- def sysinfo(self):
- """Return a list of (key, value) pairs showing internal information."""
-
- import coverage as covmod
- import platform, re
-
- try:
- implementation = platform.python_implementation()
- except AttributeError:
- implementation = "unknown"
-
- info = [
- ('version', covmod.__version__),
- ('coverage', covmod.__file__),
- ('cover_dir', self.cover_dir),
- ('pylib_dirs', self.pylib_dirs),
- ('tracer', self.collector.tracer_name()),
- ('data_path', self.data.filename),
- ('python', sys.version.replace('\n', '')),
- ('platform', platform.platform()),
- ('implementation', implementation),
- ('cwd', os.getcwd()),
- ('path', sys.path),
- ('environment', [
- ("%s = %s" % (k, v)) for k, v in os.environ.items()
- if re.search("^COV|^PY", k)
- ]),
- ]
- return info
-
-
-def process_startup():
- """Call this at Python startup to perhaps measure coverage.
-
- If the environment variable COVERAGE_PROCESS_START is defined, coverage
- measurement is started. The value of the variable is the config file
- to use.
-
- There are two ways to configure your Python installation to invoke this
- function when Python starts:
-
- #. Create or append to sitecustomize.py to add these lines::
-
- import coverage
- coverage.process_startup()
-
- #. Create a .pth file in your Python installation containing::
-
- import coverage; coverage.process_startup()
-
- """
- cps = os.environ.get("COVERAGE_PROCESS_START")
- if cps:
- cov = coverage(config_file=cps, auto_data=True)
- if os.environ.get("COVERAGE_COVERAGE"):
- # Measuring coverage within coverage.py takes yet more trickery.
- cov.cover_dir = "Please measure coverage.py!"
- cov.start()
« no previous file with comments | « sky/tools/webkitpy/thirdparty/coverage/config.py ('k') | sky/tools/webkitpy/thirdparty/coverage/data.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698