# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt

"""Central control stuff for coverage.py."""

from __future__ import annotations

import atexit
import collections
import contextlib
import datetime
import functools
import os
import os.path
import platform
import signal
import sys
import threading
import time
import warnings
from collections.abc import Iterable, Iterator
from types import FrameType
from typing import IO, Any, Callable, cast

from coverage import env
from coverage.annotate import AnnotateReporter
from coverage.collector import Collector
from coverage.config import CoverageConfig, read_coverage_config
from coverage.context import combine_context_switchers, should_start_context_test_function
from coverage.core import CTRACER_FILE, Core
from coverage.data import CoverageData, combine_parallel_data
from coverage.debug import (
    DebugControl,
    NoDebugging,
    relevant_environment_display,
    short_stack,
    write_formatted_info,
)
from coverage.disposition import disposition_debug_msg
from coverage.exceptions import ConfigError, CoverageException, CoverageWarning, PluginError
from coverage.files import PathAliases, abs_file, relative_filename, set_relative_directory
from coverage.html import HtmlReporter
from coverage.inorout import InOrOut
from coverage.jsonreport import JsonReporter
from coverage.lcovreport import LcovReporter
from coverage.misc import (
    DefaultValue,
    bool_or_none,
    ensure_dir_for_file,
    isolate_module,
    join_regex,
)
from coverage.multiproc import patch_multiprocessing
from coverage.patch import apply_patches
from coverage.plugin import FileReporter
from coverage.plugin_support import Plugins, TCoverageInit
from coverage.python import PythonFileReporter
from coverage.report import SummaryReporter
from coverage.report_core import render_report
from coverage.results import Analysis, analysis_from_file_reporter
from coverage.types import (
    FilePath,
    TConfigSectionIn,
    TConfigurable,
    TConfigValueIn,
    TConfigValueOut,
    TFileDisposition,
    TLineNo,
    TMorf,
)
from coverage.version import __url__
from coverage.xmlreport import XmlReporter

os = isolate_module(os)


@contextlib.contextmanager
def override_config(cov: Coverage, **kwargs: TConfigValueIn) -> Iterator[None]:
    """Temporarily tweak the configuration of `cov`.

    The arguments are applied to `cov.config` with the `from_args` method.
    At the end of the with-statement, the old configuration is restored.
    """
    original_config = cov.config
    cov.config = cov.config.copy()
    try:
        cov.config.from_args(**kwargs)
        yield
    finally:
        cov.config = original_config


DEFAULT_DATAFILE = DefaultValue("MISSING")
_DEFAULT_DATAFILE = DEFAULT_DATAFILE  # Just in case, for backwards compatibility
CONFIG_DATA_PREFIX = ":data:"


class Coverage(TConfigurable):
    """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")

    A context manager is available to do the same thing::

        cov = Coverage()
        with cov.collect():
            #.. call your code ..
        cov.html_report(directory="covhtml")

    Note: in keeping with Python custom, names starting with underscore are
    not part of the public API. They might stop working at any point.  Please
    limit yourself to documented methods to avoid problems.

    Methods can raise any of the exceptions described in :ref:`api_exceptions`.

    """

    # The stack of started Coverage instances.
    _instances: list[Coverage] = []

    @classmethod
    def current(cls) -> Coverage | None:
        """Get the latest started `Coverage` instance, if any.

        Returns: a `Coverage` instance, or None.

        .. versionadded:: 5.0

        """
        if cls._instances:
            return cls._instances[-1]
        else:
            return None

    def __init__(  # pylint: disable=too-many-arguments
        self,
        data_file: FilePath | DefaultValue | None = DEFAULT_DATAFILE,
        data_suffix: str | bool | None = None,
        cover_pylib: bool | None = None,
        auto_data: bool = False,
        timid: bool | None = None,
        branch: bool | None = None,
        config_file: FilePath | bool = True,
        source: Iterable[str] | None = None,
        source_pkgs: Iterable[str] | None = None,
        source_dirs: Iterable[str] | None = None,
        omit: str | Iterable[str] | None = None,
        include: str | Iterable[str] | None = None,
        debug: Iterable[str] | None = None,
        concurrency: str | Iterable[str] | None = None,
        check_preimported: bool = False,
        context: str | None = None,
        messages: bool = False,
        plugins: Iterable[Callable[..., None]] | None = None,
    ) -> None:
        """
        Many of these arguments duplicate and override values that can be
        provided in a configuration file.  Parameters that are missing here
        will use values from the config file.

        `data_file` is the base name of the data file to use. The config value
        defaults to ".coverage".  None can be provided to prevent writing a data
        file.  `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", "tox.ini").  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.

        `source_pkgs` is a list of package names. It works the same as
        `source`, but can be used to name packages where the name can also be
        interpreted as a file path.

        `source_dirs` is a list of file paths. It works the same as
        `source`, but raises an error if the path doesn't exist, rather
        than being treated as a package name.

        `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.

        If `check_preimported` is true, then when coverage is started, the
        already-imported files will be checked to see if they should be
        measured by coverage.  Importing measured files before coverage is
        started can mean that code is missed.

        `context` is a string to use as the :ref:`static context
        <static_contexts>` label for collected data.

        If `messages` is true, some messages will be printed to stdout
        indicating what is happening.

        If `plugins` are passed, they are an iterable of function objects
        accepting a `reg` object to register plugins, as described in
        :ref:`api_plugin`.  When they are provided, they will override the
        plugins found in the coverage configuration file.

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

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

        .. versionadded:: 5.0
            The `check_preimported` and `context` parameters.

        .. versionadded:: 5.3
            The `source_pkgs` parameter.

        .. versionadded:: 6.0
            The `messages` parameter.

        .. versionadded:: 7.7
            The `plugins` parameter.

        .. versionadded:: 7.8
            The `source_dirs` parameter.
        """
        # Start self.config as a usable default configuration. It will soon be
        # replaced with the real configuration.
        self.config = CoverageConfig()

        # data_file=None means no disk file at all. data_file missing means
        # use the value from the config file.
        self._no_disk = data_file is None
        if isinstance(data_file, DefaultValue):
            data_file = None
        if data_file is not None:
            data_file = os.fspath(data_file)

        # This is injectable by tests.
        self._debug_file: IO[str] | None = None

        self._auto_load = self._auto_save = auto_data
        self._data_suffix_specified = data_suffix

        # Is it ok for no data to be collected?
        self._warn_no_data = True
        self._warn_unimported_source = True
        self._warn_preimported_source = check_preimported
        self._no_warn_slugs: set[str] = set()
        self._messages = messages

        # If we're invoked from a .pth file, we shouldn't try to make another one.
        self._make_pth_file = True

        # A record of all the warnings that have been issued.
        self._warnings: list[str] = []

        # Other instance attributes, set with placebos or placeholders.
        # More useful objects will be created later.
        self._debug: DebugControl = NoDebugging()
        self._inorout: InOrOut | None = None
        self._plugins: Plugins = Plugins()
        self._plugin_override = cast(Iterable[TCoverageInit] | None, plugins)
        self._data: CoverageData | None = None
        self._data_to_close: list[CoverageData] = []
        self._core: Core | None = None
        self._collector: Collector | None = None
        self._metacov = False

        self._file_mapper: Callable[[str], str] = abs_file
        self._data_suffix = self._run_suffix = None
        self._exclude_re: dict[str, str] = {}
        self._old_sigterm: Callable[[int, FrameType | None], Any] | None = None

        # State machine variables:
        # Have we initialized everything?
        self._inited = False
        self._inited_for_start = False
        # Have we started collecting and not stopped it?
        self._started = False
        # Should we write the debug output?
        self._should_write_debug = True

        # Build our configuration from a number of sources.
        if isinstance(config_file, str) and config_file.startswith(CONFIG_DATA_PREFIX):
            self.config = CoverageConfig.deserialize(config_file[len(CONFIG_DATA_PREFIX) :])
        else:
            if not isinstance(config_file, bool):
                config_file = os.fspath(config_file)
            self.config = read_coverage_config(
                config_file=config_file,
                warn=self._warn,
                data_file=data_file,
                cover_pylib=cover_pylib,
                timid=timid,
                branch=branch,
                parallel=bool_or_none(data_suffix),
                source=source,
                source_pkgs=source_pkgs,
                source_dirs=source_dirs,
                run_omit=omit,
                run_include=include,
                debug=debug,
                report_omit=omit,
                report_include=include,
                concurrency=concurrency,
                context=context,
            )

        # If we have subprocess 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) -> None:
        """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

        self._inited = True

        # Create and configure the debugging controller.
        self._debug = DebugControl(self.config.debug, self._debug_file, self.config.debug_file)
        if self._debug.should("process"):
            self._debug.write("Coverage._init")

        if "multiprocessing" in (self.config.concurrency or ()):
            # Multi-processing uses parallel for the subprocesses, so also use
            # it for the main process.
            self.config.parallel = True

        # _exclude_re is a dict that maps exclusion list names to compiled regexes.
        self._exclude_re = {}

        set_relative_directory()
        if self.config.relative_files:
            self._file_mapper = relative_filename

        # Load plugins
        self._plugins = Plugins(self._debug)
        if self._plugin_override:
            self._plugins.load_from_callables(self._plugin_override)
        else:
            self._plugins.load_from_config(self.config.plugins, self.config)

        # Run configuring plugins.
        for plugin in self._plugins.configurers:
            # We need an object with set_option and get_option. Either self or
            # self.config will do. Choosing randomly stops people from doing
            # other things with those objects, against the public API.  Yes,
            # this is a bit childish. :)
            plugin.configure([self, self.config][int(time.time()) % 2])

    def _post_init(self) -> None:
        """Stuff to do after everything is initialized."""
        if self._should_write_debug:
            self._should_write_debug = False
            self._write_startup_debug()

        # "[run] _crash" will raise an exception if the value is close by in
        # the call stack, for testing error handling.
        if self.config._crash and self.config._crash in short_stack():
            raise RuntimeError(f"Crashing because called by {self.config._crash}")

    def _write_startup_debug(self) -> None:
        """Write out debug info at startup if needed."""
        wrote_any = False
        with self._debug.without_callers():
            if self._debug.should("config"):
                write_formatted_info(self._debug.write, "config", self.config.debug_info())
                wrote_any = True

            if self._debug.should("sys"):
                write_formatted_info(self._debug.write, "sys", self.sys_info())
                for plugin in self._plugins:
                    header = "sys: " + plugin._coverage_plugin_name
                    write_formatted_info(self._debug.write, header, plugin.sys_info())
                wrote_any = True

            if self._debug.should("pybehave"):
                write_formatted_info(self._debug.write, "pybehave", env.debug_info())
                wrote_any = True

            if self._debug.should("sqlite"):
                write_formatted_info(self._debug.write, "sqlite", CoverageData.sys_info())
                wrote_any = True

        if wrote_any:
            write_formatted_info(self._debug.write, "end", ())

    def _should_trace(self, filename: str, frame: FrameType) -> TFileDisposition:
        """Decide whether to trace execution in `filename`.

        Calls `_should_trace_internal`, and returns the FileDisposition.

        """
        assert self._inorout is not None
        disp = self._inorout.should_trace(filename, frame)
        if self._debug.should("trace"):
            self._debug.write(disposition_debug_msg(disp))
        return disp

    def _check_include_omit_etc(self, filename: str, frame: FrameType) -> bool:
        """Check a file name against the include/omit/etc, rules, verbosely.

        Returns a boolean: True if the file should be traced, False if not.

        """
        assert self._inorout is not None
        reason = self._inorout.check_include_omit_etc(filename, frame)
        if self._debug.should("trace"):
            if not reason:
                msg = f"Including {filename!r}"
            else:
                msg = f"Not including {filename!r}: {reason}"
            self._debug.write(msg)

        return not reason

    def _warn(self, msg: str, slug: str | None = None, once: bool = False) -> None:
        """Use `msg` as a warning.

        For warning suppression, use `slug` as the shorthand.

        If `once` is true, only show this warning once (determined by the
        slug.)

        """
        if not self._no_warn_slugs:
            self._no_warn_slugs = set(self.config.disable_warnings)

        if slug in self._no_warn_slugs:
            # Don't issue the warning
            return

        self._warnings.append(msg)
        if slug:
            msg = f"{msg} ({slug}); see {__url__}/messages.html#warning-{slug}"
        if self._debug.should("pid"):
            msg = f"[{os.getpid()}] {msg}"
        warnings.warn(msg, category=CoverageWarning, stacklevel=2)

        if once:
            assert slug is not None
            self._no_warn_slugs.add(slug)

    def _message(self, msg: str) -> None:
        """Write a message to the user, if configured to do so."""
        if self._messages:
            print(msg)

    def get_option(self, option_name: str) -> TConfigValueOut | None:
        """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.  The type depends on the option
        selected.

        As a special case, an `option_name` of ``"paths"`` will return an
        dictionary with the entire ``[paths]`` section value.

        .. versionadded:: 4.0

        """
        return self.config.get_option(option_name)

    def set_option(self, option_name: str, value: TConfigValueIn | TConfigSectionIn) -> None:
        """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 an
        appropriate Python value.  For example, use True for booleans, not the
        string ``"True"``.

        As an example, calling:

        .. code-block:: python

            cov.set_option("run:branch", True)

        has the same effect as this configuration file:

        .. code-block:: ini

            [run]
            branch = True

        As a special case, an `option_name` of ``"paths"`` will replace the
        entire ``[paths]`` section.  The value should be a dictionary.

        .. versionadded:: 4.0

        """
        self.config.set_option(option_name, value)

    def load(self) -> None:
        """Load previously-collected coverage data from the data file."""
        self._init()
        if self._collector is not None:
            self._collector.reset()
        should_skip = self.config.parallel and not os.path.exists(self.config.data_file)
        if not should_skip:
            self._init_data(suffix=None)
        self._post_init()
        if not should_skip:
            assert self._data is not None
            self._data.read()

    def _init_for_start(self) -> None:
        """Initialization for start()"""
        # Construct the collector.
        concurrency: list[str] = self.config.concurrency
        if "multiprocessing" in concurrency:
            if self.config.config_file is None:
                raise ConfigError("multiprocessing requires a configuration file")
            patch_multiprocessing(rcfile=self.config.config_file)

        dycon = self.config.dynamic_context
        if not dycon or dycon == "none":
            context_switchers = []
        elif dycon == "test_function":
            context_switchers = [should_start_context_test_function]
        else:
            raise ConfigError(f"Don't understand dynamic_context setting: {dycon!r}")

        context_switchers.extend(
            plugin.dynamic_context for plugin in self._plugins.context_switchers
        )

        should_start_context = combine_context_switchers(context_switchers)

        self._core = Core(
            warn=self._warn,
            debug=(self._debug if self._debug.should("core") else None),
            config=self.config,
            dynamic_contexts=(should_start_context is not None),
            metacov=self._metacov,
        )
        self._collector = Collector(
            core=self._core,
            should_trace=self._should_trace,
            check_include=self._check_include_omit_etc,
            should_start_context=should_start_context,
            file_mapper=self._file_mapper,
            branch=self.config.branch,
            warn=self._warn,
            concurrency=concurrency,
        )

        suffix = self._data_suffix_specified
        if suffix:
            if not isinstance(suffix, str):
                # if data_suffix=True, use .machinename.pid.random
                suffix = True
        elif self.config.parallel:
            if suffix is None:
                suffix = True
            elif not isinstance(suffix, str):
                suffix = bool(suffix)
        else:
            suffix = None

        self._init_data(suffix)

        assert self._data is not None
        self._collector.use_data(self._data, self.config.context)

        # Early warning if we aren't going to be able to support plugins.
        if self._plugins.file_tracers and not self._core.supports_plugins:
            self._warn(
                "Plugin file tracers ({}) aren't supported with {}".format(
                    ", ".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

        # Create the file classifying substructure.
        self._inorout = InOrOut(
            config=self.config,
            warn=self._warn,
            debug=(self._debug if self._debug.should("trace") else None),
            include_namespace_packages=self.config.include_namespace_packages,
        )
        self._inorout.plugins = self._plugins
        self._inorout.disp_class = self._core.file_disposition_class

        # It's useful to write debug info after initing for start.
        self._should_write_debug = True

        # Register our clean-up handlers.
        atexit.register(self._atexit)
        if self.config.sigterm:
            is_main = (threading.current_thread() == threading.main_thread())  # fmt: skip
            if is_main and not env.WINDOWS:
                # The Python docs seem to imply that SIGTERM works uniformly even
                # on Windows, but that's not my experience, and this agrees:
                # https://stackoverflow.com/questions/35772001/x/35792192#35792192
                self._old_sigterm = signal.signal(  # type: ignore[assignment]
                    signal.SIGTERM,
                    self._on_sigterm,
                )

    def _init_data(self, suffix: str | bool | None) -> None:
        """Create a data file if we don't have one yet."""
        if self._data is None:
            # 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.
            ensure_dir_for_file(self.config.data_file)
            self._data = CoverageData(
                basename=self.config.data_file,
                suffix=suffix,
                warn=self._warn,
                debug=self._debug,
                no_disk=self._no_disk,
            )
            self._data_to_close.append(self._data)

    def start(self) -> None:
        """Start measuring code coverage.

        Coverage measurement is only collected 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.

        The :meth:`collect` method is a context manager to handle both
        starting and stopping collection.

        """
        self._init()
        if not self._inited_for_start:
            self._inited_for_start = True
            self._init_for_start()
        self._post_init()

        assert self._collector is not None
        assert self._inorout is not None

        # Issue warnings for possible problems.
        self._inorout.warn_conflicting_settings()

        # See if we think some code that would eventually be measured has
        # already been imported.
        if self._warn_preimported_source:
            self._inorout.warn_already_imported_files()

        if self._auto_load:
            self.load()

        apply_patches(self, self.config, self._debug, make_pth_file=self._make_pth_file)

        self._collector.start()
        self._started = True
        self._instances.append(self)

    def stop(self) -> None:
        """Stop measuring code coverage."""
        if self._instances:
            if self._instances[-1] is self:
                self._instances.pop()
        if self._started:
            assert self._collector is not None
            self._collector.stop()
        self._started = False

    @contextlib.contextmanager
    def collect(self) -> Iterator[None]:
        """A context manager to start/stop coverage measurement collection.

        .. versionadded:: 7.3

        """
        self.start()
        try:
            yield
        finally:
            self.stop()  # pragma: nested

    def _atexit(self, event: str = "atexit") -> None:
        """Clean up on process shutdown."""
        if self._debug.should("process"):
            self._debug.write(f"{event}: pid: {os.getpid()}, instance: {self!r}")
        if self._started:
            self.stop()
        if self._auto_save or event == "sigterm":
            self.save()
        for d in self._data_to_close:
            d.close(force=True)

    def _on_sigterm(self, signum_unused: int, frame_unused: FrameType | None) -> None:
        """A handler for signal.SIGTERM."""
        self._atexit("sigterm")
        # Statements after here won't be seen by metacov because we just wrote
        # the data, and are about to kill the process.
        signal.signal(signal.SIGTERM, self._old_sigterm)  # pragma: not covered
        os.kill(os.getpid(), signal.SIGTERM)  # pragma: not covered

    def erase(self) -> None:
        """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._post_init()
        if self._collector is not None:
            self._collector.reset()
        self._init_data(suffix=None)
        assert self._data is not None
        self._data.erase(parallel=self.config.parallel)
        self._data = None
        self._inited_for_start = False

    def switch_context(self, new_context: str) -> None:
        """Switch to a new dynamic context.

        `new_context` is a string to use as the :ref:`dynamic context
        <dynamic_contexts>` label for collected data.  If a :ref:`static
        context <static_contexts>` is in use, the static and dynamic context
        labels will be joined together with a pipe character.

        Coverage collection must be started already.

        .. versionadded:: 5.0

        """
        if not self._started:  # pragma: part started
            raise CoverageException("Cannot switch context, coverage is not started")

        assert self._collector is not None
        if self._collector.should_start_context:
            self._warn("Conflicting dynamic contexts", slug="dynamic-conflict", once=True)

        self._collector.switch_context(new_context)

    def clear_exclude(self, which: str = "exclude") -> None:
        """Clear the exclude list."""
        self._init()
        setattr(self.config, f"{which}_list", [])
        self._exclude_regex_stale()

    def exclude(self, regex: str, which: str = "exclude") -> None:
        """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, f"{which}_list")
        excl_list.append(regex)
        self._exclude_regex_stale()

    def _exclude_regex_stale(self) -> None:
        """Drop all the compiled exclusion regexes, a list was modified."""
        self._exclude_re.clear()

    def _exclude_regex(self, which: str) -> str:
        """Return a regex string for the given exclusion list."""
        if which not in self._exclude_re:
            excl_list = getattr(self.config, f"{which}_list")
            self._exclude_re[which] = join_regex(excl_list)
        return self._exclude_re[which]

    def get_exclude_list(self, which: str = "exclude") -> list[str]:
        """Return a list of excluded regex strings.

        `which` indicates which list is desired.  See :meth:`exclude` for the
        lists that are available, and their meaning.

        """
        self._init()
        return cast(list[str], getattr(self.config, f"{which}_list"))

    def save(self) -> None:
        """Save the collected coverage data to the data file."""
        data = self.get_data()
        data.write()

    def _make_aliases(self) -> PathAliases:
        """Create a PathAliases from our configuration."""
        aliases = PathAliases(
            debugfn=(self._debug.write if self._debug.should("pathmap") else None),
            relative=self.config.relative_files,
        )
        for paths in self.config.paths.values():
            result = paths[0]
            for pattern in paths[1:]:
                aliases.add(pattern, result)
        return aliases

    def combine(
        self,
        data_paths: Iterable[str] | None = None,
        strict: bool = False,
        keep: bool = False,
    ) -> 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.

        If `strict` is true, then it is an error to attempt to combine when
        there are no data files to combine.

        If `keep` is true, then original input data files won't be deleted.

        .. versionadded:: 4.0
            The `data_paths` parameter.

        .. versionadded:: 4.3
            The `strict` parameter.

        .. versionadded: 5.5
            The `keep` parameter.
        """
        self._init()
        self._init_data(suffix=None)
        self._post_init()
        self.get_data()

        assert self._data is not None
        combine_parallel_data(
            self._data,
            aliases=self._make_aliases(),
            data_paths=data_paths,
            strict=strict,
            keep=keep,
            message=self._message,
        )

    def get_data(self) -> CoverageData:
        """Get the collected data.

        Also warn about various problems collecting data.

        Returns a :class:`coverage.CoverageData`, the collected coverage data.

        .. versionadded:: 4.0

        """
        self._init()
        self._init_data(suffix=None)
        self._post_init()

        if self._collector is not None:
            for plugin in self._plugins:
                if not plugin._coverage_enabled:
                    self._collector.plugin_was_disabled(plugin)

            if self._collector.flush_data():
                self._post_save_work()

        assert self._data is not None
        return self._data

    def _post_save_work(self) -> None:
        """After saving data, look for warnings, post-work, etc.

        Warn about things that should have happened but didn't.
        Look for un-executed files.

        """
        assert self._data is not None
        assert self._inorout is not None

        # If there are still entries in the source_pkgs_unmatched list,
        # then we never encountered those packages.
        if self._warn_unimported_source:
            self._inorout.warn_unimported_source()

        # Find out if we got any data.
        if not self._data and self._warn_no_data:
            self._warn("No data was collected.", slug="no-data-collected")

        # Touch all the files that could have executed, so that we can
        # mark completely un-executed files as 0% covered.
        file_paths = collections.defaultdict(list)
        for file_path, plugin_name in self._inorout.find_possibly_unexecuted_files():
            file_path = self._file_mapper(file_path)
            file_paths[plugin_name].append(file_path)
        for plugin_name, paths in file_paths.items():
            self._data.touch_files(paths, plugin_name)

    # Backward compatibility with version 1.
    def analysis(self, morf: TMorf) -> tuple[str, list[TLineNo], list[TLineNo], str]:
        """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: TMorf,
    ) -> tuple[str, list[TLineNo], list[TLineNo], list[TLineNo], str]:
        """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.

        """
        analysis = self._analyze(morf)
        return (
            analysis.filename,
            sorted(analysis.statements),
            sorted(analysis.excluded),
            sorted(analysis.missing),
            analysis.missing_formatted(),
        )

    @functools.lru_cache(maxsize=1)
    def _analyze(self, morf: TMorf) -> Analysis:
        """Analyze a module or file.  Private for now."""
        self._init()
        self._post_init()

        data = self.get_data()
        file_reporter = self._get_file_reporter(morf)
        filename = self._file_mapper(file_reporter.filename)
        return analysis_from_file_reporter(data, self.config.precision, file_reporter, filename)

    def branch_stats(self, morf: TMorf) -> dict[TLineNo, tuple[int, int]]:
        """Get branch statistics about a module.

        `morf` is a module or a file name.

        Returns a dict mapping line numbers to a tuple:
        (total_exits, taken_exits).

        .. versionadded:: 7.7

        """
        analysis = self._analyze(morf)
        return analysis.branch_stats()

    @functools.lru_cache(maxsize=1)
    def _get_file_reporter(self, morf: TMorf) -> FileReporter:
        """Get a FileReporter for a module or file name."""
        assert self._data is not None
        plugin = None
        file_reporter: str | FileReporter = "python"

        if isinstance(morf, str):
            mapped_morf = self._file_mapper(morf)
            plugin_name = self._data.file_tracer(mapped_morf)
            if plugin_name:
                plugin = self._plugins.get(plugin_name)

                if plugin:
                    file_reporter = plugin.file_reporter(mapped_morf)
                    if file_reporter is None:
                        raise PluginError(
                            "Plugin {!r} did not provide a file reporter for {!r}.".format(
                                plugin._coverage_plugin_name,
                                morf,
                            ),
                        )

        if file_reporter == "python":
            file_reporter = PythonFileReporter(morf, self)

        assert isinstance(file_reporter, FileReporter)
        return file_reporter

    def _get_file_reporters(
        self,
        morfs: Iterable[TMorf] | None = None,
    ) -> list[tuple[FileReporter, TMorf]]:
        """Get FileReporters for a list of modules or file names.

        For each module or file name in `morfs`, find a FileReporter.  Return
        a list pairing FileReporters with the morfs.

        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.

        """
        assert self._data is not None
        if not morfs:
            morfs = self._data.measured_files()

        # Be sure we have a collection.
        if not isinstance(morfs, (list, tuple, set)):
            morfs = [morfs]  # type: ignore[list-item]

        morfs = sorted(morfs, key=lambda m: m if isinstance(m, str) else m.__name__)
        return [(self._get_file_reporter(morf), morf) for morf in morfs]

    def _prepare_data_for_reporting(self) -> None:
        """Re-map data before reporting, to get implicit "combine" behavior."""
        if self.config.paths:
            mapped_data = CoverageData(warn=self._warn, debug=self._debug, no_disk=True)
            if self._data is not None:
                mapped_data.update(self._data, map_path=self._make_aliases().map)
            self._data = mapped_data
            self._data_to_close.append(mapped_data)

    def report(
        self,
        morfs: Iterable[TMorf] | None = None,
        show_missing: bool | None = None,
        ignore_errors: bool | None = None,
        file: IO[str] | None = None,
        omit: str | list[str] | None = None,
        include: str | list[str] | None = None,
        skip_covered: bool | None = None,
        contexts: list[str] | None = None,
        skip_empty: bool | None = None,
        precision: int | None = None,
        sort: str | None = None,
        output_format: str | None = None,
    ) -> float:
        """Write a textual summary report to `file`.

        Each module in `morfs` is listed, with counts of statements, executed
        statements, missing statements, and a list of lines missed.

        If `show_missing` is true, then details of which lines or branches are
        missing will be included in the report.  If `ignore_errors` is true,
        then a failure while reporting a single file will not stop the entire
        report.

        `file` is a file-like object, suitable for writing.

        `output_format` determines the format, either "text" (the default),
        "markdown", or "total".

        `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.

        If `skip_covered` is true, don't report on files with 100% coverage.

        If `skip_empty` is true, don't report on empty files (those that have
        no statements).

        `contexts` is a list of regular expression strings.  Only data from
        :ref:`dynamic contexts <dynamic_contexts>` that match one of those
        expressions (using :func:`re.search <python:re.search>`) will be
        included in the report.

        `precision` is the number of digits to display after the decimal
        point for percentages.

        All of the arguments default to the settings read from the
        :ref:`configuration file <config>`.

        Returns a float, the total percentage covered.

        .. versionadded:: 4.0
            The `skip_covered` parameter.

        .. versionadded:: 5.0
            The `contexts` and `skip_empty` parameters.

        .. versionadded:: 5.2
            The `precision` parameter.

        .. versionadded:: 7.0
            The `format` parameter.

        """
        self._prepare_data_for_reporting()
        with override_config(
            self,
            ignore_errors=ignore_errors,
            report_omit=omit,
            report_include=include,
            show_missing=show_missing,
            skip_covered=skip_covered,
            report_contexts=contexts,
            skip_empty=skip_empty,
            precision=precision,
            sort=sort,
            format=output_format,
        ):
            reporter = SummaryReporter(self)
            return reporter.report(morfs, outfile=file)

    def annotate(
        self,
        morfs: Iterable[TMorf] | None = None,
        directory: str | None = None,
        ignore_errors: bool | None = None,
        omit: str | list[str] | None = None,
        include: str | list[str] | None = None,
        contexts: list[str] | None = None,
    ) -> 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._prepare_data_for_reporting()
        with override_config(
            self,
            ignore_errors=ignore_errors,
            report_omit=omit,
            report_include=include,
            report_contexts=contexts,
        ):
            reporter = AnnotateReporter(self)
            reporter.report(morfs, directory=directory)

    def html_report(
        self,
        morfs: Iterable[TMorf] | None = None,
        directory: str | None = None,
        ignore_errors: bool | None = None,
        omit: str | list[str] | None = None,
        include: str | list[str] | None = None,
        extra_css: str | None = None,
        title: str | None = None,
        skip_covered: bool | None = None,
        show_contexts: bool | None = None,
        contexts: list[str] | None = None,
        skip_empty: bool | None = None,
        precision: int | None = None,
    ) -> float:
        """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.

        .. note::

            The HTML report files are generated incrementally based on the
            source files and coverage results. If you modify the report files,
            the changes will not be considered.  You should be careful about
            changing the files in the report folder.

        """
        self._prepare_data_for_reporting()
        with override_config(
            self,
            ignore_errors=ignore_errors,
            report_omit=omit,
            report_include=include,
            html_dir=directory,
            extra_css=extra_css,
            html_title=title,
            html_skip_covered=skip_covered,
            show_contexts=show_contexts,
            report_contexts=contexts,
            html_skip_empty=skip_empty,
            precision=precision,
        ):
            reporter = HtmlReporter(self)
            return reporter.report(morfs)

    def xml_report(
        self,
        morfs: Iterable[TMorf] | None = None,
        outfile: str | None = None,
        ignore_errors: bool | None = None,
        omit: str | list[str] | None = None,
        include: str | list[str] | None = None,
        contexts: list[str] | None = None,
        skip_empty: bool | None = None,
    ) -> float:
        """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._prepare_data_for_reporting()
        with override_config(
            self,
            ignore_errors=ignore_errors,
            report_omit=omit,
            report_include=include,
            xml_output=outfile,
            report_contexts=contexts,
            skip_empty=skip_empty,
        ):
            return render_report(self.config.xml_output, XmlReporter(self), morfs, self._message)

    def json_report(
        self,
        morfs: Iterable[TMorf] | None = None,
        outfile: str | None = None,
        ignore_errors: bool | None = None,
        omit: str | list[str] | None = None,
        include: str | list[str] | None = None,
        contexts: list[str] | None = None,
        pretty_print: bool | None = None,
        show_contexts: bool | None = None,
    ) -> float:
        """Generate a JSON report of coverage results.

        Each module in `morfs` is included in the report.  `outfile` is the
        path to write the file to, "-" will write to stdout.

        `pretty_print` is a boolean, whether to pretty-print the JSON output or not.

        See :meth:`report` for other arguments.

        Returns a float, the total percentage covered.

        .. versionadded:: 5.0

        """
        self._prepare_data_for_reporting()
        with override_config(
            self,
            ignore_errors=ignore_errors,
            report_omit=omit,
            report_include=include,
            json_output=outfile,
            report_contexts=contexts,
            json_pretty_print=pretty_print,
            json_show_contexts=show_contexts,
        ):
            return render_report(self.config.json_output, JsonReporter(self), morfs, self._message)

    def lcov_report(
        self,
        morfs: Iterable[TMorf] | None = None,
        outfile: str | None = None,
        ignore_errors: bool | None = None,
        omit: str | list[str] | None = None,
        include: str | list[str] | None = None,
        contexts: list[str] | None = None,
    ) -> float:
        """Generate an LCOV report of coverage results.

        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.

        .. versionadded:: 6.3
        """
        self._prepare_data_for_reporting()
        with override_config(
            self,
            ignore_errors=ignore_errors,
            report_omit=omit,
            report_include=include,
            lcov_output=outfile,
            report_contexts=contexts,
        ):
            return render_report(self.config.lcov_output, LcovReporter(self), morfs, self._message)

    def sys_info(self) -> Iterable[tuple[str, Any]]:
        """Return a list of (key, value) pairs showing internal information."""

        import coverage as covmod

        self._init()
        self._post_init()

        def plugin_info(plugins: list[Any]) -> list[str]:
            """Make an entry for the sys_info from a list of plug-ins."""
            entries = []
            for plugin in plugins:
                entry = plugin._coverage_plugin_name
                if not plugin._coverage_enabled:
                    entry += " (disabled)"
                entries.append(entry)
            return entries

        info = [
            ("coverage_version", covmod.__version__),
            ("coverage_module", covmod.__file__),
            ("core", self._collector.tracer_name() if self._collector is not None else "-none-"),
            ("CTracer", f"available from {CTRACER_FILE}" if CTRACER_FILE else "unavailable"),
            ("plugins.file_tracers", plugin_info(self._plugins.file_tracers)),
            ("plugins.configurers", plugin_info(self._plugins.configurers)),
            ("plugins.context_switchers", plugin_info(self._plugins.context_switchers)),
            ("configs_attempted", self.config.config_files_attempted),
            ("configs_read", self.config.config_files_read),
            ("config_file", self.config.config_file),
            (
                "config_contents",
                repr(self.config._config_contents) if self.config._config_contents else "-none-",
            ),
            ("data_file", self._data.data_filename() if self._data is not None else "-none-"),
            ("python", sys.version.replace("\n", "")),
            ("platform", platform.platform()),
            ("implementation", platform.python_implementation()),
            ("build", platform.python_build()),
            ("gil_enabled", getattr(sys, "_is_gil_enabled", lambda: True)()),
            ("executable", sys.executable),
            ("def_encoding", sys.getdefaultencoding()),
            ("fs_encoding", sys.getfilesystemencoding()),
            ("pid", os.getpid()),
            ("cwd", os.getcwd()),
            ("path", sys.path),
            ("environment", [f"{k} = {v}" for k, v in relevant_environment_display(os.environ)]),
            ("command_line", " ".join(getattr(sys, "argv", ["-none-"]))),
            ("time", f"{datetime.datetime.now():%Y-%m-%d %H:%M:%S}"),
        ]

        if self._inorout is not None:
            info.extend(self._inorout.sys_info())

        return info


# Mega debugging...
# $set_env.py: COVERAGE_DEBUG_CALLS - Lots and lots of output about calls to Coverage.
if int(os.getenv("COVERAGE_DEBUG_CALLS", 0)):  # pragma: debugging
    from coverage.debug import decorate_methods, show_calls

    Coverage = decorate_methods(  # type: ignore[misc]
        show_calls(show_args=True),
        butnot=["get_data"],
    )(Coverage)


def process_startup(*, force: bool = False) -> Coverage | None:
    """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.

    For details, see https://coverage.readthedocs.io/en/latest/subprocess.html.

    Returns the :class:`Coverage` instance that was started, or None if it was
    not started by this call.

    """
    config_data = os.getenv("COVERAGE_PROCESS_CONFIG")
    cps = os.getenv("COVERAGE_PROCESS_START")
    if config_data is not None:
        config_file = CONFIG_DATA_PREFIX + config_data
    elif cps is not None:
        config_file = cps
    else:
        # 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://github.com/nedbat/coveragepy/issues/340 has more details.

    if not force and hasattr(process_startup, "coverage"):
        # We've annotated this function before, so we must have already
        # auto-started coverage.py in this process.  Nothing to do.
        return None

    cov = Coverage(config_file=config_file)
    process_startup.coverage = cov  # type: ignore[attr-defined]
    cov._warn_no_data = False
    cov._warn_unimported_source = False
    cov._warn_preimported_source = False
    cov._auto_save = True
    cov._make_pth_file = False
    cov.start()

    return cov


def _after_fork_in_child() -> None:
    """Used by patch=fork in the child process to restart coverage."""
    if cov := Coverage.current():
        cov.stop()
    process_startup(force=True)


def _prevent_sub_process_measurement() -> None:
    """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_save = False
