Пример #1
0
def compare_html(expected, actual):
    """Specialized compare function for our HTML files."""
    scrubs = [
        (r'/coverage.readthedocs.io/?[-.\w/]*',
         '/coverage.readthedocs.io/VER'),
        (r'coverage.py v[\d.abc]+', 'coverage.py vVER'),
        (r'created at \d\d\d\d-\d\d-\d\d \d\d:\d\d [-+]\d\d\d\d',
         'created at DATE'),
        (r'created at \d\d\d\d-\d\d-\d\d \d\d:\d\d', 'created at DATE'),
        # Some words are identifiers in one version, keywords in another.
        (r'<span class="(nam|key)">(print|True|False)</span>',
         r'<span class="nam">\2</span>'),
        # Occasionally an absolute path is in the HTML report.
        (filepath_to_regex(TESTS_DIR), 'TESTS_DIR'),
        (filepath_to_regex(flat_rootname(unicode_class(TESTS_DIR))),
         '_TESTS_DIR'),
        # The temp dir the tests make.
        (filepath_to_regex(os.getcwd()), 'TEST_TMPDIR'),
        (filepath_to_regex(flat_rootname(unicode_class(os.getcwd()))),
         '_TEST_TMPDIR'),
        (filepath_to_regex(abs_file(os.getcwd())), 'TEST_TMPDIR'),
        (filepath_to_regex(flat_rootname(unicode_class(abs_file(
            os.getcwd())))), '_TEST_TMPDIR'),
        (r'/private/var/folders/[\w/]{35}/coverage_test/tests_test_html_\w+_\d{8}',
         'TEST_TMPDIR'),
        (r'_private_var_folders_\w{35}_coverage_test_tests_test_html_\w+_\d{8}',
         '_TEST_TMPDIR'),
    ]
    if env.WINDOWS:
        # For file paths...
        scrubs += [(r"\\", "/")]
    compare(expected, actual, file_pattern="*.html", scrubs=scrubs)
Пример #2
0
def compare_html(expected, actual, extra_scrubs=None):
    """Specialized compare function for our HTML files."""
    __tracebackhide__ = True  # pytest, please don't show me this function.
    scrubs = [
        (r'/coverage.readthedocs.io/?[-.\w/]*',
         '/coverage.readthedocs.io/VER'),
        (r'coverage.py v[\d.abc]+', 'coverage.py vVER'),
        (r'created at \d\d\d\d-\d\d-\d\d \d\d:\d\d [-+]\d\d\d\d',
         'created at DATE'),
        (r'created at \d\d\d\d-\d\d-\d\d \d\d:\d\d', 'created at DATE'),
        # Occasionally an absolute path is in the HTML report.
        (filepath_to_regex(TESTS_DIR), 'TESTS_DIR'),
        (filepath_to_regex(flat_rootname(str(TESTS_DIR))), '_TESTS_DIR'),
        # The temp dir the tests make.
        (filepath_to_regex(os.getcwd()), 'TEST_TMPDIR'),
        (filepath_to_regex(flat_rootname(str(os.getcwd()))), '_TEST_TMPDIR'),
        (filepath_to_regex(abs_file(os.getcwd())), 'TEST_TMPDIR'),
        (filepath_to_regex(flat_rootname(str(abs_file(os.getcwd())))),
         '_TEST_TMPDIR'),
        (r'/private/var/[\w/]+/pytest-of-\w+/pytest-\d+/(popen-gw\d+/)?t\d+',
         'TEST_TMPDIR'),
    ]
    if env.WINDOWS:
        # For file paths...
        scrubs += [(r"\\", "/")]
    if extra_scrubs:
        scrubs += extra_scrubs
    compare(expected, actual, file_pattern="*.html", scrubs=scrubs)
Пример #3
0
 def make_data_file():
     data = coverage.CoverageData(".coverage.1")
     data.add_lines(
         {abs_file('ci/girder/g1.py'): dict.fromkeys(range(10))})
     data.add_lines({
         abs_file('ci/girder/plugins/p1.py'):
         dict.fromkeys(range(10))
     })
     data.write()
Пример #4
0
 def test_filepath_contains_absolute_prefix_twice(self):
     # https://bitbucket.org/ned/coveragepy/issue/194
     # Build a path that has two pieces matching the absolute path prefix.
     # Technically, this test doesn't do that on Windows, but drive
     # letters make that impractical to achieve.
     files.set_relative_directory()
     d = abs_file(os.curdir)
     trick = os.path.splitdrive(d)[1].lstrip(os.path.sep)
     rel = os.path.join('sub', trick, 'file1.py')
     self.assertEqual(files.relative_filename(abs_file(rel)), rel)
Пример #5
0
 def test_filepath_contains_absolute_prefix_twice(self):
     # https://bitbucket.org/ned/coveragepy/issue/194
     # Build a path that has two pieces matching the absolute path prefix.
     # Technically, this test doesn't do that on Windows, but drive
     # letters make that impractical to achieve.
     files.set_relative_directory()
     d = abs_file(os.curdir)
     trick = os.path.splitdrive(d)[1].lstrip(os.path.sep)
     rel = os.path.join('sub', trick, 'file1.py')
     self.assertEqual(files.relative_filename(abs_file(rel)), rel)
Пример #6
0
    def test_combine_with_aliases(self):
        self.make_file("d1/x.py", """\
            a = 1
            b = 2
            print(f"{a} {b}")
            """)

        self.make_file("d2/x.py", """\
            # 1
            # 2
            # 3
            c = 4
            d = 5
            print(f"{c} {d}")
            """)

        self.make_file(".coveragerc", """\
            [run]
            source = .
            parallel = True

            [paths]
            source =
                src
                */d1
                */d2
            """)

        out = self.run_command("coverage run " + os.path.normpath("d1/x.py"))
        assert out == '1 2\n'
        out = self.run_command("coverage run " + os.path.normpath("d2/x.py"))
        assert out == '4 5\n'

        self.assert_file_count(".coverage.*", 2)

        self.run_command("coverage combine")
        self.assert_exists(".coverage")

        # After combining, there should be only the .coverage file.
        self.assert_file_count(".coverage.*", 0)

        # Read the coverage data file and see that the two different x.py
        # files have been combined together.
        data = coverage.CoverageData()
        data.read()
        summary = line_counts(data, fullpath=True)
        assert len(summary) == 1
        actual = abs_file(list(summary.keys())[0])
        expected = abs_file('src/x.py')
        assert expected == actual
        assert list(summary.values())[0] == 6
Пример #7
0
 def cached_abs_file(self, filename):
     """A locally cached version of `abs_file`."""
     key = (type(filename), filename)
     try:
         return self.abs_file_cache[key]
     except KeyError:
         return self.abs_file_cache.setdefault(key, abs_file(filename))
Пример #8
0
    def _get_file_reporter(self, morf):
        """Get a FileReporter for a module or filename."""
        plugin = None

        if isinstance(morf, string_class):
            abs_morf = abs_file(morf)
            plugin_name = self.data.plugin_data().get(abs_morf)
            if plugin_name:
                plugin = self.plugins.get(plugin_name)

        if plugin:
            file_reporter = plugin.file_reporter(abs_morf)
            if file_reporter is None:
                raise CoverageException(
                    "Plugin %r did not provide a file reporter for %r." % (
                        plugin._coverage_plugin_name, morf
                    )
                )
        else:
            file_reporter = PythonFileReporter(morf, self)

        # The FileReporter can have a name attribute, but if it doesn't, we'll
        # supply it as the relative path to self.filename.
        if not hasattr(file_reporter, "name"):
            file_reporter.name = files.relative_filename(file_reporter.filename)

        return file_reporter
Пример #9
0
    def _get_file_reporter(self, morf):
        """Get a FileReporter for a module or file name."""
        plugin = None
        file_reporter = "python"

        if isinstance(morf, string_class):
            abs_morf = abs_file(morf)
            plugin_name = self.data.file_tracer(abs_morf)
            if plugin_name:
                plugin = self.plugins.get(plugin_name)

        if plugin:
            file_reporter = plugin.file_reporter(abs_morf)
            if file_reporter is None:
                raise CoverageException(
                    "Plugin %r did not provide a file reporter for %r." % (
                        plugin._coverage_plugin_name, morf
                    )
                )

        if file_reporter == "python":
            # pylint: disable=redefined-variable-type
            file_reporter = PythonFileReporter(morf, self)

        return file_reporter
Пример #10
0
    def _get_file_reporter(self, morf):
        """Get a FileReporter for a module or filename."""
        plugin = None

        if isinstance(morf, string_class):
            abs_morf = abs_file(morf)
            plugin_name = self.data.plugin_data().get(abs_morf)
            if plugin_name:
                plugin = self.plugins.get(plugin_name)

        if plugin:
            file_reporter = plugin.file_reporter(abs_morf)
            if file_reporter is None:
                raise CoverageException(
                    "Plugin %r did not provide a file reporter for %r." % (
                        plugin._coverage_plugin_name, morf
                    )
                )
        else:
            file_reporter = PythonFileReporter(morf, self)

        # The FileReporter can have a name attribute, but if it doesn't, we'll
        # supply it as the relative path to self.filename.
        if not hasattr(file_reporter, "name"):
            file_reporter.name = self.file_locator.relative_filename(
                file_reporter.filename
            )

        return file_reporter
Пример #11
0
 def cached_abs_file(self, filename):
     """A locally cached version of `abs_file`."""
     key = (type(filename), filename)
     try:
         return self.abs_file_cache[key]
     except KeyError:
         return self.abs_file_cache.setdefault(key, abs_file(filename))
Пример #12
0
 def test_extensionless_file_collides_with_extension(self):
     # It used to be that "program" and "program.py" would both be reported
     # to "program.html".  Now they are not.
     # https://github.com/nedbat/coveragepy/issues/69
     self.make_file("program", "import program\n")
     self.make_file("program.py", "a = 1\n")
     self.make_data_file(lines={
         abs_file("program"): [1],
         abs_file("program.py"): [1],
     })
     cov = coverage.Coverage()
     cov.load()
     cov.html_report()
     self.assert_exists("htmlcov/index.html")
     self.assert_exists("htmlcov/program.html")
     self.assert_exists("htmlcov/program_py.html")
Пример #13
0
 def test_dothtml_not_python(self):
     # Run an "HTML" file
     self.make_file("innocuous.html", "a = 3")
     self.make_data_file(lines={abs_file("innocuous.html"): [1]})
     # Before reporting, change it to be an HTML file.
     self.make_file("innocuous.html", "<h1>This isn't python at all!</h1>")
     cov = coverage.Coverage()
     cov.load()
     with pytest.raises(NoDataError, match="No data to report."):
         cov.html_report()
Пример #14
0
 def test_accented_dot_py(self):
     # Make a file with a non-ascii character in the filename.
     self.make_file("h\xe2t.py", "print('accented')")
     self.make_data_file(lines={abs_file("h\xe2t.py"): [1]})
     cov = coverage.Coverage()
     cov.load()
     cov.html_report()
     self.assert_exists("htmlcov/h\xe2t_py.html")
     with open("htmlcov/index.html") as indexf:
         index = indexf.read()
     assert '<a href="h&#226;t_py.html">h&#226;t.py</a>' in index
Пример #15
0
 def test_accented_dot_py(self):
     # Make a file with a non-ascii character in the filename.
     self.make_file("h\xe2t.py", "print('accented')")
     self.make_data_file(lines={abs_file("h\xe2t.py"): [1]})
     cov = coverage.Coverage()
     cov.load()
     cov.xml_report()
     # The XML report is always UTF8-encoded.
     with open("coverage.xml", "rb") as xmlf:
         xml = xmlf.read()
     assert ' filename="h\xe2t.py"'.encode() in xml
     assert ' name="h\xe2t.py"'.encode() in xml
Пример #16
0
 def setUp(self):
     super().setUp()
     self.make_file("forty_two_plus.py", """\
         # I have 42.857% (3/7) coverage!
         a = 1
         b = 2
         if a > 3:
             b = 4
             c = 5
             d = 6
             e = 7
         """)
     self.make_data_file(lines={abs_file("forty_two_plus.py"): [2, 3, 4]})
Пример #17
0
 def test_report_99p9_is_not_ok(self):
     # A file with 99.9% coverage:
     self.make_file("ninety_nine_plus.py",
         "a = 1\n" +
         "b = 2\n" * 2000 +
         "if a > 3:\n" +
         "    c = 4\n"
         )
     self.make_data_file(lines={abs_file("ninety_nine_plus.py"): range(1, 2002)})
     st, out = self.run_command_status("coverage report --fail-under=100")
     assert st == 2
     expected = "Coverage failure: total of 99 is less than fail-under=100"
     assert expected == self.last_line_squeezed(out)
Пример #18
0
    def test_accented_directory(self):
        # Make a file with a non-ascii character in the directory name.
        self.make_file("\xe2/accented.py", "print('accented')")
        self.make_data_file(lines={abs_file("\xe2/accented.py"): [1]})
        report_expected = ("Name            Stmts   Miss  Cover\n" +
                           "-----------------------------------\n" +
                           "\xe2/accented.py       1      0   100%\n" +
                           "-----------------------------------\n" +
                           "TOTAL               1      0   100%\n")

        cov = coverage.Coverage()
        cov.load()
        output = self.get_report(cov, squeeze=False)
        assert output == report_expected
Пример #19
0
    def test_accented_directory(self):
        # Make a file with a non-ascii character in the directory name.
        self.make_file("\xe2/accented.py", "print('accented')")
        self.make_data_file(lines={abs_file("\xe2/accented.py"): [1]})

        # The HTML report uses ascii-encoded HTML entities.
        cov = coverage.Coverage()
        cov.load()
        cov.html_report()
        self.assert_exists("htmlcov/d_5786906b6f0ffeb4_accented_py.html")
        with open("htmlcov/index.html") as indexf:
            index = indexf.read()
        expected = '<a href="d_5786906b6f0ffeb4_accented_py.html">&#226;%saccented.py</a>'
        assert expected % os.sep in index
Пример #20
0
    def try_some_code(self, code, concurrency, the_module, expected_out=None):
        """Run some concurrency testing code and see that it was all covered.

        `code` is the Python code to execute.  `concurrency` is the name of
        the concurrency regime to test it under.  `the_module` is the imported
        module that must be available for this to work at all. `expected_out`
        is the text we expect the code to produce.

        """

        self.make_file("try_it.py", code)

        cmd = "coverage run --concurrency=%s try_it.py" % concurrency
        out = self.run_command(cmd)

        if not the_module:
            # We don't even have the underlying module installed, we expect
            # coverage to alert us to this fact.
            expected_out = (
                "Couldn't trace with concurrency=%s, "
                "the module isn't installed.\n" % concurrency
            )
            self.assertEqual(out, expected_out)
        elif env.C_TRACER or concurrency == "thread":
            # We can fully measure the code if we are using the C tracer, which
            # can support all the concurrency, or if we are using threads.
            if expected_out is None:
                expected_out = "%d\n" % (sum(range(self.LIMIT)))
            self.assertEqual(out, expected_out)

            # Read the coverage file and see that try_it.py has all its lines
            # executed.
            data = coverage.CoverageData()
            data.read_file(".coverage")

            # If the test fails, it's helpful to see this info:
            fname = abs_file("try_it.py")
            linenos = data.lines(fname)
            print("{0}: {1}".format(len(linenos), linenos))
            print_simple_annotation(code, linenos)

            lines = line_count(code)
            self.assertEqual(data.line_counts()['try_it.py'], lines)
        else:
            expected_out = (
                "Can't support concurrency=%s with PyTracer, "
                "only threads are supported\n" % concurrency
            )
            self.assertEqual(out, expected_out)
Пример #21
0
    def test_branch(self):
        cov = coverage.Coverage(branch=True)

        self.make_file("fun1.py", """\
            def fun1(x):
                if x == 1:
                    return

            fun1(3)
            """)

        self.start_import_stop(cov, "fun1")

        data = cov.get_data()
        fun1_lines = data.lines(abs_file("fun1.py"))
        self.assertCountEqual(fun1_lines, [1, 2, 5])
Пример #22
0
    def test_branch(self):
        cov = coverage.Coverage(branch=True)

        self.make_file("fun1.py", """\
            def fun1(x):
                if x == 1:
                    return

            fun1(3)
            """)

        self.start_import_stop(cov, "fun1")

        cov._harvest_data()
        fun1_lines = cov.data.line_data()[abs_file("fun1.py")]
        self.assertEqual(fun1_lines, [1, 2, 5])
Пример #23
0
 def test_report_no_extension(self):
     self.make_file(
         "xxx", """\
         # This is a python file though it doesn't look like it, like a main script.
         a = b = c = d = 0
         a = 3
         b = 4
         if not b:
             c = 6
         d = 7
         print(f"xxx: {a} {b} {c} {d}")
         """)
     self.make_data_file(lines={abs_file("xxx"): [2, 3, 4, 5, 7, 8]})
     cov = coverage.Coverage()
     cov.load()
     report = self.get_report(cov)
     assert self.last_line_squeezed(report) == "TOTAL 7 1 86%"
Пример #24
0
    def try_some_code(self, code, concurrency, the_module, expected_out=None):
        """Run some concurrency testing code and see that it was all covered.

        `code` is the Python code to execute.  `concurrency` is the name of
        the concurrency regime to test it under.  `the_module` is the imported
        module that must be available for this to work at all. `expected_out`
        is the text we expect the code to produce.

        """

        self.make_file("try_it.py", code)

        cmd = "coverage run --concurrency=%s try_it.py" % concurrency
        out = self.run_command(cmd)

        if not the_module:
            # We don't even have the underlying module installed, we expect
            # coverage to alert us to this fact.
            expected_out = ("Couldn't trace with concurrency=%s, "
                            "the module isn't installed.\n" % concurrency)
            self.assertEqual(out, expected_out)
        elif env.C_TRACER or concurrency == "thread":
            # We can fully measure the code if we are using the C tracer, which
            # can support all the concurrency, or if we are using threads.
            if expected_out is None:
                expected_out = "%d\n" % (sum(range(self.LIMIT)))
            self.assertEqual(out, expected_out)

            # Read the coverage file and see that try_it.py has all its lines
            # executed.
            data = coverage.CoverageData()
            data.read_file(".coverage")

            # If the test fails, it's helpful to see this info:
            fname = abs_file("try_it.py")
            linenos = data.lines(fname)
            print("{0}: {1}".format(len(linenos), linenos))
            print_simple_annotation(code, linenos)

            lines = line_count(code)
            self.assertEqual(data.line_counts()['try_it.py'], lines)
        else:
            expected_out = ("Can't support concurrency=%s with PyTracer, "
                            "only threads are supported\n" % concurrency)
            self.assertEqual(out, expected_out)
Пример #25
0
        def abs_file_dict(d):
            """Return a dict like d, but with keys modified by `abs_file`."""
            # The call to litems() ensures that the GIL protects the dictionary
            # iterator against concurrent modifications by tracers running
            # in other threads. We try three times in case of concurrent
            # access, hoping to get a clean copy.
            runtime_err = None
            for _ in range(3):
                try:
                    items = litems(d)
                except RuntimeError as ex:
                    runtime_err = ex
                else:
                    break
            else:
                raise runtime_err       # pylint: disable=raising-bad-type

            return dict((abs_file(k), v) for k, v in items)
Пример #26
0
        def abs_file_dict(d):
            """Return a dict like d, but with keys modified by `abs_file`."""
            # The call to litems() ensures that the GIL protects the dictionary
            # iterator against concurrent modifications by tracers running
            # in other threads. We try three times in case of concurrent
            # access, hoping to get a clean copy.
            runtime_err = None
            for _ in range(3):
                try:
                    items = litems(d)
                except RuntimeError as ex:
                    runtime_err = ex
                else:
                    break
            else:
                raise runtime_err  # pylint: disable=raising-bad-type

            return dict((abs_file(k), v) for k, v in items)
Пример #27
0
    def test_moving_stuff(self):
        # When using absolute file names, moving the source around results in
        # "No source for code" errors while reporting.
        self.make_file("foo.py", "a = 1")
        cov = coverage.Coverage(source=["."])
        self.start_import_stop(cov, "foo")
        res = cov.report()
        assert res == 100

        expected = re.escape("No source for code: '{}'.".format(abs_file("foo.py")))
        os.remove("foo.py")
        self.make_file("new/foo.py", "a = 1")
        shutil.move(".coverage", "new/.coverage")
        with change_dir("new"):
            cov = coverage.Coverage()
            cov.load()
            with pytest.raises(CoverageException, match=expected):
                cov.report()
Пример #28
0
    def test_branch(self):
        cov = coverage.Coverage(branch=True)

        self.make_file(
            "fun1.py",
            """\
            def fun1(x):
                if x == 1:
                    return

            fun1(3)
            """,
        )

        self.start_import_stop(cov, "fun1")

        data = cov.get_data()
        fun1_lines = data.lines(abs_file("fun1.py"))
        self.assertCountEqual(fun1_lines, [1, 2, 5])
Пример #29
0
    def test_assert_source(self):
        dom = ElementTree.fromstring("""\
            <doc>
                <src>foo</src>
                <sources>
                    <source>{cwd}something</source>
                    <source>{cwd}another</source>
                </sources>
            </doc>
            """.format(cwd=abs_file(".")+os.sep))

        self.assert_source(dom, "something")
        self.assert_source(dom, "another")

        with self.assertRaises(AssertionError):
            self.assert_source(dom, "hello")
        with self.assertRaises(AssertionError):
            self.assert_source(dom, "foo")
        with self.assertRaises(AssertionError):
            self.assert_source(dom, "thing")
Пример #30
0
    def test_assert_source(self):
        dom = ElementTree.fromstring("""\
            <doc>
                <src>foo</src>
                <sources>
                    <source>{cwd}something</source>
                    <source>{cwd}another</source>
                </sources>
            </doc>
            """.format(cwd=abs_file(".") + os.sep))

        self.assert_source(dom, "something")
        self.assert_source(dom, "another")

        with self.assertRaises(AssertionError):
            self.assert_source(dom, "hello")
        with self.assertRaises(AssertionError):
            self.assert_source(dom, "foo")
        with self.assertRaises(AssertionError):
            self.assert_source(dom, "thing")
Пример #31
0
    def try_some_code(self, code, concurrency, the_module, expected_out=None):
        """Run some concurrency testing code and see that it was all covered.

        `code` is the Python code to execute.  `concurrency` is the name of
        the concurrency regime to test it under.  `the_module` is the imported
        module that must be available for this to work at all. `expected_out`
        is the text we expect the code to produce.

        """

        self.make_file("try_it.py", code)

        cmd = "coverage run --concurrency=%s try_it.py" % concurrency
        out = self.run_command(cmd)

        expected_cant_trace = cant_trace_msg(concurrency, the_module)

        if expected_cant_trace is not None:
            assert out == expected_cant_trace
        else:
            # We can fully measure the code if we are using the C tracer, which
            # can support all the concurrency, or if we are using threads.
            if expected_out is None:
                expected_out = "%d\n" % (sum(range(self.QLIMIT)))
            print(code)
            assert out == expected_out

            # Read the coverage file and see that try_it.py has all its lines
            # executed.
            data = coverage.CoverageData(".coverage")
            data.read()

            # If the test fails, it's helpful to see this info:
            fname = abs_file("try_it.py")
            linenos = data.lines(fname)
            print(f"{len(linenos)}: {linenos}")
            print_simple_annotation(code, linenos)

            lines = line_count(code)
            assert line_counts(data)['try_it.py'] == lines
Пример #32
0
    def try_some_code(self, code, concurrency, the_module, expected_out=None):
        """Run some concurrency testing code and see that it was all covered.

        `code` is the Python code to execute.  `concurrency` is the name of
        the concurrency regime to test it under.  `the_module` is the imported
        module that must be available for this to work at all. `expected_out`
        is the text we expect the code to produce.

        """

        self.make_file("try_it.py", code)

        cmd = "coverage run --concurrency=%s try_it.py" % concurrency
        out = self.run_command(cmd)

        expected_cant_trace = cant_trace_msg(concurrency, the_module)

        if expected_cant_trace is not None:
            self.assertEqual(out, expected_cant_trace)
        else:
            # We can fully measure the code if we are using the C tracer, which
            # can support all the concurrency, or if we are using threads.
            if expected_out is None:
                expected_out = "%d\n" % (sum(range(self.QLIMIT)))
            print(code)
            self.assertEqual(out, expected_out)

            # Read the coverage file and see that try_it.py has all its lines
            # executed.
            data = coverage.CoverageData(".coverage")
            data.read()

            # If the test fails, it's helpful to see this info:
            fname = abs_file("try_it.py")
            linenos = data.lines(fname)
            print("{0}: {1}".format(len(linenos), linenos))
            print_simple_annotation(code, linenos)

            lines = line_count(code)
            self.assertEqual(line_counts(data)['try_it.py'], lines)
Пример #33
0
    def _get_file_reporter(self, morf):
        """Get a FileReporter for a module or filename."""
        plugin = None

        if isinstance(morf, string_class):
            abs_morf = abs_file(morf)
            plugin_name = self.data.plugin_name(abs_morf)
            if plugin_name:
                plugin = self.plugins.get(plugin_name)

        if plugin:
            file_reporter = plugin.file_reporter(abs_morf)
            if file_reporter is None:
                raise CoverageException(
                    "Plugin %r did not provide a file reporter for %r." % (
                        plugin._coverage_plugin_name, morf
                    )
                )
        else:
            file_reporter = PythonFileReporter(morf, self)

        return file_reporter
Пример #34
0
    def test_accented_directory(self):
        # Make a file with a non-ascii character in the directory name.
        self.make_file("\xe2/accented.py", "print('accented')")
        self.make_data_file(lines={abs_file("\xe2/accented.py"): [1]})

        # The XML report is always UTF8-encoded.
        cov = coverage.Coverage()
        cov.load()
        cov.xml_report()
        with open("coverage.xml", "rb") as xmlf:
            xml = xmlf.read()
        assert b' filename="\xc3\xa2/accented.py"' in xml
        assert b' name="accented.py"' in xml

        dom = ElementTree.parse("coverage.xml")
        elts = dom.findall(".//package[@name='â']")
        assert len(elts) == 1
        assert elts[0].attrib == {
            "branch-rate": "0",
            "complexity": "0",
            "line-rate": "1",
            "name": "â",
        }
Пример #35
0
 def abs_file_dict(d):
     """Return a dict like d, but with keys modified by `abs_file`."""
     return dict((abs_file(k), v) for k, v in iitems(d))
Пример #36
0
    def test_exception(self):
        # Python 2.3's trace function doesn't get called with "return" if the
        # scope is exiting due to an exception.  This confounds our trace
        # function which relies on scope announcements to track which files to
        # trace.
        #
        # This test is designed to sniff this out.  Each function in the call
        # stack is in a different file, to try to trip up the tracer.  Each
        # file has active lines in a different range so we'll see if the lines
        # get attributed to the wrong file.

        self.make_file("oops.py", """\
            def oops(args):
                a = 2
                raise Exception("oops")
                a = 4
            """)

        self.make_file("fly.py", "\n"*100 + """\
            def fly(calls):
                a = 2
                calls[0](calls[1:])
                a = 4
            """)

        self.make_file("catch.py", "\n"*200 + """\
            def catch(calls):
                try:
                    a = 3
                    calls[0](calls[1:])
                    a = 5
                except:
                    a = 7
            """)

        self.make_file("doit.py", "\n"*300 + """\
            def doit(calls):
                try:
                    calls[0](calls[1:])
                except:
                    a = 5
            """)

        # Import all the modules before starting coverage, so the def lines
        # won't be in all the results.
        for mod in "oops fly catch doit".split():
            import_local_file(mod)

        # Each run nests the functions differently to get different
        # combinations of catching exceptions and letting them fly.
        runs = [
            ("doit fly oops", {
                'doit.py': [302, 303, 304, 305],
                'fly.py': [102, 103],
                'oops.py': [2, 3],
                }),
            ("doit catch oops", {
                'doit.py': [302, 303],
                'catch.py': [202, 203, 204, 206, 207],
                'oops.py': [2, 3],
                }),
            ("doit fly catch oops", {
                'doit.py': [302, 303],
                'fly.py': [102, 103, 104],
                'catch.py': [202, 203, 204, 206, 207],
                'oops.py': [2, 3],
                }),
            ("doit catch fly oops", {
                'doit.py': [302, 303],
                'catch.py': [202, 203, 204, 206, 207],
                'fly.py': [102, 103],
                'oops.py': [2, 3],
                }),
            ]

        for callnames, lines_expected in runs:

            # Make the list of functions we'll call for this test.
            callnames = callnames.split()
            calls = [getattr(sys.modules[cn], cn) for cn in callnames]

            cov = coverage.Coverage()
            cov.start()
            # Call our list of functions: invoke the first, with the rest as
            # an argument.
            calls[0](calls[1:])     # pragma: nested
            cov.stop()              # pragma: nested

            # Clean the line data and compare to expected results.
            # The file names are absolute, so keep just the base.
            clean_lines = {}
            data = cov.get_data()
            for callname in callnames:
                filename = callname + ".py"
                lines = data.lines(abs_file(filename))
                clean_lines[filename] = sorted(lines)

            if env.JYTHON:                  # pragma: only jython
                # Jython doesn't report on try or except lines, so take those
                # out of the expected lines.
                invisible = [202, 206, 302, 304]
                for lines in lines_expected.values():
                    lines[:] = [l for l in lines if l not in invisible]

            self.assertEqual(clean_lines, lines_expected)
Пример #37
0
 def abs_file_dict(d):
     """Return a dict like d, but with keys modified by `abs_file`."""
     return dict((abs_file(k), v) for k, v in iitems(d))
Пример #38
0
 def assert_source(self, xmldom, src):
     """Assert that the XML has a <source> element with `src`."""
     src = abs_file(src)
     elts = xmldom.findall(".//sources/source")
     assert any(elt.text == src for elt in elts)
Пример #39
0
 def assert_source(self, xmldom, src):
     """Assert that the XML has a <source> element with `src`."""
     src = abs_file(src)
     elts = xmldom.findall(".//sources/source")
     assert any(elt.text == src for elt in elts)
Пример #40
0
 def assert_source(self, xml, src):
     """Assert that the XML has a <source> element with `src`."""
     src = abs_file(src)
     self.assertRegex(xml, r'<source>\s*{0}\s*</source>'.format(re.escape(src)))
Пример #41
0
    def test_exception(self):
        # Python 2.3's trace function doesn't get called with "return" if the
        # scope is exiting due to an exception.  This confounds our trace
        # function which relies on scope announcements to track which files to
        # trace.
        #
        # This test is designed to sniff this out.  Each function in the call
        # stack is in a different file, to try to trip up the tracer.  Each
        # file has active lines in a different range so we'll see if the lines
        # get attributed to the wrong file.

        self.make_file("oops.py", """\
            def oops(args):
                a = 2
                raise Exception("oops")
                a = 4
            """)

        self.make_file("fly.py", "\n"*100 + """\
            def fly(calls):
                a = 2
                calls[0](calls[1:])
                a = 4
            """)

        self.make_file("catch.py", "\n"*200 + """\
            def catch(calls):
                try:
                    a = 3
                    calls[0](calls[1:])
                    a = 5
                except:
                    a = 7
            """)

        self.make_file("doit.py", "\n"*300 + """\
            def doit(calls):
                try:
                    calls[0](calls[1:])
                except:
                    a = 5
            """)

        # Import all the modules before starting coverage, so the def lines
        # won't be in all the results.
        for mod in "oops fly catch doit".split():
            import_local_file(mod)

        # Each run nests the functions differently to get different
        # combinations of catching exceptions and letting them fly.
        runs = [
            ("doit fly oops", {
                'doit.py': [302, 303, 304, 305],
                'fly.py': [102, 103],
                'oops.py': [2, 3],
                }),
            ("doit catch oops", {
                'doit.py': [302, 303],
                'catch.py': [202, 203, 204, 206, 207],
                'oops.py': [2, 3],
                }),
            ("doit fly catch oops", {
                'doit.py': [302, 303],
                'fly.py': [102, 103, 104],
                'catch.py': [202, 203, 204, 206, 207],
                'oops.py': [2, 3],
                }),
            ("doit catch fly oops", {
                'doit.py': [302, 303],
                'catch.py': [202, 203, 204, 206, 207],
                'fly.py': [102, 103],
                'oops.py': [2, 3],
                }),
            ]

        for callnames, lines_expected in runs:

            # Make the list of functions we'll call for this test.
            callnames = callnames.split()
            calls = [getattr(sys.modules[cn], cn) for cn in callnames]

            cov = coverage.Coverage()
            cov.start()
            # Call our list of functions: invoke the first, with the rest as
            # an argument.
            calls[0](calls[1:])     # pragma: nested
            cov.stop()              # pragma: nested

            # Clean the line data and compare to expected results.
            # The file names are absolute, so keep just the base.
            clean_lines = {}
            data = cov.get_data()
            for callname in callnames:
                filename = callname + ".py"
                lines = data.lines(abs_file(filename))
                clean_lines[filename] = sorted(lines)

            if env.JYTHON:                  # pragma: only jython
                # Jython doesn't report on try or except lines, so take those
                # out of the expected lines.
                invisible = [202, 206, 302, 304]
                for lines in lines_expected.values():
                    lines[:] = [l for l in lines if l not in invisible]

            self.assertEqual(clean_lines, lines_expected)
Пример #42
0
 def assert_source(self, xml, src):
     """Assert that the XML has a <source> element with `src`."""
     src = abs_file(src)
     self.assertRegex(xml, r'<source>\s*{0}\s*</source>'.format(re.escape(src)))
Пример #43
0
 def make_mycode_data(self):
     """Pretend that we ran mycode.py, so we can report on it."""
     self.make_file("mycode.py", "print('hello')\n")
     self.make_data_file(lines={abs_file("mycode.py"): [1]})
Пример #44
0
 def abs_path(self, p):
     """Return the absolute path for `p`."""
     return os.path.join(abs_file(os.getcwd()), os.path.normpath(p))