dataframe-textual 0.2.1__py3-none-any.whl → 0.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dataframe_textual/data_frame_table.py +2 -4
- dataframe_textual/table_screen.py +38 -29
- {dataframe_textual-0.2.1.dist-info → dataframe_textual-0.3.1.dist-info}/METADATA +2 -3
- {dataframe_textual-0.2.1.dist-info → dataframe_textual-0.3.1.dist-info}/RECORD +7 -7
- {dataframe_textual-0.2.1.dist-info → dataframe_textual-0.3.1.dist-info}/WHEEL +0 -0
- {dataframe_textual-0.2.1.dist-info → dataframe_textual-0.3.1.dist-info}/entry_points.txt +0 -0
- {dataframe_textual-0.2.1.dist-info → dataframe_textual-0.3.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -549,7 +549,7 @@ class DataFrameTable(DataTable):
|
|
|
549
549
|
return
|
|
550
550
|
|
|
551
551
|
# Push the modal screen
|
|
552
|
-
self.app.push_screen(RowDetailScreen(row_idx, self
|
|
552
|
+
self.app.push_screen(RowDetailScreen(row_idx, self))
|
|
553
553
|
|
|
554
554
|
def _show_frequency(self) -> None:
|
|
555
555
|
"""Show frequency distribution for the current column."""
|
|
@@ -558,9 +558,7 @@ class DataFrameTable(DataTable):
|
|
|
558
558
|
return
|
|
559
559
|
|
|
560
560
|
# Push the frequency modal screen
|
|
561
|
-
self.app.push_screen(
|
|
562
|
-
FrequencyScreen(col_idx, self.df.filter(self.visible_rows))
|
|
563
|
-
)
|
|
561
|
+
self.app.push_screen(FrequencyScreen(col_idx, self))
|
|
564
562
|
|
|
565
563
|
def _open_freeze_screen(self) -> None:
|
|
566
564
|
"""Open the freeze screen to set fixed rows and columns."""
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"""Modal screens for displaying data in tables (row details and frequency)."""
|
|
2
2
|
|
|
3
|
-
from typing import Any
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from .data_frame_table import DataFrameTable
|
|
4
7
|
|
|
5
8
|
import polars as pl
|
|
6
9
|
from rich.text import Text
|
|
7
10
|
from textual.app import ComposeResult
|
|
8
11
|
from textual.coordinate import Coordinate
|
|
12
|
+
from textual.renderables.bar import Bar
|
|
9
13
|
from textual.screen import ModalScreen
|
|
10
14
|
from textual.widgets import DataTable
|
|
11
15
|
|
|
@@ -32,14 +36,14 @@ class TableScreen(ModalScreen):
|
|
|
32
36
|
}
|
|
33
37
|
"""
|
|
34
38
|
|
|
35
|
-
def __init__(self,
|
|
39
|
+
def __init__(self, dftable: DataFrameTable):
|
|
36
40
|
super().__init__()
|
|
37
|
-
self.df = df
|
|
38
|
-
self.
|
|
41
|
+
self.df: pl.DataFrame = dftable.df # Polars DataFrame
|
|
42
|
+
self.dftable = dftable # DataFrameTable
|
|
39
43
|
|
|
40
44
|
def compose(self) -> ComposeResult:
|
|
41
45
|
"""Create the table. Must be overridden by subclasses."""
|
|
42
|
-
self.table = DataTable(zebra_stripes=True
|
|
46
|
+
self.table = DataTable(zebra_stripes=True)
|
|
43
47
|
yield self.table
|
|
44
48
|
|
|
45
49
|
def on_key(self, event):
|
|
@@ -86,27 +90,26 @@ class TableScreen(ModalScreen):
|
|
|
86
90
|
expr = pl.col(col_name) == col_value
|
|
87
91
|
value_display = f"[on $primary]{col_value}[/]"
|
|
88
92
|
|
|
89
|
-
app = self.app
|
|
90
93
|
matched_indices = set(
|
|
91
|
-
|
|
94
|
+
self.dftable.df.with_row_index("__rid__").filter(expr)["__rid__"].to_list()
|
|
92
95
|
)
|
|
93
96
|
|
|
94
97
|
# Apply the action
|
|
95
98
|
if action == "filter":
|
|
96
99
|
# Update visible_rows to reflect the filter
|
|
97
|
-
for i in range(len(
|
|
98
|
-
|
|
100
|
+
for i in range(len(self.dftable.visible_rows)):
|
|
101
|
+
self.dftable.visible_rows[i] = i in matched_indices
|
|
99
102
|
title = "Filter"
|
|
100
103
|
message = f"Filtered by [on $primary]{col_name}[/] = {value_display}"
|
|
101
104
|
else: # action == "highlight"
|
|
102
105
|
# Update selected_rows to reflect the highlights
|
|
103
|
-
for i in range(len(
|
|
104
|
-
|
|
106
|
+
for i in range(len(self.dftable.selected_rows)):
|
|
107
|
+
self.dftable.selected_rows[i] = i in matched_indices
|
|
105
108
|
title = "Highlight"
|
|
106
109
|
message = f"Highlighted [on $primary]{col_name}[/] = {value_display}"
|
|
107
110
|
|
|
108
111
|
# Recreate the table display with updated data in the main app
|
|
109
|
-
|
|
112
|
+
self.dftable._setup_table()
|
|
110
113
|
|
|
111
114
|
# Dismiss the frequency screen
|
|
112
115
|
self.app.pop_screen()
|
|
@@ -119,8 +122,8 @@ class RowDetailScreen(TableScreen):
|
|
|
119
122
|
|
|
120
123
|
CSS = TableScreen.DEFAULT_CSS.replace("TableScreen", "RowDetailScreen")
|
|
121
124
|
|
|
122
|
-
def __init__(self, row_idx: int,
|
|
123
|
-
super().__init__(
|
|
125
|
+
def __init__(self, row_idx: int, dftable):
|
|
126
|
+
super().__init__(dftable)
|
|
124
127
|
self.row_idx = row_idx
|
|
125
128
|
|
|
126
129
|
def on_mount(self) -> None:
|
|
@@ -136,6 +139,8 @@ class RowDetailScreen(TableScreen):
|
|
|
136
139
|
*_format_row([col, val], [None, dtype], apply_justify=False)
|
|
137
140
|
)
|
|
138
141
|
|
|
142
|
+
self.table.cursor_type = "row"
|
|
143
|
+
|
|
139
144
|
def on_key(self, event):
|
|
140
145
|
if event.key == "v":
|
|
141
146
|
# Filter the main table by the selected value
|
|
@@ -166,8 +171,8 @@ class FrequencyScreen(TableScreen):
|
|
|
166
171
|
|
|
167
172
|
CSS = TableScreen.DEFAULT_CSS.replace("TableScreen", "FrequencyScreen")
|
|
168
173
|
|
|
169
|
-
def __init__(self, col_idx: int,
|
|
170
|
-
super().__init__(
|
|
174
|
+
def __init__(self, col_idx: int, dftable):
|
|
175
|
+
super().__init__(dftable)
|
|
171
176
|
self.col_idx = col_idx
|
|
172
177
|
self.sorted_columns = {
|
|
173
178
|
1: True, # Count
|
|
@@ -188,6 +193,7 @@ class FrequencyScreen(TableScreen):
|
|
|
188
193
|
self.table.add_column(Text(column, justify=dc.justify), key=column)
|
|
189
194
|
self.table.add_column(Text("Count", justify="right"), key="Count")
|
|
190
195
|
self.table.add_column(Text("%", justify="right"), key="%")
|
|
196
|
+
self.table.add_column(Text("Histogram", justify="left"), key="Histogram")
|
|
191
197
|
|
|
192
198
|
# Get style config for Int64 and Float64
|
|
193
199
|
ds_int = DtypeConfig("Int64")
|
|
@@ -204,16 +210,16 @@ class FrequencyScreen(TableScreen):
|
|
|
204
210
|
style=dc.style,
|
|
205
211
|
justify=dc.justify,
|
|
206
212
|
),
|
|
207
|
-
Text(
|
|
208
|
-
str(count),
|
|
209
|
-
style=ds_int.style,
|
|
210
|
-
justify=ds_int.justify,
|
|
211
|
-
),
|
|
213
|
+
Text(str(count), style=ds_int.style, justify=ds_int.justify),
|
|
212
214
|
Text(
|
|
213
215
|
f"{percentage:.2f}",
|
|
214
216
|
style=ds_float.style,
|
|
215
217
|
justify=ds_float.justify,
|
|
216
218
|
),
|
|
219
|
+
Bar(
|
|
220
|
+
highlight_range=(0.0, percentage / 100 * 10),
|
|
221
|
+
width=10,
|
|
222
|
+
),
|
|
217
223
|
key=str(row_idx + 1),
|
|
218
224
|
)
|
|
219
225
|
|
|
@@ -279,14 +285,17 @@ class FrequencyScreen(TableScreen):
|
|
|
279
285
|
def key_fun(freq_col):
|
|
280
286
|
col_value = freq_col.plain
|
|
281
287
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
288
|
+
try:
|
|
289
|
+
if col_dtype == "Int64":
|
|
290
|
+
return int(col_value)
|
|
291
|
+
elif col_dtype == "Float64":
|
|
292
|
+
return float(col_value)
|
|
293
|
+
elif col_dtype == "Boolean":
|
|
294
|
+
return BOOLS[col_value]
|
|
295
|
+
else:
|
|
296
|
+
return col_value
|
|
297
|
+
except ValueError:
|
|
298
|
+
return 0
|
|
290
299
|
|
|
291
300
|
# Sort the table
|
|
292
301
|
freq_table.sort(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dataframe-textual
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Interactive CSV/Excel viewer for the terminal (Textual TUI)
|
|
5
5
|
Project-URL: Homepage, https://github.com/need47/dataframe-textual
|
|
6
6
|
Project-URL: Repository, https://github.com/need47/dataframe-textual.git
|
|
@@ -9,7 +9,7 @@ Project-URL: Bug Tracker, https://github.com/need47/dataframe-textual/issues
|
|
|
9
9
|
Author-email: Tiejun Cheng <need47@gmail.com>
|
|
10
10
|
License: MIT
|
|
11
11
|
License-File: LICENSE
|
|
12
|
-
Keywords: csv,data-analysis,interactive,polars,terminal,textual,tui,viewer
|
|
12
|
+
Keywords: csv,data-analysis,excel,interactive,polars,terminal,textual,tui,viewer
|
|
13
13
|
Classifier: Development Status :: 3 - Alpha
|
|
14
14
|
Classifier: Environment :: Console
|
|
15
15
|
Classifier: Intended Audience :: Developers
|
|
@@ -29,7 +29,6 @@ Classifier: Topic :: Utilities
|
|
|
29
29
|
Classifier: Typing :: Typed
|
|
30
30
|
Requires-Python: >=3.11
|
|
31
31
|
Requires-Dist: polars>=1.34.0
|
|
32
|
-
Requires-Dist: rich>=14.2.0
|
|
33
32
|
Requires-Dist: textual>=1.0.0
|
|
34
33
|
Provides-Extra: dev
|
|
35
34
|
Requires-Dist: textual-dev>=1.8.0; extra == 'dev'
|
|
@@ -2,12 +2,12 @@ dataframe_textual/__init__.py,sha256=uzB3bjlbm8JbsjxEgwqvPcYERktm3F9d9Op_6cWJ1sk
|
|
|
2
2
|
dataframe_textual/__main__.py,sha256=LPLyZcv4hAFfF3hUt1S2dtZOqaAZnlguicgwiDrtXgk,1349
|
|
3
3
|
dataframe_textual/common.py,sha256=3zzhI__F_hoOFDRe-wt-oTfMDFik1ohraIa6rXcVit8,6357
|
|
4
4
|
dataframe_textual/data_frame_help_panel.py,sha256=SQ2lulb1SPxItR9tMvIgOzzeCcW9SB1rRojAcwZ7Vis,2730
|
|
5
|
-
dataframe_textual/data_frame_table.py,sha256=
|
|
5
|
+
dataframe_textual/data_frame_table.py,sha256=8CCTwhi0cYPr9yEuMlv76rzPT48PzxyjsCIP2P3g3_c,50025
|
|
6
6
|
dataframe_textual/data_frame_viewer.py,sha256=BP-pCYIG5bEDFkUmUyA3sxWc3z1zI_viClDZlT-s_uE,11715
|
|
7
|
-
dataframe_textual/table_screen.py,sha256=
|
|
7
|
+
dataframe_textual/table_screen.py,sha256=elY0gBdc0PQlh82N7lu3FHeVoFprqd-8iUBVvfSdah0,11015
|
|
8
8
|
dataframe_textual/yes_no_screen.py,sha256=z7MEVTMepFuGWFIthhQlAT3m69D6lgIl4tb2_oJAWWQ,13207
|
|
9
|
-
dataframe_textual-0.
|
|
10
|
-
dataframe_textual-0.
|
|
11
|
-
dataframe_textual-0.
|
|
12
|
-
dataframe_textual-0.
|
|
13
|
-
dataframe_textual-0.
|
|
9
|
+
dataframe_textual-0.3.1.dist-info/METADATA,sha256=nmpsgfqdd5E9RAe3rMwI_qkX3V_n_k_bVFP-DX9bAzY,17109
|
|
10
|
+
dataframe_textual-0.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
11
|
+
dataframe_textual-0.3.1.dist-info/entry_points.txt,sha256=FkXDHVYYtGud6F2Jm2X9OMFAuFrSflNfgcNP5c2469M,70
|
|
12
|
+
dataframe_textual-0.3.1.dist-info/licenses/LICENSE,sha256=AVTg0gk1X-LHI-nnHlAMDQetrwuDZK4eypgSMDO46Yc,1069
|
|
13
|
+
dataframe_textual-0.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|