Skip to content

Commit 3856082

Browse files
authored
Merge pull request #12 from machow/fix-gt-deps
Fix gt deps
2 parents 0e33b89 + 299c13d commit 3856082

File tree

5 files changed

+95
-12
lines changed

5 files changed

+95
-12
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ jobs:
2929
# we are using the -e flag, so that code cov finds the source.
3030
# this is not ideal, since installing an editable can technically
3131
# differ from a normal install in surprising ways.
32-
python -m pip install "git+https://github.com/posit-dev/great-tables.git@feat-interactive"
3332
pip install -e '.[all]'
3433
- name: Unit tests
3534
run: |

.github/workflows/docs.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ jobs:
1818
python-version: "3.10"
1919
- name: Install dependencies
2020
run: |
21-
python -m pip install "git+https://github.com/posit-dev/great-tables.git@feat-interactive"
2221
python -m pip install ".[dev]"
2322
- uses: quarto-dev/quarto-actions/setup@v2
2423
with:

reactable/_tbl_data.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from datetime import datetime, date, time
66
from functools import singledispatch
7-
from typing import TYPE_CHECKING, Any, Union, Literal
7+
from typing import TYPE_CHECKING, Any, Union, Literal, Optional
88
from typing_extensions import TypeAlias
99

1010
from abc import ABC
@@ -163,3 +163,33 @@ def _(data: PdDataFrame) -> "list[str]":
163163
@column_names.register
164164
def _(data: SimpleFrame) -> "list[str]":
165165
return list(data.columns)
166+
167+
168+
# subset_frame --------------------------------------------------------
169+
@singledispatch
170+
def subset_frame(
171+
data: DataFrameLike, row: Optional[list[int]], column: Optional[list[str]]
172+
) -> DataFrameLike:
173+
raise TypeError(f"Unsupported type: {type(data)}")
174+
175+
176+
@subset_frame.register
177+
def _(
178+
data: PdDataFrame, rows: Optional[list[int]] = None, cols: Optional[list[str]] = None
179+
) -> PdDataFrame:
180+
181+
cols_indx = slice(None) if cols is None else data.columns.get_indexer_for(cols)
182+
rows_indx = slice(None) if rows is None else rows
183+
184+
return data.iloc[rows_indx, cols_indx]
185+
186+
187+
@subset_frame.register
188+
def _(
189+
data: PlDataFrame, rows: Optional[list[int]] = None, cols: Optional[list[str]] = None
190+
) -> PlDataFrame:
191+
192+
cols_indx = slice(None) if cols is None else cols
193+
rows_indx = slice(None) if rows is None else rows
194+
195+
return data[rows_indx, cols_indx]

reactable/render_gt.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,30 @@
55
import ipywidgets
66

77
from great_tables import GT
8-
from great_tables._tbl_data import n_rows, subset_frame
8+
from great_tables._tbl_data import n_rows
99
from great_tables._helpers import random_id
1010
from great_tables._text import _process_text
1111
from great_tables._gt_data import ColInfoTypeEnum
1212
from great_tables._scss import compile_scss
13-
from typing import TYPE_CHECKING
13+
from typing import TYPE_CHECKING, Any
1414

1515
from .models import Column, Language, Theme, ColGroup
1616
from . import Reactable
1717
from .tags import as_react_style, to_widget
18+
from ._tbl_data import subset_frame, to_dict
1819

1920
if TYPE_CHECKING:
20-
from great_tables._gt_data import Locale, Spanners, Heading, Footnotes, SourceNotes
21+
from great_tables._gt_data import Locale, Spanners, Heading, Footnotes, SourceNotes, Options
22+
23+
24+
class OptWrapper:
25+
_d: Options
26+
27+
def __init__(self, d: Options):
28+
self._d = d
29+
30+
def __getitem__(self, k: str) -> Any:
31+
return getattr(self._d, k).value
2132

2233

2334
def dict_to_css(dict_: dict[str, str]) -> str:
@@ -48,8 +59,14 @@ def create_col_groups(spanners: Spanners) -> list[ColGroup]:
4859
return col_groups
4960

5061

62+
def _is_empty(heading: Heading):
63+
# TODO: this should be moved into great tables
64+
self = heading
65+
return self.title is None and self.subtitle is None and self.preheader is None
66+
67+
5168
def create_heading(heading: Heading, use_search: bool) -> html.Tag | None:
52-
if heading.is_empty():
69+
if _is_empty(heading):
5370
return None
5471

5572
el = html.div(
@@ -117,8 +134,6 @@ def extract_cells(
117134
from great_tables._tbl_data import (
118135
cast_frame_to_string,
119136
replace_null_frame,
120-
subset_frame,
121-
to_column_dict,
122137
)
123138

124139
if rows is not None:
@@ -137,7 +152,7 @@ def extract_cells(
137152

138153
# TODO: get_cell gets individual cell, need one that gets columns
139154
df_subset = subset_frame(df_stringified, cols=columns)
140-
return to_column_dict(df_subset)
155+
return to_dict(df_subset)
141156

142157

143158
def _render(self: GT):
@@ -146,7 +161,7 @@ def _render(self: GT):
146161

147162
# add_css_styles()
148163

149-
table_id = self._options["table_id"] or random_id()
164+
table_id = OptWrapper(self._options)["table_id"] or random_id()
150165
locale = self._locale
151166

152167
# generate Language -------------------------------------------------------
@@ -243,7 +258,7 @@ def _render(self: GT):
243258
)
244259

245260
# Generate theme ----------------------------------------------------------
246-
opts = self._options
261+
opts = OptWrapper(self._options)
247262
theme = Theme(
248263
color=opts["table_font_color"],
249264
background_color=opts["table_background_color"],

tests/test_tbl_data.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import pandas as pd
2+
import polars as pl
3+
import polars.testing
4+
import pytest
5+
6+
from reactable._tbl_data import subset_frame, SimpleFrame, SimpleColumn
7+
8+
params_frames = [pytest.param(pd.DataFrame, id="pandas"), pytest.param(pl.DataFrame, id="polars")]
9+
params_series = [pytest.param(pd.Series, id="pandas"), pytest.param(pl.Series, id="polars")]
10+
11+
12+
@pytest.fixture(params=params_frames, scope="function")
13+
def df(request) -> pd.DataFrame:
14+
return request.param({"col1": [1, 2, 3], "col2": ["a", "b", "c"], "col3": [4.0, 5.0, 6.0]})
15+
16+
17+
@pytest.fixture(params=params_series, scope="function")
18+
def ser(request):
19+
return request.param([1.0, 2.0, None])
20+
21+
22+
def assert_frame_equal(src, target, include_index=True):
23+
if isinstance(src, pd.DataFrame):
24+
if not include_index:
25+
src = src.reset_index(drop=True)
26+
target = target.reset_index(drop=True)
27+
pd.testing.assert_frame_equal(src, target)
28+
elif isinstance(src, pl.DataFrame):
29+
pl.testing.assert_frame_equal(src, target)
30+
else:
31+
raise NotImplementedError(f"Unsupported data type: {type(src)}")
32+
33+
34+
def test_subset_frame(df):
35+
res = subset_frame(df, rows=[0, 2], cols=["col1", "col3"])
36+
assert_frame_equal(
37+
res,
38+
df.__class__({"col1": [1, 3], "col3": [4.0, 6.0]}),
39+
include_index=False,
40+
)

0 commit comments

Comments
 (0)