# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt

"""Coverage data for coverage.py."""

import glob
import itertools
import json
import optparse
import os
import os.path
import random
import re
import socket

from coverage import env
from coverage.backward import iitems, string_class
from coverage.debug import _TEST_NAME_FILE
from coverage.files import PathAliases
from coverage.misc import CoverageException, file_be_gone, isolate_module

os = isolate_module(os)


class CoverageData(object):
    """Manages collected coverage data, including file storage.

    This class is the public supported API to the data coverage.py collects
    during program execution.  It includes information about what code was
    executed. It does not include information from the analysis phase, to
    determine what lines could have been executed, or what lines were not
    executed.

    .. note::

        The file format is not documented or guaranteed.  It will change in
        the future, in possibly complicated ways.  Do not read coverage.py
        data files directly.  Use this API to avoid disruption.

    There are a number of kinds of data that can be collected:

    * **lines**: the line numbers of source lines that were executed.
      These are always available.

    * **arcs**: pairs of source and destination line numbers for transitions
      between source lines.  These are only available if branch coverage was
      used.

    * **file tracer names**: the module names of the file tracer plugins that
      handled each file in the data.

    * **run information**: information about the program execution.  This is
      written during "coverage run", and then accumulated during "coverage
      combine".

    Lines, arcs, and file tracer names are stored for each source file. File
    names in this API are case-sensitive, even on platforms with
    case-insensitive file systems.

    To read a coverage.py data file, use :meth:`read_file`, or
    :meth:`read_fileobj` if you have an already-opened file.  You can then
    access the line, arc, or file tracer data with :meth:`lines`, :meth:`arcs`,
    or :meth:`file_tracer`.  Run information is available with
    :meth:`run_infos`.

    The :meth:`has_arcs` method indicates whether arc data is available.  You
    can get a list of the files in the data with :meth:`measured_files`.
    A summary of the line data is available from :meth:`line_counts`.  As with
    most Python containers, you can determine if there is any data at all by
    using this object as a boolean value.


    Most data files will be created by coverage.py itself, but you can use
    methods here to create data files if you like.  The :meth:`add_lines`,
    :meth:`add_arcs`, and :meth:`add_file_tracers` methods add data, in ways
    that are convenient for coverage.py.  The :meth:`add_run_info` method adds
    key-value pairs to the run information.

    To add a file without any measured data, use :meth:`touch_file`.

    You write to a named file with :meth:`write_file`, or to an already opened
    file with :meth:`write_fileobj`.

    You can clear the data in memory with :meth:`erase`.  Two data collections
    can be combined by using :meth:`update` on one :class:`CoverageData`,
    passing it the other.

    """

    # The data file format is JSON, with these keys:
    #
    #     * lines: a dict mapping file names to lists of line numbers
    #       executed::
    #
    #         { "file1": [17,23,45], "file2": [1,2,3], ... }
    #
    #     * arcs: a dict mapping file names to lists of line number pairs::
    #
    #         { "file1": [[17,23], [17,25], [25,26]], ... }
    #
    #     * file_tracers: a dict mapping file names to plugin names::
    #
    #         { "file1": "django.coverage", ... }
    #
    #     * runs: a list of dicts of information about the coverage.py runs
    #       contributing to the data::
    #
    #         [ { "brief_sys": "CPython 2.7.10 Darwin" }, ... ]
    #
    # Only one of `lines` or `arcs` will be present: with branch coverage, data
    # is stored as arcs. Without branch coverage, it is stored as lines.  The
    # line data is easily recovered from the arcs: it is all the first elements
    # of the pairs that are greater than zero.

    def __init__(self, debug=None):
        """Create a CoverageData.

        `debug` is a `DebugControl` object for writing debug messages.

        """
        self._debug = debug

        # A map from canonical Python source file name to a dictionary in
        # which there's an entry for each line number that has been
        # executed:
        #
        #   { 'filename1.py': [12, 47, 1001], ... }
        #
        self._lines = None

        # A map from canonical Python source file name to a dictionary with an
        # entry for each pair of line numbers forming an arc:
        #
        #   { 'filename1.py': [(12,14), (47,48), ... ], ... }
        #
        self._arcs = None

        # A map from canonical source file name to a plugin module name:
        #
        #   { 'filename1.py': 'django.coverage', ... }
        #
        self._file_tracers = {}

        # A list of dicts of information about the coverage.py runs.
        self._runs = []

    def __repr__(self):
        return "<{klass} lines={lines} arcs={arcs} tracers={tracers} runs={runs}>".format(
            klass=self.__class__.__name__,
            lines="None" if self._lines is None else "{{{0}}}".format(len(self._lines)),
            arcs="None" if self._arcs is None else "{{{0}}}".format(len(self._arcs)),
            tracers="{{{0}}}".format(len(self._file_tracers)),
            runs="[{0}]".format(len(self._runs)),
        )

    ##
    ## Reading data
    ##

    def has_arcs(self):
        """Does this data have arcs?

        Arc data is only available if branch coverage was used during
        collection.

        Returns a boolean.

        """
        return self._has_arcs()

    def lines(self, filename):
        """Get the list of lines executed for a file.

        If the file was not measured, returns None.  A file might be measured,
        and have no lines executed, in which case an empty list is returned.

        If the file was executed, returns a list of integers, the line numbers
        executed in the file. The list is in no particular order.

        """
        if self._arcs is not None:
            arcs = self._arcs.get(filename)
            if arcs is not None:
                all_lines = itertools.chain.from_iterable(arcs)
                return list(set(l for l in all_lines if l > 0))
        elif self._lines is not None:
            return self._lines.get(filename)
        return None

    def arcs(self, filename):
        """Get the list of arcs executed for a file.

        If the file was not measured, returns None.  A file might be measured,
        and have no arcs executed, in which case an empty list is returned.

        If the file was executed, returns a list of 2-tuples of integers. Each
        pair is a starting line number and an ending line number for a
        transition from one line to another. The list is in no particular
        order.

        Negative numbers have special meaning.  If the starting line number is
        -N, it represents an entry to the code object that starts at line N.
        If the ending ling number is -N, it's an exit from the code object that
        starts at line N.

        """
        if self._arcs is not None:
            if filename in self._arcs:
                return self._arcs[filename]
        return None

    def file_tracer(self, filename):
        """Get the plugin name of the file tracer for a file.

        Returns the name of the plugin that handles this file.  If the file was
        measured, but didn't use a plugin, then "" is returned.  If the file
        was not measured, then None is returned.

        """
        # Because the vast majority of files involve no plugin, we don't store
        # them explicitly in self._file_tracers.  Check the measured data
        # instead to see if it was a known file with no plugin.
        if filename in (self._arcs or self._lines or {}):
            return self._file_tracers.get(filename, "")
        return None

    def run_infos(self):
        """Return the list of dicts of run information.

        For data collected during a single run, this will be a one-element
        list.  If data has been combined, there will be one element for each
        original data file.

        """
        return self._runs

    def measured_files(self):
        """A list of all files that had been measured."""
        return list(self._arcs or self._lines or {})

    def line_counts(self, fullpath=False):
        """Return a dict summarizing the line coverage data.

        Keys are based on the file names, and values are the number of executed
        lines.  If `fullpath` is true, then the keys are the full pathnames of
        the files, otherwise they are the basenames of the files.

        Returns a dict mapping file names to counts of lines.

        """
        summ = {}
        if fullpath:
            filename_fn = lambda f: f
        else:
            filename_fn = os.path.basename
        for filename in self.measured_files():
            summ[filename_fn(filename)] = len(self.lines(filename))
        return summ

    def __nonzero__(self):
        return bool(self._lines or self._arcs)

    __bool__ = __nonzero__

    def read_fileobj(self, file_obj):
        """Read the coverage data from the given file object.

        Should only be used on an empty CoverageData object.

        """
        data = self._read_raw_data(file_obj)

        self._lines = self._arcs = None

        if 'lines' in data:
            self._lines = data['lines']
        if 'arcs' in data:
            self._arcs = dict(
                (fname, [tuple(pair) for pair in arcs])
                for fname, arcs in iitems(data['arcs'])
            )
        self._file_tracers = data.get('file_tracers', {})
        self._runs = data.get('runs', [])

        self._validate()

    def read_file(self, filename):
        """Read the coverage data from `filename` into this object."""
        if self._debug and self._debug.should('dataio'):
            self._debug.write("Reading data from %r" % (filename,))
        try:
            with self._open_for_reading(filename) as f:
                self.read_fileobj(f)
        except Exception as exc:
            raise CoverageException(
                "Couldn't read data from '%s': %s: %s" % (
                    filename, exc.__class__.__name__, exc,
                )
            )

    _GO_AWAY = "!coverage.py: This is a private format, don't read it directly!"

    @classmethod
    def _open_for_reading(cls, filename):
        """Open a file appropriately for reading data."""
        return open(filename, "r")

    @classmethod
    def _read_raw_data(cls, file_obj):
        """Read the raw data from a file object."""
        go_away = file_obj.read(len(cls._GO_AWAY))
        if go_away != cls._GO_AWAY:
            raise CoverageException("Doesn't seem to be a coverage.py data file")
        return json.load(file_obj)

    @classmethod
    def _read_raw_data_file(cls, filename):
        """Read the raw data from a file, for debugging."""
        with cls._open_for_reading(filename) as f:
            return cls._read_raw_data(f)

    ##
    ## Writing data
    ##

    def add_lines(self, line_data):
        """Add measured line data.

        `line_data` is a dictionary mapping file names to dictionaries::

            { filename: { lineno: None, ... }, ...}

        """
        if self._debug and self._debug.should('dataop'):
            self._debug.write("Adding lines: %d files, %d lines total" % (
                len(line_data), sum(len(lines) for lines in line_data.values())
            ))
        if self._has_arcs():
            raise CoverageException("Can't add lines to existing arc data")

        if self._lines is None:
            self._lines = {}
        for filename, linenos in iitems(line_data):
            if filename in self._lines:
                new_linenos = set(self._lines[filename])
                new_linenos.update(linenos)
                linenos = new_linenos
            self._lines[filename] = list(linenos)

        self._validate()

    def add_arcs(self, arc_data):
        """Add measured arc data.

        `arc_data` is a dictionary mapping file names to dictionaries::

            { filename: { (l1,l2): None, ... }, ...}

        """
        if self._debug and self._debug.should('dataop'):
            self._debug.write("Adding arcs: %d files, %d arcs total" % (
                len(arc_data), sum(len(arcs) for arcs in arc_data.values())
            ))
        if self._has_lines():
            raise CoverageException("Can't add arcs to existing line data")

        if self._arcs is None:
            self._arcs = {}
        for filename, arcs in iitems(arc_data):
            if filename in self._arcs:
                new_arcs = set(self._arcs[filename])
                new_arcs.update(arcs)
                arcs = new_arcs
            self._arcs[filename] = list(arcs)

        self._validate()

    def add_file_tracers(self, file_tracers):
        """Add per-file plugin information.

        `file_tracers` is { filename: plugin_name, ... }

        """
        if self._debug and self._debug.should('dataop'):
            self._debug.write("Adding file tracers: %d files" % (len(file_tracers),))

        existing_files = self._arcs or self._lines or {}
        for filename, plugin_name in iitems(file_tracers):
            if filename not in existing_files:
                raise CoverageException(
                    "Can't add file tracer data for unmeasured file '%s'" % (filename,)
                )
            existing_plugin = self._file_tracers.get(filename)
            if existing_plugin is not None and plugin_name != existing_plugin:
                raise CoverageException(
                    "Conflicting file tracer name for '%s': %r vs %r" % (
                        filename, existing_plugin, plugin_name,
                    )
                )
            self._file_tracers[filename] = plugin_name

        self._validate()

    def add_run_info(self, **kwargs):
        """Add information about the run.

        Keywords are arbitrary, and are stored in the run dictionary. Values
        must be JSON serializable.  You may use this function more than once,
        but repeated keywords overwrite each other.

        """
        if self._debug and self._debug.should('dataop'):
            self._debug.write("Adding run info: %r" % (kwargs,))
        if not self._runs:
            self._runs = [{}]
        self._runs[0].update(kwargs)
        self._validate()

    def touch_file(self, filename):
        """Ensure that `filename` appears in the data, empty if needed."""
        if self._debug and self._debug.should('dataop'):
            self._debug.write("Touching %r" % (filename,))
        if not self._has_arcs() and not self._has_lines():
            raise CoverageException("Can't touch files in an empty CoverageData")

        if self._has_arcs():
            where = self._arcs
        else:
            where = self._lines
        where.setdefault(filename, [])

        self._validate()

    def write_fileobj(self, file_obj):
        """Write the coverage data to `file_obj`."""

        # Create the file data.
        file_data = {}

        if self._has_arcs():
            file_data['arcs'] = self._arcs

        if self._has_lines():
            file_data['lines'] = self._lines

        if self._file_tracers:
            file_data['file_tracers'] = self._file_tracers

        if self._runs:
            file_data['runs'] = self._runs

        # Write the data to the file.
        file_obj.write(self._GO_AWAY)
        json.dump(file_data, file_obj, separators=(',', ':'))

    def write_file(self, filename):
        """Write the coverage data to `filename`."""
        if self._debug and self._debug.should('dataio'):
            self._debug.write("Writing data to %r" % (filename,))
        with open(filename, 'w') as fdata:
            self.write_fileobj(fdata)

    def erase(self):
        """Erase the data in this object."""
        self._lines = None
        self._arcs = None
        self._file_tracers = {}
        self._runs = []
        self._validate()

    def update(self, other_data, aliases=None):
        """Update this data with data from another `CoverageData`.

        If `aliases` is provided, it's a `PathAliases` object that is used to
        re-map paths to match the local machine's.

        """
        if self._has_lines() and other_data._has_arcs():
            raise CoverageException("Can't combine arc data with line data")
        if self._has_arcs() and other_data._has_lines():
            raise CoverageException("Can't combine line data with arc data")

        aliases = aliases or PathAliases()

        # _file_tracers: only have a string, so they have to agree.
        # Have to do these first, so that our examination of self._arcs and
        # self._lines won't be confused by data updated from other_data.
        for filename in other_data.measured_files():
            other_plugin = other_data.file_tracer(filename)
            filename = aliases.map(filename)
            this_plugin = self.file_tracer(filename)
            if this_plugin is None:
                if other_plugin:
                    self._file_tracers[filename] = other_plugin
            elif this_plugin != other_plugin:
                raise CoverageException(
                    "Conflicting file tracer name for '%s': %r vs %r" % (
                        filename, this_plugin, other_plugin,
                    )
                )

        # _runs: add the new runs to these runs.
        self._runs.extend(other_data._runs)

        # _lines: merge dicts.
        if other_data._has_lines():
            if self._lines is None:
                self._lines = {}
            for filename, file_lines in iitems(other_data._lines):
                filename = aliases.map(filename)
                if filename in self._lines:
                    lines = set(self._lines[filename])
                    lines.update(file_lines)
                    file_lines = list(lines)
                self._lines[filename] = file_lines

        # _arcs: merge dicts.
        if other_data._has_arcs():
            if self._arcs is None:
                self._arcs = {}
            for filename, file_arcs in iitems(other_data._arcs):
                filename = aliases.map(filename)
                if filename in self._arcs:
                    arcs = set(self._arcs[filename])
                    arcs.update(file_arcs)
                    file_arcs = list(arcs)
                self._arcs[filename] = file_arcs

        self._validate()

    ##
    ## Miscellaneous
    ##

    def _validate(self):
        """If we are in paranoid mode, validate that everything is right."""
        if env.TESTING:
            self._validate_invariants()

    def _validate_invariants(self):
        """Validate internal invariants."""
        # Only one of _lines or _arcs should exist.
        assert not(self._has_lines() and self._has_arcs()), (
            "Shouldn't have both _lines and _arcs"
        )

        # _lines should be a dict of lists of ints.
        if self._has_lines():
            for fname, lines in iitems(self._lines):
                assert isinstance(fname, string_class), "Key in _lines shouldn't be %r" % (fname,)
                assert all(isinstance(x, int) for x in lines), (
                    "_lines[%r] shouldn't be %r" % (fname, lines)
                )

        # _arcs should be a dict of lists of pairs of ints.
        if self._has_arcs():
            for fname, arcs in iitems(self._arcs):
                assert isinstance(fname, string_class), "Key in _arcs shouldn't be %r" % (fname,)
                assert all(isinstance(x, int) and isinstance(y, int) for x, y in arcs), (
                    "_arcs[%r] shouldn't be %r" % (fname, arcs)
                )

        # _file_tracers should have only non-empty strings as values.
        for fname, plugin in iitems(self._file_tracers):
            assert isinstance(fname, string_class), (
                "Key in _file_tracers shouldn't be %r" % (fname,)
            )
            assert plugin and isinstance(plugin, string_class), (
                "_file_tracers[%r] shoudn't be %r" % (fname, plugin)
            )

        # _runs should be a list of dicts.
        for val in self._runs:
            assert isinstance(val, dict)
            for key in val:
                assert isinstance(key, string_class), "Key in _runs shouldn't be %r" % (key,)

    def add_to_hash(self, filename, hasher):
        """Contribute `filename`'s data to the `hasher`.

        `hasher` is a `coverage.misc.Hasher` instance to be updated with
        the file's data.  It should only get the results data, not the run
        data.

        """
        if self._has_arcs():
            hasher.update(sorted(self.arcs(filename) or []))
        else:
            hasher.update(sorted(self.lines(filename) or []))
        hasher.update(self.file_tracer(filename))

    ##
    ## Internal
    ##

    def _has_lines(self):
        """Do we have data in self._lines?"""
        return self._lines is not None

    def _has_arcs(self):
        """Do we have data in self._arcs?"""
        return self._arcs is not None


class CoverageDataFiles(object):
    """Manage the use of coverage data files."""

    def __init__(self, basename=None, warn=None, debug=None):
        """Create a CoverageDataFiles to manage data files.

        `warn` is the warning function to use.

        `basename` is the name of the file to use for storing data.

        `debug` is a `DebugControl` object for writing debug messages.

        """
        self.warn = warn
        self.debug = debug

        # Construct the file name that will be used for data storage.
        self.filename = os.path.abspath(basename or ".coverage")

    def erase(self, parallel=False):
        """Erase the data from the file storage.

        If `parallel` is true, then also deletes data files created from the
        basename by parallel-mode.

        """
        if self.debug and self.debug.should('dataio'):
            self.debug.write("Erasing data file %r" % (self.filename,))
        file_be_gone(self.filename)
        if parallel:
            data_dir, local = os.path.split(self.filename)
            localdot = local + '.*'
            pattern = os.path.join(os.path.abspath(data_dir), localdot)
            for filename in glob.glob(pattern):
                if self.debug and self.debug.should('dataio'):
                    self.debug.write("Erasing parallel data file %r" % (filename,))
                file_be_gone(filename)

    def read(self, data):
        """Read the coverage data."""
        if os.path.exists(self.filename):
            data.read_file(self.filename)

    def write(self, data, suffix=None):
        """Write the collected coverage data to a file.

        `suffix` is a suffix to append to the base file name. This can be used
        for multiple or parallel execution, so that many coverage data files
        can exist simultaneously.  A dot will be used to join the base name and
        the suffix.

        """
        filename = self.filename
        if suffix is True:
            # If data_suffix was a simple true value, then make a suffix with
            # plenty of distinguishing information.  We do this here in
            # `save()` at the last minute so that the pid will be correct even
            # if the process forks.
            extra = ""
            if _TEST_NAME_FILE:                             # pragma: debugging
                with open(_TEST_NAME_FILE) as f:
                    test_name = f.read()
                extra = "." + test_name
            dice = random.Random(os.urandom(8)).randint(0, 999999)
            suffix = "%s%s.%s.%06d" % (socket.gethostname(), extra, os.getpid(), dice)

        if suffix:
            filename += "." + suffix
        data.write_file(filename)

    def combine_parallel_data(self, data, aliases=None, data_paths=None, strict=False):
        """Combine a number of data files together.

        Treat `self.filename` as a file prefix, and combine the data from all
        of the data files starting with that prefix plus a dot.

        If `aliases` is provided, it's a `PathAliases` object that is used to
        re-map paths to match the local machine's.

        If `data_paths` is provided, it is a list of directories or files to
        combine.  Directories are searched for files that start with
        `self.filename` plus dot as a prefix, and those files are combined.

        If `data_paths` is not provided, then the directory portion of
        `self.filename` is used as the directory to search for data files.

        Every data file found and combined is then deleted from disk. If a file
        cannot be read, a warning will be issued, and the file will not be
        deleted.

        If `strict` is true, and no files are found to combine, an error is
        raised.

        """
        # Because of the os.path.abspath in the constructor, data_dir will
        # never be an empty string.
        data_dir, local = os.path.split(self.filename)
        localdot = local + '.*'

        data_paths = data_paths or [data_dir]
        files_to_combine = []
        for p in data_paths:
            if os.path.isfile(p):
                files_to_combine.append(os.path.abspath(p))
            elif os.path.isdir(p):
                pattern = os.path.join(os.path.abspath(p), localdot)
                files_to_combine.extend(glob.glob(pattern))
            else:
                raise CoverageException("Couldn't combine from non-existent path '%s'" % (p,))

        if strict and not files_to_combine:
            raise CoverageException("No data to combine")

        for f in files_to_combine:
            new_data = CoverageData(debug=self.debug)
            try:
                new_data.read_file(f)
            except CoverageException as exc:
                if self.warn:
                    # The CoverageException has the file name in it, so just
                    # use the message as the warning.
                    self.warn(str(exc))
            else:
                data.update(new_data, aliases=aliases)
                if self.debug and self.debug.should('dataio'):
                    self.debug.write("Deleting combined data file %r" % (f,))
                file_be_gone(f)


def canonicalize_json_data(data):
    """Canonicalize our JSON data so it can be compared."""
    for fname, lines in iitems(data.get('lines', {})):
        data['lines'][fname] = sorted(lines)
    for fname, arcs in iitems(data.get('arcs', {})):
        data['arcs'][fname] = sorted(arcs)


def pretty_data(data):
    """Format data as JSON, but as nicely as possible.

    Returns a string.

    """
    # Start with a basic JSON dump.
    out = json.dumps(data, indent=4, sort_keys=True)
    # But pairs of numbers shouldn't be split across lines...
    out = re.sub(r"\[\s+(-?\d+),\s+(-?\d+)\s+]", r"[\1, \2]", out)
    # Trailing spaces mess with tests, get rid of them.
    out = re.sub(r"(?m)\s+$", "", out)
    return out


def debug_main(args):
    """Dump the raw data from data files.

    Run this as::

        $ python -m coverage.data [FILE]

    """
    parser = optparse.OptionParser()
    parser.add_option(
        "-c", "--canonical", action="store_true",
        help="Sort data into a canonical order",
    )
    options, args = parser.parse_args(args)

    for filename in (args or [".coverage"]):
        print("--- {0} ------------------------------".format(filename))
        data = CoverageData._read_raw_data_file(filename)
        if options.canonical:
            canonicalize_json_data(data)
        print(pretty_data(data))


if __name__ == '__main__':
    import sys
    debug_main(sys.argv[1:])
