DebugClients/Python/coverage/control.py

changeset 5141
bc64243b7672
parent 5126
d28b92dabc2b
parent 5140
01484c0afbc6
child 5144
1ab536d25072
--- a/DebugClients/Python/coverage/control.py	Fri Sep 02 19:08:02 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1202 +0,0 @@
-# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
-# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
-
-"""Core control stuff for coverage.py."""
-
-import atexit
-import inspect
-import os
-import platform
-import re
-import sys
-import traceback
-
-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, CoverageDataFiles
-from coverage.debug import DebugControl
-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
-from coverage.misc import CoverageException, bool_or_none, join_regex
-from coverage.misc import file_be_gone, isolate_module
-from coverage.monkey import patch_multiprocessing
-from coverage.plugin import FileReporter
-from coverage.plugin_support import Plugins
-from coverage.python import PythonFileReporter
-from coverage.results import Analysis, Numbers
-from coverage.summary import SummaryReporter
-from coverage.xmlreport import XmlReporter
-
-os = isolate_module(os)
-
-# Pypy has some unusual stuff in the "stdlib".  Consider those locations
-# when deciding where the stdlib is.
-try:
-    import _structseq
-except ImportError:
-    _structseq = None
-
-
-class Coverage(object):
-    """Programmatic access to coverage.py.
-
-    To use::
-
-        from coverage import Coverage
-
-        cov = Coverage()
-        cov.start()
-        #.. call your code ..
-        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, debug=None,
-        concurrency=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 configuration file to read:
-
-            * If it is ".coveragerc", it is interpreted as if it were True,
-              for backward compatibility.
-
-            * If it is a string, it is the name of the file to read.  If the
-              file can't be read, it is an error.
-
-            * If it is True, then a few standard files names are tried
-              (".coveragerc", "setup.cfg").  It is not an error for these files
-              to not be found.
-
-            * If it is False, then no configuration 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 file name patterns. Files that match
-        `include` will be measured, files that match `omit` will not.  Each
-        will also accept a single string argument.
-
-        `debug` is a list of strings indicating what debugging information is
-        desired.
-
-        `concurrency` is a string indicating the concurrency library being used
-        in the measured code.  Without this, coverage.py will get incorrect
-        results.  Valid strings are "greenlet", "eventlet", "gevent",
-        "multiprocessing", or "thread" (the default).
-
-        .. versionadded:: 4.0
-            The `concurrency` parameter.
-
-        """
-        # Build our configuration from a number of sources:
-        # 1: defaults:
-        self.config = CoverageConfig()
-
-        # 2: from the rcfile, .coveragerc or setup.cfg file:
-        if config_file:
-            did_read_rc = False
-            # Some API users were specifying ".coveragerc" to mean the same as
-            # True, so make it so.
-            if config_file == ".coveragerc":
-                config_file = True
-            specified_file = (config_file is not True)
-            if not specified_file:
-                config_file = ".coveragerc"
-
-            did_read_rc = self.config.from_file(config_file)
-
-            if not did_read_rc:
-                if specified_file:
-                    raise CoverageException(
-                        "Couldn't read '%s' as a config file" % config_file
-                        )
-                self.config.from_file("setup.cfg", section_prefix="coverage:")
-
-        # 3: from environment variables:
-        env_data_file = os.environ.get('COVERAGE_FILE')
-        if env_data_file:
-            self.config.data_file = env_data_file
-        debugs = os.environ.get('COVERAGE_DEBUG')
-        if debugs:
-            self.config.debug.extend(debugs.split(","))
-
-        # 4: from constructor arguments:
-        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, debug=debug,
-            concurrency=concurrency,
-            )
-
-        self._debug_file = None
-        self._auto_data = auto_data
-        self._data_suffix = data_suffix
-
-        # The matchers for _should_trace.
-        self.source_match = None
-        self.source_pkgs_match = None
-        self.pylib_match = self.cover_match = None
-        self.include_match = self.omit_match = None
-
-        # Is it ok for no data to be collected?
-        self._warn_no_data = True
-        self._warn_unimported_source = True
-
-        # A record of all the warnings that have been issued.
-        self._warnings = []
-
-        # Other instance attributes, set later.
-        self.omit = self.include = self.source = None
-        self.source_pkgs = None
-        self.data = self.data_files = self.collector = None
-        self.plugins = None
-        self.pylib_dirs = self.cover_dirs = None
-        self.data_suffix = self.run_suffix = None
-        self._exclude_re = None
-        self.debug = None
-
-        # State machine variables:
-        # Have we initialized everything?
-        self._inited = False
-        # Have we started collecting and not stopped it?
-        self._started = False
-        # Have we measured some data and not harvested it?
-        self._measured = False
-
-    def _init(self):
-        """Set all the initial state.
-
-        This is called by the public methods to initialize state. This lets us
-        construct a :class:`Coverage` object, then tweak its state before this
-        function is called.
-
-        """
-        if self._inited:
-            return
-
-        # Create and configure the debugging controller. COVERAGE_DEBUG_FILE
-        # is an environment variable, the name of a file to append debug logs
-        # to.
-        if self._debug_file is None:
-            debug_file_name = os.environ.get("COVERAGE_DEBUG_FILE")
-            if debug_file_name:
-                self._debug_file = open(debug_file_name, "a")
-            else:
-                self._debug_file = sys.stderr
-        self.debug = DebugControl(self.config.debug, self._debug_file)
-
-        # Load plugins
-        self.plugins = Plugins.load_plugins(self.config.plugins, self.config, self.debug)
-
-        # _exclude_re is a dict that maps exclusion list names to compiled
-        # regexes.
-        self._exclude_re = {}
-        self._exclude_regex_stale()
-
-        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(files.canonical_filename(src))
-            else:
-                self.source_pkgs.append(src)
-
-        self.omit = prep_patterns(self.config.omit)
-        self.include = prep_patterns(self.config.include)
-
-        concurrency = self.config.concurrency
-        if concurrency == "multiprocessing":
-            patch_multiprocessing()
-            concurrency = None
-
-        self.collector = Collector(
-            should_trace=self._should_trace,
-            check_include=self._check_include_omit_etc,
-            timid=self.config.timid,
-            branch=self.config.branch,
-            warn=self._warn,
-            concurrency=concurrency,
-            )
-
-        # Early warning if we aren't going to be able to support plugins.
-        if self.plugins.file_tracers and not self.collector.supports_plugins:
-            self._warn(
-                "Plugin file tracers (%s) aren't supported with %s" % (
-                    ", ".join(
-                        plugin._coverage_plugin_name
-                            for plugin in self.plugins.file_tracers
-                        ),
-                    self.collector.tracer_name(),
-                    )
-                )
-            for plugin in self.plugins.file_tracers:
-                plugin._coverage_enabled = False
-
-        # 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 self._data_suffix or self.config.parallel:
-            if not isinstance(self._data_suffix, string_class):
-                # if data_suffix=True, use .machinename.pid.random
-                self._data_suffix = True
-        else:
-            self._data_suffix = None
-        self.data_suffix = None
-        self.run_suffix = self._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(debug=self.debug)
-        self.data_files = CoverageDataFiles(basename=self.config.data_file, warn=self._warn)
-
-        # The directories for files considered "installed with the interpreter".
-        self.pylib_dirs = set()
-        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, inspect, os, platform, re, _structseq, traceback):
-                if m is not None and hasattr(m, "__file__"):
-                    self.pylib_dirs.add(self._canonical_dir(m))
-            if _structseq and not hasattr(_structseq, '__file__'):
-                # PyPy 2.4 has no __file__ in the builtin modules, but the code
-                # objects still have the file names.  So dig into one to find
-                # the path to exclude.
-                structseq_new = _structseq.structseq_new
-                try:
-                    structseq_file = structseq_new.func_code.co_filename
-                except AttributeError:
-                    structseq_file = structseq_new.__code__.co_filename
-                self.pylib_dirs.add(self._canonical_dir(structseq_file))
-
-        # To avoid tracing the coverage.py code itself, we skip anything
-        # located where we are.
-        self.cover_dirs = [self._canonical_dir(__file__)]
-        if env.TESTING:
-            # When testing, we use PyContracts, which should be considered
-            # part of coverage.py, and it uses six. Exclude those directories
-            # just as we exclude ourselves.
-            import contracts, six
-            for mod in [contracts, six]:
-                self.cover_dirs.append(self._canonical_dir(mod))
-
-        # Set the reporting precision.
-        Numbers.set_precision(self.config.precision)
-
-        atexit.register(self._atexit)
-
-        self._inited = True
-
-        # Create the matchers we need for _should_trace
-        if self.source or self.source_pkgs:
-            self.source_match = TreeMatcher(self.source)
-            self.source_pkgs_match = ModuleMatcher(self.source_pkgs)
-        else:
-            if self.cover_dirs:
-                self.cover_match = TreeMatcher(self.cover_dirs)
-            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)
-
-        # The user may want to debug things, show info if desired.
-        wrote_any = False
-        if self.debug.should('config'):
-            config_info = sorted(self.config.__dict__.items())
-            self.debug.write_formatted_info("config", config_info)
-            wrote_any = True
-
-        if self.debug.should('sys'):
-            self.debug.write_formatted_info("sys", self.sys_info())
-            for plugin in self.plugins:
-                header = "sys: " + plugin._coverage_plugin_name
-                info = plugin.sys_info()
-                self.debug.write_formatted_info(header, info)
-            wrote_any = True
-
-        if wrote_any:
-            self.debug.write_formatted_info("end", ())
-
-    def _canonical_dir(self, morf):
-        """Return the canonical directory of the module or file `morf`."""
-        morf_filename = PythonFileReporter(morf, self).filename
-        return os.path.split(morf_filename)[0]
-
-    def _source_for_file(self, filename):
-        """Return the source file for `filename`.
-
-        Given a file name being traced, return the best guess as to the source
-        file to attribute it to.
-
-        """
-        if filename.endswith(".py"):
-            # .py files are themselves source files.
-            return filename
-
-        elif filename.endswith((".pyc", ".pyo")):
-            # Bytecode files probably have source files near them.
-            py_filename = filename[:-1]
-            if os.path.exists(py_filename):
-                # Found a .py file, use that.
-                return py_filename
-            if env.WINDOWS:
-                # On Windows, it could be a .pyw file.
-                pyw_filename = py_filename + "w"
-                if os.path.exists(pyw_filename):
-                    return pyw_filename
-            # Didn't find source, but it's probably the .py file we want.
-            return py_filename
-
-        elif filename.endswith("$py.class"):
-            # Jython is easy to guess.
-            return filename[:-9] + ".py"
-
-        # No idea, just use the file name as-is.
-        return filename
-
-    def _name_for_module(self, module_globals, filename):
-        """Get the name of the module for a set of globals and file name.
-
-        For configurability's sake, we allow __main__ modules to be matched by
-        their importable name.
-
-        If loaded via runpy (aka -m), we can usually recover the "original"
-        full dotted module name, otherwise, we resort to interpreting the
-        file name to get the module's name.  In the case that the module name
-        can't be determined, None is returned.
-
-        """
-        dunder_name = module_globals.get('__name__', None)
-
-        if isinstance(dunder_name, str) and dunder_name != '__main__':
-            # This is the usual case: an imported module.
-            return dunder_name
-
-        loader = module_globals.get('__loader__', None)
-        for attrname in ('fullname', 'name'):   # attribute renamed in py3.2
-            if hasattr(loader, attrname):
-                fullname = getattr(loader, attrname)
-            else:
-                continue
-
-            if isinstance(fullname, str) and fullname != '__main__':
-                # Module loaded via: runpy -m
-                return fullname
-
-        # Script as first argument to Python command line.
-        inspectedname = inspect.getmodulename(filename)
-        if inspectedname is not None:
-            return inspectedname
-        else:
-            return dunder_name
-
-    def _should_trace_internal(self, filename, frame):
-        """Decide whether to trace execution in `filename`, with a reason.
-
-        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 FileDisposition object.
-
-        """
-        original_filename = filename
-        disp = _disposition_init(self.collector.file_disposition_class, filename)
-
-        def nope(disp, reason):
-            """Simple helper to make it easy to return NO."""
-            disp.trace = False
-            disp.reason = reason
-            return disp
-
-        # Compiled Python files have two file names: frame.f_code.co_filename is
-        # the file name 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)
-            if original_filename and not original_filename.startswith('<'):
-                orig = os.path.basename(original_filename)
-                if orig != os.path.basename(filename):
-                    # Files shouldn't be renamed when moved. This happens when
-                    # exec'ing code.  If it seems like something is wrong with
-                    # the frame's file name, then just use the original.
-                    filename = original_filename
-
-        if not filename:
-            # Empty string is pretty useless.
-            return nope(disp, "empty string isn't a file name")
-
-        if filename.startswith('memory:'):
-            return nope(disp, "memory isn't traceable")
-
-        if filename.startswith('<'):
-            # Lots of non-file execution is represented with artificial
-            # file names 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 nope(disp, "not a real file name")
-
-        # pyexpat does a dumb thing, calling the trace function explicitly from
-        # C code with a C file name.
-        if re.search(r"[/\\]Modules[/\\]pyexpat.c", filename):
-            return nope(disp, "pyexpat lies about itself")
-
-        # Jython reports the .class file to the tracer, use the source file.
-        if filename.endswith("$py.class"):
-            filename = filename[:-9] + ".py"
-
-        canonical = files.canonical_filename(filename)
-        disp.canonical_filename = canonical
-
-        # Try the plugins, see if they have an opinion about the file.
-        plugin = None
-        for plugin in self.plugins.file_tracers:
-            if not plugin._coverage_enabled:
-                continue
-
-            try:
-                file_tracer = plugin.file_tracer(canonical)
-                if file_tracer is not None:
-                    file_tracer._coverage_plugin = plugin
-                    disp.trace = True
-                    disp.file_tracer = file_tracer
-                    if file_tracer.has_dynamic_source_filename():
-                        disp.has_dynamic_filename = True
-                    else:
-                        disp.source_filename = files.canonical_filename(
-                            file_tracer.source_filename()
-                        )
-                    break
-            except Exception:
-                self._warn(
-                    "Disabling plugin %r due to an exception:" % (
-                        plugin._coverage_plugin_name
-                    )
-                )
-                traceback.print_exc()
-                plugin._coverage_enabled = False
-                continue
-        else:
-            # No plugin wanted it: it's Python.
-            disp.trace = True
-            disp.source_filename = canonical
-
-        if not disp.has_dynamic_filename:
-            if not disp.source_filename:
-                raise CoverageException(
-                    "Plugin %r didn't set source_filename for %r" %
-                    (plugin, disp.original_filename)
-                )
-            reason = self._check_include_omit_etc_internal(
-                disp.source_filename, frame,
-            )
-            if reason:
-                nope(disp, reason)
-
-        return disp
-
-    def _check_include_omit_etc_internal(self, filename, frame):
-        """Check a file name against the include, omit, etc, rules.
-
-        Returns a string or None.  String means, don't trace, and is the reason
-        why.  None means no reason found to not trace.
-
-        """
-        modulename = self._name_for_module(frame.f_globals, 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 self.source_pkgs_match.match(modulename):
-                if modulename in self.source_pkgs:
-                    self.source_pkgs.remove(modulename)
-                return None  # There's no reason to skip this file.
-
-            if not self.source_match.match(filename):
-                return "falls outside the --source trees"
-        elif self.include_match:
-            if not self.include_match.match(filename):
-                return "falls outside the --include trees"
-        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(filename):
-                return "is in the stdlib"
-
-            # We exclude the coverage.py code itself, since a little of it
-            # will be measured otherwise.
-            if self.cover_match and self.cover_match.match(filename):
-                return "is part of coverage.py"
-
-        # Check the file against the omit pattern.
-        if self.omit_match and self.omit_match.match(filename):
-            return "is inside an --omit pattern"
-
-        # No reason found to skip this file.
-        return None
-
-    def _should_trace(self, filename, frame):
-        """Decide whether to trace execution in `filename`.
-
-        Calls `_should_trace_internal`, and returns the FileDisposition.
-
-        """
-        disp = self._should_trace_internal(filename, frame)
-        if self.debug.should('trace'):
-            self.debug.write(_disposition_debug_msg(disp))
-        return disp
-
-    def _check_include_omit_etc(self, filename, frame):
-        """Check a file name against the include/omit/etc, rules, verbosely.
-
-        Returns a boolean: True if the file should be traced, False if not.
-
-        """
-        reason = self._check_include_omit_etc_internal(filename, frame)
-        if self.debug.should('trace'):
-            if not reason:
-                msg = "Including %r" % (filename,)
-            else:
-                msg = "Not including %r: %s" % (filename, reason)
-            self.debug.write(msg)
-
-        return not reason
-
-    def _warn(self, msg):
-        """Use `msg` as a warning."""
-        self._warnings.append(msg)
-        if self.debug.should('pid'):
-            msg = "[%d] %s" % (os.getpid(), msg)
-        sys.stderr.write("Coverage.py warning: %s\n" % msg)
-
-    def get_option(self, option_name):
-        """Get an option from the configuration.
-
-        `option_name` is a colon-separated string indicating the section and
-        option name.  For example, the ``branch`` option in the ``[run]``
-        section of the config file would be indicated with `"run:branch"`.
-
-        Returns the value of the option.
-
-        .. versionadded:: 4.0
-
-        """
-        return self.config.get_option(option_name)
-
-    def set_option(self, option_name, value):
-        """Set an option in the configuration.
-
-        `option_name` is a colon-separated string indicating the section and
-        option name.  For example, the ``branch`` option in the ``[run]``
-        section of the config file would be indicated with ``"run:branch"``.
-
-        `value` is the new value for the option.  This should be a Python
-        value where appropriate.  For example, use True for booleans, not the
-        string ``"True"``.
-
-        As an example, calling::
-
-            cov.set_option("run:branch", True)
-
-        has the same effect as this configuration file::
-
-            [run]
-            branch = True
-
-        .. versionadded:: 4.0
-
-        """
-        self.config.set_option(option_name, value)
-
-    def use_cache(self, usecache):
-        """Obsolete method."""
-        self._init()
-        if not usecache:
-            self._warn("use_cache(False) is no longer supported.")
-
-    def load(self):
-        """Load previously-collected coverage data from the data file."""
-        self._init()
-        self.collector.reset()
-        self.data_files.read(self.data)
-
-    def start(self):
-        """Start measuring code coverage.
-
-        Coverage measurement actually occurs in functions called after
-        :meth:`start` is invoked.  Statements in the same scope as
-        :meth:`start` won't be measured.
-
-        Once you invoke :meth:`start`, you must also call :meth:`stop`
-        eventually, or your process might not shut down cleanly.
-
-        """
-        self._init()
-        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()
-
-        self.collector.start()
-        self._started = True
-        self._measured = True
-
-    def stop(self):
-        """Stop measuring code coverage."""
-        if self._started:
-            self.collector.stop()
-        self._started = False
-
-    def _atexit(self):
-        """Clean up on process shutdown."""
-        if self._started:
-            self.stop()
-        if self._auto_data:
-            self.save()
-
-    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._init()
-        self.collector.reset()
-        self.data.erase()
-        self.data_files.erase(parallel=self.config.parallel)
-
-    def clear_exclude(self, which='exclude'):
-        """Clear the exclude list."""
-        self._init()
-        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.
-
-        """
-        self._init()
-        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 :meth:`exclude` for the
-        lists that are available, and their meaning.
-
-        """
-        self._init()
-        return getattr(self.config, which + "_list")
-
-    def save(self):
-        """Save the collected coverage data to the data file."""
-        self._init()
-        self.get_data()
-        self.data_files.write(self.data, suffix=self.data_suffix)
-
-    def combine(self, data_paths=None):
-        """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.
-
-        `data_paths` is a list of files or directories from which data should
-        be combined. If no list is passed, then the data files from the
-        directory indicated by the current data file (probably the current
-        directory) will be combined.
-
-        .. versionadded:: 4.0
-            The `data_paths` parameter.
-
-        """
-        self._init()
-        self.get_data()
-
-        aliases = None
-        if self.config.paths:
-            aliases = PathAliases()
-            for paths in self.config.paths.values():
-                result = paths[0]
-                for pattern in paths[1:]:
-                    aliases.add(pattern, result)
-
-        self.data_files.combine_parallel_data(self.data, aliases=aliases, data_paths=data_paths)
-
-    def get_data(self):
-        """Get the collected data and reset the collector.
-
-        Also warn about various problems collecting data.
-
-        Returns a :class:`coverage.CoverageData`, the collected coverage data.
-
-        .. versionadded:: 4.0
-
-        """
-        self._init()
-        if not self._measured:
-            return self.data
-
-        self.collector.save_data(self.data)
-
-        # If there are still entries in the source_pkgs list, then we never
-        # encountered those packages.
-        if self._warn_unimported_source:
-            for pkg in self.source_pkgs:
-                if pkg not in sys.modules:
-                    self._warn("Module %s was never imported." % pkg)
-                elif not (
-                    hasattr(sys.modules[pkg], '__file__') and
-                    os.path.exists(sys.modules[pkg].__file__)
-                ):
-                    self._warn("Module %s has no Python source." % pkg)
-                else:
-                    self._warn("Module %s was previously imported, but not measured." % pkg)
-
-        # Find out if we got any data.
-        if not self.data and self._warn_no_data:
-            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):
-                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
-                    # in as unexecuted.
-                    continue
-
-                self.data.touch_file(py_file)
-
-        if self.config.note:
-            self.data.add_run_info(note=self.config.note)
-
-        self._measured = False
-        return self.data
-
-    # 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 file name.  It will be analyzed to determine
-        its coverage statistics.  The return value is a 5-tuple:
-
-        * The file name 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.
-
-        """
-        self._init()
-        analysis = self._analyze(morf)
-        return (
-            analysis.filename,
-            sorted(analysis.statements),
-            sorted(analysis.excluded),
-            sorted(analysis.missing),
-            analysis.missing_formatted(),
-            )
-
-    def _analyze(self, it):
-        """Analyze a single morf or code unit.
-
-        Returns an `Analysis` object.
-
-        """
-        self.get_data()
-        if not isinstance(it, FileReporter):
-            it = self._get_file_reporter(it)
-
-        return Analysis(self.data, it)
-
-    def _get_file_reporter(self, morf):
-        """Get a FileReporter for a module or file name."""
-        plugin = None
-        file_reporter = "python"
-
-        if isinstance(morf, string_class):
-            abs_morf = abs_file(morf)
-            plugin_name = self.data.file_tracer(abs_morf)
-            if plugin_name:
-                plugin = self.plugins.get(plugin_name)
-
-        if plugin:
-            file_reporter = plugin.file_reporter(abs_morf)
-            if file_reporter is None:
-                raise CoverageException(
-                    "Plugin %r did not provide a file reporter for %r." % (
-                        plugin._coverage_plugin_name, morf
-                    )
-                )
-
-        if file_reporter == "python":
-            file_reporter = PythonFileReporter(morf, self)
-
-        return file_reporter
-
-    def _get_file_reporters(self, morfs=None):
-        """Get a list of FileReporters for a list of modules or file names.
-
-        For each module or file name in `morfs`, find a FileReporter.  Return
-        the list of FileReporters.
-
-        If `morfs` is a single module or file name, this returns a list of one
-        FileReporter.  If `morfs` is empty or None, then the list of all files
-        measured is used to find the FileReporters.
-
-        """
-        if not morfs:
-            morfs = self.data.measured_files()
-
-        # Be sure we have a list.
-        if not isinstance(morfs, (list, tuple)):
-            morfs = [morfs]
-
-        file_reporters = []
-        for morf in morfs:
-            file_reporter = self._get_file_reporter(morf)
-            file_reporters.append(file_reporter)
-
-        return file_reporters
-
-    def report(
-        self, morfs=None, show_missing=None, ignore_errors=None,
-        file=None,                  # pylint: disable=redefined-builtin
-        omit=None, include=None, skip_covered=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 file name patterns.  Files that match will be
-        included in the report. Files matching `omit` will not be included in
-        the report.
-
-        Returns a float, the total percentage covered.
-
-        """
-        self.get_data()
-        self.config.from_args(
-            ignore_errors=ignore_errors, omit=omit, include=include,
-            show_missing=show_missing, skip_covered=skip_covered,
-            )
-        reporter = SummaryReporter(self, self.config)
-        return reporter.report(morfs, outfile=file)
-
-    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 :meth:`report` for other arguments.
-
-        """
-        self.get_data()
-        self.config.from_args(
-            ignore_errors=ignore_errors, omit=omit, include=include
-            )
-        reporter = AnnotateReporter(self, self.config)
-        reporter.report(morfs, directory=directory)
-
-    def html_report(self, morfs=None, directory=None, ignore_errors=None,
-                    omit=None, include=None, extra_css=None, title=None):
-        """Generate an HTML report.
-
-        The HTML is written to `directory`.  The file "index.html" is the
-        overview starting point, with links to more detailed pages for
-        individual modules.
-
-        `extra_css` is a path to a file of other CSS to apply on the page.
-        It will be copied into the HTML directory.
-
-        `title` is a text string (not HTML) to use as the title of the HTML
-        report.
-
-        See :meth:`report` for other arguments.
-
-        Returns a float, the total percentage covered.
-
-        """
-        self.get_data()
-        self.config.from_args(
-            ignore_errors=ignore_errors, omit=omit, include=include,
-            html_dir=directory, extra_css=extra_css, html_title=title,
-            )
-        reporter = HtmlReporter(self, self.config)
-        return reporter.report(morfs)
-
-    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 :meth:`report` for other arguments.
-
-        Returns a float, the total percentage covered.
-
-        """
-        self.get_data()
-        self.config.from_args(
-            ignore_errors=ignore_errors, omit=omit, include=include,
-            xml_output=outfile,
-            )
-        file_to_close = None
-        delete_file = False
-        if self.config.xml_output:
-            if self.config.xml_output == '-':
-                outfile = sys.stdout
-            else:
-                # Ensure that the output directory is created; done here
-                # because this report pre-opens the output file.
-                # HTMLReport does this using the Report plumbing because
-                # its task is more complex, being multiple files.
-                output_dir = os.path.dirname(self.config.xml_output)
-                if output_dir and not os.path.isdir(output_dir):
-                    os.makedirs(output_dir)
-                open_kwargs = {}
-                if env.PY3:
-                    open_kwargs['encoding'] = 'utf8'
-                outfile = open(self.config.xml_output, "w", **open_kwargs)
-                file_to_close = outfile
-        try:
-            reporter = XmlReporter(self, self.config)
-            return reporter.report(morfs, outfile=outfile)
-        except CoverageException:
-            delete_file = True
-            raise
-        finally:
-            if file_to_close:
-                file_to_close.close()
-                if delete_file:
-                    file_be_gone(self.config.xml_output)
-
-    def sys_info(self):
-        """Return a list of (key, value) pairs showing internal information."""
-
-        import coverage as covmod
-
-        self._init()
-
-        ft_plugins = []
-        for ft in self.plugins.file_tracers:
-            ft_name = ft._coverage_plugin_name
-            if not ft._coverage_enabled:
-                ft_name += " (disabled)"
-            ft_plugins.append(ft_name)
-
-        info = [
-            ('version', covmod.__version__),
-            ('coverage', covmod.__file__),
-            ('cover_dirs', self.cover_dirs),
-            ('pylib_dirs', self.pylib_dirs),
-            ('tracer', self.collector.tracer_name()),
-            ('plugins.file_tracers', ft_plugins),
-            ('config_files', self.config.attempted_config_files),
-            ('configs_read', self.config.config_files),
-            ('data_path', self.data_files.filename),
-            ('python', sys.version.replace('\n', '')),
-            ('platform', platform.platform()),
-            ('implementation', platform.python_implementation()),
-            ('executable', sys.executable),
-            ('cwd', os.getcwd()),
-            ('path', sys.path),
-            ('environment', sorted(
-                ("%s = %s" % (k, v))
-                for k, v in iitems(os.environ)
-                if k.startswith(("COV", "PY"))
-            )),
-            ('command_line', " ".join(getattr(sys, 'argv', ['???']))),
-            ]
-
-        matcher_names = [
-            'source_match', 'source_pkgs_match',
-            'include_match', 'omit_match',
-            'cover_match', 'pylib_match',
-            ]
-
-        for matcher_name in matcher_names:
-            matcher = getattr(self, matcher_name)
-            if matcher:
-                matcher_info = matcher.info()
-            else:
-                matcher_info = '-none-'
-            info.append((matcher_name, matcher_info))
-
-        return info
-
-
-# FileDisposition "methods": FileDisposition is a pure value object, so it can
-# be implemented in either C or Python.  Acting on them is done with these
-# functions.
-
-def _disposition_init(cls, original_filename):
-    """Construct and initialize a new FileDisposition object."""
-    disp = cls()
-    disp.original_filename = original_filename
-    disp.canonical_filename = original_filename
-    disp.source_filename = None
-    disp.trace = False
-    disp.reason = ""
-    disp.file_tracer = None
-    disp.has_dynamic_filename = False
-    return disp
-
-
-def _disposition_debug_msg(disp):
-    """Make a nice debug message of what the FileDisposition is doing."""
-    if disp.trace:
-        msg = "Tracing %r" % (disp.original_filename,)
-        if disp.file_tracer:
-            msg += ": will be traced by %r" % disp.file_tracer
-    else:
-        msg = "Not tracing %r: %s" % (disp.original_filename, disp.reason)
-    return msg
-
-
-def process_startup():
-    """Call this at Python start-up 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()
-
-    Returns the :class:`Coverage` instance that was started, or None if it was
-    not started by this call.
-
-    """
-    cps = os.environ.get("COVERAGE_PROCESS_START")
-    if not cps:
-        # No request for coverage, nothing to do.
-        return None
-
-    # This function can be called more than once in a process. This happens
-    # because some virtualenv configurations make the same directory visible
-    # twice in sys.path.  This means that the .pth file will be found twice,
-    # and executed twice, executing this function twice.  We set a global
-    # flag (an attribute on this function) to indicate that coverage.py has
-    # already been started, so we can avoid doing it twice.
-    #
-    # https://bitbucket.org/ned/coveragepy/issue/340/keyerror-subpy has more
-    # details.
-
-    if hasattr(process_startup, "done"):
-        # We've annotated this function before, so we must have already
-        # started coverage.py in this process.  Nothing to do.
-        return None
-
-    process_startup.done = True
-    cov = Coverage(config_file=cps, auto_data=True)
-    cov.start()
-    cov._warn_no_data = False
-    cov._warn_unimported_source = False
-
-    return cov
-
-#
-# eflag: FileType = Python2

eric ide

mercurial