Skip to content

Commit fe27982

Browse files
authored
lengthMenu can be either a 1D or 2D array (#153)
* update the csv file only if it is missing * passing an option with value=None is not allowed * fix set dom=t when the table fits on one page * Version 1.4.5
1 parent 992a3f2 commit fe27982

File tree

7 files changed

+132
-34
lines changed

7 files changed

+132
-34
lines changed

docs/changelog.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
ITables ChangeLog
22
=================
33

4+
1.4.5 (2023-01-23)
5+
------------------
6+
7+
**Fixed**
8+
- Fixed an issue when `lengthMenu` is a 2D array ([#151](https://github.com/mwouts/itables/issues/151))
9+
10+
11+
**Changed**
12+
- We make sure that no argument passed to `show` is equal to `None` (for all tested options, passing `None` results in a datatable that never loads)
13+
- Running the test collection will not update the CSV files used for testing anymore
14+
15+
416
1.4.4 (2023-01-15)
517
------------------
618

itables/javascript.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,16 +220,21 @@ def to_html_datatable(df=None, caption=None, tableId=None, connected=True, **kwa
220220
):
221221
kwargs[option] = getattr(opt, option)
222222

223+
for name, value in kwargs.items():
224+
if value is None:
225+
raise ValueError(
226+
"Please don't pass an option with a value equal to None ('{}=None')".format(
227+
name
228+
)
229+
)
230+
223231
# These options are used here, not in DataTable
224232
classes = kwargs.pop("classes")
225233
style = kwargs.pop("style")
226234
css = kwargs.pop("css")
227235
tags = kwargs.pop("tags")
228236

229-
# Only display the table if the rows fit on one 'page'
230-
if "dom" not in kwargs and len(df) <= 10: # the default page has 10 rows
231-
if "lengthMenu" not in kwargs or len(df) <= min(kwargs["lengthMenu"]):
232-
kwargs["dom"] = "t"
237+
_set_dom_equals_t_if_df_fits_in_one_page(df, kwargs)
233238

234239
if caption is not None:
235240
tags = '{}<caption style="white-space: nowrap; overflow: hidden">{}</caption>'.format(
@@ -275,10 +280,6 @@ def to_html_datatable(df=None, caption=None, tableId=None, connected=True, **kwa
275280
"'header', 'footer' or False, not {}".format(column_filters)
276281
)
277282

278-
# Do not show the page menu when the table has fewer rows than min length menu
279-
if "paging" not in kwargs and len(df.index) <= kwargs.get("lengthMenu", [10])[0]:
280-
kwargs["paging"] = False
281-
282283
# Load the HTML template
283284
if connected:
284285
output = read_package_file("html/datatables_template_connected.html")
@@ -362,6 +363,29 @@ def _column_count_in_header(table_header):
362363
return max(line.count("</th>") for line in table_header.split("</tr>"))
363364

364365

366+
def _min_rows(kwargs):
367+
if "lengthMenu" not in kwargs:
368+
return 10
369+
370+
lengthMenu = kwargs["lengthMenu"]
371+
min_rows = lengthMenu[0]
372+
373+
if isinstance(min_rows, (int, float)):
374+
return min_rows
375+
376+
return min_rows[0]
377+
378+
379+
def _set_dom_equals_t_if_df_fits_in_one_page(df, kwargs):
380+
"""Display just the table (not the search box, etc...) if the rows fit on one 'page'"""
381+
if "dom" in kwargs:
382+
return
383+
384+
if len(df) <= _min_rows(kwargs):
385+
kwargs["dom"] = "t"
386+
return
387+
388+
365389
def safe_reset_index(df):
366390
try:
367391
return df.reset_index()

itables/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""ITables' version number"""
22

3-
__version__ = "1.4.4"
3+
__version__ = "1.4.5"

tests/conftest.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import pandas as pd
2+
import pytest
3+
4+
from itables.sample_dfs import get_dict_of_test_dfs
5+
6+
7+
@pytest.fixture(params=list(get_dict_of_test_dfs()))
8+
def df(request):
9+
name = request.param
10+
df = get_dict_of_test_dfs()[name]
11+
assert isinstance(df, pd.DataFrame)
12+
return df
13+
14+
15+
@pytest.fixture(params=["None", "1D-array", "2D-array"])
16+
def lengthMenu(request):
17+
if request.param == "None":
18+
return None
19+
if request.param == "1D-array":
20+
return [2, 5, 10, 20, 50]
21+
if request.param == "2D-array":
22+
return [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]]
23+
raise KeyError(request.param)
24+
25+
26+
@pytest.fixture(params=["None", "lfrtip"])
27+
def dom(request):
28+
if request.param == "None":
29+
return None
30+
return request.param

tests/test_javascript.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,38 @@
1-
import pandas as pd
2-
import pytest
3-
4-
from itables.javascript import to_html_datatable
5-
6-
7-
@pytest.fixture()
8-
def df():
9-
return pd.DataFrame([1, 2])
1+
from itables.javascript import (
2+
_set_dom_equals_t_if_df_fits_in_one_page,
3+
to_html_datatable,
4+
)
105

116

127
def test_warn_on_unexpected_types_not_in_html(df):
138
html = to_html_datatable(df)
149
assert "warn_on_unexpected_types" not in html
10+
11+
12+
def test_set_dom_equals_t_if_df_fits_in_one_page(df, dom, lengthMenu):
13+
kwargs = dict(lengthMenu=lengthMenu, dom=dom)
14+
kwargs = {key: value for key, value in kwargs.items() if value is not None}
15+
_set_dom_equals_t_if_df_fits_in_one_page(df, kwargs)
16+
17+
if dom is not None:
18+
assert kwargs["dom"] == dom
19+
return
20+
21+
if lengthMenu is None:
22+
if len(df) <= 10:
23+
assert kwargs["dom"] == "t"
24+
return
25+
26+
assert "dom" not in kwargs
27+
return
28+
29+
min_rows = lengthMenu[0]
30+
if isinstance(min_rows, list):
31+
min_rows = min_rows[0]
32+
33+
if len(df) <= min_rows:
34+
assert kwargs["dom"] == "t"
35+
return
36+
37+
assert "dom" not in kwargs
38+
return

tests/test_sample_dfs.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pandas as pd
55
import pytest
66

7-
from itables import show
7+
from itables import show, to_html_datatable
88
from itables.datatables_format import TableValuesEncoder, _format_column
99
from itables.sample_dfs import (
1010
COLUMN_TYPES,
@@ -48,9 +48,16 @@ def test_get_indicators():
4848
show(df)
4949

5050

51-
@pytest.mark.parametrize("df_name,df", get_dict_of_test_dfs().items())
52-
def test_show_test_dfs(df_name, df):
53-
show(df)
51+
def kwargs_remove_none(**kwargs):
52+
return {key: value for key, value in kwargs.items() if value is not None}
53+
54+
55+
def test_show_test_dfs(df, lengthMenu):
56+
show(df, **kwargs_remove_none(lengthMenu=lengthMenu))
57+
58+
59+
def test_to_html_datatable(df, lengthMenu):
60+
to_html_datatable(df, **kwargs_remove_none(lengthMenu=lengthMenu))
5461

5562

5663
def test_ordered_categories():

tests/test_update_samples.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
from pathlib import Path
22

3-
import pytest
43
import world_bank_data as wb
54

6-
sample_dir = Path(__file__).parent / ".." / "itables" / "samples"
5+
SAMPLE_DIR = Path(__file__).parent / ".." / "itables" / "samples"
76

87

9-
def test_update_countries():
8+
def create_csv_file_if_missing(df, csv_file):
9+
if not csv_file.exists():
10+
with open(str(csv_file), "w") as fp:
11+
fp.write(df.to_csv())
12+
13+
14+
def test_update_countries(csv_file=SAMPLE_DIR / "countries.csv"):
1015
df = wb.get_countries()
11-
with open(str(sample_dir / "countries.csv"), "w") as fp:
12-
fp.write(df.to_csv())
16+
create_csv_file_if_missing(df, csv_file)
1317

1418

15-
def test_update_population():
19+
def test_update_population(csv_file=SAMPLE_DIR / "population.csv"):
1620
x = wb.get_series("SP.POP.TOTL", mrv=1, simplify_index=True)
17-
with open(str(sample_dir / "population.csv"), "w") as fp:
18-
fp.write(x.to_csv())
21+
create_csv_file_if_missing(x, csv_file)
1922

2023

21-
@pytest.mark.skip("The indicators appear to change often")
22-
def test_update_indicators():
24+
def test_update_indicators(csv_file=SAMPLE_DIR / "indicators.csv"):
2325
df = wb.get_indicators().sort_index().head(500)
24-
with open(str(sample_dir / "indicators.csv"), "w") as fp:
25-
fp.write(df.to_csv())
26+
create_csv_file_if_missing(df, csv_file)

0 commit comments

Comments
 (0)