Skip to content

CLN: Styler HTML output adopt structured code standard #39627

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v1.3.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ Other
- :meth:`Index.where` behavior now mirrors :meth:`Index.putmask` behavior, i.e. ``index.where(mask, other)`` matches ``index.putmask(~mask, other)`` (:issue:`39412`)
- 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`)
- Bug in :class:`Styler` where ``subset`` arg in methods raised an error for some valid multiindex slices (:issue:`33562`)
-
- :class:`Styler` rendered HTML output minor alterations to support w3 good code standard (:issue:`39626`)
-

.. ---------------------------------------------------------------------------
Expand Down
112 changes: 56 additions & 56 deletions pandas/io/formats/templates/html.tpl
Original file line number Diff line number Diff line change
@@ -1,70 +1,70 @@
{# Update the template_structure.html document too #}
{%- block before_style -%}{%- endblock before_style -%}
{% block style %}
<style type="text/css" >
<style type="text/css">
{% block table_styles %}
{% for s in table_styles %}
#T_{{uuid}} {{s.selector}} {
{% for p,val in s.props %}
{{p}}: {{val}};
{% endfor -%}
}
{%- endfor -%}
#T_{{uuid}} {{s.selector}} {
{% for p,val in s.props %}
{{p}}: {{val}};
{% endfor %}
}
{% endfor %}
{% endblock table_styles %}
{% block before_cellstyle %}{% endblock before_cellstyle %}
{% block cellstyle %}
{%- for s in cellstyle %}
{%- for selector in s.selectors -%}{%- if not loop.first -%},{%- endif -%}#T_{{uuid}}{{selector}}{%- endfor -%} {
{% for p,val in s.props %}
{{p}}: {{val}};
{% endfor %}
}
{%- endfor -%}
{%- endblock cellstyle %}
{% for s in cellstyle %}
{% for selector in s.selectors %}{% if not loop.first %}, {% endif %}#T_{{uuid}}{{selector}}{% endfor %} {
{% for p,val in s.props %}
{{p}}: {{val}};
{% endfor %}
}
{% endfor %}
{% endblock cellstyle %}
</style>
{%- endblock style %}
{%- block before_table %}{% endblock before_table %}
{%- block table %}
<table id="T_{{uuid}}" {% if table_attributes %}{{ table_attributes }}{% endif %}>
{%- block caption %}
{%- if caption -%}
<caption>{{caption}}</caption>
{%- endif -%}
{%- endblock caption %}
{%- block thead %}
<thead>
{%- block before_head_rows %}{% endblock %}
{%- for r in head %}
{%- block head_tr scoped %}
{% endblock style %}
{% block before_table %}{% endblock before_table %}
{% block table %}
<table id="T_{{uuid}}"{% if table_attributes %} {{table_attributes}}{% endif %}>
{% block caption %}
{% if caption %}
<caption>{{caption}}</caption>
{% endif %}
{% endblock caption %}
{% block thead %}
<thead>
{% block before_head_rows %}{% endblock %}
{% for r in head %}
{% block head_tr scoped %}
<tr>
{%- for c in r %}
{%- if c.is_visible != False %}
<{{ c.type }} class="{{c.class}}" {{ c.attributes|join(" ") }}>{{c.value}}</{{ c.type }}>
{%- endif %}
{%- endfor %}
{% for c in r %}
{% if c.is_visible != False %}
<{{c.type}} class="{{c.class}}" {{c.attributes|join(" ")}}>{{c.value}}</{{c.type}}>
{% endif %}
{% endfor %}
</tr>
{%- endblock head_tr %}
{%- endfor %}
{%- block after_head_rows %}{% endblock %}
</thead>
{%- endblock thead %}
{%- block tbody %}
<tbody>
{% block before_rows %}{% endblock before_rows %}
{% for r in body %}
{% block tr scoped %}
{% endblock head_tr %}
{% endfor %}
{% block after_head_rows %}{% endblock %}
</thead>
{% endblock thead %}
{% block tbody %}
<tbody>
{% block before_rows %}{% endblock before_rows %}
{% for r in body %}
{% block tr scoped %}
<tr>
{% for c in r %}
{% if c.is_visible != False %}
<{{ c.type }} {% if c.id is defined -%} id="T_{{ uuid }}{{ c.id }}" {%- endif %} class="{{ c.class }}" {{ c.attributes|join(" ") }}>{{ c.display_value }}</{{ c.type }}>
{% endif %}
{%- endfor %}
{% for c in r %}
{% if c.is_visible != False %}
<{{c.type}} {% if c.id is defined -%} id="T_{{uuid}}{{c.id}}" {%- endif %} class="{{c.class}}" {{c.attributes|join(" ")}}>{{c.display_value}}</{{c.type}}>
{% endif %}
{% endfor %}
</tr>
{% endblock tr %}
{%- endfor %}
{%- block after_rows %}{%- endblock after_rows %}
</tbody>
{%- endblock tbody %}
{% endblock tr %}
{% endfor %}
{% block after_rows %}{% endblock after_rows %}
</tbody>
{% endblock tbody %}
</table>
{%- endblock table %}
{%- block after_table %}{% endblock after_table %}
{% endblock table %}
{% block after_table %}{% endblock after_table %}
81 changes: 59 additions & 22 deletions pandas/tests/io/formats/test_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ def test_multiple_render(self):
s = Styler(self.df, uuid_len=0).applymap(lambda x: "color: red;", subset=["A"])
s.render() # do 2 renders to ensure css styles not duplicated
assert (
'<style type="text/css" >\n#T__row0_col0,#T__row1_col0{\n '
"color: red;\n }</style>" in s.render()
'<style type="text/css">\n#T__row0_col0, #T__row1_col0 {\n'
" color: red;\n}\n</style>" in s.render()
)

def test_render_empty_dfs(self):
Expand Down Expand Up @@ -1794,11 +1794,11 @@ def test_column_and_row_styling(self):
df = DataFrame(data=[[0, 1], [1, 2]], columns=["A", "B"])
s = Styler(df, uuid_len=0)
s = s.set_table_styles({"A": [{"selector": "", "props": [("color", "blue")]}]})
assert "#T__ .col0 {\n color: blue;\n }" in s.render()
assert "#T__ .col0 {\n color: blue;\n}" in s.render()
s = s.set_table_styles(
{0: [{"selector": "", "props": [("color", "blue")]}]}, axis=1
)
assert "#T__ .row0 {\n color: blue;\n }" in s.render()
assert "#T__ .row0 {\n color: blue;\n}" in s.render()

def test_colspan_w3(self):
# GH 36223
Expand Down Expand Up @@ -1855,12 +1855,12 @@ def test_tooltip_render(self, ttips):
s = Styler(df, uuid_len=0).set_tooltips(ttips).render()

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

# test 'Min' tooltip added
assert (
"#T__ #T__row0_col0:hover .pd-t {\n visibility: visible;\n } "
+ ' #T__ #T__row0_col0 .pd-t::after {\n content: "Min";\n }'
"#T__ #T__row0_col0:hover .pd-t {\n visibility: visible;\n}\n"
+ '#T__ #T__row0_col0 .pd-t::after {\n content: "Min";\n}'
in s
)
assert (
Expand All @@ -1871,8 +1871,8 @@ def test_tooltip_render(self, ttips):

# test 'Max' tooltip added
assert (
"#T__ #T__row0_col1:hover .pd-t {\n visibility: visible;\n } "
+ ' #T__ #T__row0_col1 .pd-t::after {\n content: "Max";\n }'
"#T__ #T__row0_col1:hover .pd-t {\n visibility: visible;\n}\n"
+ '#T__ #T__row0_col1 .pd-t::after {\n content: "Max";\n}'
in s
)
assert (
Expand All @@ -1892,16 +1892,16 @@ def test_tooltip_reindex(self):
index=[0, 2],
)
s = Styler(df, uuid_len=0).set_tooltips(DataFrame(ttips)).render()
assert '#T__ #T__row0_col0 .pd-t::after {\n content: "Mi";\n }' in s
assert '#T__ #T__row0_col2 .pd-t::after {\n content: "Ma";\n }' in s
assert '#T__ #T__row2_col0 .pd-t::after {\n content: "Mu";\n }' in s
assert '#T__ #T__row2_col2 .pd-t::after {\n content: "Mo";\n }' in s
assert '#T__ #T__row0_col0 .pd-t::after {\n content: "Mi";\n}' in s
assert '#T__ #T__row0_col2 .pd-t::after {\n content: "Ma";\n}' in s
assert '#T__ #T__row2_col0 .pd-t::after {\n content: "Mu";\n}' in s
assert '#T__ #T__row2_col2 .pd-t::after {\n content: "Mo";\n}' in s

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

def test_tooltip_class(self):
Expand All @@ -1913,11 +1913,8 @@ def test_tooltip_class(self):
.set_tooltips_class(name="other-class", properties=[("color", "green")])
.render()
)
assert "#T__ .other-class {\n color: green;\n" in s
assert (
'#T__ #T__row0_col0 .other-class::after {\n content: "tooltip";\n'
in s
)
assert "#T__ .other-class {\n color: green;\n" in s
assert '#T__ #T__row0_col0 .other-class::after {\n content: "tooltip";\n' in s

# GH 39563
s = (
Expand All @@ -1926,10 +1923,50 @@ def test_tooltip_class(self):
.set_tooltips_class(name="other-class", properties="color:green;color:red;")
.render()
)
assert (
"#T__ .other-class {\n color: green;\n color: red;\n "
in s
assert "#T__ .other-class {\n color: green;\n color: red;\n}" in s

def test_w3_html_format(self):
s = (
Styler(
DataFrame([[2.61], [2.69]], index=["a", "b"], columns=["A"]),
uuid_len=0,
)
.set_table_styles([{"selector": "th", "props": "att2:v2;"}])
.applymap(lambda x: "att1:v1;")
.set_table_attributes('class="my-cls1" style="attr3:v3;"')
.set_td_classes(DataFrame(["my-cls2"], index=["a"], columns=["A"]))
.format("{:.1f}")
.set_caption("A comprehensive test")
)
expected = """<style type="text/css">
#T__ th {
att2: v2;
}
#T__row0_col0, #T__row1_col0 {
att1: v1;
}
</style>
<table id="T__" class="my-cls1" style="attr3:v3;">
<caption>A comprehensive test</caption>
<thead>
<tr>
<th class="blank level0" ></th>
<th class="col_heading level0 col0" >A</th>
</tr>
</thead>
<tbody>
<tr>
<th id="T__level0_row0" class="row_heading level0 row0" >a</th>
<td id="T__row0_col0" class="data row0 col0 my-cls2" >2.6</td>
</tr>
<tr>
<th id="T__level0_row1" class="row_heading level0 row1" >b</th>
<td id="T__row1_col0" class="data row1 col0" >2.7</td>
</tr>
</tbody>
</table>
"""
assert expected == s.render()


@td.skip_if_no_mpl
Expand Down