Skip to content

Commit 2b24efa

Browse files
authored
Version 1.6.4 (#221)
* Fix complex table footers * Address pytest.skip warning pytest.PytestRemovedIn8Warning: pytest.skip(msg=...) is now deprecated, use pytest.skip(reason=...) instead * Address pandas warning FutureWarning: 'S' is deprecated and will be removed in a future version, please use 's' instead. * Remove environment2.yml * Adjust the tests for pandas=2.2.0 pandas-dev/pandas#57229 pandas-dev/pandas#55080
1 parent a526158 commit 2b24efa

9 files changed

+101
-45
lines changed

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2019-2023 Marc Wouts
3+
Copyright (c) 2019-2024 Marc Wouts
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

docs/changelog.md

+11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
ITables ChangeLog
22
=================
33

4+
1.6.4 (2024-02-03)
5+
------------------
6+
7+
**Fixed**
8+
- Complex table footers are now in the correct order ([#219](https://github.com/mwouts/itables/issues/219))
9+
- We have adjusted the test suite for `pandas==2.2.0`
10+
([#223](https://github.com/mwouts/itables/issues/223),
11+
[pandas-57229](https://github.com/pandas-dev/pandas/issues/57229),
12+
[pandas-55080](https://github.com/pandas-dev/pandas/issues/55080))
13+
14+
415
1.6.3 (2023-12-10)
516
------------------
617

environment2.yml

-17
This file was deleted.

itables/javascript.py

+26-16
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,6 @@ def _table_header(
154154
if not show_index and len(df.columns):
155155
thead = thead.replace("<th></th>", "", 1)
156156

157-
if column_filters:
158-
# We use this header in the column filters, so we need to remove any column multiindex first"""
159-
thead_flat = ""
160-
if show_index:
161-
for index in df.index.names:
162-
thead_flat += "<th>{}</th>".format(index)
163-
164-
for column in df.columns:
165-
thead_flat += "<th>{}</th>".format(column)
166-
167157
loading = "<td>Loading... (need <a href=https://mwouts.github.io/itables/troubleshooting.html>help</a>?)</td>"
168158
tbody = "<tr>{}</tr>".format(loading)
169159

@@ -172,15 +162,14 @@ def _table_header(
172162
else:
173163
style = ""
174164

175-
if column_filters == "header":
176-
header = "<thead>{}</thead>".format(thead_flat)
177-
else:
178-
header = "<thead>{}</thead>".format(thead)
165+
header = "<thead>{}</thead>".format(
166+
_flat_header(df, show_index) if column_filters == "header" else thead
167+
)
179168

180169
if column_filters == "footer":
181-
footer = "<tfoot>{}</tfoot>".format(thead_flat)
170+
footer = "<tfoot>{}</tfoot>".format(_flat_header(df, show_index))
182171
elif footer:
183-
footer = "<tfoot>{}</tfoot>".format(thead)
172+
footer = "<tfoot>{}</tfoot>".format(_tfoot_from_thead(thead))
184173
else:
185174
footer = ""
186175

@@ -195,6 +184,27 @@ def _table_header(
195184
)
196185

197186

187+
def _flat_header(df, show_index):
188+
"""When column filters are shown, we need to remove any column multiindex"""
189+
header = ""
190+
if show_index:
191+
for index in df.index.names:
192+
header += "<th>{}</th>".format(index)
193+
194+
for column in df.columns:
195+
header += "<th>{}</th>".format(column)
196+
197+
return header
198+
199+
200+
def _tfoot_from_thead(thead):
201+
header_rows = thead.split("</tr>")
202+
last_row = header_rows[-1]
203+
assert not last_row.strip(), last_row
204+
header_rows = header_rows[:-1]
205+
return "".join(row + "</tr>" for row in header_rows[::-1] if "<tr" in row) + "\n"
206+
207+
198208
def json_dumps(obj, eval_functions):
199209
"""
200210
This is a replacement for json.dumps that

itables/sample_dfs.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import math
22
import string
33
from datetime import datetime, timedelta
4-
5-
try:
6-
from functools import lru_cache
7-
except ImportError:
8-
from functools32 import lru_cache
9-
4+
from functools import lru_cache
105
from itertools import cycle
116

127
import numpy as np
@@ -176,7 +171,7 @@ def get_dict_of_test_dfs(N=100, M=100, polars=False):
176171
}
177172
),
178173
"date_range": pd.DataFrame(
179-
{"timestamps": pd.date_range("now", periods=5, freq="S")}
174+
{"timestamps": pd.date_range("now", periods=5, freq="s")}
180175
),
181176
"ordered_categories": pd.DataFrame(
182177
{"int": np.arange(4)},
@@ -317,6 +312,9 @@ def get_dict_of_test_series(polars=False):
317312

318313
@lru_cache()
319314
def generate_date_series():
315+
if pd.__version__ >= "2.2.0":
316+
# https://github.com/pandas-dev/pandas/issues/55080 is back in 2.2.0?
317+
return pd.Series(pd.date_range("1970-01-01", "2099-12-31", freq="D"))
320318
return pd.Series(pd.date_range("1677-09-23", "2262-04-10", freq="D"))
321319

322320

itables/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""ITables' version number"""
22

3-
__version__ = "1.6.3"
3+
__version__ = "1.6.4"

tests/test_documentation_notebooks_run.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ def list_doc_notebooks():
2727
)
2828
def test_run_documentation_notebooks(notebook):
2929
if "polars" in notebook.stem and pl is None:
30-
pytest.skip(msg="Polars is not available")
30+
pytest.skip("Polars is not available")
3131
if "pandas_style" in notebook.stem and pd_style is None:
32-
pytest.skip(msg="Pandas Style is not available")
32+
pytest.skip("Pandas Style is not available")
3333

3434
nb = jupytext.read(notebook)
3535
py_notebook = jupytext.writes(nb, "py:percent")

tests/test_javascript.py

+51-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import pytest
22

3-
from itables.javascript import _df_fits_in_one_page, replace_value, to_html_datatable
3+
from itables.javascript import (
4+
_df_fits_in_one_page,
5+
_tfoot_from_thead,
6+
replace_value,
7+
to_html_datatable,
8+
)
49

510

611
def test_replace_value(
@@ -46,3 +51,48 @@ def test_df_fits_in_one_page(df, lengthMenu):
4651
min_rows = min_rows[0]
4752

4853
assert _df_fits_in_one_page(df, kwargs) == (len(df) <= min_rows)
54+
55+
56+
def test_tfoot_from_thead(
57+
thead="""
58+
<tr style="text-align: right;">
59+
<th></th>
60+
<th>region</th>
61+
<th>country</th>
62+
<th>capital</th>
63+
<th>longitude</th>
64+
<th>latitude</th>
65+
<th>flag</th>
66+
</tr>
67+
<tr>
68+
<th>code</th>
69+
<th></th>
70+
<th></th>
71+
<th></th>
72+
<th></th>
73+
<th></th>
74+
<th></th>
75+
</tr>
76+
""",
77+
expected_tfoot="""
78+
<tr>
79+
<th>code</th>
80+
<th></th>
81+
<th></th>
82+
<th></th>
83+
<th></th>
84+
<th></th>
85+
<th></th>
86+
</tr>
87+
<tr style="text-align: right;">
88+
<th></th>
89+
<th>region</th>
90+
<th>country</th>
91+
<th>capital</th>
92+
<th>longitude</th>
93+
<th>latitude</th>
94+
<th>flag</th>
95+
</tr>
96+
""",
97+
):
98+
assert _tfoot_from_thead(thead) == expected_tfoot

tests/test_sample_dfs.py

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
pytest.mark.filterwarnings("error"),
2626
# Seen on the CI on Py38 and Py39
2727
pytest.mark.filterwarnings("ignore::ResourceWarning"),
28+
# TODO: https://github.com/mwouts/itables/issues/223
29+
pytest.mark.filterwarnings(
30+
"ignore:Setting an item of incompatible dtype is deprecated:FutureWarning"
31+
),
2832
]
2933

3034
if PANDAS_VERSION_MAJOR < 2:

0 commit comments

Comments
 (0)