DebugClients/Python/coverage/html.py

changeset 5141
bc64243b7672
parent 5126
d28b92dabc2b
parent 5140
01484c0afbc6
child 5144
1ab536d25072
--- a/DebugClients/Python/coverage/html.py	Fri Sep 02 19:08:02 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,438 +0,0 @@
-# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
-# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
-
-"""HTML reporting for coverage.py."""
-
-import datetime
-import json
-import os
-import shutil
-
-import coverage
-from coverage import env
-from coverage.backward import iitems
-from coverage.files import flat_rootname
-from coverage.misc import CoverageException, Hasher, isolate_module
-from coverage.report import Reporter
-from coverage.results import Numbers
-from coverage.templite import Templite
-
-os = isolate_module(os)
-
-
-# Static files are looked for in a list of places.
-STATIC_PATH = [
-    # The place Debian puts system Javascript libraries.
-    "/usr/share/javascript",
-
-    # Our htmlfiles directory.
-    os.path.join(os.path.dirname(__file__), "htmlfiles"),
-]
-
-
-def data_filename(fname, pkgdir=""):
-    """Return the path to a data file of ours.
-
-    The file is searched for on `STATIC_PATH`, and the first place it's found,
-    is returned.
-
-    Each directory in `STATIC_PATH` is searched as-is, and also, if `pkgdir`
-    is provided, at that sub-directory.
-
-    """
-    tried = []
-    for static_dir in STATIC_PATH:
-        static_filename = os.path.join(static_dir, fname)
-        if os.path.exists(static_filename):
-            return static_filename
-        else:
-            tried.append(static_filename)
-        if pkgdir:
-            static_filename = os.path.join(static_dir, pkgdir, fname)
-            if os.path.exists(static_filename):
-                return static_filename
-            else:
-                tried.append(static_filename)
-    raise CoverageException(
-        "Couldn't find static file %r from %r, tried: %r" % (fname, os.getcwd(), tried)
-    )
-
-
-def read_data(fname):
-    """Return the contents of a data file of ours."""
-    with open(data_filename(fname)) as data_file:
-        return data_file.read()
-
-
-def write_html(fname, html):
-    """Write `html` to `fname`, properly encoded."""
-    with open(fname, "wb") as fout:
-        fout.write(html.encode('ascii', 'xmlcharrefreplace'))
-
-
-class HtmlReporter(Reporter):
-    """HTML reporting."""
-
-    # These files will be copied from the htmlfiles directory to the output
-    # directory.
-    STATIC_FILES = [
-        ("style.css", ""),
-        ("jquery.min.js", "jquery"),
-        ("jquery.debounce.min.js", "jquery-debounce"),
-        ("jquery.hotkeys.js", "jquery-hotkeys"),
-        ("jquery.isonscreen.js", "jquery-isonscreen"),
-        ("jquery.tablesorter.min.js", "jquery-tablesorter"),
-        ("coverage_html.js", ""),
-        ("keybd_closed.png", ""),
-        ("keybd_open.png", ""),
-    ]
-
-    def __init__(self, cov, config):
-        super(HtmlReporter, self).__init__(cov, config)
-        self.directory = None
-        title = self.config.html_title
-        if env.PY2:
-            title = title.decode("utf8")
-        self.template_globals = {
-            'escape': escape,
-            'pair': pair,
-            'title': title,
-            '__url__': coverage.__url__,
-            '__version__': coverage.__version__,
-        }
-        self.source_tmpl = Templite(read_data("pyfile.html"), self.template_globals)
-
-        self.coverage = cov
-
-        self.files = []
-        self.has_arcs = self.coverage.data.has_arcs()
-        self.status = HtmlStatus()
-        self.extra_css = None
-        self.totals = Numbers()
-        self.time_stamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
-
-    def report(self, morfs):
-        """Generate an HTML report for `morfs`.
-
-        `morfs` is a list of modules or file names.
-
-        """
-        assert self.config.html_dir, "must give a directory for html reporting"
-
-        # Read the status data.
-        self.status.read(self.config.html_dir)
-
-        # Check that this run used the same settings as the last run.
-        m = Hasher()
-        m.update(self.config)
-        these_settings = m.hexdigest()
-        if self.status.settings_hash() != these_settings:
-            self.status.reset()
-            self.status.set_settings_hash(these_settings)
-
-        # The user may have extra CSS they want copied.
-        if self.config.extra_css:
-            self.extra_css = os.path.basename(self.config.extra_css)
-
-        # Process all the files.
-        self.report_files(self.html_file, morfs, self.config.html_dir)
-
-        if not self.files:
-            raise CoverageException("No data to report.")
-
-        # Write the index file.
-        self.index_file()
-
-        self.make_local_static_report_files()
-        return self.totals.n_statements and self.totals.pc_covered
-
-    def make_local_static_report_files(self):
-        """Make local instances of static files for HTML report."""
-        # The files we provide must always be copied.
-        for static, pkgdir in self.STATIC_FILES:
-            shutil.copyfile(
-                data_filename(static, pkgdir),
-                os.path.join(self.directory, static)
-            )
-
-        # The user may have extra CSS they want copied.
-        if self.extra_css:
-            shutil.copyfile(
-                self.config.extra_css,
-                os.path.join(self.directory, self.extra_css)
-            )
-
-    def file_hash(self, source, fr):
-        """Compute a hash that changes if the file needs to be re-reported."""
-        m = Hasher()
-        m.update(source)
-        self.coverage.data.add_to_hash(fr.filename, m)
-        return m.hexdigest()
-
-    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)
-
-    def index_file(self):
-        """Write the index.html file for this report."""
-        index_tmpl = Templite(read_data("index.html"), self.template_globals)
-
-        self.totals = sum(f['nums'] for f in self.files)
-
-        html = index_tmpl.render({
-            'has_arcs': self.has_arcs,
-            'extra_css': self.extra_css,
-            'files': self.files,
-            'totals': self.totals,
-            'time_stamp': self.time_stamp,
-        })
-
-        write_html(os.path.join(self.directory, "index.html"), html)
-
-        # Write the latest hashes for next time.
-        self.status.write(self.directory)
-
-
-class HtmlStatus(object):
-    """The status information we keep to support incremental reporting."""
-
-    STATUS_FILE = "status.json"
-    STATUS_FORMAT = 1
-
-    #           pylint: disable=wrong-spelling-in-comment,useless-suppression
-    #  The data looks like:
-    #
-    #  {
-    #      'format': 1,
-    #      'settings': '540ee119c15d52a68a53fe6f0897346d',
-    #      'version': '4.0a1',
-    #      'files': {
-    #          'cogapp___init__': {
-    #              'hash': 'e45581a5b48f879f301c0f30bf77a50c',
-    #              'index': {
-    #                  'html_filename': 'cogapp___init__.html',
-    #                  'name': 'cogapp/__init__',
-    #                  'nums': <coverage.results.Numbers object at 0x10ab7ed0>,
-    #              }
-    #          },
-    #          ...
-    #          'cogapp_whiteutils': {
-    #              'hash': '8504bb427fc488c4176809ded0277d51',
-    #              'index': {
-    #                  'html_filename': 'cogapp_whiteutils.html',
-    #                  'name': 'cogapp/whiteutils',
-    #                  'nums': <coverage.results.Numbers object at 0x10ab7d90>,
-    #              }
-    #          },
-    #      },
-    #  }
-
-    def __init__(self):
-        self.reset()
-
-    def reset(self):
-        """Initialize to empty."""
-        self.settings = ''
-        self.files = {}
-
-    def read(self, directory):
-        """Read the last status in `directory`."""
-        usable = False
-        try:
-            status_file = os.path.join(directory, self.STATUS_FILE)
-            with open(status_file, "r") as fstatus:
-                status = json.load(fstatus)
-        except (IOError, ValueError):
-            usable = False
-        else:
-            usable = True
-            if status['format'] != self.STATUS_FORMAT:
-                usable = False
-            elif status['version'] != coverage.__version__:
-                usable = False
-
-        if usable:
-            self.files = {}
-            for filename, fileinfo in iitems(status['files']):
-                fileinfo['index']['nums'] = Numbers(*fileinfo['index']['nums'])
-                self.files[filename] = fileinfo
-            self.settings = status['settings']
-        else:
-            self.reset()
-
-    def write(self, directory):
-        """Write the current status to `directory`."""
-        status_file = os.path.join(directory, self.STATUS_FILE)
-        files = {}
-        for filename, fileinfo in iitems(self.files):
-            fileinfo['index']['nums'] = fileinfo['index']['nums'].init_args()
-            files[filename] = fileinfo
-
-        status = {
-            'format': self.STATUS_FORMAT,
-            'version': coverage.__version__,
-            'settings': self.settings,
-            'files': files,
-        }
-        with open(status_file, "w") as fout:
-            json.dump(status, fout)
-
-        # Older versions of ShiningPanda look for the old name, status.dat.
-        # Accomodate them if we are running under Jenkins.
-        # https://issues.jenkins-ci.org/browse/JENKINS-28428
-        if "JENKINS_URL" in os.environ:
-            with open(os.path.join(directory, "status.dat"), "w") as dat:
-                dat.write("https://issues.jenkins-ci.org/browse/JENKINS-28428\n")
-
-    def settings_hash(self):
-        """Get the hash of the coverage.py settings."""
-        return self.settings
-
-    def set_settings_hash(self, settings):
-        """Set the hash of the coverage.py settings."""
-        self.settings = settings
-
-    def file_hash(self, fname):
-        """Get the hash of `fname`'s contents."""
-        return self.files.get(fname, {}).get('hash', '')
-
-    def set_file_hash(self, fname, val):
-        """Set the hash of `fname`'s contents."""
-        self.files.setdefault(fname, {})['hash'] = val
-
-    def index_info(self, fname):
-        """Get the information for index.html for `fname`."""
-        return self.files.get(fname, {}).get('index', {})
-
-    def set_index_info(self, fname, info):
-        """Set the information for index.html for `fname`."""
-        self.files.setdefault(fname, {})['index'] = info
-
-
-# Helpers for templates and generating HTML
-
-def escape(t):
-    """HTML-escape the text in `t`.
-
-    This is only suitable for HTML text, not attributes.
-
-    """
-    # Convert HTML special chars into HTML entities.
-    return t.replace("&", "&amp;").replace("<", "&lt;")
-
-
-def pair(ratio):
-    """Format a pair of numbers so JavaScript can read them in an attribute."""
-    return "%s %s" % ratio
-
-#
-# eflag: FileType = Python2

eric ide

mercurial