1
1
"""HTML formatting utilities for DataFusion DataFrames."""
2
2
3
- from typing import Dict , Optional , Any , Union , List
3
+ from typing import Dict , Optional , Any , Union , List , Callable , Type
4
4
5
5
6
6
class DataFrameHtmlFormatter :
@@ -9,6 +9,12 @@ class DataFrameHtmlFormatter:
9
9
This class handles the HTML rendering of DataFrames for display in
10
10
Jupyter notebooks and other rich display contexts.
11
11
12
+ This class is designed to be extended by subclassing. Key extension points:
13
+ - Override `get_cell_style()` and `get_header_style()` to customize styling
14
+ - Override `_format_cell_value()` to customize value formatting
15
+ - Use `register_formatter()` to add custom formatters for specific types
16
+ - Override any `_build_*` method to customize component generation
17
+
12
18
Args:
13
19
max_cell_length: Maximum characters to display in a cell before truncation
14
20
max_width: Maximum width of the HTML table in pixels
@@ -33,6 +39,44 @@ def __init__(
33
39
self .enable_cell_expansion = enable_cell_expansion
34
40
self .custom_css = custom_css
35
41
self .show_truncation_message = show_truncation_message
42
+ # Registry for custom type formatters
43
+ self ._type_formatters : Dict [Type , Callable [[Any ], str ]] = {}
44
+
45
+ def register_formatter (
46
+ self , type_class : Type , formatter : Callable [[Any ], str ]
47
+ ) -> None :
48
+ """Register a custom formatter for a specific data type.
49
+
50
+ Args:
51
+ type_class: The type to register a formatter for
52
+ formatter: Function that takes a value of the given type and returns
53
+ a formatted string
54
+ """
55
+ self ._type_formatters [type_class ] = formatter
56
+
57
+ def get_cell_style (self ) -> str :
58
+ """Get the CSS style for regular table cells.
59
+
60
+ This method can be overridden by subclasses to customize cell styling.
61
+
62
+ Returns:
63
+ CSS style string
64
+ """
65
+ return "border: 1px solid black; padding: 8px; text-align: left; white-space: nowrap;"
66
+
67
+ def get_header_style (self ) -> str :
68
+ """Get the CSS style for table header cells.
69
+
70
+ This method can be overridden by subclasses to customize header styling.
71
+
72
+ Returns:
73
+ CSS style string
74
+ """
75
+ return (
76
+ "border: 1px solid black; padding: 8px; text-align: left; "
77
+ "background-color: #f2f2f2; white-space: nowrap; min-width: fit-content; "
78
+ "max-width: fit-content;"
79
+ )
36
80
37
81
def format_html (
38
82
self ,
@@ -104,12 +148,7 @@ def _build_table_header(self, schema: Any) -> List[str]:
104
148
html .append ("<thead>" )
105
149
html .append ("<tr>" )
106
150
for field in schema :
107
- html .append (
108
- "<th style='border: 1px solid black; padding: 8px; "
109
- "text-align: left; background-color: #f2f2f2; "
110
- "white-space: nowrap; min-width: fit-content; "
111
- f"max-width: fit-content;'>{ field .name } </th>"
112
- )
151
+ html .append (f"<th style='{ self .get_header_style ()} '>{ field .name } </th>" )
113
152
html .append ("</tr>" )
114
153
html .append ("</thead>" )
115
154
return html
@@ -151,8 +190,7 @@ def _build_expandable_cell(
151
190
"""Build an expandable cell for long content."""
152
191
short_value = str (cell_value )[: self .max_cell_length ]
153
192
return (
154
- f"<td style='border: 1px solid black; padding: 8px; "
155
- f"text-align: left; white-space: nowrap;'>"
193
+ f"<td style='{ self .get_cell_style ()} '>"
156
194
f"<div class='expandable-container'>"
157
195
f"<span class='expandable' id='{ table_uuid } -min-text-{ row_count } -{ col_idx } '>"
158
196
f"{ short_value } </span>"
@@ -167,10 +205,7 @@ def _build_expandable_cell(
167
205
168
206
def _build_regular_cell (self , cell_value : Any ) -> str :
169
207
"""Build a regular table cell."""
170
- return (
171
- f"<td style='border: 1px solid black; padding: 8px; "
172
- f"text-align: left; white-space: nowrap;'>{ cell_value } </td>"
173
- )
208
+ return f"<td style='{ self .get_cell_style ()} '>{ cell_value } </td>"
174
209
175
210
def _build_html_footer (self , has_more : bool ) -> List [str ]:
176
211
"""Build the HTML footer with JavaScript and messages."""
@@ -189,17 +224,25 @@ def _build_html_footer(self, has_more: bool) -> List[str]:
189
224
def _format_cell_value (self , column : Any , row_idx : int ) -> str :
190
225
"""Format a cell value for display.
191
226
227
+ This method can be overridden by subclasses to customize cell formatting.
228
+ It also checks for registered type formatters before falling back to str().
229
+
192
230
Args:
193
231
column: Arrow array
194
232
row_idx: Row index
195
233
196
234
Returns:
197
235
Formatted cell value a
6302
s string
198
236
"""
199
- # This is a simplified implementation for Python-side formatting
200
- # In practice, we'd want to handle different Arrow types appropriately
201
237
try :
202
- return str (column [row_idx ])
238
+ value = column [row_idx ]
239
+
240
+ # Check for custom type formatters
241
+ for type_cls , formatter in self ._type_formatters .items ():
242
+ if isinstance (value , type_cls ):
243
+ return formatter (value )
244
+
245
+ return str (value )
203
246
except (IndexError , TypeError ):
204
247
return ""
205
248
0 commit comments