diff options
author | Oleh Krehel <ohwoeowho@gmail.com> | 2023-03-22 17:42:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-22 09:42:35 -0700 |
commit | d6cb1cdca6d15f5ec02eb6708314589290321faf (patch) | |
tree | 1cf7f910a9e9b1b1ad7f1a40dad59231da4e0d42 | |
parent | 551522eb214ad0c3f1dc48cd112a4f0ba6ddc6b6 (diff) | |
download | python-coveragepy-git-d6cb1cdca6d15f5ec02eb6708314589290321faf.tar.gz |
fix: put contexts dict in <script> and reveal them using JavaScript (#1587)
* Put contexts dict in <script> and reveal them using JavaScript
Fixes #1584
* Address review comments
* coverage/htmlfiles/style.css: Align the contexts to the right
* coverage/htmlfiles/style.scss: Match style.css
* coverage/html.py: Fix linting and mypy errors
* two_tests_py.html: make update-gold
-rw-r--r-- | coverage/html.py | 14 | ||||
-rw-r--r-- | coverage/htmlfiles/coverage_html.js | 21 | ||||
-rw-r--r-- | coverage/htmlfiles/pyfile.html | 13 | ||||
-rw-r--r-- | coverage/htmlfiles/style.css | 2 | ||||
-rw-r--r-- | coverage/htmlfiles/style.scss | 1 | ||||
-rw-r--r-- | tests/gold/html/contexts/two_tests_py.html | 29 | ||||
-rw-r--r-- | tests/gold/html/styled/style.css | 2 |
7 files changed, 65 insertions, 17 deletions
diff --git a/coverage/html.py b/coverage/html.py index ae09bc37..23fba3f0 100644 --- a/coverage/html.py +++ b/coverage/html.py @@ -10,6 +10,7 @@ import json import os import re import shutil +from collections import Counter from dataclasses import dataclass from typing import Any, Dict, Iterable, List, Optional, Tuple, TYPE_CHECKING, cast @@ -84,6 +85,7 @@ class LineData: short_annotations: List[str] long_annotations: List[str] html: str = "" + context_str: Optional[str] = None annotate: Optional[str] = None annotate_long: Optional[str] = None css_class: str = "" @@ -367,6 +369,11 @@ class HtmlReporter: # Write the HTML page for this file. file_data = self.datagen.data_for_file(ftr.fr, ftr.analysis) + + contexts = Counter(c for cline in file_data.lines for c in cline.contexts) + context_codes = {y: i for (i, y) in enumerate(x[0] for x in contexts.most_common())} + contexts_json = json.dumps({v: k for (k, v) in context_codes.items()}, indent=2) + for ldata in file_data.lines: # Build the HTML for the line. html_parts = [] @@ -380,6 +387,9 @@ class HtmlReporter: ) ldata.html = ''.join(html_parts) + ldata.context_str = ",".join( + str(context_codes[c_context]) for c_context in ldata.context_list) + if ldata.short_annotations: # 202F is NARROW NO-BREAK SPACE. # 219B is RIGHTWARDS ARROW WITH STROKE. @@ -412,6 +422,10 @@ class HtmlReporter: ) ldata.css_class = ' '.join(css_classes) or "pln" + if context_codes: + file_data.__dict__["contexts_json"] = contexts_json + else: + file_data.__dict__["contexts_json"] = None html_path = os.path.join(self.directory, ftr.html_filename) html = self.source_tmpl.render({ **file_data.__dict__, diff --git a/coverage/htmlfiles/coverage_html.js b/coverage/htmlfiles/coverage_html.js index 1c4eb988..8b7fb96f 100644 --- a/coverage/htmlfiles/coverage_html.js +++ b/coverage/htmlfiles/coverage_html.js @@ -212,6 +212,11 @@ coverage.index_ready = function () { coverage.LINE_FILTERS_STORAGE = "COVERAGE_LINE_FILTERS"; coverage.pyfile_ready = function () { + cboxes = document.querySelectorAll('[id^=ctxs]') + cboxes.forEach(function(cbox) { + cbox.addEventListener("click", coverage.showContexts) + }); + // If we're directed to a particular line number, highlight the line. var frag = location.hash; if (frag.length > 2 && frag[1] === 't') { @@ -595,10 +600,26 @@ coverage.wire_up_sticky_header = function () { updateHeader(); }; +coverage.showContexts = function (e) { + span = e.target.nextElementSibling.nextElementSibling; + span_text = span.textContent; + + if (/^[0-9,]+$/.test(span_text)) + { + span.textContent = ""; + span_text.split(",").forEach(function(s) { + ctx = contexts[s]; + span.appendChild(document.createTextNode(ctx)); + span.appendChild(document.createElement("br")); + }) + } +}; + document.addEventListener("DOMContentLoaded", () => { if (document.body.classList.contains("indexfile")) { coverage.index_ready(); } else { coverage.pyfile_ready(); } + }); diff --git a/coverage/htmlfiles/pyfile.html b/coverage/htmlfiles/pyfile.html index 8fcfc660..1921e1c2 100644 --- a/coverage/htmlfiles/pyfile.html +++ b/coverage/htmlfiles/pyfile.html @@ -11,6 +11,13 @@ {% if extra_css %} <link rel="stylesheet" href="{{ extra_css }}" type="text/css"> {% endif %} + + {% if contexts_json %} + <script type="text/javascript"> + contexts = {{ contexts_json }} + </script> + {% endif %} + <script type="text/javascript" src="coverage_html.js" defer></script> </head> <body class="pyfile"> @@ -117,11 +124,9 @@ {% endif %} </span> {# Things that should appear below the line. #} - {% if line.context_list %} + {% if line.context_str %} <span class="ctxs"> - {% for context in line.context_list %} - <span>{{context}}</span> - {% endfor %} + {{ line.context_str }} </span> {% endif %} </p> diff --git a/coverage/htmlfiles/style.css b/coverage/htmlfiles/style.css index d6768a35..ace48c2c 100644 --- a/coverage/htmlfiles/style.css +++ b/coverage/htmlfiles/style.css @@ -258,7 +258,7 @@ kbd { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em @media (prefers-color-scheme: dark) { #source p label.ctx { color: #777; } } -#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; white-space: nowrap; background: #d0e8ff; border-radius: .25em; margin-right: 1.75em; } +#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; white-space: nowrap; background: #d0e8ff; border-radius: .25em; margin-right: 1.75em; text-align: right; } @media (prefers-color-scheme: dark) { #source p .ctxs { background: #056; } } diff --git a/coverage/htmlfiles/style.scss b/coverage/htmlfiles/style.scss index 1e9103fd..fe388487 100644 --- a/coverage/htmlfiles/style.scss +++ b/coverage/htmlfiles/style.scss @@ -622,6 +622,7 @@ $border-indicator-width: .2em; @include background-dark($dark-context-bg-color); border-radius: .25em; margin-right: 1.75em; + text-align: right; span { display: block; text-align: right; diff --git a/tests/gold/html/contexts/two_tests_py.html b/tests/gold/html/contexts/two_tests_py.html index 5e107b5e..86239bd8 100644 --- a/tests/gold/html/contexts/two_tests_py.html +++ b/tests/gold/html/contexts/two_tests_py.html @@ -5,6 +5,13 @@ <title>Coverage for two_tests.py: 94%</title> <link rel="icon" sizes="32x32" href="favicon_32.png"> <link rel="stylesheet" href="style.css" type="text/css"> + <script type="text/javascript"> + contexts = { + "0": "(empty)", + "1": "two_tests.test_two", + "2": "two_tests.test_one" +} + </script> <script type="text/javascript" src="coverage_html.js" defer></script> </head> <body class="pyfile"> @@ -65,7 +72,7 @@ <a id="nextFileLink" class="nav" href="index.html">» next</a> <a class="nav" href="https://coverage.readthedocs.io/en/7.2.3a0.dev1">coverage.py v7.2.3a0.dev1</a>, - created at 2023-03-21 08:44 -0400 + created at 2023-03-22 16:13 +0100 </p> <aside class="hidden"> <button type="button" class="button_next_chunk" data-shortcut="j"/> @@ -81,20 +88,20 @@ </header> <main id="source"> <p class="run"><span class="n"><a id="t1" href="#t1">1</a></span><span class="t"><span class="key">def</span> <span class="nam">helper</span><span class="op">(</span><span class="nam">lineno</span><span class="op">)</span><span class="op">:</span> </span><span class="r"><label for="ctxs1" class="ctx">(empty)</label></span></p> - <p class="run"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t"> <span class="nam">x</span> <span class="op">=</span> <span class="num">2</span> </span><input type="checkbox" id="ctxs2" /><span class="r"><label for="ctxs2" class="ctx">3 ctx</label></span><span class="ctxs"><span>(empty)</span><span>two_tests.test_one</span><span>two_tests.test_two</span></span></p> + <p class="run"><span class="n"><a id="t2" href="#t2">2</a></span><span class="t"> <span class="nam">x</span> <span class="op">=</span> <span class="num">2</span> </span><input type="checkbox" id="ctxs2" /><span class="r"><label for="ctxs2" class="ctx">3 ctx</label></span><span class="ctxs">0,2,1</span></p> <p class="pln"><span class="n"><a id="t3" href="#t3">3</a></span><span class="t"> </span><span class="r"></span></p> <p class="run"><span class="n"><a id="t4" href="#t4">4</a></span><span class="t"><span class="key">def</span> <span class="nam">test_one</span><span class="op">(</span><span class="op">)</span><span class="op">:</span> </span><span class="r"><label for="ctxs4" class="ctx">(empty)</label></span></p> - <p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"> <span class="nam">a</span> <span class="op">=</span> <span class="num">5</span> </span><input type="checkbox" id="ctxs5" /><span class="r"><label for="ctxs5" class="ctx">1 ctx</label></span><span class="ctxs"><span>two_tests.test_one</span></span></p> - <p class="run"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"> <span class="nam">helper</span><span class="op">(</span><span class="num">6</span><span class="op">)</span> </span><input type="checkbox" id="ctxs6" /><span class="r"><label for="ctxs6" class="ctx">1 ctx</label></span><span class="ctxs"><span>two_tests.test_one</span></span></p> + <p class="run"><span class="n"><a id="t5" href="#t5">5</a></span><span class="t"> <span class="nam">a</span> <span class="op">=</span> <span class="num">5</span> </span><input type="checkbox" id="ctxs5" /><span class="r"><label for="ctxs5" class="ctx">1 ctx</label></span><span class="ctxs">2</span></p> + <p class="run"><span class="n"><a id="t6" href="#t6">6</a></span><span class="t"> <span class="nam">helper</span><span class="op">(</span><span class="num">6</span><span class="op">)</span> </span><input type="checkbox" id="ctxs6" /><span class="r"><label for="ctxs6" class="ctx">1 ctx</label></span><span class="ctxs">2</span></p> <p class="pln"><span class="n"><a id="t7" href="#t7">7</a></span><span class="t"> </span><span class="r"></span></p> <p class="run"><span class="n"><a id="t8" href="#t8">8</a></span><span class="t"><span class="key">def</span> <span class="nam">test_two</span><span class="op">(</span><span class="op">)</span><span class="op">:</span> </span><span class="r"><label for="ctxs8" class="ctx">(empty)</label></span></p> - <p class="run"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t"> <span class="nam">a</span> <span class="op">=</span> <span class="num">9</span> </span><input type="checkbox" id="ctxs9" /><span class="r"><label for="ctxs9" class="ctx">1 ctx</label></span><span class="ctxs"><span>two_tests.test_two</span></span></p> - <p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"> <span class="nam">b</span> <span class="op">=</span> <span class="num">10</span> </span><input type="checkbox" id="ctxs10" /><span class="r"><label for="ctxs10" class="ctx">1 ctx</label></span><span class="ctxs"><span>two_tests.test_two</span></span></p> - <p class="run"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t"> <span class="key">if</span> <span class="nam">a</span> <span class="op">></span> <span class="num">11</span><span class="op">:</span> </span><input type="checkbox" id="ctxs11" /><span class="r"><label for="ctxs11" class="ctx">1 ctx</label></span><span class="ctxs"><span>two_tests.test_two</span></span></p> + <p class="run"><span class="n"><a id="t9" href="#t9">9</a></span><span class="t"> <span class="nam">a</span> <span class="op">=</span> <span class="num">9</span> </span><input type="checkbox" id="ctxs9" /><span class="r"><label for="ctxs9" class="ctx">1 ctx</label></span><span class="ctxs">1</span></p> + <p class="run"><span class="n"><a id="t10" href="#t10">10</a></span><span class="t"> <span class="nam">b</span> <span class="op">=</span> <span class="num">10</span> </span><input type="checkbox" id="ctxs10" /><span class="r"><label for="ctxs10" class="ctx">1 ctx</label></span><span class="ctxs">1</span></p> + <p class="run"><span class="n"><a id="t11" href="#t11">11</a></span><span class="t"> <span class="key">if</span> <span class="nam">a</span> <span class="op">></span> <span class="num">11</span><span class="op">:</span> </span><input type="checkbox" id="ctxs11" /><span class="r"><label for="ctxs11" class="ctx">1 ctx</label></span><span class="ctxs">1</span></p> <p class="mis show_mis"><span class="n"><a id="t12" href="#t12">12</a></span><span class="t"> <span class="nam">b</span> <span class="op">=</span> <span class="num">12</span> </span><span class="r"></span></p> - <p class="run"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="key">assert</span> <span class="nam">a</span> <span class="op">==</span> <span class="op">(</span><span class="num">13</span><span class="op">-</span><span class="num">4</span><span class="op">)</span> </span><input type="checkbox" id="ctxs13" /><span class="r"><label for="ctxs13" class="ctx">1 ctx</label></span><span class="ctxs"><span>two_tests.test_two</span></span></p> - <p class="run"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t"> <span class="key">assert</span> <span class="nam">b</span> <span class="op">==</span> <span class="op">(</span><span class="num">14</span><span class="op">-</span><span class="num">4</span><span class="op">)</span> </span><input type="checkbox" id="ctxs14" /><span class="r"><label for="ctxs14" class="ctx">1 ctx</label></span><span class="ctxs"><span>two_tests.test_two</span></span></p> - <p class="run"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="nam">helper</span><span class="op">(</span> </span><input type="checkbox" id="ctxs15" /><span class="r"><label for="ctxs15" class="ctx">1 ctx</label></span><span class="ctxs"><span>two_tests.test_two</span></span></p> + <p class="run"><span class="n"><a id="t13" href="#t13">13</a></span><span class="t"> <span class="key">assert</span> <span class="nam">a</span> <span class="op">==</span> <span class="op">(</span><span class="num">13</span><span class="op">-</span><span class="num">4</span><span class="op">)</span> </span><input type="checkbox" id="ctxs13" /><span class="r"><label for="ctxs13" class="ctx">1 ctx</label></span><span class="ctxs">1</span></p> + <p class="run"><span class="n"><a id="t14" href="#t14">14</a></span><span class="t"> <span class="key">assert</span> <span class="nam">b</span> <span class="op">==</span> <span class="op">(</span><span class="num">14</span><span class="op">-</span><span class="num">4</span><span class="op">)</span> </span><input type="checkbox" id="ctxs14" /><span class="r"><label for="ctxs14" class="ctx">1 ctx</label></span><span class="ctxs">1</span></p> + <p class="run"><span class="n"><a id="t15" href="#t15">15</a></span><span class="t"> <span class="nam">helper</span><span class="op">(</span> </span><input type="checkbox" id="ctxs15" /><span class="r"><label for="ctxs15" class="ctx">1 ctx</label></span><span class="ctxs">1</span></p> <p class="pln"><span class="n"><a id="t16" href="#t16">16</a></span><span class="t"> <span class="num">16</span> </span><span class="r"></span></p> <p class="pln"><span class="n"><a id="t17" href="#t17">17</a></span><span class="t"> <span class="op">)</span> </span><span class="r"></span></p> <p class="pln"><span class="n"><a id="t18" href="#t18">18</a></span><span class="t"> </span><span class="r"></span></p> @@ -111,7 +118,7 @@ <a id="nextFileLink" class="nav" href="index.html">» next</a> <a class="nav" href="https://coverage.readthedocs.io/en/7.2.3a0.dev1">coverage.py v7.2.3a0.dev1</a>, - created at 2023-03-21 08:44 -0400 + created at 2023-03-22 16:13 +0100 </p> </div> </footer> diff --git a/tests/gold/html/styled/style.css b/tests/gold/html/styled/style.css index d6768a35..ace48c2c 100644 --- a/tests/gold/html/styled/style.css +++ b/tests/gold/html/styled/style.css @@ -258,7 +258,7 @@ kbd { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em @media (prefers-color-scheme: dark) { #source p label.ctx { color: #777; } } -#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; white-space: nowrap; background: #d0e8ff; border-radius: .25em; margin-right: 1.75em; } +#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; white-space: nowrap; background: #d0e8ff; border-radius: .25em; margin-right: 1.75em; text-align: right; } @media (prefers-color-scheme: dark) { #source p .ctxs { background: #056; } } |