Skip to content

Commit f10da19

Browse files
authored
CLN: Styler HTML output adopt structured code standard (#39627)
1 parent 4861964 commit f10da19

File tree

3 files changed

+116
-79
lines changed

3 files changed

+116
-79
lines changed

doc/source/whatsnew/v1.3.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ Other
450450
- :meth:`Index.where` behavior now mirrors :meth:`Index.putmask` behavior, i.e. ``index.where(mask, other)`` matches ``index.putmask(~mask, other)`` (:issue:`39412`)
451451
- Bug in :func:`pandas.testing.assert_series_equal`, :func:`pandas.testing.assert_frame_equal`, :func:`pandas.testing.assert_index_equal` and :func:`pandas.testing.assert_extension_array_equal` incorrectly raising when an attribute has an unrecognized NA type (:issue:`39461`)
452452
- Bug in :class:`Styler` where ``subset`` arg in methods raised an error for some valid multiindex slices (:issue:`33562`)
453-
-
453+
- :class:`Styler` rendered HTML output minor alterations to support w3 good code standard (:issue:`39626`)
454454
-
455455

456456
.. ---------------------------------------------------------------------------

pandas/io/formats/templates/html.tpl

+56-56
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,70 @@
11
{# Update the template_structure.html document too #}
22
{%- block before_style -%}{%- endblock before_style -%}
33
{% block style %}
4-
<style type="text/css" >
4+
<style type="text/css">
55
{% block table_styles %}
66
{% for s in table_styles %}
7-
#T_{{uuid}} {{s.selector}} {
8-
{% for p,val in s.props %}
9-
{{p}}: {{val}};
10-
{% endfor -%}
11-
}
12-
{%- endfor -%}
7+
#T_{{uuid}} {{s.selector}} {
8+
{% for p,val in s.props %}
9+
{{p}}: {{val}};
10+
{% endfor %}
11+
}
12+
{% endfor %}
1313
{% endblock table_styles %}
1414
{% block before_cellstyle %}{% endblock before_cellstyle %}
1515
{% block cellstyle %}
16-
{%- for s in cellstyle %}
17-
{%- for selector in s.selectors -%}{%- if not loop.first -%},{%- endif -%}#T_{{uuid}}{{selector}}{%- endfor -%} {
18-
{% for p,val in s.props %}
19-
{{p}}: {{val}};
20-
{% endfor %}
21-
}
22-
{%- endfor -%}
23-
{%- endblock cellstyle %}
16+
{% for s in cellstyle %}
17+
{% for selector in s.selectors %}{% if not loop.first %}, {% endif %}#T_{{uuid}}{{selector}}{% endfor %} {
18+
{% for p,val in s.props %}
19+
{{p}}: {{val}};
20+
{% endfor %}
21+
}
22+
{% endfor %}
23+
{% endblock cellstyle %}
2424
</style>
25-
{%- endblock style %}
26-
{%- block before_table %}{% endblock before_table %}
27-
{%- block table %}
28-
<table id="T_{{uuid}}" {% if table_attributes %}{{ table_attributes }}{% endif %}>
29-
{%- block caption %}
30-
{%- if caption -%}
31-
<caption>{{caption}}</caption>
32-
{%- endif -%}
33-
{%- endblock caption %}
34-
{%- block thead %}
35-
<thead>
36-
{%- block before_head_rows %}{% endblock %}
37-
{%- for r in head %}
38-
{%- block head_tr scoped %}
25+
{% endblock style %}
26+
{% block before_table %}{% endblock before_table %}
27+
{% block table %}
28+
<table id="T_{{uuid}}"{% if table_attributes %} {{table_attributes}}{% endif %}>
29+
{% block caption %}
30+
{% if caption %}
31+
<caption>{{caption}}</caption>
32+
{% endif %}
33+
{% endblock caption %}
34+
{% block thead %}
35+
<thead>
36+
{% block before_head_rows %}{% endblock %}
37+
{% for r in head %}
38+
{% block head_tr scoped %}
3939
<tr>
40-
{%- for c in r %}
41-
{%- if c.is_visible != False %}
42-
<{{ c.type }} class="{{c.class}}" {{ c.attributes|join(" ") }}>{{c.value}}</{{ c.type }}>
43-
{%- endif %}
44-
{%- endfor %}
40+
{% for c in r %}
41+
{% if c.is_visible != False %}
42+
<{{c.type}} class="{{c.class}}" {{c.attributes|join(" ")}}>{{c.value}}</{{c.type}}>
43+
{% endif %}
44+
{% endfor %}
4545
</tr>
46-
{%- endblock head_tr %}
47-
{%- endfor %}
48-
{%- block after_head_rows %}{% endblock %}
49-
</thead>
50-
{%- endblock thead %}
51-
{%- block tbody %}
52-
<tbody>
53-
{% block before_rows %}{% endblock before_rows %}
54-
{% for r in body %}
55-
{% block tr scoped %}
46+
{% endblock head_tr %}
47+
{% endfor %}
48+
{% block after_head_rows %}{% endblock %}
49+
</thead>
50+
{% endblock thead %}
51+
{% block tbody %}
52+
<tbody>
53+
{% block before_rows %}{% endblock before_rows %}
54+
{% for r in body %}
55+
{% block tr scoped %}
5656
<tr>
57-
{% for c in r %}
58-
{% if c.is_visible != False %}
59-
<{{ c.type }} {% if c.id is defined -%} id="T_{{ uuid }}{{ c.id }}" {%- endif %} class="{{ c.class }}" {{ c.attributes|join(" ") }}>{{ c.display_value }}</{{ c.type }}>
60-
{% endif %}
61-
{%- endfor %}
57+
{% for c in r %}
58+
{% if c.is_visible != False %}
59+
<{{c.type}} {% if c.id is defined -%} id="T_{{uuid}}{{c.id}}" {%- endif %} class="{{c.class}}" {{c.attributes|join(" ")}}>{{c.display_value}}</{{c.type}}>
60+
{% endif %}
61+
{% endfor %}
6262
</tr>
63-
{% endblock tr %}
64-
{%- endfor %}
65-
{%- block after_rows %}{%- endblock after_rows %}
66-
</tbody>
67-
{%- endblock tbody %}
63+
{% endblock tr %}
64+
{% endfor %}
65+
{% block after_rows %}{% endblock after_rows %}
66+
</tbody>
67+
{% endblock tbody %}
6868
</table>
69-
{%- endblock table %}
70-
{%- block after_table %}{% endblock after_table %}
69+
{% endblock table %}
70+
{% block after_table %}{% endblock after_table %}

pandas/tests/io/formats/test_style.py

+59-22
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ def test_multiple_render(self):
140140
s = Styler(self.df, uuid_len=0).applymap(lambda x: "color: red;", subset=["A"])
141141
s.render() # do 2 renders to ensure css styles not duplicated
142142
assert (
143-
'<style type="text/css" >\n#T__row0_col0,#T__row1_col0{\n '
144-
"color: red;\n }</style>" in s.render()
143+
'<style type="text/css">\n#T__row0_col0, #T__row1_col0 {\n'
144+
" color: red;\n}\n</style>" in s.render()
145145
)
146146

147147
def test_render_empty_dfs(self):
@@ -1794,11 +1794,11 @@ def test_column_and_row_styling(self):
17941794
df = DataFrame(data=[[0, 1], [1, 2]], columns=["A", "B"])
17951795
s = Styler(df, uuid_len=0)
17961796
s = s.set_table_styles({"A": [{"selector": "", "props": [("color", "blue")]}]})
1797-
assert "#T__ .col0 {\n color: blue;\n }" in s.render()
1797+
assert "#T__ .col0 {\n color: blue;\n}" in s.render()
17981798
s = s.set_table_styles(
17991799
{0: [{"selector": "", "props": [("color", "blue")]}]}, axis=1
18001800
)
1801-
assert "#T__ .row0 {\n color: blue;\n }" in s.render()
1801+
assert "#T__ .row0 {\n color: blue;\n}" in s.render()
18021802

18031803
def test_colspan_w3(self):
18041804
# GH 36223
@@ -1855,12 +1855,12 @@ def test_tooltip_render(self, ttips):
18551855
s = Styler(df, uuid_len=0).set_tooltips(ttips).render()
18561856

18571857
# test tooltip table level class
1858-
assert "#T__ .pd-t {\n visibility: hidden;\n" in s
1858+
assert "#T__ .pd-t {\n visibility: hidden;\n" in s
18591859

18601860
# test 'Min' tooltip added
18611861
assert (
1862-
"#T__ #T__row0_col0:hover .pd-t {\n visibility: visible;\n } "
1863-
+ ' #T__ #T__row0_col0 .pd-t::after {\n content: "Min";\n }'
1862+
"#T__ #T__row0_col0:hover .pd-t {\n visibility: visible;\n}\n"
1863+
+ '#T__ #T__row0_col0 .pd-t::after {\n content: "Min";\n}'
18641864
in s
18651865
)
18661866
assert (
@@ -1871,8 +1871,8 @@ def test_tooltip_render(self, ttips):
18711871

18721872
# test 'Max' tooltip added
18731873
assert (
1874-
"#T__ #T__row0_col1:hover .pd-t {\n visibility: visible;\n } "
1875-
+ ' #T__ #T__row0_col1 .pd-t::after {\n content: "Max";\n }'
1874+
"#T__ #T__row0_col1:hover .pd-t {\n visibility: visible;\n}\n"
1875+
+ '#T__ #T__row0_col1 .pd-t::after {\n content: "Max";\n}'
18761876
in s
18771877
)
18781878
assert (
@@ -1892,16 +1892,16 @@ def test_tooltip_reindex(self):
18921892
index=[0, 2],
18931893
)
18941894
s = Styler(df, uuid_len=0).set_tooltips(DataFrame(ttips)).render()
1895-
assert '#T__ #T__row0_col0 .pd-t::after {\n content: "Mi";\n }' in s
1896-
assert '#T__ #T__row0_col2 .pd-t::after {\n content: "Ma";\n }' in s
1897-
assert '#T__ #T__row2_col0 .pd-t::after {\n content: "Mu";\n }' in s
1898-
assert '#T__ #T__row2_col2 .pd-t::after {\n content: "Mo";\n }' in s
1895+
assert '#T__ #T__row0_col0 .pd-t::after {\n content: "Mi";\n}' in s
1896+
assert '#T__ #T__row0_col2 .pd-t::after {\n content: "Ma";\n}' in s
1897+
assert '#T__ #T__row2_col0 .pd-t::after {\n content: "Mu";\n}' in s
1898+
assert '#T__ #T__row2_col2 .pd-t::after {\n content: "Mo";\n}' in s
18991899

19001900
def test_tooltip_ignored(self):
19011901
# GH 21266
19021902
df = DataFrame(data=[[0, 1], [2, 3]])
19031903
s = Styler(df).set_tooltips_class("pd-t").render() # no set_tooltips()
1904-
assert '<style type="text/css" >\n</style>' in s
1904+
assert '<style type="text/css">\n</style>' in s
19051905
assert '<span class="pd-t"></span>' not in s
19061906

19071907
def test_tooltip_class(self):
@@ -1913,11 +1913,8 @@ def test_tooltip_class(self):
19131913
.set_tooltips_class(name="other-class", properties=[("color", "green")])
19141914
.render()
19151915
)
1916-
assert "#T__ .other-class {\n color: green;\n" in s
1917-
assert (
1918-
'#T__ #T__row0_col0 .other-class::after {\n content: "tooltip";\n'
1919-
in s
1920-
)
1916+
assert "#T__ .other-class {\n color: green;\n" in s
1917+
assert '#T__ #T__row0_col0 .other-class::after {\n content: "tooltip";\n' in s
19211918

19221919
# GH 39563
19231920
s = (
@@ -1926,10 +1923,50 @@ def test_tooltip_class(self):
19261923
.set_tooltips_class(name="other-class", properties="color:green;color:red;")
19271924
.render()
19281925
)
1929-
assert (
1930-
"#T__ .other-class {\n color: green;\n color: red;\n "
1931-
in s
1926+
assert "#T__ .other-class {\n color: green;\n color: red;\n}" in s
1927+
1928+
def test_w3_html_format(self):
1929+
s = (
1930+
Styler(
1931+
DataFrame([[2.61], [2.69]], index=["a", "b"], columns=["A"]),
1932+
uuid_len=0,
1933+
)
1934+
.set_table_styles([{"selector": "th", "props": "att2:v2;"}])
1935+
.applymap(lambda x: "att1:v1;")
1936+
.set_table_attributes('class="my-cls1" style="attr3:v3;"')
1937+
.set_td_classes(DataFrame(["my-cls2"], index=["a"], columns=["A"]))
1938+
.format("{:.1f}")
1939+
.set_caption("A comprehensive test")
19321940
)
1941+
expected = """<style type="text/css">
1942+
#T__ th {
1943+
att2: v2;
1944+
}
1945+
#T__row0_col0, #T__row1_col0 {
1946+
att1: v1;
1947+
}
1948+
</style>
1949+
<table id="T__" class="my-cls1" style="attr3:v3;">
1950+
<caption>A comprehensive test</caption>
1951+
<thead>
1952+
<tr>
1953+
<th class="blank level0" ></th>
1954+
<th class="col_heading level0 col0" >A</th>
1955+
</tr>
1956+
</thead>
1957+
<tbody>
1958+
<tr>
1959+
<th id="T__level0_row0" class="row_heading level0 row0" >a</th>
1960+
<td id="T__row0_col0" class="data row0 col0 my-cls2" >2.6</td>
1961+
</tr>
1962+
<tr>
1963+
<th id="T__level0_row1" class="row_heading level0 row1" >b</th>
1964+
<td id="T__row1_col0" class="data row1 col0" >2.7</td>
1965+
</tr>
1966+
</tbody>
1967+
</table>
1968+
"""
1969+
assert expected == s.render()
19331970

19341971

19351972
@td.skip_if_no_mpl

0 commit comments

Comments
 (0)