예제 #1
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)
예제 #2
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)
예제 #3
0
def compare_html(dir1, dir2):
    """Specialized compare function for 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', '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.
        (re.escape(TESTS_DIR), 'TESTS_DIR'),
        (r'/Users/ned/coverage/trunk/tests', 'TESTS_DIR'),
        (flat_rootname(unicode_class(TESTS_DIR)), '_TESTS_DIR'),
        (flat_rootname(u'/Users/ned/coverage/trunk/tests'), '_TESTS_DIR'),
    ]
    if env.WINDOWS:
        # For file paths...
        scrubs += [(r"\\", "/")]
    return compare(dir1, dir2, file_pattern="*.html", scrubs=scrubs)
예제 #4
0
    def annotate_file(self, fr, analysis):
        """Annotate a single file.

        `fr` is the FileReporter for the file to annotate.

        """
        statements = sorted(analysis.statements)
        missing = sorted(analysis.missing)
        excluded = sorted(analysis.excluded)

        if self.directory:
            ensure_dir(self.directory)
            dest_file = os.path.join(self.directory,
                                     flat_rootname(fr.relative_filename()))
            if dest_file.endswith("_py"):
                dest_file = dest_file[:-3] + ".py"
            dest_file += ",cover"
        else:
            dest_file = fr.filename + ",cover"

        with io.open(dest_file, 'w', encoding='utf8') as dest:
            i = 0
            j = 0
            covered = True
            source = fr.source()
            for lineno, line in enumerate(source.splitlines(True), start=1):
                while i < len(statements) and statements[i] < lineno:
                    i += 1
                while j < len(missing) and missing[j] < lineno:
                    j += 1
                if i < len(statements) and statements[i] == lineno:
                    covered = j >= len(missing) or missing[j] > lineno
                if self.blank_re.match(line):
                    dest.write(u'  ')
                elif self.else_re.match(line):
                    # Special logic for lines containing only 'else:'.
                    if i >= len(statements) and j >= len(missing):
                        dest.write(u'! ')
                    elif i >= len(statements) or j >= len(missing):
                        dest.write(u'> ')
                    elif statements[i] == missing[j]:
                        dest.write(u'! ')
                    else:
                        dest.write(u'> ')
                elif lineno in excluded:
                    dest.write(u'- ')
                elif covered:
                    dest.write(u'> ')
                else:
                    dest.write(u'! ')

                dest.write(line)
예제 #5
0
    def annotate_file(self, fr, analysis):
        """Annotate a single file.

        `fr` is the FileReporter for the file to annotate.

        """
        statements = sorted(analysis.statements)
        missing = sorted(analysis.missing)
        excluded = sorted(analysis.excluded)

        if self.directory:
            dest_file = os.path.join(self.directory, flat_rootname(fr.relative_filename()))
            if dest_file.endswith("_py"):
                dest_file = dest_file[:-3] + ".py"
            dest_file += ",cover"
        else:
            dest_file = fr.filename + ",cover"

        with open(dest_file, 'w') as dest:
            i = 0
            j = 0
            covered = True
            source = fr.source()
            for lineno, line in enumerate(source.splitlines(True), start=1):
                while i < len(statements) and statements[i] < lineno:
                    i += 1
                while j < len(missing) and missing[j] < lineno:
                    j += 1
                if i < len(statements) and statements[i] == lineno:
                    covered = j >= len(missing) or missing[j] > lineno
                if self.blank_re.match(line):
                    dest.write(u'  ')
                elif self.else_re.match(line):
                    # Special logic for lines containing only 'else:'.
                    if i >= len(statements) and j >= len(missing):
                        dest.write(u'! ')
                    elif i >= len(statements) or j >= len(missing):
                        dest.write(u'> ')
                    elif statements[i] == missing[j]:
                        dest.write(u'! ')
                    else:
                        dest.write(u'> ')
                elif lineno in excluded:
                    dest.write(u'- ')
                elif covered:
                    dest.write(u'> ')
                else:
                    dest.write(u'! ')

                dest.write(line)
예제 #6
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', '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'),
        (r'/Users/ned/coverage/trunk/tests', 'TESTS_DIR'),
        (filepath_to_regex(flat_rootname(unicode_class(TESTS_DIR))), '_TESTS_DIR'),
        (flat_rootname(u'/Users/ned/coverage/trunk/tests'), '_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'),
        (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)
예제 #7
0
 def test_flat_rootname(self):
     self.assertEqual(flat_rootname("a/b/c.py"), "a_b_c_py")
     self.assertEqual(flat_rootname(r"c:\foo\bar.html"), "c__foo_bar_html")
예제 #8
0
    def html_file(self, fr, analysis):
        """Generate an HTML file for one source file."""
        rootname = flat_rootname(fr.relative_filename())
        html_filename = rootname + ".html"
        ensure_dir(self.directory)
        html_path = os.path.join(self.directory, html_filename)

        # Get the numbers for this file.
        nums = analysis.numbers
        self.all_files_nums.append(nums)

        if self.skip_covered:
            # Don't report on 100% files.
            no_missing_lines = (nums.n_missing == 0)
            no_missing_branches = (nums.n_partial_branches == 0)
            if no_missing_lines and no_missing_branches:
                # If there's an existing file, remove it.
                file_be_gone(html_path)
                self.skipped_covered_count += 1
                return

        if self.skip_empty:
            # Don't report on empty files.
            if nums.n_statements == 0:
                file_be_gone(html_path)
                self.skipped_empty_count += 1
                return

        # Find out if the file on disk is already correct.
        if self.incr.can_skip_file(self.data, fr, rootname):
            self.file_summaries.append(self.incr.index_info(rootname))
            return

        # Write the HTML page for this file.
        file_data = self.datagen.data_for_file(fr, analysis)
        for ldata in file_data.lines:
            # Build the HTML for the line.
            html = []
            for tok_type, tok_text in ldata.tokens:
                if tok_type == "ws":
                    html.append(escape(tok_text))
                else:
                    tok_html = escape(tok_text) or '&nbsp;'
                    html.append(f'<span class="{tok_type}">{tok_html}</span>')
            ldata.html = ''.join(html)

            if ldata.short_annotations:
                # 202F is NARROW NO-BREAK SPACE.
                # 219B is RIGHTWARDS ARROW WITH STROKE.
                ldata.annotate = ",&nbsp;&nbsp; ".join(
                    f"{ldata.number}&#x202F;&#x219B;&#x202F;{d}"
                    for d in ldata.short_annotations)
            else:
                ldata.annotate = None

            if ldata.long_annotations:
                longs = ldata.long_annotations
                if len(longs) == 1:
                    ldata.annotate_long = longs[0]
                else:
                    ldata.annotate_long = "{:d} missed branches: {}".format(
                        len(longs),
                        ", ".join(
                            f"{num:d}) {ann_long}"
                            for num, ann_long in enumerate(longs, start=1)),
                    )
            else:
                ldata.annotate_long = None

            css_classes = []
            if ldata.category:
                css_classes.append(
                    self.template_globals['category'][ldata.category])
            ldata.css_class = ' '.join(css_classes) or "pln"

        html = self.source_tmpl.render(file_data.__dict__)
        write_html(html_path, html)

        # Save this file's information for the index file.
        index_info = {
            'nums': nums,
            'html_filename': html_filename,
            'relative_filename': fr.relative_filename(),
        }
        self.file_summaries.append(index_info)
        self.incr.set_index_info(rootname, index_info)
예제 #9
0
    def html_file(self, fr, analysis):
        """Generate an HTML file for one source file."""
        source = fr.source()

        # Find out if the file on disk is already correct.
        rootname = flat_rootname(fr.relative_filename())
        this_hash = self.file_hash(source.encode('utf-8'), fr)
        that_hash = self.status.file_hash(rootname)
        if this_hash == that_hash:
            # Nothing has changed to require the file to be reported again.
            self.files.append(self.status.index_info(rootname))
            return

        self.status.set_file_hash(rootname, this_hash)

        # Get the numbers for this file.
        nums = analysis.numbers

        if self.has_arcs:
            missing_branch_arcs = analysis.missing_branch_arcs()
            arcs_executed = analysis.arcs_executed()

        # These classes determine which lines are highlighted by default.
        c_run = "run hide_run"
        c_exc = "exc"
        c_mis = "mis"
        c_par = "par " + c_run

        lines = []

        for lineno, line in enumerate(fr.source_token_lines(), start=1):
            # Figure out how to mark this line.
            line_class = []
            annotate_html = ""
            annotate_long = ""
            if lineno in analysis.statements:
                line_class.append("stm")
            if lineno in analysis.excluded:
                line_class.append(c_exc)
            elif lineno in analysis.missing:
                line_class.append(c_mis)
            elif self.has_arcs and lineno in missing_branch_arcs:
                line_class.append(c_par)
                shorts = []
                longs = []
                for b in missing_branch_arcs[lineno]:
                    if b < 0:
                        shorts.append("exit")
                    else:
                        shorts.append(b)
                    longs.append(
                        fr.missing_arc_description(lineno, b, arcs_executed))
                # 202F is NARROW NO-BREAK SPACE.
                # 219B is RIGHTWARDS ARROW WITH STROKE.
                short_fmt = "%s&#x202F;&#x219B;&#x202F;%s"
                annotate_html = ",&nbsp;&nbsp; ".join(short_fmt % (lineno, d)
                                                      for d in shorts)

                if len(longs) == 1:
                    annotate_long = longs[0]
                else:
                    annotate_long = "%d missed branches: %s" % (
                        len(longs),
                        ", ".join(
                            "%d) %s" % (num, ann_long)
                            for num, ann_long in enumerate(longs, start=1)),
                    )
            elif lineno in analysis.statements:
                line_class.append(c_run)

            # Build the HTML for the line.
            html = []
            for tok_type, tok_text in line:
                if tok_type == "ws":
                    html.append(escape(tok_text))
                else:
                    tok_html = escape(tok_text) or '&nbsp;'
                    html.append('<span class="%s">%s</span>' %
                                (tok_type, tok_html))

            lines.append({
                'html': ''.join(html),
                'number': lineno,
                'class': ' '.join(line_class) or "pln",
                'annotate': annotate_html,
                'annotate_long': annotate_long,
            })

        # Write the HTML page for this file.
        html = self.source_tmpl.render({
            'c_exc': c_exc,
            'c_mis': c_mis,
            'c_par': c_par,
            'c_run': c_run,
            'has_arcs': self.has_arcs,
            'extra_css': self.extra_css,
            'fr': fr,
            'nums': nums,
            'lines': lines,
            'time_stamp': self.time_stamp,
        })

        html_filename = rootname + ".html"
        html_path = os.path.join(self.directory, html_filename)
        write_html(html_path, html)

        # Save this file's information for the index file.
        index_info = {
            'nums': nums,
            'html_filename': html_filename,
            'relative_filename': fr.relative_filename(),
        }
        self.files.append(index_info)
        self.status.set_index_info(rootname, index_info)
예제 #10
0
 def test_flat_rootname(self):
     self.assertEqual(flat_rootname("a/b/c.py"), "a_b_c_py")
     self.assertEqual(flat_rootname(r"c:\foo\bar.html"), "_foo_bar_html")
예제 #11
0
 def get_html_report_content(self, module):
     """Return the content of the HTML report for `module`."""
     filename = flat_rootname(module) + ".html"
     filename = os.path.join("htmlcov", filename)
     with open(filename) as f:
         return f.read()
예제 #12
0
def test_flat_rootname(original, flat):
    assert flat_rootname(original) == flat
예제 #13
0
파일: html.py 프로젝트: pycom/EricShort
    def html_file(self, fr, analysis):
        """Generate an HTML file for one source file."""
        source = fr.source()

        # Find out if the file on disk is already correct.
        rootname = flat_rootname(fr.relative_filename())
        this_hash = self.file_hash(source.encode('utf-8'), fr)
        that_hash = self.status.file_hash(rootname)
        if this_hash == that_hash:
            # Nothing has changed to require the file to be reported again.
            self.files.append(self.status.index_info(rootname))
            return

        self.status.set_file_hash(rootname, this_hash)

        # Get the numbers for this file.
        nums = analysis.numbers

        if self.has_arcs:
            missing_branch_arcs = analysis.missing_branch_arcs()

        # These classes determine which lines are highlighted by default.
        c_run = "run hide_run"
        c_exc = "exc"
        c_mis = "mis"
        c_par = "par " + c_run

        lines = []

        for lineno, line in enumerate(fr.source_token_lines(), start=1):
            # Figure out how to mark this line.
            line_class = []
            annotate_html = ""
            annotate_title = ""
            if lineno in analysis.statements:
                line_class.append("stm")
            if lineno in analysis.excluded:
                line_class.append(c_exc)
            elif lineno in analysis.missing:
                line_class.append(c_mis)
            elif self.has_arcs and lineno in missing_branch_arcs:
                line_class.append(c_par)
                shorts = []
                longs = []
                for b in missing_branch_arcs[lineno]:
                    if b < 0:
                        shorts.append("exit")
                        longs.append("the function exit")
                    else:
                        shorts.append(b)
                        longs.append("line %d" % b)
                # 202F is NARROW NO-BREAK SPACE.
                # 219B is RIGHTWARDS ARROW WITH STROKE.
                short_fmt = "%s&#x202F;&#x219B;&#x202F;%s"
                annotate_html = ",&nbsp;&nbsp; ".join(short_fmt % (lineno, d) for d in shorts)
                annotate_html += " [?]"

                annotate_title = "Line %d was executed, but never jumped to " % lineno
                if len(longs) == 1:
                    annotate_title += longs[0]
                elif len(longs) == 2:
                    annotate_title += longs[0] + " or " + longs[1]
                else:
                    annotate_title += ", ".join(longs[:-1]) + ", or " + longs[-1]
            elif lineno in analysis.statements:
                line_class.append(c_run)

            # Build the HTML for the line.
            html = []
            for tok_type, tok_text in line:
                if tok_type == "ws":
                    html.append(escape(tok_text))
                else:
                    tok_html = escape(tok_text) or '&nbsp;'
                    html.append(
                        '<span class="%s">%s</span>' % (tok_type, tok_html)
                    )

            lines.append({
                'html': ''.join(html),
                'number': lineno,
                'class': ' '.join(line_class) or "pln",
                'annotate': annotate_html,
                'annotate_title': annotate_title,
            })

        # Write the HTML page for this file.
        template_values = {
            'c_exc': c_exc, 'c_mis': c_mis, 'c_par': c_par, 'c_run': c_run,
            'has_arcs': self.has_arcs, 'extra_css': self.extra_css,
            'fr': fr, 'nums': nums, 'lines': lines,
            'time_stamp': self.time_stamp,
        }
        html = spaceless(self.source_tmpl.render(template_values))

        html_filename = rootname + ".html"
        html_path = os.path.join(self.directory, html_filename)
        self.write_html(html_path, html)

        # Save this file's information for the index file.
        index_info = {
            'nums': nums,
            'html_filename': html_filename,
            'relative_filename': fr.relative_filename(),
        }
        self.files.append(index_info)
        self.status.set_index_info(rootname, index_info)
예제 #14
0
파일: html.py 프로젝트: hugovk/coveragepy
    def html_file(self, fr, analysis):
        """Generate an HTML file for one source file."""
        rootname = flat_rootname(fr.relative_filename())
        html_filename = rootname + ".html"
        html_path = os.path.join(self.directory, html_filename)

        # Get the numbers for this file.
        nums = analysis.numbers
        self.all_files_nums.append(nums)

        if self.config.skip_covered:
            # Don't report on 100% files.
            no_missing_lines = (nums.n_missing == 0)
            no_missing_branches = (nums.n_partial_branches == 0)
            if no_missing_lines and no_missing_branches:
                # If there's an existing file, remove it.
                file_be_gone(html_path)
                return

        source = fr.source()

        # Find out if the file on disk is already correct.
        this_hash = self.file_hash(source.encode('utf-8'), fr)
        that_hash = self.status.file_hash(rootname)
        if this_hash == that_hash:
            # Nothing has changed to require the file to be reported again.
            self.files.append(self.status.index_info(rootname))
            return

        self.status.set_file_hash(rootname, this_hash)

        if self.has_arcs:
            missing_branch_arcs = analysis.missing_branch_arcs()
            arcs_executed = analysis.arcs_executed()

        # These classes determine which lines are highlighted by default.
        c_run = "run hide_run"
        c_exc = "exc"
        c_mis = "mis"
        c_par = "par " + c_run

        lines = []

        for lineno, line in enumerate(fr.source_token_lines(), start=1):
            # Figure out how to mark this line.
            line_class = []
            annotate_html = ""
            annotate_long = ""
            if lineno in analysis.statements:
                line_class.append("stm")
            if lineno in analysis.excluded:
                line_class.append(c_exc)
            elif lineno in analysis.missing:
                line_class.append(c_mis)
            elif self.has_arcs and lineno in missing_branch_arcs:
                line_class.append(c_par)
                shorts = []
                longs = []
                for b in missing_branch_arcs[lineno]:
                    if b < 0:
                        shorts.append("exit")
                    else:
                        shorts.append(b)
                    longs.append(fr.missing_arc_description(lineno, b, arcs_executed))
                # 202F is NARROW NO-BREAK SPACE.
                # 219B is RIGHTWARDS ARROW WITH STROKE.
                short_fmt = "%s&#x202F;&#x219B;&#x202F;%s"
                annotate_html = ",&nbsp;&nbsp; ".join(short_fmt % (lineno, d) for d in shorts)

                if len(longs) == 1:
                    annotate_long = longs[0]
                else:
                    annotate_long = "%d missed branches: %s" % (
                        len(longs),
                        ", ".join("%d) %s" % (num, ann_long)
                            for num, ann_long in enumerate(longs, start=1)),
                    )
            elif lineno in analysis.statements:
                line_class.append(c_run)

            # Build the HTML for the line.
            html = []
            for tok_type, tok_text in line:
                if tok_type == "ws":
                    html.append(escape(tok_text))
                else:
                    tok_html = escape(tok_text) or '&nbsp;'
                    html.append(
                        '<span class="%s">%s</span>' % (tok_type, tok_html)
                    )

            lines.append({
                'html': ''.join(html),
                'number': lineno,
                'class': ' '.join(line_class) or "pln",
                'annotate': annotate_html,
                'annotate_long': annotate_long,
            })

        # Write the HTML page for this file.
        html = self.source_tmpl.render({
            'c_exc': c_exc,
            'c_mis': c_mis,
            'c_par': c_par,
            'c_run': c_run,
            'has_arcs': self.has_arcs,
            'extra_css': self.extra_css,
            'fr': fr,
            'nums': nums,
            'lines': lines,
            'time_stamp': self.time_stamp,
        })

        write_html(html_path, html)

        # Save this file's information for the index file.
        index_info = {
            'nums': nums,
            'html_filename': html_filename,
            'relative_filename': fr.relative_filename(),
        }
        self.files.append(index_info)
        self.status.set_index_info(rootname, index_info)