From a6e530272b0eef17753e39cdf62c02708c0d3c96 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Tue, 25 May 2021 09:55:07 +0200 Subject: [PATCH 1/4] add long and short captions to Styler.to_latex --- pandas/io/formats/style.py | 19 +++++++++++-------- pandas/io/formats/style_render.py | 2 +- pandas/io/formats/templates/html.tpl | 2 +- pandas/io/formats/templates/latex.tpl | 5 ++++- pandas/tests/io/formats/style/test_style.py | 5 +++++ .../tests/io/formats/style/test_to_latex.py | 5 +++++ 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 977a3a24f0844..d34efb9821147 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -87,8 +87,8 @@ class Styler(StylerRenderer): List of {selector: (attr, value)} dicts; see Notes. uuid : str, default None A unique identifier to avoid CSS collisions; generated automatically. - caption : str, default None - Caption to attach to the table. + caption : str, tuple, default None + String caption to attach to the table. Tuple only used for LaTeX dual captions. table_attributes : str, default None Items that show up in the opening ```` tag in addition to automatic (by default) id. @@ -172,7 +172,7 @@ def __init__( precision: int | None = None, table_styles: CSSStyles | None = None, uuid: str | None = None, - caption: str | None = None, + caption: str | tuple | None = None, table_attributes: str | None = None, cell_ids: bool = True, na_rep: str | None = None, @@ -416,7 +416,7 @@ def to_latex( position_float: str | None = None, hrules: bool = False, label: str | None = None, - caption: str | None = None, + caption: str | tuple | None = None, sparse_index: bool | None = None, sparse_columns: bool | None = None, multirow_align: str = "c", @@ -457,8 +457,9 @@ def to_latex( label : str, optional The LaTeX label included as: \\label{
}. + caption : str, tuple, optional + If string, the LaTeX table caption included as: \\caption{}. + If tuple, the caption included as: \\caption[]{}. sparse_index : bool, optional Whether to sparsify the display of a hierarchical index. Setting to False will display each explicit level element in a hierarchical key for each row. @@ -1273,13 +1274,15 @@ def set_uuid(self, uuid: str) -> Styler: self.uuid = uuid return self - def set_caption(self, caption: str) -> Styler: + def set_caption(self, caption: str | tuple) -> Styler: """ Set the text added to a ```` HTML element. Parameters ---------- - caption : str + caption : str, tuple + For HTML output only string input is used, for LaTeX the additional + tuple input allows for short and long captions. Returns ------- diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index ce328f00cf794..6f1af4bcc66e9 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -75,7 +75,7 @@ def __init__( uuid_len: int = 5, table_styles: CSSStyles | None = None, table_attributes: str | None = None, - caption: str | None = None, + caption: str | tuple | None = None, cell_ids: bool = True, ): diff --git a/pandas/io/formats/templates/html.tpl b/pandas/io/formats/templates/html.tpl index 65fc1dfbb37c4..4b80d2d2d826b 100644 --- a/pandas/io/formats/templates/html.tpl +++ b/pandas/io/formats/templates/html.tpl @@ -27,7 +27,7 @@ {% block table %} {% block caption %} -{% if caption %} +{% if caption and caption is string %} {% endif %} {% endblock caption %} diff --git a/pandas/io/formats/templates/latex.tpl b/pandas/io/formats/templates/latex.tpl index e5db6ad8ca7f8..31c4166074240 100644 --- a/pandas/io/formats/templates/latex.tpl +++ b/pandas/io/formats/templates/latex.tpl @@ -9,9 +9,12 @@ {% if position_float is not none%} \{{position_float}} {% endif %} -{% if caption %} +{% if caption and caption is string %} \caption{% raw %}{{% endraw %}{{caption}}{% raw %}}{% endraw %} +{% elif caption and caption is sequence %} +\caption[{{caption[0]}}]{% raw %}{{% endraw %}{{caption[1]}}{% raw %}}{% endraw %} + {% endif %} {% for style in table_styles %} {% if style['selector'] not in ['position', 'position_float', 'caption', 'toprule', 'midrule', 'bottomrule', 'column_format'] %} diff --git a/pandas/tests/io/formats/style/test_style.py b/pandas/tests/io/formats/style/test_style.py index c556081b5f562..1e4881690572c 100644 --- a/pandas/tests/io/formats/style/test_style.py +++ b/pandas/tests/io/formats/style/test_style.py @@ -1502,3 +1502,8 @@ def test_from_custom_template(tmpdir): assert result.template_html is not Styler.template_html styler = result(DataFrame({"A": [1, 2]})) assert styler.render() + + +def test_caption_no_sequence(mi_styler): + mi_styler.set_caption(("short cap", "long_cap")) + assert " +{% elif caption and caption is sequence %} + {% endif %} {% endblock caption %} {% block thead %} diff --git a/pandas/io/formats/templates/latex.tpl b/pandas/io/formats/templates/latex.tpl index 31c4166074240..66fe99642850f 100644 --- a/pandas/io/formats/templates/latex.tpl +++ b/pandas/io/formats/templates/latex.tpl @@ -13,7 +13,7 @@ \caption{% raw %}{{% endraw %}{{caption}}{% raw %}}{% endraw %} {% elif caption and caption is sequence %} -\caption[{{caption[0]}}]{% raw %}{{% endraw %}{{caption[1]}}{% raw %}}{% endraw %} +\caption[{{caption[1]}}]{% raw %}{{% endraw %}{{caption[0]}}{% raw %}}{% endraw %} {% endif %} {% for style in table_styles %} diff --git a/pandas/tests/io/formats/style/test_style.py b/pandas/tests/io/formats/style/test_style.py index 1e4881690572c..69f4dc6e8865f 100644 --- a/pandas/tests/io/formats/style/test_style.py +++ b/pandas/tests/io/formats/style/test_style.py @@ -1504,6 +1504,6 @@ def test_from_custom_template(tmpdir): assert styler.render() -def test_caption_no_sequence(mi_styler): - mi_styler.set_caption(("short cap", "long_cap")) - assert "" in mi_styler.render() diff --git a/pandas/tests/io/formats/style/test_to_latex.py b/pandas/tests/io/formats/style/test_to_latex.py index 08b387f0b6c15..97347bddaa187 100644 --- a/pandas/tests/io/formats/style/test_to_latex.py +++ b/pandas/tests/io/formats/style/test_to_latex.py @@ -440,6 +440,6 @@ def test_parse_latex_table_wrapping(styler): assert _parse_latex_table_wrapping(styler.table_styles, None) is True -def test_long_captions(styler): - result = styler.to_latex(caption=("short cap", "long cap")) - assert "\\caption[short cap]{long cap}" in result +def test_short_caption(styler): + result = styler.to_latex(caption=("full cap", "short cap")) + assert "\\caption[short cap]{full cap}" in result From 89a2bff562364ce408b494982018098e951cd8d5 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Wed, 26 May 2021 07:39:07 +0200 Subject: [PATCH 3/4] merge upstream/master --- pandas/io/formats/templates/html_table.tpl | 4 +++- pandas/tests/io/formats/style/test_html.py | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pandas/io/formats/templates/html_table.tpl b/pandas/io/formats/templates/html_table.tpl index dadefa4bd8365..33153af6f0882 100644 --- a/pandas/io/formats/templates/html_table.tpl +++ b/pandas/io/formats/templates/html_table.tpl @@ -6,8 +6,10 @@
{{caption}}" not in mi_styler.render() diff --git a/pandas/tests/io/formats/style/test_to_latex.py b/pandas/tests/io/formats/style/test_to_latex.py index 5945502a4c90c..08b387f0b6c15 100644 --- a/pandas/tests/io/formats/style/test_to_latex.py +++ b/pandas/tests/io/formats/style/test_to_latex.py @@ -438,3 +438,8 @@ def test_parse_latex_table_wrapping(styler): overwrite=False, ) assert _parse_latex_table_wrapping(styler.table_styles, None) is True + + +def test_long_captions(styler): + result = styler.to_latex(caption=("short cap", "long cap")) + assert "\\caption[short cap]{long cap}" in result From cac0262bbe5fd0c7e594e1691765927ffd64391d Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Tue, 25 May 2021 13:22:27 +0200 Subject: [PATCH 2/4] reverse order of caption and allow with HTML as first element --- pandas/io/formats/style.py | 7 ++++--- pandas/io/formats/templates/html.tpl | 2 ++ pandas/io/formats/templates/latex.tpl | 2 +- pandas/tests/io/formats/style/test_style.py | 6 +++--- pandas/tests/io/formats/style/test_to_latex.py | 6 +++--- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index d34efb9821147..08c1bcb8c5893 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -459,7 +459,7 @@ def to_latex( This is used with \\ref{}. - If tuple, the caption included as: \\caption[]{}. + If tuple, the caption included as: \\caption[]{}. sparse_index : bool, optional Whether to sparsify the display of a hierarchical index. Setting to False will display each explicit level element in a hierarchical key for each row. @@ -1281,8 +1281,9 @@ def set_caption(self, caption: str | tuple) -> Styler: Parameters ---------- caption : str, tuple - For HTML output only string input is used, for LaTeX the additional - tuple input allows for short and long captions. + For HTML output either the string input is used or the first element of the + tuple. For LaTeX the string input provides a caption and the additional + tuple input allows for full captions and short captions, in that order. Returns ------- diff --git a/pandas/io/formats/templates/html.tpl b/pandas/io/formats/templates/html.tpl index 4b80d2d2d826b..b90a7251d0abc 100644 --- a/pandas/io/formats/templates/html.tpl +++ b/pandas/io/formats/templates/html.tpl @@ -29,6 +29,8 @@ {% block caption %} {% if caption and caption is string %} {{caption}}{{caption[0]}}" not in mi_styler.render() +def test_caption_as_sequence(mi_styler): + mi_styler.set_caption(("full cap", "short cap")) + assert "full cap
{% endif %} {% block caption %} -{% if caption %} +{% if caption and caption is string %} +{% elif caption and caption is sequence %} + {% endif %} {% endblock caption %} {% block thead %} diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index 6c3abe04db926..74b4c7ea3977c 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -231,3 +231,8 @@ def test_from_custom_template(tmpdir): assert result.template_html is not Styler.template_html styler = result(DataFrame({"A": [1, 2]})) assert styler.render() + + +def test_caption_as_sequence(styler): + styler.set_caption(("full cap", "short cap")) + assert "" in styler.render() From ab83ef146bd2fbc94768e12e20101f42ad0b923e Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Fri, 4 Jun 2021 10:19:51 +0200 Subject: [PATCH 4/4] add whats new and emphasise in doc string --- doc/source/whatsnew/v1.3.0.rst | 2 +- pandas/io/formats/style.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 88c69335b39f4..0a85f2550563f 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -142,7 +142,7 @@ properly format HTML and eliminate some inconsistencies (:issue:`39942` :issue:` One also has greater control of the display through separate sparsification of the index or columns, using the new 'styler' options context (:issue:`41142`). We have added an extension to allow LaTeX styling as an alternative to CSS styling and a method :meth:`.Styler.to_latex` -which renders the necessary LaTeX format including built-up styles. An additional file io function :meth:`Styler.to_html` has been added for convenience (:issue:`40312`). +which renders the necessary LaTeX format including built-up styles (:issue:`21673`, :issue:`41659`). An additional file io function :meth:`Styler.to_html` has been added for convenience (:issue:`40312`). Documentation has also seen major revisions in light of new features (:issue:`39720` :issue:`39317` :issue:`40493`) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 496d1d12590ca..849e28905c916 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -462,7 +462,8 @@ def to_latex( This is used with \\ref{
{{caption}}{{caption[0]}}full cap}. - If tuple, the caption included as: \\caption[]{}. + If tuple, i.e ("full caption", "short caption"), the caption included + as: \\caption[]{}. sparse_index : bool, optional Whether to sparsify the display of a hierarchical index. Setting to False will display each explicit level element in a hierarchical key for each row.