coverage 7.6.7__cp311-cp311-win_amd64.whl → 7.11.1__cp311-cp311-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coverage/__init__.py +2 -0
- coverage/__main__.py +2 -0
- coverage/annotate.py +1 -2
- coverage/bytecode.py +177 -3
- coverage/cmdline.py +329 -154
- coverage/collector.py +31 -42
- coverage/config.py +166 -62
- coverage/context.py +4 -5
- coverage/control.py +164 -85
- coverage/core.py +70 -33
- coverage/data.py +3 -4
- coverage/debug.py +112 -56
- coverage/disposition.py +1 -0
- coverage/env.py +65 -55
- coverage/exceptions.py +35 -7
- coverage/execfile.py +18 -13
- coverage/files.py +23 -18
- coverage/html.py +134 -88
- coverage/htmlfiles/style.css +42 -2
- coverage/htmlfiles/style.scss +65 -1
- coverage/inorout.py +61 -44
- coverage/jsonreport.py +17 -8
- coverage/lcovreport.py +16 -20
- coverage/misc.py +50 -46
- coverage/multiproc.py +12 -7
- coverage/numbits.py +3 -4
- coverage/parser.py +193 -269
- coverage/patch.py +166 -0
- coverage/phystokens.py +24 -25
- coverage/plugin.py +13 -13
- coverage/plugin_support.py +36 -35
- coverage/python.py +9 -13
- coverage/pytracer.py +40 -33
- coverage/regions.py +2 -1
- coverage/report.py +59 -43
- coverage/report_core.py +6 -9
- coverage/results.py +118 -66
- coverage/sqldata.py +260 -210
- coverage/sqlitedb.py +33 -25
- coverage/sysmon.py +195 -157
- coverage/templite.py +6 -6
- coverage/tomlconfig.py +12 -12
- coverage/tracer.cp311-win_amd64.pyd +0 -0
- coverage/tracer.pyi +2 -0
- coverage/types.py +25 -22
- coverage/version.py +3 -18
- coverage/xmlreport.py +16 -13
- {coverage-7.6.7.dist-info → coverage-7.11.1.dist-info}/METADATA +40 -18
- coverage-7.11.1.dist-info/RECORD +59 -0
- {coverage-7.6.7.dist-info → coverage-7.11.1.dist-info}/WHEEL +1 -1
- coverage-7.6.7.dist-info/RECORD +0 -58
- {coverage-7.6.7.dist-info → coverage-7.11.1.dist-info}/entry_points.txt +0 -0
- {coverage-7.6.7.dist-info → coverage-7.11.1.dist-info/licenses}/LICENSE.txt +0 -0
- {coverage-7.6.7.dist-info → coverage-7.11.1.dist-info}/top_level.txt +0 -0
coverage/html.py
CHANGED
|
@@ -13,26 +13,30 @@ import json
|
|
|
13
13
|
import os
|
|
14
14
|
import re
|
|
15
15
|
import string
|
|
16
|
-
|
|
17
|
-
from dataclasses import dataclass, field
|
|
18
|
-
from typing import Any, TYPE_CHECKING
|
|
19
16
|
from collections.abc import Iterable
|
|
17
|
+
from dataclasses import dataclass, field
|
|
18
|
+
from typing import TYPE_CHECKING, Any
|
|
20
19
|
|
|
21
20
|
import coverage
|
|
22
21
|
from coverage.data import CoverageData, add_data_to_hash
|
|
23
22
|
from coverage.exceptions import NoDataError
|
|
24
23
|
from coverage.files import flat_rootname
|
|
25
24
|
from coverage.misc import (
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
Hasher,
|
|
26
|
+
ensure_dir,
|
|
27
|
+
file_be_gone,
|
|
28
|
+
format_local_datetime,
|
|
29
|
+
human_sorted,
|
|
30
|
+
isolate_module,
|
|
31
|
+
plural,
|
|
32
|
+
stdout_link,
|
|
28
33
|
)
|
|
29
34
|
from coverage.report_core import get_analysis_to_report
|
|
30
|
-
from coverage.results import Analysis, Numbers
|
|
35
|
+
from coverage.results import Analysis, AnalysisNarrower, Numbers
|
|
31
36
|
from coverage.templite import Templite
|
|
32
37
|
from coverage.types import TLineNo, TMorf
|
|
33
38
|
from coverage.version import __url__
|
|
34
39
|
|
|
35
|
-
|
|
36
40
|
if TYPE_CHECKING:
|
|
37
41
|
from coverage import Coverage
|
|
38
42
|
from coverage.plugins import FileReporter
|
|
@@ -42,8 +46,7 @@ os = isolate_module(os)
|
|
|
42
46
|
|
|
43
47
|
|
|
44
48
|
def data_filename(fname: str) -> str:
|
|
45
|
-
"""Return the path to an "htmlfiles" data file of ours.
|
|
46
|
-
"""
|
|
49
|
+
"""Return the path to an "htmlfiles" data file of ours."""
|
|
47
50
|
static_dir = os.path.join(os.path.dirname(__file__), "htmlfiles")
|
|
48
51
|
static_filename = os.path.join(static_dir, fname)
|
|
49
52
|
return static_filename
|
|
@@ -51,7 +54,7 @@ def data_filename(fname: str) -> str:
|
|
|
51
54
|
|
|
52
55
|
def read_data(fname: str) -> str:
|
|
53
56
|
"""Return the contents of a data file of ours."""
|
|
54
|
-
with open(data_filename(fname)) as data_file:
|
|
57
|
+
with open(data_filename(fname), encoding="utf-8") as data_file:
|
|
55
58
|
return data_file.read()
|
|
56
59
|
|
|
57
60
|
|
|
@@ -65,6 +68,7 @@ def write_html(fname: str, html: str) -> None:
|
|
|
65
68
|
@dataclass
|
|
66
69
|
class LineData:
|
|
67
70
|
"""The data for each source line of HTML output."""
|
|
71
|
+
|
|
68
72
|
tokens: list[tuple[str, str]]
|
|
69
73
|
number: TLineNo
|
|
70
74
|
category: str
|
|
@@ -83,6 +87,7 @@ class LineData:
|
|
|
83
87
|
@dataclass
|
|
84
88
|
class FileData:
|
|
85
89
|
"""The data for each source file of HTML output."""
|
|
90
|
+
|
|
86
91
|
relative_filename: str
|
|
87
92
|
nums: Numbers
|
|
88
93
|
lines: list[LineData]
|
|
@@ -91,6 +96,7 @@ class FileData:
|
|
|
91
96
|
@dataclass
|
|
92
97
|
class IndexItem:
|
|
93
98
|
"""Information for each index entry, to render an index page."""
|
|
99
|
+
|
|
94
100
|
url: str = ""
|
|
95
101
|
file: str = ""
|
|
96
102
|
description: str = ""
|
|
@@ -100,6 +106,7 @@ class IndexItem:
|
|
|
100
106
|
@dataclass
|
|
101
107
|
class IndexPage:
|
|
102
108
|
"""Data for each index page."""
|
|
109
|
+
|
|
103
110
|
noun: str
|
|
104
111
|
plural: str
|
|
105
112
|
filename: str
|
|
@@ -137,10 +144,14 @@ class HtmlDataGeneration:
|
|
|
137
144
|
contexts_by_lineno = self.data.contexts_by_lineno(analysis.filename)
|
|
138
145
|
|
|
139
146
|
lines = []
|
|
147
|
+
branch_stats = analysis.branch_stats()
|
|
148
|
+
multiline_map = {}
|
|
149
|
+
if hasattr(fr, "multiline_map"):
|
|
150
|
+
multiline_map = fr.multiline_map()
|
|
140
151
|
|
|
141
152
|
for lineno, tokens in enumerate(fr.source_token_lines(), start=1):
|
|
142
153
|
# Figure out how to mark this line.
|
|
143
|
-
category = ""
|
|
154
|
+
category = category2 = ""
|
|
144
155
|
short_annotations = []
|
|
145
156
|
long_annotations = []
|
|
146
157
|
|
|
@@ -150,14 +161,36 @@ class HtmlDataGeneration:
|
|
|
150
161
|
category = "mis"
|
|
151
162
|
elif self.has_arcs and lineno in missing_branch_arcs:
|
|
152
163
|
category = "par"
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
164
|
+
mba = missing_branch_arcs[lineno]
|
|
165
|
+
if len(mba) == branch_stats[lineno][0]:
|
|
166
|
+
# None of the branches were taken from this line.
|
|
167
|
+
short_annotations.append("anywhere")
|
|
168
|
+
long_annotations.append(
|
|
169
|
+
f"line {lineno} didn't jump anywhere: it always raised an exception."
|
|
170
|
+
)
|
|
171
|
+
else:
|
|
172
|
+
for b in missing_branch_arcs[lineno]:
|
|
173
|
+
if b < 0:
|
|
174
|
+
short_annotations.append("exit")
|
|
175
|
+
else:
|
|
176
|
+
short_annotations.append(str(b))
|
|
177
|
+
long_annotations.append(
|
|
178
|
+
fr.missing_arc_description(lineno, b, arcs_executed)
|
|
179
|
+
)
|
|
159
180
|
elif lineno in analysis.statements:
|
|
160
181
|
category = "run"
|
|
182
|
+
elif first_line := multiline_map.get(lineno):
|
|
183
|
+
if first_line in analysis.excluded:
|
|
184
|
+
category2 = "exc2"
|
|
185
|
+
elif first_line in analysis.missing:
|
|
186
|
+
category2 = "mis2"
|
|
187
|
+
elif self.has_arcs and first_line in missing_branch_arcs:
|
|
188
|
+
category2 = "par2"
|
|
189
|
+
# I don't understand why this last condition is marked as
|
|
190
|
+
# partial. If I add an else with an exception, the exception
|
|
191
|
+
# is raised.
|
|
192
|
+
elif first_line in analysis.statements: # pragma: part covered
|
|
193
|
+
category2 = "run2"
|
|
161
194
|
|
|
162
195
|
contexts = []
|
|
163
196
|
contexts_label = ""
|
|
@@ -170,16 +203,18 @@ class HtmlDataGeneration:
|
|
|
170
203
|
contexts_label = f"{len(contexts)} ctx"
|
|
171
204
|
context_list = contexts
|
|
172
205
|
|
|
173
|
-
lines.append(
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
206
|
+
lines.append(
|
|
207
|
+
LineData(
|
|
208
|
+
tokens=tokens,
|
|
209
|
+
number=lineno,
|
|
210
|
+
category=category or category2,
|
|
211
|
+
contexts=contexts,
|
|
212
|
+
contexts_label=contexts_label,
|
|
213
|
+
context_list=context_list,
|
|
214
|
+
short_annotations=short_annotations,
|
|
215
|
+
long_annotations=long_annotations,
|
|
216
|
+
)
|
|
217
|
+
)
|
|
183
218
|
|
|
184
219
|
file_data = FileData(
|
|
185
220
|
relative_filename=fr.relative_filename(),
|
|
@@ -192,6 +227,7 @@ class HtmlDataGeneration:
|
|
|
192
227
|
|
|
193
228
|
class FileToReport:
|
|
194
229
|
"""A file we're considering reporting."""
|
|
230
|
+
|
|
195
231
|
def __init__(self, fr: FileReporter, analysis: Analysis) -> None:
|
|
196
232
|
self.fr = fr
|
|
197
233
|
self.analysis = analysis
|
|
@@ -202,6 +238,7 @@ class FileToReport:
|
|
|
202
238
|
|
|
203
239
|
HTML_SAFE = string.ascii_letters + string.digits + "!#$%'()*+,-./:;=?@[]^_`{|}~"
|
|
204
240
|
|
|
241
|
+
|
|
205
242
|
@functools.cache
|
|
206
243
|
def encode_int(n: int) -> str:
|
|
207
244
|
"""Create a short HTML-safe string from an integer, using HTML_SAFE."""
|
|
@@ -277,7 +314,6 @@ class HtmlReporter:
|
|
|
277
314
|
"escape": escape,
|
|
278
315
|
"pair": pair,
|
|
279
316
|
"len": len,
|
|
280
|
-
|
|
281
317
|
# Constants for this report.
|
|
282
318
|
"__url__": __url__,
|
|
283
319
|
"__version__": coverage.__version__,
|
|
@@ -287,7 +323,6 @@ class HtmlReporter:
|
|
|
287
323
|
"has_arcs": self.has_arcs,
|
|
288
324
|
"show_contexts": self.config.show_contexts,
|
|
289
325
|
"statics": {},
|
|
290
|
-
|
|
291
326
|
# Constants for all reports.
|
|
292
327
|
# These css classes determine which lines are highlighted by default.
|
|
293
328
|
"category": {
|
|
@@ -295,6 +330,10 @@ class HtmlReporter:
|
|
|
295
330
|
"mis": "mis show_mis",
|
|
296
331
|
"par": "par run show_par",
|
|
297
332
|
"run": "run",
|
|
333
|
+
"exc2": "exc exc2 show_exc",
|
|
334
|
+
"mis2": "mis mis2 show_mis",
|
|
335
|
+
"par2": "par par2 ru2 show_par",
|
|
336
|
+
"run2": "run run2",
|
|
298
337
|
},
|
|
299
338
|
}
|
|
300
339
|
self.index_tmpl = Templite(read_data("index.html"), self.template_globals)
|
|
@@ -383,7 +422,7 @@ class HtmlReporter:
|
|
|
383
422
|
dest = copy_with_cache_bust(src, self.directory)
|
|
384
423
|
if not slug:
|
|
385
424
|
slug = os.path.basename(src).replace(".", "_")
|
|
386
|
-
self.template_globals["statics"][slug] = dest
|
|
425
|
+
self.template_globals["statics"][slug] = dest # type: ignore
|
|
387
426
|
|
|
388
427
|
def make_local_static_report_files(self) -> None:
|
|
389
428
|
"""Make local instances of static files for HTML report."""
|
|
@@ -401,7 +440,7 @@ class HtmlReporter:
|
|
|
401
440
|
# .gitignore can't be copied from the source tree because if it was in
|
|
402
441
|
# the source tree, it would stop the static files from being checked in.
|
|
403
442
|
if self.directory_was_empty:
|
|
404
|
-
with open(os.path.join(self.directory, ".gitignore"), "w") as fgi:
|
|
443
|
+
with open(os.path.join(self.directory, ".gitignore"), "w", encoding="utf-8") as fgi:
|
|
405
444
|
fgi.write("# Created by coverage.py\n*\n")
|
|
406
445
|
|
|
407
446
|
def should_report(self, analysis: Analysis, index_page: IndexPage) -> bool:
|
|
@@ -412,8 +451,8 @@ class HtmlReporter:
|
|
|
412
451
|
|
|
413
452
|
if self.skip_covered:
|
|
414
453
|
# Don't report on 100% files.
|
|
415
|
-
no_missing_lines = (nums.n_missing == 0)
|
|
416
|
-
no_missing_branches = (nums.n_partial_branches == 0)
|
|
454
|
+
no_missing_lines = (nums.n_missing == 0) # fmt: skip
|
|
455
|
+
no_missing_branches = (nums.n_partial_branches == 0) # fmt: skip
|
|
417
456
|
if no_missing_lines and no_missing_branches:
|
|
418
457
|
index_page.skipped_covered_count += 1
|
|
419
458
|
return False
|
|
@@ -467,9 +506,8 @@ class HtmlReporter:
|
|
|
467
506
|
encode_int(context_codes[c_context]) for c_context in ldata.context_list
|
|
468
507
|
]
|
|
469
508
|
code_width = max(len(ec) for ec in encoded_contexts)
|
|
470
|
-
ldata.context_str = (
|
|
471
|
-
|
|
472
|
-
+ "".join(ec.ljust(code_width) for ec in encoded_contexts)
|
|
509
|
+
ldata.context_str = str(code_width) + "".join(
|
|
510
|
+
ec.ljust(code_width) for ec in encoded_contexts
|
|
473
511
|
)
|
|
474
512
|
else:
|
|
475
513
|
ldata.context_str = ""
|
|
@@ -478,48 +516,45 @@ class HtmlReporter:
|
|
|
478
516
|
# 202F is NARROW NO-BREAK SPACE.
|
|
479
517
|
# 219B is RIGHTWARDS ARROW WITH STROKE.
|
|
480
518
|
ldata.annotate = ", ".join(
|
|
481
|
-
f"{ldata.number} ↛ {d}"
|
|
482
|
-
for d in ldata.short_annotations
|
|
519
|
+
f"{ldata.number} ↛ {d}" for d in ldata.short_annotations
|
|
483
520
|
)
|
|
484
521
|
else:
|
|
485
522
|
ldata.annotate = None
|
|
486
523
|
|
|
487
524
|
if ldata.long_annotations:
|
|
488
525
|
longs = ldata.long_annotations
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
f"{num:d}) {ann_long}"
|
|
496
|
-
for num, ann_long in enumerate(longs, start=1)
|
|
497
|
-
),
|
|
498
|
-
)
|
|
526
|
+
# A line can only have two branch destinations. If there were
|
|
527
|
+
# two missing, we would have written one as "always raised."
|
|
528
|
+
assert len(longs) == 1, (
|
|
529
|
+
f"Had long annotations in {ftr.fr.relative_filename()}: {longs}"
|
|
530
|
+
)
|
|
531
|
+
ldata.annotate_long = longs[0]
|
|
499
532
|
else:
|
|
500
533
|
ldata.annotate_long = None
|
|
501
534
|
|
|
502
535
|
css_classes = []
|
|
503
536
|
if ldata.category:
|
|
504
537
|
css_classes.append(
|
|
505
|
-
self.template_globals["category"][ldata.category],
|
|
538
|
+
self.template_globals["category"][ldata.category], # type: ignore[index]
|
|
506
539
|
)
|
|
507
540
|
ldata.css_class = " ".join(css_classes) or "pln"
|
|
508
541
|
|
|
509
542
|
html_path = os.path.join(self.directory, ftr.html_filename)
|
|
510
|
-
html = self.source_tmpl.render(
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
543
|
+
html = self.source_tmpl.render(
|
|
544
|
+
{
|
|
545
|
+
**file_data.__dict__,
|
|
546
|
+
"contexts_json": contexts_json,
|
|
547
|
+
"prev_html": ftr.prev_html,
|
|
548
|
+
"next_html": ftr.next_html,
|
|
549
|
+
}
|
|
550
|
+
)
|
|
516
551
|
write_html(html_path, html)
|
|
517
552
|
|
|
518
553
|
# Save this file's information for the index page.
|
|
519
554
|
index_info = IndexItem(
|
|
520
|
-
url
|
|
521
|
-
file
|
|
522
|
-
nums
|
|
555
|
+
url=ftr.html_filename,
|
|
556
|
+
file=escape(ftr.fr.relative_filename()),
|
|
557
|
+
nums=ftr.analysis.numbers,
|
|
523
558
|
)
|
|
524
559
|
self.index_pages["file"].summaries.append(index_info)
|
|
525
560
|
self.incr.set_index_info(ftr.rootname, index_info)
|
|
@@ -547,39 +582,51 @@ class HtmlReporter:
|
|
|
547
582
|
|
|
548
583
|
for noun in region_nouns:
|
|
549
584
|
page_data = self.index_pages[noun]
|
|
550
|
-
outside_lines = set(range(1, num_lines + 1))
|
|
551
585
|
|
|
586
|
+
outside_lines = set(range(1, num_lines + 1))
|
|
552
587
|
for region in regions:
|
|
553
588
|
if region.kind != noun:
|
|
554
589
|
continue
|
|
555
590
|
outside_lines -= region.lines
|
|
556
|
-
|
|
591
|
+
|
|
592
|
+
narrower = AnalysisNarrower(ftr.analysis)
|
|
593
|
+
narrower.add_regions(r.lines for r in regions if r.kind == noun)
|
|
594
|
+
narrower.add_regions([outside_lines])
|
|
595
|
+
|
|
596
|
+
for region in regions:
|
|
597
|
+
if region.kind != noun:
|
|
598
|
+
continue
|
|
599
|
+
analysis = narrower.narrow(region.lines)
|
|
557
600
|
if not self.should_report(analysis, page_data):
|
|
558
601
|
continue
|
|
559
602
|
sorting_name = region.name.rpartition(".")[-1].lstrip("_")
|
|
560
|
-
page_data.summaries.append(
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
603
|
+
page_data.summaries.append(
|
|
604
|
+
IndexItem(
|
|
605
|
+
url=f"{ftr.html_filename}#t{region.start}",
|
|
606
|
+
file=escape(ftr.fr.relative_filename()),
|
|
607
|
+
description=(
|
|
608
|
+
f"<data value='{escape(sorting_name)}'>"
|
|
609
|
+
+ escape(region.name)
|
|
610
|
+
+ "</data>"
|
|
611
|
+
),
|
|
612
|
+
nums=analysis.numbers,
|
|
613
|
+
)
|
|
614
|
+
)
|
|
615
|
+
|
|
616
|
+
analysis = narrower.narrow(outside_lines)
|
|
572
617
|
if self.should_report(analysis, page_data):
|
|
573
|
-
page_data.summaries.append(
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
618
|
+
page_data.summaries.append(
|
|
619
|
+
IndexItem(
|
|
620
|
+
url=ftr.html_filename,
|
|
621
|
+
file=escape(ftr.fr.relative_filename()),
|
|
622
|
+
description=(
|
|
623
|
+
"<data value=''>"
|
|
624
|
+
+ f"<span class='no-noun'>(no {escape(noun)})</span>"
|
|
625
|
+
+ "</data>"
|
|
626
|
+
),
|
|
627
|
+
nums=analysis.numbers,
|
|
628
|
+
)
|
|
629
|
+
)
|
|
583
630
|
|
|
584
631
|
for noun, index_page in self.index_pages.items():
|
|
585
632
|
if noun != "file":
|
|
@@ -629,6 +676,7 @@ class HtmlReporter:
|
|
|
629
676
|
@dataclass
|
|
630
677
|
class FileInfo:
|
|
631
678
|
"""Summary of the information from last rendering, to avoid duplicate work."""
|
|
679
|
+
|
|
632
680
|
hash: str = ""
|
|
633
681
|
index: IndexItem = field(default_factory=IndexItem)
|
|
634
682
|
|
|
@@ -699,7 +747,7 @@ class IncrementalChecker:
|
|
|
699
747
|
"""Read the information we stored last time."""
|
|
700
748
|
try:
|
|
701
749
|
status_file = os.path.join(self.directory, self.STATUS_FILE)
|
|
702
|
-
with open(status_file) as fstatus:
|
|
750
|
+
with open(status_file, encoding="utf-8") as fstatus:
|
|
703
751
|
status = json.load(fstatus)
|
|
704
752
|
except (OSError, ValueError):
|
|
705
753
|
# Status file is missing or malformed.
|
|
@@ -735,12 +783,9 @@ class IncrementalChecker:
|
|
|
735
783
|
"format": self.STATUS_FORMAT,
|
|
736
784
|
"version": coverage.__version__,
|
|
737
785
|
"globals": self.globals,
|
|
738
|
-
"files": {
|
|
739
|
-
fname: dataclasses.asdict(finfo)
|
|
740
|
-
for fname, finfo in self.files.items()
|
|
741
|
-
},
|
|
786
|
+
"files": {fname: dataclasses.asdict(finfo) for fname, finfo in self.files.items()},
|
|
742
787
|
}
|
|
743
|
-
with open(status_file, "w") as fout:
|
|
788
|
+
with open(status_file, "w", encoding="utf-8") as fout:
|
|
744
789
|
json.dump(status_data, fout, separators=(",", ":"))
|
|
745
790
|
|
|
746
791
|
def check_global_data(self, *data: Any) -> None:
|
|
@@ -795,6 +840,7 @@ class IncrementalChecker:
|
|
|
795
840
|
|
|
796
841
|
# Helpers for templates and generating HTML
|
|
797
842
|
|
|
843
|
+
|
|
798
844
|
def escape(t: str) -> str:
|
|
799
845
|
"""HTML-escape the text in `t`.
|
|
800
846
|
|
coverage/htmlfiles/style.css
CHANGED
|
@@ -200,9 +200,9 @@ kbd { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em
|
|
|
200
200
|
|
|
201
201
|
#source p .t .key { font-weight: bold; line-height: 1px; }
|
|
202
202
|
|
|
203
|
-
#source p .t .str { color: #0451a5; }
|
|
203
|
+
#source p .t .str, #source p .t .fst { color: #0451a5; }
|
|
204
204
|
|
|
205
|
-
@media (prefers-color-scheme: dark) { #source p .t .str { color: #9cdcfe; } }
|
|
205
|
+
@media (prefers-color-scheme: dark) { #source p .t .str, #source p .t .fst { color: #9cdcfe; } }
|
|
206
206
|
|
|
207
207
|
#source p.mis .t { border-left: 0.2em solid #ff0000; }
|
|
208
208
|
|
|
@@ -214,6 +214,16 @@ kbd { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em
|
|
|
214
214
|
|
|
215
215
|
@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t:hover { background: #532323; } }
|
|
216
216
|
|
|
217
|
+
#source p.mis.mis2 .t { border-left: 0.2em dotted #ff0000; }
|
|
218
|
+
|
|
219
|
+
#source p.mis.mis2.show_mis .t { background: #ffeeee; }
|
|
220
|
+
|
|
221
|
+
@media (prefers-color-scheme: dark) { #source p.mis.mis2.show_mis .t { background: #351b1b; } }
|
|
222
|
+
|
|
223
|
+
#source p.mis.mis2.show_mis .t:hover { background: #f2d2d2; }
|
|
224
|
+
|
|
225
|
+
@media (prefers-color-scheme: dark) { #source p.mis.mis2.show_mis .t:hover { background: #532323; } }
|
|
226
|
+
|
|
217
227
|
#source p.run .t { border-left: 0.2em solid #00dd00; }
|
|
218
228
|
|
|
219
229
|
#source p.run.show_run .t { background: #dfd; }
|
|
@@ -224,6 +234,16 @@ kbd { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em
|
|
|
224
234
|
|
|
225
235
|
@media (prefers-color-scheme: dark) { #source p.run.show_run .t:hover { background: #404633; } }
|
|
226
236
|
|
|
237
|
+
#source p.run.run2 .t { border-left: 0.2em dotted #00dd00; }
|
|
238
|
+
|
|
239
|
+
#source p.run.run2.show_run .t { background: #eeffee; }
|
|
240
|
+
|
|
241
|
+
@media (prefers-color-scheme: dark) { #source p.run.run2.show_run .t { background: #2b2e24; } }
|
|
242
|
+
|
|
243
|
+
#source p.run.run2.show_run .t:hover { background: #d2f2d2; }
|
|
244
|
+
|
|
245
|
+
@media (prefers-color-scheme: dark) { #source p.run.run2.show_run .t:hover { background: #404633; } }
|
|
246
|
+
|
|
227
247
|
#source p.exc .t { border-left: 0.2em solid #808080; }
|
|
228
248
|
|
|
229
249
|
#source p.exc.show_exc .t { background: #eee; }
|
|
@@ -234,6 +254,16 @@ kbd { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em
|
|
|
234
254
|
|
|
235
255
|
@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t:hover { background: #3c3c3c; } }
|
|
236
256
|
|
|
257
|
+
#source p.exc.exc2 .t { border-left: 0.2em dotted #808080; }
|
|
258
|
+
|
|
259
|
+
#source p.exc.exc2.show_exc .t { background: #f7f7f7; }
|
|
260
|
+
|
|
261
|
+
@media (prefers-color-scheme: dark) { #source p.exc.exc2.show_exc .t { background: #292929; } }
|
|
262
|
+
|
|
263
|
+
#source p.exc.exc2.show_exc .t:hover { background: #e2e2e2; }
|
|
264
|
+
|
|
265
|
+
@media (prefers-color-scheme: dark) { #source p.exc.exc2.show_exc .t:hover { background: #3c3c3c; } }
|
|
266
|
+
|
|
237
267
|
#source p.par .t { border-left: 0.2em solid #bbbb00; }
|
|
238
268
|
|
|
239
269
|
#source p.par.show_par .t { background: #ffa; }
|
|
@@ -244,6 +274,16 @@ kbd { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em
|
|
|
244
274
|
|
|
245
275
|
@media (prefers-color-scheme: dark) { #source p.par.show_par .t:hover { background: #6d5d0c; } }
|
|
246
276
|
|
|
277
|
+
#source p.par.par2 .t { border-left: 0.2em dotted #bbbb00; }
|
|
278
|
+
|
|
279
|
+
#source p.par.par2.show_par .t { background: #ffffd5; }
|
|
280
|
+
|
|
281
|
+
@media (prefers-color-scheme: dark) { #source p.par.par2.show_par .t { background: #423a0f; } }
|
|
282
|
+
|
|
283
|
+
#source p.par.par2.show_par .t:hover { background: #f2f2a2; }
|
|
284
|
+
|
|
285
|
+
@media (prefers-color-scheme: dark) { #source p.par.par2.show_par .t:hover { background: #6d5d0c; } }
|
|
286
|
+
|
|
247
287
|
#source p .r { position: absolute; top: 0; right: 2.5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; }
|
|
248
288
|
|
|
249
289
|
#source p .annotate { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; color: #666; padding-right: .5em; }
|
coverage/htmlfiles/style.scss
CHANGED
|
@@ -27,6 +27,7 @@ $font-code: SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
|
27
27
|
|
|
28
28
|
$off-button-lighten: 50%;
|
|
29
29
|
$hover-dark-amt: 95%;
|
|
30
|
+
$multi-dim-amt: 50%;
|
|
30
31
|
|
|
31
32
|
$focus-color: #007acc;
|
|
32
33
|
|
|
@@ -501,7 +502,7 @@ $border-indicator-width: .2em;
|
|
|
501
502
|
font-weight: bold;
|
|
502
503
|
line-height: 1px;
|
|
503
504
|
}
|
|
504
|
-
.str {
|
|
505
|
+
.str, .fst {
|
|
505
506
|
color: $light-token-str;
|
|
506
507
|
@include color-dark($dark-token-str);
|
|
507
508
|
}
|
|
@@ -521,6 +522,22 @@ $border-indicator-width: .2em;
|
|
|
521
522
|
@include background-dark(mix($dark-mis-bg, $dark-fg, $hover-dark-amt));
|
|
522
523
|
}
|
|
523
524
|
}
|
|
525
|
+
|
|
526
|
+
&.mis2 {
|
|
527
|
+
.t {
|
|
528
|
+
border-left: $border-indicator-width dotted $mis-color;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
&.show_mis .t {
|
|
532
|
+
background: mix($light-mis-bg, $light-bg, $multi-dim-amt);
|
|
533
|
+
@include background-dark(mix($dark-mis-bg, $dark-bg, $multi-dim-amt));
|
|
534
|
+
|
|
535
|
+
&:hover {
|
|
536
|
+
background: mix($light-mis-bg, $light-fg, $hover-dark-amt);
|
|
537
|
+
@include background-dark(mix($dark-mis-bg, $dark-fg, $hover-dark-amt));
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
524
541
|
}
|
|
525
542
|
|
|
526
543
|
&.run {
|
|
@@ -537,6 +554,22 @@ $border-indicator-width: .2em;
|
|
|
537
554
|
@include background-dark(mix($dark-run-bg, $dark-fg, $hover-dark-amt));
|
|
538
555
|
}
|
|
539
556
|
}
|
|
557
|
+
|
|
558
|
+
&.run2 {
|
|
559
|
+
.t {
|
|
560
|
+
border-left: $border-indicator-width dotted $run-color;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
&.show_run .t {
|
|
564
|
+
background: mix($light-run-bg, $light-bg, $multi-dim-amt);
|
|
565
|
+
@include background-dark(mix($dark-run-bg, $dark-bg, $multi-dim-amt));
|
|
566
|
+
|
|
567
|
+
&:hover {
|
|
568
|
+
background: mix($light-run-bg, $light-fg, $hover-dark-amt);
|
|
569
|
+
@include background-dark(mix($dark-run-bg, $dark-fg, $hover-dark-amt));
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
540
573
|
}
|
|
541
574
|
|
|
542
575
|
&.exc {
|
|
@@ -553,6 +586,22 @@ $border-indicator-width: .2em;
|
|
|
553
586
|
@include background-dark(mix($dark-exc-bg, $dark-fg, $hover-dark-amt));
|
|
554
587
|
}
|
|
555
588
|
}
|
|
589
|
+
|
|
590
|
+
&.exc2 {
|
|
591
|
+
.t {
|
|
592
|
+
border-left: $border-indicator-width dotted $exc-color;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
&.show_exc .t {
|
|
596
|
+
background: mix($light-exc-bg, $light-bg, $multi-dim-amt);
|
|
597
|
+
@include background-dark(mix($dark-exc-bg, $dark-bg, $multi-dim-amt));
|
|
598
|
+
|
|
599
|
+
&:hover {
|
|
600
|
+
background: mix($light-exc-bg, $light-fg, $hover-dark-amt);
|
|
601
|
+
@include background-dark(mix($dark-exc-bg, $dark-fg, $hover-dark-amt));
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
556
605
|
}
|
|
557
606
|
|
|
558
607
|
&.par {
|
|
@@ -570,6 +619,21 @@ $border-indicator-width: .2em;
|
|
|
570
619
|
}
|
|
571
620
|
}
|
|
572
621
|
|
|
622
|
+
&.par2 {
|
|
623
|
+
.t {
|
|
624
|
+
border-left: $border-indicator-width dotted $par-color;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
&.show_par .t {
|
|
628
|
+
background: mix($light-par-bg, $light-bg, $multi-dim-amt);
|
|
629
|
+
@include background-dark(mix($dark-par-bg, $dark-bg, $multi-dim-amt));
|
|
630
|
+
|
|
631
|
+
&:hover {
|
|
632
|
+
background: mix($light-par-bg, $light-fg, $hover-dark-amt);
|
|
633
|
+
@include background-dark(mix($dark-par-bg, $dark-fg, $hover-dark-amt));
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
573
637
|
}
|
|
574
638
|
|
|
575
639
|
.r {
|