diff options
-rw-r--r-- | coverage/backward.py | 18 | ||||
-rw-r--r-- | coverage/html.py | 70 | ||||
-rw-r--r-- | coverage/htmlfiles/pyfile.html | 4 |
3 files changed, 55 insertions, 37 deletions
diff --git a/coverage/backward.py b/coverage/backward.py index 1d92469d..05fa261e 100644 --- a/coverage/backward.py +++ b/coverage/backward.py @@ -155,6 +155,24 @@ except AttributeError: PYC_MAGIC_NUMBER = imp.get_magic() +try: + from types import SimpleNamespace +except ImportError: + # The code from https://docs.python.org/3/library/types.html#types.SimpleNamespace + class SimpleNamespace: + """Python implementation of SimpleNamespace, for Python 2.""" + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + def __repr__(self): + keys = sorted(self.__dict__) + items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys) + return "{}({})".format(type(self).__name__, ", ".join(items)) + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + def invalidate_import_caches(): """Invalidate any import caches that may or may not exist.""" if importlib and hasattr(importlib, "invalidate_caches"): diff --git a/coverage/html.py b/coverage/html.py index 6b3c272a..21bb183c 100644 --- a/coverage/html.py +++ b/coverage/html.py @@ -12,7 +12,7 @@ import shutil import coverage from coverage import env -from coverage.backward import iitems +from coverage.backward import iitems, SimpleNamespace from coverage.data import add_data_to_hash from coverage.files import flat_rootname from coverage.misc import CoverageException, ensure_dir, file_be_gone, Hasher, isolate_module @@ -210,10 +210,10 @@ class HtmlReporter(object): # Write the HTML page for this file. file_data = self.data_for_file(fr, analysis) - for ldata in file_data['lines']: + for ldata in file_data.lines: # Build the HTML for the line. html = [] - for tok_type, tok_text in ldata['tokens']: + for tok_type, tok_text in ldata.tokens: if tok_type == "ws": html.append(escape(tok_text)) else: @@ -221,24 +221,24 @@ class HtmlReporter(object): html.append( '<span class="{}">{}</span>'.format(tok_type, tok_html) ) - ldata['html'] = ''.join(html) + ldata.html = ''.join(html) - if ldata['short_annotations']: + if ldata.short_annotations: # 202F is NARROW NO-BREAK SPACE. # 219B is RIGHTWARDS ARROW WITH STROKE. - ldata['annotate'] = ", ".join( - "{} ↛ {}".format(ldata['number'], d) - for d in ldata['short_annotations'] + ldata.annotate = ", ".join( + "{} ↛ {}".format(ldata.number, d) + for d in ldata.short_annotations ) else: - ldata['annotate'] = None + ldata.annotate = None - if ldata['long_annotations']: - longs = ldata['long_annotations'] + if ldata.long_annotations: + longs = ldata.long_annotations if len(longs) == 1: - ldata['annotate_long'] = longs[0] + ldata.annotate_long = longs[0] else: - ldata['annotate_long'] = "{:d} missed branches: {}".format( + ldata.annotate_long = "{:d} missed branches: {}".format( len(longs), ", ".join( "{:d}) {}".format(num, ann_long) @@ -246,9 +246,9 @@ class HtmlReporter(object): ), ) else: - ldata['annotate_long'] = None + ldata.annotate_long = None - html = self.source_tmpl.render(file_data) + html = self.source_tmpl.render(file_data.__dict__) write_html(html_path, html) # Save this file's information for the index file. @@ -275,19 +275,19 @@ class HtmlReporter(object): for lineno, tokens in enumerate(fr.source_token_lines(), start=1): # Figure out how to mark this line. - line_class = [] + css_classes = [] short_annotations = [] long_annotations = [] if lineno in analysis.statements: - line_class.append("stm") + css_classes.append("stm") if lineno in analysis.excluded: - line_class.append(self.c_exc) + css_classes.append(self.c_exc) elif lineno in analysis.missing: - line_class.append(self.c_mis) + css_classes.append(self.c_mis) elif self.has_arcs and lineno in missing_branch_arcs: - line_class.append(self.c_par) + css_classes.append(self.c_par) for b in missing_branch_arcs[lineno]: if b < 0: short_annotations.append("exit") @@ -295,27 +295,27 @@ class HtmlReporter(object): short_annotations.append(b) long_annotations.append(fr.missing_arc_description(lineno, b, arcs_executed)) elif lineno in analysis.statements: - line_class.append(self.c_run) + css_classes.append(self.c_run) if self.config.show_contexts: contexts = sorted(filter(None, contexts_by_lineno[lineno])) else: contexts = None - lines.append({ - 'tokens': tokens, - 'number': lineno, - 'class': ' '.join(line_class) or "pln", - 'contexts': contexts, - 'short_annotations': short_annotations, - 'long_annotations': long_annotations, - }) - - file_data = { - 'relative_filename': fr.relative_filename(), - 'nums': analysis.numbers, - 'lines': lines, - } + lines.append(SimpleNamespace( + tokens=tokens, + number=lineno, + css_class=' '.join(css_classes) or "pln", + contexts=contexts, + short_annotations=short_annotations, + long_annotations=long_annotations, + )) + + file_data = SimpleNamespace( + relative_filename=fr.relative_filename(), + nums=analysis.numbers, + lines=lines, + ) return file_data diff --git a/coverage/htmlfiles/pyfile.html b/coverage/htmlfiles/pyfile.html index 33f1fbb1..72cf77c9 100644 --- a/coverage/htmlfiles/pyfile.html +++ b/coverage/htmlfiles/pyfile.html @@ -72,14 +72,14 @@ <tr> <td class="linenos"> {% for line in lines -%} - <p id="n{{line.number}}" class="{{line.class}}"><a href="#n{{line.number}}">{{line.number}}</a></p> + <p id="n{{line.number}}" class="{{line.css_class}}"><a href="#n{{line.number}}">{{line.number}}</a></p> {% endfor %} </td> <td class="text"> {# These are the source lines, which are very sensitive to whitespace. -#} {# The `{ # - # }` below are comments which slurp up the following space. -#} {% for line in lines -%} - <p id="t{{line.number}}" class="{{line.class}}">{#-#} + <p id="t{{line.number}}" class="{{line.css_class}}">{#-#} {% if line.annotate -%} <span class="annotate short">{{line.annotate}}</span>{#-#} <span class="annotate long">{{line.annotate_long}}</span>{#-#} |