Skip to content

Commit

Permalink
Use the same layout adjusment everywhere (#264)
Browse files Browse the repository at this point in the history
  • Loading branch information
mwouts committed Apr 28, 2024
1 parent 800bc4a commit e8f3d08
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 49 deletions.
1 change: 1 addition & 0 deletions docs/changelog.md
Expand Up @@ -14,6 +14,7 @@ ITables ChangeLog
**Fixed**
- We have improve the compatibility with dark themes ([#255](https://github.com/mwouts/itables/issues/255))
- We now enforce non-sparse index when displaying Pandas Style objects with a multiindex ([#254](https://github.com/mwouts/itables/issues/254))
- Export buttons are shown when using `show(df, buttons=...)` on a Pandas Style object ([#259](https://github.com/mwouts/itables/issues/259))


2.0.0 (2024-03-16)
Expand Down
87 changes: 38 additions & 49 deletions itables/javascript.py
Expand Up @@ -80,7 +80,6 @@
def init_notebook_mode(
all_interactive=False,
connected=GOOGLE_COLAB,
warn_if_call_is_superfluous=True,
dt_bundle=None,
):
"""Load the DataTables library and the corresponding css (if connected=False),
Expand All @@ -98,20 +97,6 @@ def init_notebook_mode(
"This is because HTML outputs in Google Colab are encapsulated in iframes."
)

if (
all_interactive is False
and pd.DataFrame._repr_html_ == _ORIGINAL_DATAFRAME_REPR_HTML
and connected is True
and _CONNECTED == connected
):
if warn_if_call_is_superfluous:
warnings.warn(
"Did you know? "
"init_notebook_mode(all_interactive=False, connected=True) does nothing. "
"Feel free to remove this line, or pass warn_if_call_is_superfluous=False."
)
return

_CONNECTED = connected

if all_interactive:
Expand Down Expand Up @@ -385,38 +370,7 @@ def to_html_datatable(
)
)

has_default_layout = kwargs["layout"] == DEFAULT_LAYOUT

if "dom" in kwargs:
if opt.warn_on_dom:
warnings.warn(
"The 'dom' argument has been deprecated in DataTables==2.0.",
DeprecationWarning,
)
if not has_default_layout:
raise ValueError("You can pass both 'dom' and 'layout'")
del kwargs["layout"]
has_default_layout = False

if has_default_layout and _df_fits_in_one_page(df, kwargs):

def filter_control(control):
if control == "info" and downsampling_warning:
return control
if control not in DEFAULT_LAYOUT_CONTROLS:
return control
return None

kwargs["layout"] = {
key: filter_control(control) for key, control in kwargs["layout"].items()
}

if (
"buttons" in kwargs
and "layout" in kwargs
and "buttons" not in kwargs["layout"].values()
):
kwargs["layout"] = {**kwargs["layout"], "topStart": "buttons"}
_adjust_layout(df, kwargs, downsampling_warning)

footer = kwargs.pop("footer")
column_filters = kwargs.pop("column_filters")
Expand Down Expand Up @@ -549,8 +503,7 @@ def to_html_datatable_using_to_html(
# Polars DataFrame
showIndex = False

if "dom" not in kwargs and _df_fits_in_one_page(df, kwargs):
kwargs["dom"] = "t"
_adjust_layout(df, kwargs, downsampling_warning="")

tableId = (
tableId
Expand Down Expand Up @@ -713,6 +666,34 @@ def _min_rows(kwargs):
return min_rows[0]


def _adjust_layout(df, kwargs, downsampling_warning):
has_default_layout = kwargs["layout"] == DEFAULT_LAYOUT

if "dom" in kwargs:
if opt.warn_on_dom:
warnings.warn(
"The 'dom' argument has been deprecated in DataTables==2.0.",
DeprecationWarning,
)
if not has_default_layout:
raise ValueError("You cannot pass both 'dom' and 'layout'")
del kwargs["layout"]
has_default_layout = False

if has_default_layout and _df_fits_in_one_page(df, kwargs):
kwargs["layout"] = {
key: _filter_control(control, downsampling_warning)
for key, control in kwargs["layout"].items()
}

if (
"buttons" in kwargs
and "layout" in kwargs
and "buttons" not in kwargs["layout"].values()
):
kwargs["layout"] = {**kwargs["layout"], "topStart": "buttons"}


def _df_fits_in_one_page(df, kwargs):
"""Display just the table (not the search box, etc...) if the rows fit on one 'page'"""
try:
Expand All @@ -723,6 +704,14 @@ def _df_fits_in_one_page(df, kwargs):
return len(df) <= _min_rows(kwargs)


def _filter_control(control, downsampling_warning):
if control == "info" and downsampling_warning:
return control
if control not in DEFAULT_LAYOUT_CONTROLS:
return control
return None


def safe_reset_index(df):
try:
return df.reset_index()
Expand Down
36 changes: 36 additions & 0 deletions tests/test_pandas_style.py
@@ -0,0 +1,36 @@
import json

import pandas as pd
import pytest

from itables import to_html_datatable

pytest.importorskip("jinja2")


@pytest.mark.skipif(
pd.__version__.startswith("0."),
reason="AttributeError: 'Styler' object has no attribute 'to_html'",
)
def test_buttons_are_shown_on_pd_style_objects():
df = pd.DataFrame({"A": ["a"]}).style
html = to_html_datatable(
df, buttons=["pageLength", "copyHtml5", "csvHtml5", "excelHtml5"]
)

# Extract the dt_args passed to datatables
dt_args = ""
for line in html.splitlines():
line = line.strip()
if line.startswith("let dt_args"):
dt_args = line.split("=", 1)[1]
break

assert dt_args.endswith(";"), dt_args
dt_args = dt_args[:-1]
dt_args = json.loads(dt_args)

print(dt_args)
assert "dom" not in dt_args
assert "buttons" in dt_args
assert "buttons" in dt_args["layout"].values()

0 comments on commit e8f3d08

Please sign in to comment.