@@ -119,7 +119,7 @@ def __init__(
119
119
"blank" : "blank" ,
120
120
"foot" : "foot" ,
121
121
}
122
- self .concatenated : StylerRenderer | None = None
122
+ self .concatenated : list [ StylerRenderer ] = []
123
123
# add rendering variables
124
124
self .hide_index_names : bool = False
125
125
self .hide_column_names : bool = False
@@ -161,27 +161,34 @@ def _render(
161
161
stylers for use within `_translate_latex`
162
162
"""
163
163
self ._compute ()
164
- dx = None
165
- if self .concatenated is not None :
166
- self .concatenated .hide_index_ = self .hide_index_
167
- self .concatenated .hidden_columns = self .hidden_columns
168
- self .concatenated .css = {
164
+ dxs = []
165
+ ctx_len = len (self .index )
166
+ for i , concatenated in enumerate (self .concatenated ):
167
+ concatenated .hide_index_ = self .hide_index_
168
+ concatenated .hidden_columns = self .hidden_columns
169
+ foot = f"{ self .css ['foot' ]} { i } "
170
+ concatenated .css = {
169
171
** self .css ,
170
- "data" : f"{ self . css [ ' foot' ] } _ { self . css [ 'data' ] } " ,
171
- "row_heading" : f"{ self . css [ ' foot' ] } _ { self . css [ 'row_heading' ] } " ,
172
- "row" : f"{ self . css [ ' foot' ] } _ { self . css [ 'row' ] } " ,
173
- "foot" : self . css [ " foot" ] ,
172
+ "data" : f"{ foot } _data " ,
173
+ "row_heading" : f"{ foot } _row_heading " ,
174
+ "row" : f"{ foot } _row " ,
175
+ "foot" : f" { foot } _foot" ,
174
176
}
175
- dx = self . concatenated ._render (
177
+ dx = concatenated ._render (
176
178
sparse_index , sparse_columns , max_rows , max_cols , blank
177
179
)
180
+ dxs .append (dx )
178
181
179
- for (r , c ), v in self . concatenated .ctx .items ():
180
- self .ctx [(r + len ( self . index ) , c )] = v
181
- for (r , c ), v in self . concatenated .ctx_index .items ():
182
- self .ctx_index [(r + len ( self . index ) , c )] = v
182
+ for (r , c ), v in concatenated .ctx .items ():
183
+ self .ctx [(r + ctx_len , c )] = v
184
+ for (r , c ), v in concatenated .ctx_index .items ():
185
+ self .ctx_index [(r + ctx_len , c )] = v
183
186
184
- d = self ._translate (sparse_index , sparse_columns , max_rows , max_cols , blank , dx )
187
+ ctx_len += len (concatenated .index )
188
+
189
+ d = self ._translate (
190
+ sparse_index , sparse_columns , max_rows , max_cols , blank , dxs
191
+ )
185
192
return d
186
193
187
194
def _render_html (
@@ -258,7 +265,7 @@ def _translate(
258
265
max_rows : int | None = None ,
259
266
max_cols : int | None = None ,
260
267
blank : str = " " ,
261
- dx : dict | None = None ,
268
+ dxs : list [ dict ] | None = None ,
262
269
):
263
270
"""
264
271
Process Styler data and settings into a dict for template rendering.
@@ -278,15 +285,17 @@ def _translate(
278
285
Specific max rows and cols. max_elements always take precedence in render.
279
286
blank : str
280
287
Entry to top-left blank cells.
281
- dx : dict
282
- The render dict of the concatenated Styler .
288
+ dxs : list[ dict]
289
+ The render dicts of the concatenated Stylers .
283
290
284
291
Returns
285
292
-------
286
293
d : dict
287
294
The following structure: {uuid, table_styles, caption, head, body,
288
295
cellstyle, table_attributes}
289
296
"""
297
+ if dxs is None :
298
+ dxs = []
290
299
self .css ["blank_value" ] = blank
291
300
292
301
# construct render dict
@@ -340,10 +349,12 @@ def _translate(
340
349
]
341
350
d .update ({k : map })
342
351
343
- if dx is not None : # self.concatenated is not None
352
+ for dx in dxs : # self.concatenated is not empty
344
353
d ["body" ].extend (dx ["body" ]) # type: ignore[union-attr]
345
354
d ["cellstyle" ].extend (dx ["cellstyle" ]) # type: ignore[union-attr]
346
- d ["cellstyle_index" ].extend (dx ["cellstyle" ]) # type: ignore[union-attr]
355
+ d ["cellstyle_index" ].extend ( # type: ignore[union-attr]
356
+ dx ["cellstyle_index" ]
357
+ )
347
358
348
359
table_attr = self .table_attributes
349
360
if not get_option ("styler.html.mathjax" ):
@@ -847,23 +858,27 @@ def _translate_latex(self, d: dict, clines: str | None) -> None:
847
858
for r , row in enumerate (d ["head" ])
848
859
]
849
860
850
- def concatenated_visible_rows (obj , n , row_indices ):
861
+ def _concatenated_visible_rows (obj , n , row_indices ):
851
862
"""
852
863
Extract all visible row indices recursively from concatenated stylers.
853
864
"""
854
865
row_indices .extend (
855
866
[r + n for r in range (len (obj .index )) if r not in obj .hidden_rows ]
856
867
)
857
- return (
858
- row_indices
859
- if obj .concatenated is None
860
- else concatenated_visible_rows (
861
- obj .concatenated , n + len (obj .index ), row_indices
862
- )
863
- )
868
+ n += len (obj .index )
869
+ for concatenated in obj .concatenated :
870
+ n = _concatenated_visible_rows (concatenated , n , row_indices )
871
+ return n
872
+
873
+ def concatenated_visible_rows (obj ):
874
+ row_indices : list [int ] = []
875
+ _concatenated_visible_rows (obj , 0 , row_indices )
876
+ # TODO try to consolidate the concat visible rows
877
+ # methods to a single function / recursion for simplicity
878
+ return row_indices
864
879
865
880
body = []
866
- for r , row in zip (concatenated_visible_rows (self , 0 , [] ), d ["body" ]):
881
+ for r , row in zip (concatenated_visible_rows (self ), d ["body" ]):
867
882
# note: cannot enumerate d["body"] because rows were dropped if hidden
868
883
# during _translate_body so must zip to acquire the true r-index associated
869
884
# with the ctx obj which contains the cell styles.
0 commit comments