from textwrap import dedent import numpy as np import pytest from pandas import ( DataFrame, MultiIndex, ) jinja2 = pytest.importorskip("jinja2") from pandas.io.formats.style import Styler loader = jinja2.PackageLoader("pandas", "io/formats/templates") env = jinja2.Environment(loader=loader, trim_blocks=True) @pytest.fixture def styler(): return Styler(DataFrame([[2.61], [2.69]], index=["a", "b"], columns=["A"])) @pytest.fixture def styler_mi(): midx = MultiIndex.from_product([["a", "b"], ["c", "d"]]) return Styler(DataFrame(np.arange(16).reshape(4, 4), index=midx, columns=midx)) @pytest.fixture def tpl_style(): return env.get_template("html_style.tpl") @pytest.fixture def tpl_table(): return env.get_template("html_table.tpl") def test_html_template_extends_options(): # make sure if templates are edited tests are updated as are setup fixtures # to understand the dependency with open("pandas/io/formats/templates/html.tpl") as file: result = file.read() assert "{% include html_style_tpl %}" in result assert "{% include html_table_tpl %}" in result def test_exclude_styles(styler): result = styler.to_html(exclude_styles=True, doctype_html=True) expected = dedent( """\
  A
a 2.610000
b 2.690000
""" ) assert result == expected def test_w3_html_format(styler): styler.set_uuid("").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 = dedent( """\
A comprehensive test
  A
a 2.6
b 2.7
""" ) assert expected == styler.render() def test_colspan_w3(): # GH 36223 df = DataFrame(data=[[1, 2]], columns=[["l0", "l0"], ["l1a", "l1b"]]) styler = Styler(df, uuid="_", cell_ids=False) assert 'l0' in styler.render() def test_rowspan_w3(): # GH 38533 df = DataFrame(data=[[1, 2]], index=[["l0", "l0"], ["l1a", "l1b"]]) styler = Styler(df, uuid="_", cell_ids=False) assert ( 'l0' in styler.render() ) def test_styles(styler): styler.set_uuid("abc_") styler.set_table_styles([{"selector": "td", "props": "color: red;"}]) result = styler.to_html(doctype_html=True) expected = dedent( """\
  A
a 2.610000
b 2.690000
""" ) assert result == expected def test_doctype(styler): result = styler.to_html(doctype_html=False) assert "" not in result assert "" not in result assert "" not in result assert "" not in result def test_block_names(tpl_style, tpl_table): # catch accidental removal of a block expected_style = { "before_style", "style", "table_styles", "before_cellstyle", "cellstyle", } expected_table = { "before_table", "table", "caption", "thead", "tbody", "after_table", "before_head_rows", "head_tr", "after_head_rows", "before_rows", "tr", "after_rows", } result1 = set(tpl_style.blocks) assert result1 == expected_style result2 = set(tpl_table.blocks) assert result2 == expected_table def test_from_custom_template_table(tmpdir): p = tmpdir.mkdir("tpl").join("myhtml_table.tpl") p.write( dedent( """\ {% extends "html_table.tpl" %} {% block table %}

{{custom_title}}

{{ super() }} {% endblock table %}""" ) ) result = Styler.from_custom_template(str(tmpdir.join("tpl")), "myhtml_table.tpl") assert issubclass(result, Styler) assert result.env is not Styler.env assert result.template_html_table is not Styler.template_html_table styler = result(DataFrame({"A": [1, 2]})) assert "

My Title

\n\n\n {{ super() }} {% endblock style %}""" ) ) result = Styler.from_custom_template( str(tmpdir.join("tpl")), html_style="myhtml_style.tpl" ) assert issubclass(result, Styler) assert result.env is not Styler.env assert result.template_html_style is not Styler.template_html_style styler = result(DataFrame({"A": [1, 2]})) assert '\n\nfull cap" in styler.render() @pytest.mark.parametrize("index", [False, True]) @pytest.mark.parametrize("columns", [False, True]) def test_sticky_basic(styler, index, columns): if index: styler.set_sticky(axis=0) if columns: styler.set_sticky(axis=1) res = styler.set_uuid("").to_html() cs1 = "tbody th {\n position: sticky;\n left: 0px;\n background-color: white;\n}" assert (cs1 in res) is index cs2 = "thead th {\n position: sticky;\n top: 0px;\n background-color: white;\n}" assert (cs2 in res) is columns @pytest.mark.parametrize("index", [False, True]) @pytest.mark.parametrize("columns", [False, True]) def test_sticky_mi(styler_mi, index, columns): if index: styler_mi.set_sticky(axis=0) if columns: styler_mi.set_sticky(axis=1) res = styler_mi.set_uuid("").to_html() assert ( ( dedent( """\ #T_ tbody th.level0 { position: sticky; left: 0px; min-width: 75px; max-width: 75px; background-color: white; } """ ) in res ) is index ) assert ( ( dedent( """\ #T_ tbody th.level1 { position: sticky; left: 75px; min-width: 75px; max-width: 75px; background-color: white; } """ ) in res ) is index ) assert ( ( dedent( """\ #T_ thead th.level0 { position: sticky; top: 0px; height: 25px; background-color: white; } """ ) in res ) is columns ) assert ( ( dedent( """\ #T_ thead th.level1 { position: sticky; top: 25px; height: 25px; background-color: white; } """ ) in res ) is columns ) @pytest.mark.parametrize("index", [False, True]) @pytest.mark.parametrize("columns", [False, True]) def test_sticky_levels(styler_mi, index, columns): if index: styler_mi.set_sticky(axis=0, levels=[1]) if columns: styler_mi.set_sticky(axis=1, levels=[1]) res = styler_mi.set_uuid("").to_html() assert "#T_ tbody th.level0 {" not in res assert "#T_ thead th.level0 {" not in res assert ( ( dedent( """\ #T_ tbody th.level1 { position: sticky; left: 0px; min-width: 75px; max-width: 75px; background-color: white; } """ ) in res ) is index ) assert ( ( dedent( """\ #T_ thead th.level1 { position: sticky; top: 0px; height: 25px; background-color: white; } """ ) in res ) is columns ) def test_sticky_raises(styler): with pytest.raises(ValueError, match="`axis` must be"): styler.set_sticky(axis="bad")