Skip to content

Commit e4a5e20

Browse files
committed
requested changes jreback
1 parent c0b004e commit e4a5e20

File tree

1 file changed

+80
-61
lines changed

1 file changed

+80
-61
lines changed

pandas/io/formats/style.py

Lines changed: 80 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def __init__(
181181
self.cell_ids = cell_ids
182182
self.na_rep = na_rep
183183

184-
self.tooltips = _Tooltips()
184+
self.tooltips: Optional[_Tooltips] = None
185185

186186
self.cell_context: Dict[str, Any] = {}
187187

@@ -206,6 +206,19 @@ def _repr_html_(self) -> str:
206206
"""
207207
return self.render()
208208

209+
def _init_tooltips(self):
210+
"""
211+
Checks parameters compatible with tooltips and creates instance if necessary
212+
"""
213+
if not self.cell_ids:
214+
# tooltips not optimised for individual cell check. requires reasonable
215+
# redesign and more extensive code for a feature that might be rarely used.
216+
raise NotImplementedError(
217+
"Tooltips can only render with 'cell_ids' is True."
218+
)
219+
if self.tooltips is None:
220+
self.tooltips = _Tooltips()
221+
209222
def set_tooltips(self, ttips: DataFrame) -> "Styler":
210223
"""
211224
Add string based tooltips that will appear in the `Styler` HTML result. These
@@ -241,11 +254,8 @@ def set_tooltips(self, ttips: DataFrame) -> "Styler":
241254
... )
242255
>>> s = df.style.set_tooltips(ttips).render()
243256
"""
244-
if not self.cell_ids:
245-
# tooltips not optimised for individual cell check.
246-
raise NotImplementedError(
247-
"Tooltips can only render with 'cell_ids' is True."
248-
)
257+
self._init_tooltips()
258+
assert self.tooltips is not None # mypy requiremen
249259
self.tooltips.tt_data = ttips
250260
return self
251261

@@ -295,6 +305,8 @@ def set_tooltips_class(
295305
... ('position', 'absolute'),
296306
... ('z-index', 1)])
297307
"""
308+
self._init_tooltips()
309+
assert self.tooltips is not None # mypy requirement
298310
if properties:
299311
self.tooltips.class_properties = properties
300312
if name:
@@ -530,7 +542,7 @@ def format_attr(pair):
530542
else:
531543
table_attr += ' class="tex2jax_ignore"'
532544

533-
return {
545+
d = {
534546
"head": head,
535547
"cellstyle": cellstyle,
536548
"body": body,
@@ -540,6 +552,10 @@ def format_attr(pair):
540552
"caption": caption,
541553
"table_attributes": table_attr,
542554
}
555+
if self.tooltips:
556+
d = self.tooltips._translate(self.data, self.uuid, d)
557+
558+
return d
543559

544560
def format(self, formatter, subset=None, na_rep: Optional[str] = None) -> "Styler":
545561
"""
@@ -716,7 +732,6 @@ def render(self, **kwargs) -> str:
716732
self._compute()
717733
# TODO: namespace all the pandas keys
718734
d = self._translate()
719-
d = self.tooltips._translate_tooltips(self.data, self.uuid, d)
720735
# filter out empty styles, every cell will have a class
721736
# but the list of props may just be [['', '']].
722737
# so we have the nested anys below
@@ -786,7 +801,7 @@ def clear(self) -> None:
786801
Returns None.
787802
"""
788803
self.ctx.clear()
789-
self.tooltips = _Tooltips()
804+
self.tooltips = None
790805
self.cell_context = {}
791806
self._todo = []
792807

@@ -1817,7 +1832,61 @@ def _class_styles(self):
18171832
"""
18181833
return [{"selector": f".{self.class_name}", "props": self.class_properties}]
18191834

1820-
def _translate_tooltips(self, styler_data, uuid, d):
1835+
def _pseudo_css(self, uuid: str, name: str, row: int, col: int, text: str):
1836+
"""
1837+
For every table data-cell that has a valid tooltip (not None, NaN or
1838+
empty string) must create two pseudo CSS entries for the specific
1839+
<td> element id which are added to overall table styles:
1840+
an on hover visibility change and a content change
1841+
dependent upon the user's chosen display string.
1842+
1843+
For example:
1844+
[{"selector": "T__row1_col1:hover .pd-t",
1845+
"props": [("visibility", "visible")]},
1846+
{"selector": "T__row1_col1 .pd-t::after",
1847+
"props": [("content", "Some Valid Text String")]}]
1848+
1849+
Parameters
1850+
----------
1851+
uuid: str
1852+
The uuid of the Styler instance
1853+
name: str
1854+
The css-name of the class used for styling tooltips
1855+
row : int
1856+
The row index of the specified tooltip string data
1857+
col : int
1858+
The col index of the specified tooltip string data
1859+
text : str
1860+
The textual content of the tooltip to be displayed in HTML.
1861+
1862+
Returns
1863+
-------
1864+
pseudo_css : List
1865+
"""
1866+
return [
1867+
{
1868+
"selector": "#T_"
1869+
+ uuid
1870+
+ "row"
1871+
+ str(row)
1872+
+ "_col"
1873+
+ str(col)
1874+
+ f":hover .{name}",
1875+
"props": [("visibility", "visible")],
1876+
},
1877+
{
1878+
"selector": "#T_"
1879+
+ uuid
1880+
+ "row"
1881+
+ str(row)
1882+
+ "_col"
1883+
+ str(col)
1884+
+ f" .{name}::after",
1885+
"props": [("content", f'"{text}"')],
1886+
},
1887+
]
1888+
1889+
def _translate(self, styler_data, uuid, d):
18211890
"""
18221891
Mutate the render dictionary to allow for tooltips:
18231892
@@ -1844,61 +1913,11 @@ def _translate_tooltips(self, styler_data, uuid, d):
18441913

18451914
name = self.class_name
18461915

1847-
def _pseudo_css(row: int, col: int, text: str):
1848-
"""
1849-
For every table data-cell that has a valid tooltip (not None, NaN or
1850-
empty string) must create two pseudo CSS entries for the specific
1851-
<td> element id which are added to overall table styles:
1852-
an on hover visibility change and a content change
1853-
dependent upon the user's chosen display string.
1854-
1855-
For example:
1856-
[{"selector": "T__row1_col1:hover .pd-t",
1857-
"props": [("visibility", "visible")]},
1858-
{"selector": "T__row1_col1 .pd-t::after",
1859-
"props": [("content", "Some Valid Text String")]}]
1860-
1861-
Parameters
1862-
----------
1863-
row : int
1864-
The row index of the specified tooltip string data
1865-
col : int
1866-
The col index of the specified tooltip string data
1867-
text : str
1868-
The textual content of the tooltip to be displayed in HTML.
1869-
1870-
Returns
1871-
-------
1872-
pseudo_css : List
1873-
"""
1874-
return [
1875-
{
1876-
"selector": "#T_"
1877-
+ uuid
1878-
+ "row"
1879-
+ str(row)
1880-
+ "_col"
1881-
+ str(col)
1882-
+ f":hover .{name}",
1883-
"props": [("visibility", "visible")],
1884-
},
1885-
{
1886-
"selector": "#T_"
1887-
+ uuid
1888-
+ "row"
1889-
+ str(row)
1890-
+ "_col"
1891-
+ str(col)
1892-
+ f" .{name}::after",
1893-
"props": [("content", f'"{text}"')],
1894-
},
1895-
]
1896-
18971916
mask = (self.tt_data.isna()) | (self.tt_data.eq("")) # empty string = no ttip
18981917
self.table_styles = [
18991918
style
19001919
for sublist in [
1901-
_pseudo_css(i, j, str(self.tt_data.iloc[i, j]))
1920+
self._pseudo_css(uuid, name, i, j, str(self.tt_data.iloc[i, j]))
19021921
for i in range(len(self.tt_data.index))
19031922
for j in range(len(self.tt_data.columns))
19041923
if not mask.iloc[i, j]

0 commit comments

Comments
 (0)