Skip to content

REF: type change escape in Styler.format to str to allow "html" and "latex" #41619

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 16 commits into from
May 27, 2021
Merged
Show file tree
Hide file tree
Changes from 4 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
6 changes: 3 additions & 3 deletions doc/source/user_guide/style.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
"\n",
"Before adding styles it is useful to show that the [Styler][styler] can distinguish the *display* value from the *actual* value. To control the display value, the text is printed in each cell, and we can use the [.format()][formatfunc] method to manipulate this according to a [format spec string][format] or a callable that takes a single value and returns a string. It is possible to define this for the whole table or for individual columns. \n",
"\n",
"Additionally, the format function has a **precision** argument to specifically help formatting floats, an **na_rep** argument to display missing data, and an **escape** argument to help displaying safe-HTML. The default formatter is configured to adopt pandas' regular `display.precision` option, controllable using `with pd.option_context('display.precision', 2):`\n",
"Additionally, the format function has a **precision** argument to specifically help formatting floats, an **na_rep** argument to display missing data, and an **escape_html** argument to help displaying safe-HTML. The default formatter is configured to adopt pandas' regular `display.precision` option, controllable using `with pd.option_context('display.precision', 2):`\n",
"\n",
"Here is an example of using the multiple options to control the formatting generally and with specific column formatters.\n",
"\n",
Expand Down Expand Up @@ -1448,7 +1448,7 @@
"metadata": {},
"outputs": [],
"source": [
"df4.style.format(escape=True)"
"df4.style.format(escape_html=True)"
]
},
{
Expand All @@ -1457,7 +1457,7 @@
"metadata": {},
"outputs": [],
"source": [
"df4.style.format('<a href=\"https://pandas.pydata.org\" target=\"_blank\">{}</a>', escape=True)"
"df4.style.format('<a href=\"https://pandas.pydata.org\" target=\"_blank\">{}</a>', escape_html=True)"
]
},
{
Expand Down
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 @@ -214,7 +214,7 @@ Other enhancements
- :meth:`.Styler.set_table_styles` amended to optionally allow certain css-string input arguments (:issue:`39564`)
- :meth:`.Styler.apply` now more consistently accepts ndarray function returns, i.e. in all cases for ``axis`` is ``0, 1 or None`` (:issue:`39359`)
- :meth:`.Styler.apply` and :meth:`.Styler.applymap` now raise errors if wrong format CSS is passed on render (:issue:`39660`)
- :meth:`.Styler.format` adds keyword argument ``escape`` for optional HTML escaping (:issue:`40437`)
- :meth:`.Styler.format` adds keyword argument ``escape_html`` for optional HTML escaping (:issue:`40437` :issue:`41619`)
- :meth:`.Styler.background_gradient` now allows the ability to supply a specific gradient map (:issue:`22727`)
- :meth:`.Styler.clear` now clears :attr:`Styler.hidden_index` and :attr:`Styler.hidden_columns` as well (:issue:`40484`)
- Builtin highlighting methods in :class:`Styler` have a more consistent signature and css customisability (:issue:`40242`)
Expand Down
6 changes: 3 additions & 3 deletions pandas/io/formats/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class Styler(StylerRenderer):

.. versionadded:: 1.3.0

escape : bool, default False
escape_html : bool, default False
Replace the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in cell display
strings with HTML-safe sequences.

Expand Down Expand Up @@ -179,7 +179,7 @@ def __init__(
uuid_len: int = 5,
decimal: str = ".",
thousands: str | None = None,
escape: bool = False,
escape_html: bool = False,
):
super().__init__(
data=data,
Expand All @@ -198,7 +198,7 @@ def __init__(
formatter=None,
precision=precision,
na_rep=na_rep,
escape=escape,
escape_html=escape_html,
decimal=decimal,
thousands=thousands,
)
Expand Down
20 changes: 11 additions & 9 deletions pandas/io/formats/style_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import pandas.core.common as com

jinja2 = import_optional_dependency("jinja2", extra="DataFrame.style requires jinja2.")
from markupsafe import escape as escape_html # markupsafe is jinja2 dependency
from markupsafe import escape as escape_html_f # markupsafe is jinja2 dependency

BaseFormatter = Union[str, Callable]
ExtFormatter = Union[BaseFormatter, Dict[Any, Optional[BaseFormatter]]]
Expand Down Expand Up @@ -457,7 +457,7 @@ def format(
precision: int | None = None,
decimal: str = ".",
thousands: str | None = None,
escape: bool = False,
escape_html: bool = False,
) -> StylerRenderer:
"""
Format the text display value of cells.
Expand Down Expand Up @@ -492,7 +492,7 @@ def format(

.. versionadded:: 1.3.0

escape : bool, default False
escape_html : bool, default False
Replace the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in cell display
string with HTML-safe sequences. Escaping is done before ``formatter``.

Expand Down Expand Up @@ -571,7 +571,9 @@ def format(
Using a ``formatter`` with HTML ``escape`` and ``na_rep``.

>>> df = pd.DataFrame([['<div></div>', '"A&B"', None]])
>>> s = df.style.format('<a href="a.com/{0}">{0}</a>', escape=True, na_rep="NA")
>>> s = df.style.format(
... '<a href="a.com/{0}">{0}</a>', escape_html=True, na_rep="NA"
... )
>>> s.render()
...
<td .. ><a href="a.com/&lt;div&gt;&lt;/div&gt;">&lt;div&gt;&lt;/div&gt;</a></td>
Expand All @@ -587,7 +589,7 @@ def format(
decimal == ".",
thousands is None,
na_rep is None,
escape is False,
escape_html is False,
)
):
self._display_funcs.clear()
Expand All @@ -609,7 +611,7 @@ def format(
precision=precision,
decimal=decimal,
thousands=thousands,
escape=escape,
escape_html=escape_html,
)
for ri in ris:
self._display_funcs[(ri, ci)] = format_func
Expand Down Expand Up @@ -774,7 +776,7 @@ def wrapper(x):
def _str_escape_html(x):
"""if escaping html: only use on str, else return input"""
if isinstance(x, str):
return escape_html(x)
return escape_html_f(x)
return x


Expand All @@ -784,7 +786,7 @@ def _maybe_wrap_formatter(
precision: int | None = None,
decimal: str = ".",
thousands: str | None = None,
escape: bool = False,
escape_html: bool = False,
) -> Callable:
"""
Allows formatters to be expressed as str, callable or None, where None returns
Expand All @@ -805,7 +807,7 @@ def _maybe_wrap_formatter(
raise TypeError(f"'formatter' expected str or callable, got {type(formatter)}")

# Replace HTML chars if escaping
if escape:
if escape_html:
func_1 = lambda x: func_0(_str_escape_html(x))
else:
func_1 = func_0
Expand Down
10 changes: 5 additions & 5 deletions pandas/tests/io/formats/style/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,20 +108,20 @@ def test_format_clear(styler):

def test_format_escape():
df = DataFrame([['<>&"']])
s = Styler(df, uuid_len=0).format("X&{0}>X", escape=False)
s = Styler(df, uuid_len=0).format("X&{0}>X", escape_html=False)
expected = '<td id="T__row0_col0" class="data row0 col0" >X&<>&">X</td>'
assert expected in s.render()

# only the value should be escaped before passing to the formatter
s = Styler(df, uuid_len=0).format("X&{0}>X", escape=True)
s = Styler(df, uuid_len=0).format("X&{0}>X", escape_html=True)
ex = '<td id="T__row0_col0" class="data row0 col0" >X&&lt;&gt;&amp;&#34;>X</td>'
assert ex in s.render()


def test_format_escape_na_rep():
# tests the na_rep is not escaped
df = DataFrame([['<>&"', None]])
s = Styler(df, uuid_len=0).format("X&{0}>X", escape=True, na_rep="&")
s = Styler(df, uuid_len=0).format("X&{0}>X", escape_html=True, na_rep="&")
ex = '<td id="T__row0_col0" class="data row0 col0" >X&&lt;&gt;&amp;&#34;>X</td>'
expected2 = '<td id="T__row0_col1" class="data row0 col1" >&</td>'
assert ex in s.render()
Expand All @@ -130,11 +130,11 @@ def test_format_escape_na_rep():

def test_format_escape_floats(styler):
# test given formatter for number format is not impacted by escape
s = styler.format("{:.1f}", escape=True)
s = styler.format("{:.1f}", escape_html=True)
for expected in [">0.0<", ">1.0<", ">-1.2<", ">-0.6<"]:
assert expected in s.render()
# tests precision of floats is not impacted by escape
s = styler.format(precision=1, escape=True)
s = styler.format(precision=1, escape_html=True)
for expected in [">0<", ">1<", ">-1.2<", ">-0.6<"]:
assert expected in s.render()

Expand Down