Skip to content

Commit ba2ffa8

Browse files
committed
Add HTML report type with tooltips
This adds a HTML reporter that will produce mouse-over type tooltips in the output. The command line argument is --xslt-html-tooltips-report.
1 parent e56f751 commit ba2ffa8

File tree

4 files changed

+149
-2
lines changed

4 files changed

+149
-2
lines changed

mypy/report.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ def __init__(self, reports: Reports, output_dir: str) -> None:
288288

289289
self.xslt_html_path = os.path.join(
290290
reports.data_dir, 'xml', 'mypy-html.xslt')
291+
self.xslt_html_tooltips_path = os.path.join(
292+
reports.data_dir, 'xml', 'mypy-html-tooltips.xslt')
291293
self.xslt_txt_path = os.path.join(
292294
reports.data_dir, 'xml', 'mypy-txt.xslt')
293295
self.css_html_path = os.path.join(
@@ -563,10 +565,12 @@ class XsltHtmlReporter(AbstractXmlReporter):
563565
def __init__(self, reports: Reports, output_dir: str) -> None:
564566
super().__init__(reports, output_dir)
565567

566-
self.xslt_html = etree.XSLT(
567-
etree.parse(self.memory_xml.xslt_html_path))
568+
self.xslt_html = etree.XSLT(etree.parse(self.xslt_file_to_use()))
568569
self.param_html = etree.XSLT.strparam('html')
569570

571+
def xslt_file_to_use(self) -> str:
572+
return self.memory_xml.xslt_html_path
573+
570574
def on_file(self, tree: MypyFile, type_map: Dict[Expression, Type]) -> None:
571575
last_xml = self.memory_xml.last_xml
572576
if last_xml is None:
@@ -594,6 +598,19 @@ def on_finish(self) -> None:
594598
register_reporter('xslt-html', XsltHtmlReporter, needs_lxml=True)
595599

596600

601+
class XsltHtmlTooltipsReporter(XsltHtmlReporter):
602+
def __init__(self, reports: Reports, output_dir: str) -> None:
603+
super().__init__(reports, output_dir)
604+
self.memory_xml.set_type_columns(True)
605+
606+
def xslt_file_to_use(self) -> str:
607+
return self.memory_xml.xslt_html_tooltips_path
608+
609+
610+
register_reporter('xslt-html-tooltips',
611+
XsltHtmlTooltipsReporter, needs_lxml=True)
612+
613+
597614
class XsltTxtReporter(AbstractXmlReporter):
598615
"""Public reporter that exports TXT via XSLT.
599616

xml/mypy-html-tooltips.xslt

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- vim: set sts=2 sw=2: -->
3+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4+
<xsl:param name="ext" select="'xml'"/>
5+
<xsl:output method="html"/>
6+
<xsl:variable name="xml_stylesheet_pi" select="string(//processing-instruction('xml-stylesheet'))"/>
7+
<xsl:variable name="stylesheet_name" select="substring($xml_stylesheet_pi, 23, string-length($xml_stylesheet_pi) - 28)"/>
8+
<xsl:template match="/mypy-report-index">
9+
<xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html&gt;&#10;</xsl:text>
10+
<html>
11+
<head>
12+
<link rel="stylesheet" type="text/css" href="{$stylesheet_name}.css"/>
13+
</head>
14+
<body>
15+
<h1>Mypy Type Check Coverage Summary</h1>
16+
<table class="summary">
17+
<caption>Summary from <xsl:value-of select="@name"/></caption>
18+
<thead>
19+
<tr class="summary">
20+
<th class="summary">File</th>
21+
<th class="summary">Imprecision</th>
22+
<th class="summary">Lines</th>
23+
</tr>
24+
</thead>
25+
<tfoot>
26+
<xsl:variable name="bad_lines" select="sum(file/@imprecise|file/@any)"/>
27+
<xsl:variable name="total_lines" select="sum(file/@total)"/>
28+
<xsl:variable name="global_score" select="$bad_lines div ($total_lines + not(number($total_lines)))"/>
29+
<xsl:variable name="global_quality" select="string(number(number($global_score) &gt; 0.00) + number(number($global_score) &gt;= 0.20))"/>
30+
<tr class="summary summary-quality-{$global_quality}">
31+
<th class="summary summary-filename">Total</th>
32+
<th class="summary summary-precision"><xsl:value-of select="format-number($global_score, '0.00%')"/> imprecise</th>
33+
<th class="summary summary-lines"><xsl:value-of select="$total_lines"/> LOC</th>
34+
</tr>
35+
</tfoot>
36+
<tbody>
37+
<xsl:for-each select="file">
38+
<xsl:variable name="local_score" select="(@imprecise + @any) div (@total + not(number(@total)))"/>
39+
<xsl:variable name="local_quality" select="string(number(number($local_score) &gt; 0.00) + number(number($local_score) &gt;= 0.20))"/>
40+
<tr class="summary summary-quality-{$local_quality}">
41+
<td class="summary summary-filename"><a href="{$ext}/{@name}.{$ext}"><xsl:value-of select="@module"/></a></td>
42+
<td class="summary summary-precision"><xsl:value-of select="format-number($local_score, '0.00%')"/> imprecise</td>
43+
<td class="summary summary-lines"><xsl:value-of select="@total"/> LOC</td>
44+
</tr>
45+
</xsl:for-each>
46+
</tbody>
47+
</table>
48+
</body>
49+
</html>
50+
</xsl:template>
51+
<xsl:template match="/mypy-report-file">
52+
<xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html&gt;&#10;</xsl:text>
53+
<html>
54+
<head>
55+
<link rel="stylesheet" type="text/css" href="{$stylesheet_name}.css"/>
56+
</head>
57+
<body>
58+
<h2><xsl:value-of select="@module"/></h2>
59+
<table>
60+
<caption><xsl:value-of select="@name"/></caption>
61+
<tbody>
62+
<tr>
63+
<td class="table-lines">
64+
<pre>
65+
<xsl:for-each select="line">
66+
<span id="L{@number}" class="lineno"><a class="lineno" href="#L{@number}"><xsl:value-of select="@number"/></a></span><xsl:text>&#10;</xsl:text>
67+
</xsl:for-each>
68+
</pre>
69+
</td>
70+
<td class="table-code">
71+
<pre>
72+
<xsl:for-each select="line">
73+
<span class="line-{@precision}">
74+
<xsl:for-each select="char">
75+
<xsl:if test="@typestr!=''">
76+
<span class="type-char">
77+
<xsl:value-of select="@content"/>
78+
<span class="type-tooltip">
79+
<xsl:value-of select="@typestr"/>
80+
</span>
81+
</span>
82+
</xsl:if>
83+
<xsl:if test="@typestr=''">
84+
<xsl:value-of select="@content"/>
85+
</xsl:if>
86+
</xsl:for-each>
87+
</span>
88+
<xsl:text>&#10;</xsl:text>
89+
</xsl:for-each>
90+
</pre>
91+
</td>
92+
</tr>
93+
</tbody>
94+
</table>
95+
</body>
96+
</html>
97+
</xsl:template>
98+
</xsl:stylesheet>

xml/mypy-html.css

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,26 @@ a:hover.lineno, a:active.lineno {
102102
.line-any {
103103
background-color: #faa;
104104
}
105+
106+
.type-char {
107+
position : relative;
108+
border-bottom : 1px dotted black;
109+
}
110+
111+
.type-char:hover .type-tooltip {
112+
visibility: visible;
113+
}
114+
115+
.type-char .type-tooltip {
116+
visibility: hidden;
117+
background-color : #f80;
118+
position : absolute;
119+
z-index : 1;
120+
padding : 5px 0;
121+
text-align : center;
122+
border-radius : 6px;
123+
}
124+
125+
.type-char .type-tooltip {
126+
top : 200%;
127+
}

xml/mypy.xsd

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@
3434
<xs:sequence>
3535
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
3636
<xs:complexType>
37+
<xs:sequence>
38+
<xs:element name="char" minOccurs="0" maxOccurs="unbounded">
39+
<xs:complexType>
40+
<xs:attribute name="column" type="xs:integer" use="required"/>
41+
<xs:attribute name="typestr" type="xs:string" use="required"/>
42+
<xs:attribute name="content" type="xs:string" use="required"/>
43+
</xs:complexType>
44+
</xs:element>
45+
</xs:sequence>
3746
<xs:attribute name="number" type="xs:integer" use="required"/>
3847
<xs:attribute name="precision" type="precision" use="required"/>
3948
<xs:attribute name="content" type="xs:string" use="required"/>

0 commit comments

Comments
 (0)