Ejemplo n.º 1
0
    def run(self) -> int:
        coverage = Coverage()
        coverage.start()
        exit_code = main(['-v', 'tests'])
        coverage.stop()

        # Early exit if pytest failed
        if exit_code != 0:
            return 0

        # Generate xml report in StringIO file
        coverage.get_data()
        coverage.config.from_args(
            ignore_errors=None,
            report_omit=None,
            report_include=None,
            xml_output=None,
        )
        data = StringIO()
        reporter = XmlReporter(coverage, coverage.config)
        reporter.report(None, data)
        data.seek(0)

        # Check diff cover compared to origin/master using xml
        score = generate_coverage_report(coverage_xml=[data],
                                         compare_branch='origin/master',
                                         exclude=self.exclude_paths)

        return score
Ejemplo n.º 2
0
    def run_coverage(self, test_name):
        cov = Coverage(source=self.config.source, omit=self.config.omit)
        cov.start()
        self.map_test(test_name)
        cov.stop()

        return cov.get_data()
Ejemplo n.º 3
0
def read_coverage_data():
    """
    :rtype: CoverageData or None
    """
    print('Using coverage data from .coverage file')
    # noinspection PyPackageRequirements,PyUnresolvedReferences
    from coverage import Coverage
    cov = Coverage('.coverage')
    cov.load()
    return cov.get_data()
Ejemplo n.º 4
0
class AutotestConfig(AppConfig):
    name = 'autotest'

    def __init__(self, *args, **kwargs):
        super(AutotestConfig, self).__init__(*args, **kwargs)
        self.coverage = None

    def coverage_start(self):
        if coverage and not self.coverage:
            self.coverage = Coverage()
            self.coverage.start()
            return self.coverage

    def coverage_report(self):
        if coverage and self.coverage:
            self.coverage.stop()
            coverage.stop()
            self.coverage.get_data().update(coverage.get_data())
            self.coverage.html_report()
Ejemplo n.º 5
0
class AutotestConfig(AppConfig):
    name = 'autotest'

    def __init__(self, *args, **kwargs):
        super(AutotestConfig, self).__init__(*args, **kwargs)
        self.coverage = None

    def coverage_start(self):
        if coverage and not self.coverage:
            self.coverage = Coverage()
            self.coverage.start()
            return self.coverage

    def coverage_report(self):
        if coverage and self.coverage:
            self.coverage.stop()
            coverage.stop()
            self.coverage.get_data().update(coverage.get_data())
            self.coverage.html_report()
Ejemplo n.º 6
0
def read_coverage_data():
    """
    :rtype: CoverageData or None
    """
    try:
        # noinspection PyPackageRequirements,PyUnresolvedReferences
        from coverage import Coverage
    except ImportError as e:
        raise ImportError('The --use-coverage feature requires the coverage library. Run "pip install coverage"') from e
    cov = Coverage('.coverage')
    cov.load()
    return cov.get_data()
Ejemplo n.º 7
0
def read_coverage_data():
    """
    :rtype: CoverageData or None
    """
    try:
        # noinspection PyPackageRequirements,PyUnresolvedReferences
        from coverage import Coverage
    except ImportError as e:
        raise ImportError('The --use-coverage feature requires the coverage library. Run "pip install --force-reinstall mutmut[coverage]"') from e
    cov = Coverage('.coverage')
    cov.load()
    data = cov.get_data()
    return {filepath: data.lines(filepath) for filepath in data.measured_files()}
Ejemplo n.º 8
0
def coverage_read(root):
    coverage = Coverage(".coverage")  # use pathlib
    coverage.load()
    data = coverage.get_data()
    filepaths = data.measured_files()
    out = dict()
    root = root.resolve()
    for filepath in filepaths:
        key = str(Path(filepath).relative_to(root))
        value = set(data.lines(filepath))
        print(key)
        out[key] = value
    return out
Ejemplo n.º 9
0
    def run(self) -> int:
        coverage = Coverage()
        coverage.start()
        exit_code = main(['-v', 'tests'])
        coverage.stop()

        # Set score to zero if exit code was non-zero
        if exit_code != 0:
            return 0

        # Generate xml report in StringIO file
        coverage.get_data()
        coverage.config.from_args(
            ignore_errors=None,
            report_omit=None,
            report_include=None,
            xml_output=None,
        )
        data = StringIO()
        reporter = XmlReporter(coverage, coverage.config)
        reporter.report(None, data)
        data.seek(0)

        return round(coverage.report(show_missing=True))
Ejemplo n.º 10
0
def test_does_not_trace_files_outside_inclusion(tmpdir, branch, timid):
    @given(st.booleans())
    def test(a):
        rnd()

    cov = Coverage(
        config_file=False, data_file=str(tmpdir.join('.coverage')),
        branch=branch, timid=timid, include=[__file__],
    )
    cov._warn = escalate_warning
    cov.start()
    test()
    cov.stop()

    data = cov.get_data()
    assert len(list(data.measured_files())) == 1
Ejemplo n.º 11
0
def test_does_not_trace_files_outside_inclusion(tmpdir, branch, timid):
    @given(st.booleans())
    def test(a):
        rnd()

    cov = Coverage(
        config_file=False, data_file=str(tmpdir.join('.coverage')),
        branch=branch, timid=timid, include=[__file__],
    )
    cov._warn = escalate_warning
    cov.start()
    test()
    cov.stop()

    data = cov.get_data()
    assert len(list(data.measured_files())) == 1
Ejemplo n.º 12
0
def test_achieves_full_coverage(tmpdir, branch, timid):
    @given(st.booleans(), st.booleans(), st.booleans())
    def test(a, b, c):
        some_function_to_test(a, b, c)

    cov = Coverage(
        config_file=False, data_file=str(tmpdir.join('.coverage')),
        branch=branch, timid=timid,
    )
    cov._warn = escalate_warning
    cov.start()
    test()
    cov.stop()

    data = cov.get_data()
    lines = data.lines(__file__)
    for i in hrange(LINE_START + 1, LINE_END + 1):
        assert i in lines
Ejemplo n.º 13
0
def test_achieves_full_coverage(tmpdir, branch, timid):
    @given(st.booleans(), st.booleans(), st.booleans())
    def test(a, b, c):
        some_function_to_test(a, b, c)

    cov = Coverage(
        config_file=False, data_file=str(tmpdir.join('.coverage')),
        branch=branch, timid=timid,
    )
    cov._warn = escalate_warning
    cov.start()
    test()
    cov.stop()

    data = cov.get_data()
    lines = data.lines(__file__)
    for i in hrange(LINE_START + 1, LINE_END + 1):
        assert i in lines
Ejemplo n.º 14
0
def test_coverage_includes_unexecuted_files(testdir, branch, timid):
    # Setup two files under test in a Python package.
    # One will be imported explicitly (foo), one will not (bar)
    testdir.syspathinsert()
    testdir.tmpdir.ensure('__init__.py')

    testdir.tmpdir.ensure('foo.py').write('''
def foo(x):
    return x
''')

    testdir.tmpdir.ensure('bar.py').write('''
def bar(x):
    return x
''')

    # Setup a function to exercise the functionality in `foo` only
    @given(st.booleans())
    def test(a):
        package = testdir.tmpdir.pyimport()
        foo = importlib.import_module('foo', package.__name__)
        foo.foo(a)

    # Exercise test function, restricting coverage to just our custom package
    cov = Coverage(
        config_file=False, data_file=str(testdir.tmpdir.join('.coverage')),
        branch=branch, timid=timid,
        source=[str(testdir.tmpdir)],
    )
    cov._warn = escalate_warning
    cov.start()
    test()
    cov.stop()

    # Verify
    data = cov.get_data()
    filenames = {os.path.split(f)[1] for f in data.measured_files()}
    assert filenames == {'__init__.py', 'bar.py', 'foo.py'}
Ejemplo n.º 15
0
test_counter = 0


probability = float(sys.argv[1])/100.0
pathname = os.path.dirname(sys.argv[0])
statement_stats_dict = {} # maps a line number to a list (# successful runs where statement ran, # failed runs where statement ran)

for i, arg1 in enumerate(args1):
    result = 0.0
    abserr = 0.0
    cov = Coverage()
    cov.start()
    bad_outcome = gsl_deriv_central(F, arg1, 1e-8, result, abserr)
    cov.stop()
    cov.save()
    for line_number in cov.get_data().lines(os.path.abspath(pathname)+ "/" + sys.argv[0]):
        if line_number > 301:
            continue
        if line_number not in statement_stats_dict.keys():
            statement_stats_dict[line_number] = [0, 0]
        if bad_outcome == good_dict[i]:
            statement_stats_dict[line_number][0] = statement_stats_dict[line_number][0] + 1
        else:
            statement_stats_dict[line_number][1] = statement_stats_dict[line_number][1] + 1
    bad_dict[test_counter] = bad_outcome
    test_counter += 1

print(statement_stats_dict)
exit()

diff_dict = {index : 0.0 if bad_dict[index] == good_dict[index] else 1.0 for index in bad_dict }
Ejemplo n.º 16
0
def coverage_combine(data_files, output_path, source, process=None):
    """
    Merges multiples reports.

    @param      data_files                  report files (``.coverage``)
    @param      output_path                 output path
    @param      source                      source directory
    @param      process                     function which processes the coverage report
    @return                                 coverage report

    The function *process* should have the signature:

    ::

        def process(content):
            # ...
            return content

    On :epkg:`Windows`, file name have to have the right case.
    If not, coverage reports an empty coverage and raises an exception.
    """
    def raise_exc(exc, content, ex, ex2, outfile, destcov, source, dests,
                  inter, cov, infos):  # pragma: no cover
        def shorten(t):
            if len(t) > 2000:
                return t[:2000] + "\n..."
            else:
                return t

        if len(content) > 2000:
            content = content[:2000] + '\n...'
        ex = "\n-\n".join(shorten(_) for _ in ex)
        ex2 = "\n-\n".join(shorten(_) for _ in ex2)
        rows = [
            '-----------------', "destcov='{0}'".format(destcov),
            "outfile='{0}'".format(outfile), "source='{0}'".format(source),
            "cov.source={0}".format(get_source(cov)),
            "dests='{0}'".format(';'.join(dests)), "inter={0}".format(inter)
        ]
        for ii, info in enumerate(infos):
            rows.append('----------------- {}/{}'.format(ii, len(infos)))
            for k, v in sorted(info.items()):
                rows.append("{}='{}'".format(k, v))
        rows.append('-----------------')
        if cov is not None and _attr_(cov, '_data', 'data')._lines is not None:
            rows.append("##### LINES")
            end = min(5, len(_attr_(cov, '_data', 'data')._lines))
            for k, v in list(
                    sorted(_attr_(cov, '_data', 'data')._lines.items()))[:end]:
                rows.append('   {0}:{1}'.format(k, v))
            rows.append("----- RUNS")
            end = min(5, len(_attr_(cov, '_data', 'data')._runs))
            for k in _attr_(cov, '_data', 'data')._runs[:end]:
                rows.append('   {0}'.format(k))
            rows.append("----- END")

        mes = "{5}. In '{0}'.\n{1}\n{2}\n---AFTER---\n{3}\n---BEGIN---\n{4}"
        raise RuntimeError(
            mes.format(output_path, "\n".join(rows), content, ex, ex2, exc,
                       cov)) from exc

    # We copy the origin coverage if the report is produced
    # in a folder part of the merge.
    destcov = os.path.join(output_path, '.coverage')
    if os.path.exists(destcov):
        destcov2 = destcov + '_old'
        shutil.copy(destcov, destcov2)

    # Starts merging coverage.
    from coverage import Coverage
    cov = Coverage(data_file=destcov, source=[source])
    cov._init()
    cov.get_data()
    if get_source(cov) is None or len(get_source(cov)) == 0:
        raise_exc(
            FileNotFoundError("Probably unable to find '{0}'".format(source)),
            "", [], [], "", destcov, source, [], [], cov, [])

    inter = []

    def find_longest_common_root(names, begin):
        counts = {}
        for name in names:
            spl = name.split(begin)
            for i in range(1, len(spl) + 1):
                if spl[i - 1] == 'src':
                    break
                sub = begin.join(spl[:i])
                if sub in counts:
                    counts[sub] += 1
                else:
                    counts[sub] = 1
        item = max((v, k) for k, v in counts.items())
        return item[1]

    def copy_replace(source, dest, root_source, keep_infos):
        shutil.copy(source, dest)

        co = Counter(root_source)
        slash = co.get('/', 0) >= co.get('\\', 0)
        if slash:
            begin = "/"
            root_source_dup = root_source.replace('\\', '/').replace('//', '/')
        else:
            begin = "\\"
            root_source_dup = root_source.replace("\\", "\\\\")

        keep_infos["slash"] = slash
        keep_infos["begin"] = begin
        keep_infos["root_source_dup"] = root_source_dup
        keep_infos["root_source"] = root_source
        keep_infos["source"] = source
        keep_infos["dest"] = dest

        conn = sqlite3.connect(dest)
        sql = []
        names = []
        for row in conn.execute("select * from file"):
            names.append(row[1])
            name = row[1].replace('/', begin)
            if not name.startswith(root_source):
                name = root_source + begin + name
            s = "UPDATE file SET path='{}' WHERE id={};".format(name, row[0])
            sql.append(s)

        keep_infos['root_common'] = find_longest_common_root(names, begin)

        c = conn.cursor()
        for s in sql:
            c.execute(s)
        conn.commit()
        conn.close()

    # We modify the root in every coverage file.
    dests = [
        os.path.join(output_path, '.coverage{0}'.format(i))
        for i in range(len(data_files))
    ]
    infos = []
    for fi, de in zip(data_files, dests):
        keep_infos = {}
        copy_replace(fi, de, source, keep_infos)
        infos.append(keep_infos)
        shutil.copy(de, de + "~")

    # Keeping information (for exception).
    ex = []
    for d in dests:
        with open(d, "rb") as f:
            ex.append(f.read())
    ex2 = []
    for d in data_files:
        with open(d, "rb") as f:
            ex2.append(f.read())

    # We replace destcov by destcov2 if found in dests.
    if destcov in dests:
        ind = dests.index(destcov)
        dests[ind] = destcov2

    # Let's combine.
    cov.combine(dests)  # dest
    cov.save()
    report = True

    try:
        from coverage.exceptions import CoverageException
    except ImportError:
        # older version of coverage
        from coverage.misc import CoverageException
    try:
        from coverage.exceptions import NoSource
    except ImportError:
        # older version of coverage
        from coverage.misc import NoSource
    try:
        cov.html_report(directory=output_path, ignore_errors=True)
    except NoSource as e:
        raise_exc(e, "", ex, ex2, "", destcov, source, dests, inter, cov,
                  infos)
    except CoverageException as e:
        if "No data to report" in str(e):
            # issue with path
            report = False
        else:
            msg = pprint.pformat(infos)
            raise RuntimeError(  # pragma: no cover
                "Unable to process report in '{0}'.\n----\n{1}".format(
                    output_path, msg)) from e

    if report:
        outfile = os.path.join(output_path, "coverage_report.xml")
        cov.xml_report(outfile=outfile)
        cov.save()

        # Verifications
        with open(outfile, "r", encoding="utf-8") as f:
            content = f.read()
        if len(content) == 0:
            raise RuntimeError("No report was generated.")

    return cov
Ejemplo n.º 17
0
class CoverageScript(object):
    """The command-line interface to coverage.py."""
    def __init__(self):
        self.global_option = False
        self.coverage = None

    def command_line(self, argv):
        """The bulk of the command line interface to coverage.py.

        `argv` is the argument list to process.

        Returns 0 if all is well, 1 if something went wrong.

        """
        # Collect the command-line options.
        if not argv:
            show_help(topic='minimum_help')
            return OK

        # The command syntax we parse depends on the first argument.  Global
        # switch syntax always starts with an option.
        self.global_option = argv[0].startswith('-')
        if self.global_option:
            parser = GlobalOptionParser()
        else:
            parser = CMDS.get(argv[0])
            if not parser:
                show_help("Unknown command: '%s'" % argv[0])
                return ERR
            argv = argv[1:]

        ok, options, args = parser.parse_args_ok(argv)
        if not ok:
            return ERR

        # Handle help and version.
        if self.do_help(options, args, parser):
            return OK

        # Listify the list options.
        source = unshell_list(options.source)
        omit = unshell_list(options.omit)
        include = unshell_list(options.include)
        debug = unshell_list(options.debug)
        contexts = unshell_list(options.contexts)

        # Do something.
        self.coverage = Coverage(
            data_suffix=options.parallel_mode,
            cover_pylib=options.pylib,
            timid=options.timid,
            branch=options.branch,
            config_file=options.rcfile,
            source=source,
            omit=omit,
            include=include,
            debug=debug,
            concurrency=options.concurrency,
            check_preimported=True,
            context=options.context,
        )

        if options.action == "debug":
            return self.do_debug(args)

        elif options.action == "erase":
            self.coverage.erase()
            return OK

        elif options.action == "run":
            return self.do_run(options, args)

        elif options.action == "combine":
            if options.append:
                self.coverage.load()
            data_dirs = args or None
            self.coverage.combine(data_dirs, strict=True)
            self.coverage.save()
            return OK

        # Remaining actions are reporting, with some common options.
        report_args = dict(
            morfs=unglob_args(args),
            ignore_errors=options.ignore_errors,
            omit=omit,
            include=include,
            contexts=contexts,
        )

        # We need to be able to import from the current directory, because
        # plugins may try to, for example, to read Django settings.
        sys.path.insert(0, '')

        self.coverage.load()

        total = None
        if options.action == "report":
            total = self.coverage.report(show_missing=options.show_missing,
                                         skip_covered=options.skip_covered,
                                         **report_args)
        elif options.action == "annotate":
            self.coverage.annotate(directory=options.directory, **report_args)
        elif options.action == "html":
            total = self.coverage.html_report(
                directory=options.directory,
                title=options.title,
                skip_covered=options.skip_covered,
                show_contexts=options.show_contexts,
                **report_args)
        elif options.action == "xml":
            outfile = options.outfile
            total = self.coverage.xml_report(outfile=outfile, **report_args)

        if total is not None:
            # Apply the command line fail-under options, and then use the config
            # value, so we can get fail_under from the config file.
            if options.fail_under is not None:
                self.coverage.set_option("report:fail_under",
                                         options.fail_under)

            fail_under = self.coverage.get_option("report:fail_under")
            precision = self.coverage.get_option("report:precision")
            if should_fail_under(total, fail_under, precision):
                return FAIL_UNDER

        return OK

    def do_help(self, options, args, parser):
        """Deal with help requests.

        Return True if it handled the request, False if not.

        """
        # Handle help.
        if options.help:
            if self.global_option:
                show_help(topic='help')
            else:
                show_help(parser=parser)
            return True

        if options.action == "help":
            if args:
                for a in args:
                    parser = CMDS.get(a)
                    if parser:
                        show_help(parser=parser)
                    else:
                        show_help(topic=a)
            else:
                show_help(topic='help')
            return True

        # Handle version.
        if options.version:
            show_help(topic='version')
            return True

        return False

    def do_run(self, options, args):
        """Implementation of 'coverage run'."""

        if not args:
            if options.module:
                # Specified -m with nothing else.
                show_help("No module specified for -m")
                return ERR
            command_line = self.coverage.get_option("run:command_line")
            if command_line is not None:
                args = shlex.split(command_line)
                if args and args[0] == "-m":
                    options.module = True
                    args = args[1:]
        if not args:
            show_help("Nothing to do.")
            return ERR

        if options.append and self.coverage.get_option("run:parallel"):
            show_help("Can't append to data files in parallel mode.")
            return ERR

        if options.concurrency == "multiprocessing":
            # Can't set other run-affecting command line options with
            # multiprocessing.
            for opt_name in [
                    'branch', 'include', 'omit', 'pylib', 'source', 'timid'
            ]:
                # As it happens, all of these options have no default, meaning
                # they will be None if they have not been specified.
                if getattr(options, opt_name) is not None:
                    show_help(
                        "Options affecting multiprocessing must only be specified "
                        "in a configuration file.\n"
                        "Remove --{} from the command line.".format(opt_name))
                    return ERR

        runner = PyRunner(args, as_module=bool(options.module))
        runner.prepare()

        if options.append:
            self.coverage.load()

        # Run the script.
        self.coverage.start()
        code_ran = True
        try:
            runner.run()
        except NoSource:
            code_ran = False
            raise
        finally:
            self.coverage.stop()
            if code_ran:
                self.coverage.save()

        return OK

    def do_debug(self, args):
        """Implementation of 'coverage debug'."""

        if not args:
            show_help("What information would you like: config, data, sys?")
            return ERR

        for info in args:
            if info == 'sys':
                sys_info = self.coverage.sys_info()
                print(info_header("sys"))
                for line in info_formatter(sys_info):
                    print(" %s" % line)
            elif info == 'data':
                self.coverage.load()
                data = self.coverage.get_data()
                print(info_header("data"))
                print("path: %s" % self.coverage.get_data().data_filename())
                if data:
                    print("has_arcs: %r" % data.has_arcs())
                    summary = line_counts(data, fullpath=True)
                    filenames = sorted(summary.keys())
                    print("\n%d files:" % len(filenames))
                    for f in filenames:
                        line = "%s: %d lines" % (f, summary[f])
                        plugin = data.file_tracer(f)
                        if plugin:
                            line += " [%s]" % plugin
                        print(line)
                else:
                    print("No data collected")
            elif info == 'config':
                print(info_header("config"))
                config_info = self.coverage.config.__dict__.items()
                for line in info_formatter(config_info):
                    print(" %s" % line)
            else:
                show_help("Don't know what you mean by %r" % info)
                return ERR

        return OK
Ejemplo n.º 18
0
def coverage_combine(data_files, output_path, source, process=None, absolute_path=True):
    """
    Merges multiples reports.

    @param      data_files      report files (``.coverage``)
    @param      output_path     output path
    @param      source          source directory
    @param      process         function which processes the coverage report
    @param      absolute_path   relocate sources with absolute paths
    @return                     coverage report

    The function *process* should have the signature:

    ::

        def process(content):
            # ...
            return content
    """
    def raise_exc(exc, content, ex, ex2, outfile, destcov, source, dests, inter, cov):

        from coverage.data import CoverageData

        def shorten(t):
            if len(t) > 2000:
                return t[:2000] + "\n..."
            else:
                return t
        if len(content) > 2000:
            content = content[:2000] + '\n...'
        ex = "\n-\n".join(shorten(_) for _ in ex)
        ex2 = "\n-\n".join(shorten(_) for _ in ex2)
        rows = ["destcov='{0}'".format(destcov),
                "outfile='{0}'".format(outfile),
                "source='{0}'".format(source),
                "cov.source={0}".format(cov.source),
                "dests='{0}'".format(';'.join(dests)),
                "inter={0}".format(inter)]
        if cov is not None and cov.data is not None and cov.data._lines is not None:
            rows.append("----- LINES")
            end = min(5, len(cov.data._lines))
            for k, v in list(sorted(cov.data._lines.items()))[:end]:
                rows.append('   {0}:{1}'.format(k, v))
            rows.append("----- RUNS")
            end = min(5, len(cov.data._runs))
            for k in cov.data._runs[:end]:
                rows.append('   {0}'.format(k))
            rows.append("----- END")
        for d in dests:
            dd = CoverageData()
            dd.read_file(d + "~")
            rows.append("------- LINES - '{0}'".format(d))
            end = min(5, len(dd._lines))
            for k, v in list(sorted(dd._lines.items()))[:end]:
                rows.append('   {0}:{1}'.format(k, v))
            rows.append("------- RUNS - '{0}'".format(d))
            end = min(5, len(dd._runs))
            for k in dd._runs[:end]:
                rows.append('   {0}'.format(k))
            rows.append("------- END")

        mes = "{5}. In '{0}'.\n{1}\n{2}\n---AFTER---\n{3}\n---BEGIN---\n{4}"
        raise RuntimeError(mes.format(output_path, "\n".join(
            rows), content, ex, ex2, exc, cov)) from exc

    # We copy the origin coverage if the report is produced
    # in a folder part of the merge.
    destcov = os.path.join(output_path, '.coverage')
    if os.path.exists(destcov):
        destcov2 = destcov + '_old'
        shutil.copy(destcov, destcov2)

    # Starts merging coverage.
    from coverage import Coverage
    cov = Coverage(data_file=destcov, source=[source])
    # Module coverage may modify the folder,
    # we take the one it considers.
    # On Windows, it has to have the right case.
    # If not, coverage reports an empty coverage and
    # raises an exception.
    cov._init()
    cov.get_data()
    if cov.source is None or len(cov.source) == 0:
        raise_exc(FileNotFoundError("Probably unable to find '{0}'".format(source)),
                  "", [], [], "", destcov, source, [], [], cov)
    source = cov.source[0]

    inter = []
    reg = re.compile(',\\"(.*?[.]py)\\"')

    def copy_replace(source, dest, root_source):
        with open(source, "r") as f:
            content = f.read()
        if process is not None:
            content = process(content)
        cf = reg.findall(content)
        co = Counter([_.split('src')[0] for _ in cf])
        mx = max((v, k) for k, v in co.items())
        root = mx[1].rstrip('\\/')
        if absolute_path:
            if '\\\\' in root:
                s2 = root_source.replace('\\', '\\\\').replace('/', '\\\\')
                s2 += "\\\\"
                root += "\\\\"
            elif '\\' in root:
                s2 = root_source
                s2 += "\\\\"
                root += "\\"
            else:
                s2 = root_source
                s2 += "/"
                root += "/"
        else:
            s2 = ""
            if '\\\\' in root:
                root += "\\\\"
            elif '\\' in root:
                root += "\\"
            else:
                root += "/"
        inter.append((root, root_source, s2))
        content = content.replace(root, s2)
        with open(dest, "w") as f:
            f.write(content)

    # We modify the root in every coverage file.
    dests = [os.path.join(output_path, '.coverage{0}'.format(
        i)) for i in range(len(data_files))]
    for fi, de in zip(data_files, dests):
        copy_replace(fi, de, source)
        shutil.copy(de, de + "~")

    # Keeping information (for exception).
    ex = []
    for d in dests:
        with open(d, "r") as f:
            ex.append(f.read())
    ex2 = []
    for d in data_files:
        with open(d, "r") as f:
            ex2.append(f.read())

    # We replace destcov by destcov2 if found in dests.
    if destcov in dests:
        ind = dests.index(destcov)
        dests[ind] = destcov2

    # Let's combine.
    cov.combine(dests)

    from coverage.misc import NoSource
    try:
        cov.html_report(directory=output_path)
    except NoSource as e:
        raise_exc(e, "", ex, ex2, "", destcov, source, dests, inter, cov)

    outfile = os.path.join(output_path, "coverage_report.xml")
    cov.xml_report(outfile=outfile)
    cov.save()

    # Verifications
    with open(outfile, "r", encoding="utf-8") as f:
        content = f.read()

    if 'line hits="1"' not in content:
        raise_exc(Exception("Coverage is empty"), content, ex,
                  ex2, outfile, destcov, source, dests, inter, cov)

    return cov
Ejemplo n.º 19
0
class CoverageScript(object):
    """The command-line interface to coverage.py."""

    def __init__(self):
        self.global_option = False
        self.coverage = None

    def command_line(self, argv):
        """The bulk of the command line interface to coverage.py.

        `argv` is the argument list to process.

        Returns 0 if all is well, 1 if something went wrong.

        """
        # Collect the command-line options.
        if not argv:
            show_help(topic='minimum_help')
            return OK

        # The command syntax we parse depends on the first argument.  Global
        # switch syntax always starts with an option.
        self.global_option = argv[0].startswith('-')
        if self.global_option:
            parser = GlobalOptionParser()
        else:
            parser = CMDS.get(argv[0])
            if not parser:
                show_help("Unknown command: '%s'" % argv[0])
                return ERR
            argv = argv[1:]

        ok, options, args = parser.parse_args_ok(argv)
        if not ok:
            return ERR

        # Handle help and version.
        if self.do_help(options, args, parser):
            return OK

        # Listify the list options.
        source = unshell_list(options.source)
        omit = unshell_list(options.omit)
        include = unshell_list(options.include)
        debug = unshell_list(options.debug)

        # Do something.
        self.coverage = Coverage(
            data_suffix=options.parallel_mode,
            cover_pylib=options.pylib,
            timid=options.timid,
            branch=options.branch,
            config_file=options.rcfile,
            source=source,
            omit=omit,
            include=include,
            debug=debug,
            concurrency=options.concurrency,
            check_preimported=True,
            context=options.context,
            )

        if options.action == "debug":
            return self.do_debug(args)

        elif options.action == "erase":
            self.coverage.erase()
            return OK

        elif options.action == "run":
            return self.do_run(options, args)

        elif options.action == "combine":
            if options.append:
                self.coverage.load()
            data_dirs = args or None
            self.coverage.combine(data_dirs, strict=True)
            self.coverage.save()
            return OK

        # Remaining actions are reporting, with some common options.
        report_args = dict(
            morfs=unglob_args(args),
            ignore_errors=options.ignore_errors,
            omit=omit,
            include=include,
            )

        # We need to be able to import from the current directory, because
        # plugins may try to, for example, to read Django settings.
        sys.path.insert(0, '')

        self.coverage.load()

        total = None
        if options.action == "report":
            total = self.coverage.report(
                show_missing=options.show_missing,
                skip_covered=options.skip_covered,
                **report_args
                )
        elif options.action == "annotate":
            self.coverage.annotate(directory=options.directory, **report_args)
        elif options.action == "html":
            total = self.coverage.html_report(
                directory=options.directory,
                title=options.title,
                skip_covered=options.skip_covered,
                **report_args
                )
        elif options.action == "xml":
            outfile = options.outfile
            total = self.coverage.xml_report(outfile=outfile, **report_args)

        if total is not None:
            # Apply the command line fail-under options, and then use the config
            # value, so we can get fail_under from the config file.
            if options.fail_under is not None:
                self.coverage.set_option("report:fail_under", options.fail_under)

            fail_under = self.coverage.get_option("report:fail_under")
            precision = self.coverage.get_option("report:precision")
            if should_fail_under(total, fail_under, precision):
                return FAIL_UNDER

        return OK

    def do_help(self, options, args, parser):
        """Deal with help requests.

        Return True if it handled the request, False if not.

        """
        # Handle help.
        if options.help:
            if self.global_option:
                show_help(topic='help')
            else:
                show_help(parser=parser)
            return True

        if options.action == "help":
            if args:
                for a in args:
                    parser = CMDS.get(a)
                    if parser:
                        show_help(parser=parser)
                    else:
                        show_help(topic=a)
            else:
                show_help(topic='help')
            return True

        # Handle version.
        if options.version:
            show_help(topic='version')
            return True

        return False

    def do_run(self, options, args):
        """Implementation of 'coverage run'."""

        if not args:
            if options.module:
                # Specified -m with nothing else.
                show_help("No module specified for -m")
                return ERR
            command_line = self.coverage.get_option("run:command_line")
            if command_line is not None:
                args = shlex.split(command_line)
                if args and args[0] == "-m":
                    options.module = True
                    args = args[1:]
        if not args:
            show_help("Nothing to do.")
            return ERR

        if options.append and self.coverage.get_option("run:parallel"):
            show_help("Can't append to data files in parallel mode.")
            return ERR

        if options.concurrency == "multiprocessing":
            # Can't set other run-affecting command line options with
            # multiprocessing.
            for opt_name in ['branch', 'include', 'omit', 'pylib', 'source', 'timid']:
                # As it happens, all of these options have no default, meaning
                # they will be None if they have not been specified.
                if getattr(options, opt_name) is not None:
                    show_help(
                        "Options affecting multiprocessing must only be specified "
                        "in a configuration file.\n"
                        "Remove --{} from the command line.".format(opt_name)
                    )
                    return ERR

        runner = PyRunner(args, as_module=bool(options.module))
        runner.prepare()

        if options.append:
            self.coverage.load()

        # Run the script.
        self.coverage.start()
        code_ran = True
        try:
            runner.run()
        except NoSource:
            code_ran = False
            raise
        finally:
            self.coverage.stop()
            if code_ran:
                self.coverage.save()

        return OK

    def do_debug(self, args):
        """Implementation of 'coverage debug'."""

        if not args:
            show_help("What information would you like: config, data, sys?")
            return ERR

        for info in args:
            if info == 'sys':
                sys_info = self.coverage.sys_info()
                print(info_header("sys"))
                for line in info_formatter(sys_info):
                    print(" %s" % line)
            elif info == 'data':
                self.coverage.load()
                data = self.coverage.get_data()
                print(info_header("data"))
                print("path: %s" % self.coverage.get_data().data_filename())
                if data:
                    print("has_arcs: %r" % data.has_arcs())
                    summary = line_counts(data, fullpath=True)
                    filenames = sorted(summary.keys())
                    print("\n%d files:" % len(filenames))
                    for f in filenames:
                        line = "%s: %d lines" % (f, summary[f])
                        plugin = data.file_tracer(f)
                        if plugin:
                            line += " [%s]" % plugin
                        print(line)
                else:
                    print("No data collected")
            elif info == 'config':
                print(info_header("config"))
                config_info = self.coverage.config.__dict__.items()
                for line in info_formatter(config_info):
                    print(" %s" % line)
            else:
                show_help("Don't know what you mean by %r" % info)
                return ERR

        return OK