# 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.multiproc 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 if these libraries are in use.  Valid strings are "greenlet",
        "eventlet", "gevent", "multiprocessing", or "thread" (the default).
        This can also be a list of these strings.

        .. versionadded:: 4.0
            The `concurrency` parameter.

        .. versionadded:: 4.2
            The `concurrency` parameter can now be a list of strings.

        """
        # 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:
            # pylint: disable=redefined-variable-type
            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"
            self.config_file = config_file

            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

        # If we have sub-process measurement happening automatically, then we
        # want any explicit creation of a Coverage object to mean, this process
        # is already coverage-aware, so don't auto-measure it.  By now, the
        # auto-creation of a Coverage object has already happened.  But we can
        # find it and tell it not to save its data.
        if not env.METACOV:
            _prevent_sub_process_measurement()

    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 or []
        if "multiprocessing" in concurrency:
            patch_multiprocessing(rcfile=self.config_file)
            #concurrency = None
            # Multi-processing uses parallel for the subprocesses, so also use
            # it for the main process.
            self.config.parallel = True

        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
            import 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":
            # pylint: disable=redefined-variable-type
            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, "coverage"):
        # We've annotated this function before, so we must have already
        # started coverage.py in this process.  Nothing to do.
        return None

    cov = Coverage(config_file=cps, auto_data=True)
    process_startup.coverage = cov
    cov.start()
    cov._warn_no_data = False
    cov._warn_unimported_source = False

    return cov


def _prevent_sub_process_measurement():
    """Stop any subprocess auto-measurement from writing data."""
    auto_created_coverage = getattr(process_startup, "coverage", None)
    if auto_created_coverage is not None:
        auto_created_coverage._auto_data = False
