dataframe-textual 2.9.0__tar.gz → 2.10.0__tar.gz
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-2.9.0 → dataframe_textual-2.10.0}/PKG-INFO +7 -1
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/README.md +6 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/pyproject.toml +1 -1
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/data_frame_table.py +21 -17
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/table_screen.py +91 -11
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/uv.lock +1 -1
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/.gitignore +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/1811.csv.gz +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/LICENSE +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/glycosmos_glycans_list.csv.gz +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/large_malformed.tsv.gz +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/main.py +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/__init__.py +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/__main__.py +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/common.py +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/data_frame_help_panel.py +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/data_frame_viewer.py +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/sql_screen.py +0 -0
- {dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/yes_no_screen.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dataframe-textual
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.10.0
|
|
4
4
|
Summary: Interactive terminal viewer/editor for tabular data
|
|
5
5
|
Project-URL: Homepage, https://github.com/need47/dataframe-textual
|
|
6
6
|
Project-URL: Repository, https://github.com/need47/dataframe-textual.git
|
|
@@ -423,6 +423,8 @@ Useful for examining wide datasets where columns don't fit well on screen.
|
|
|
423
423
|
- Press `"` to **filter** all rows containing the selected column value (others removed)
|
|
424
424
|
- Press `{` to move to the previous row
|
|
425
425
|
- Press `}` to move to the next row
|
|
426
|
+
- Press `F` to show the frequency table for the selected column
|
|
427
|
+
- Press `s` to show the statistics table for the selected column
|
|
426
428
|
- Press `q` or `Escape` to close the modal
|
|
427
429
|
|
|
428
430
|
### 3. Row Selection
|
|
@@ -587,6 +589,10 @@ View quick metadata about your dataframe and columns to understand their structu
|
|
|
587
589
|
- **Name** - Column name
|
|
588
590
|
- **Type** - Data type (e.g., Int64, String, Float64, Boolean)
|
|
589
591
|
|
|
592
|
+
**In the Column Metadata Table**
|
|
593
|
+
- Press `F` to show the frequency table for the selected column
|
|
594
|
+
- Press `s` to show the statistics table for the selected column
|
|
595
|
+
|
|
590
596
|
**In Metadata Modals**:
|
|
591
597
|
- Press `q` or `Escape` to close
|
|
592
598
|
|
|
@@ -384,6 +384,8 @@ Useful for examining wide datasets where columns don't fit well on screen.
|
|
|
384
384
|
- Press `"` to **filter** all rows containing the selected column value (others removed)
|
|
385
385
|
- Press `{` to move to the previous row
|
|
386
386
|
- Press `}` to move to the next row
|
|
387
|
+
- Press `F` to show the frequency table for the selected column
|
|
388
|
+
- Press `s` to show the statistics table for the selected column
|
|
387
389
|
- Press `q` or `Escape` to close the modal
|
|
388
390
|
|
|
389
391
|
### 3. Row Selection
|
|
@@ -548,6 +550,10 @@ View quick metadata about your dataframe and columns to understand their structu
|
|
|
548
550
|
- **Name** - Column name
|
|
549
551
|
- **Type** - Data type (e.g., Int64, String, Float64, Boolean)
|
|
550
552
|
|
|
553
|
+
**In the Column Metadata Table**
|
|
554
|
+
- Press `F` to show the frequency table for the selected column
|
|
555
|
+
- Press `s` to show the statistics table for the selected column
|
|
556
|
+
|
|
551
557
|
**In Metadata Modals**:
|
|
552
558
|
- Press `q` or `Escape` to close
|
|
553
559
|
|
{dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/data_frame_table.py
RENAMED
|
@@ -260,7 +260,7 @@ class DataFrameTable(DataTable):
|
|
|
260
260
|
("enter", "view_row_detail", "View row details"),
|
|
261
261
|
("F", "show_frequency", "Show frequency"),
|
|
262
262
|
("s", "show_statistics", "Show statistics for column"),
|
|
263
|
-
("S", "show_statistics(
|
|
263
|
+
("S", "show_statistics(-1)", "Show statistics for dataframe"),
|
|
264
264
|
# Sort
|
|
265
265
|
("left_square_bracket", "sort_ascending", "Sort ascending"), # `[`
|
|
266
266
|
("right_square_bracket", "sort_descending", "Sort descending"), # `]`
|
|
@@ -747,13 +747,16 @@ class DataFrameTable(DataTable):
|
|
|
747
747
|
"""Show frequency distribution for the current column."""
|
|
748
748
|
self.do_show_frequency()
|
|
749
749
|
|
|
750
|
-
def action_show_statistics(self,
|
|
750
|
+
def action_show_statistics(self, cidx: int | None = None) -> None:
|
|
751
751
|
"""Show statistics for the current column or entire dataframe.
|
|
752
752
|
|
|
753
753
|
Args:
|
|
754
|
-
|
|
754
|
+
cidx: Column index
|
|
755
|
+
If -1, show statistics for entire dataframe.
|
|
756
|
+
If None, show statistics for current column, otherwise for specified column.
|
|
757
|
+
|
|
755
758
|
"""
|
|
756
|
-
self.do_show_statistics(
|
|
759
|
+
self.do_show_statistics(cidx)
|
|
757
760
|
|
|
758
761
|
def action_metadata_shape(self) -> None:
|
|
759
762
|
"""Show metadata about the dataframe (row and column counts)."""
|
|
@@ -1661,26 +1664,26 @@ class DataFrameTable(DataTable):
|
|
|
1661
1664
|
# Push the modal screen
|
|
1662
1665
|
self.app.push_screen(RowDetailScreen(ridx, self))
|
|
1663
1666
|
|
|
1664
|
-
def do_show_frequency(self) -> None:
|
|
1665
|
-
"""Show frequency distribution for
|
|
1666
|
-
cidx = self.cursor_col_idx
|
|
1667
|
+
def do_show_frequency(self, cidx=None) -> None:
|
|
1668
|
+
"""Show frequency distribution for a given columnn."""
|
|
1669
|
+
cidx = cidx or self.cursor_col_idx
|
|
1667
1670
|
|
|
1668
1671
|
# Push the frequency modal screen
|
|
1669
1672
|
self.app.push_screen(FrequencyScreen(cidx, self))
|
|
1670
1673
|
|
|
1671
|
-
def do_show_statistics(self,
|
|
1674
|
+
def do_show_statistics(self, cidx: int | None = None) -> None:
|
|
1672
1675
|
"""Show statistics for the current column or entire dataframe.
|
|
1673
1676
|
|
|
1674
1677
|
Args:
|
|
1675
|
-
|
|
1678
|
+
cidx: Column index to show statistics for. If None, show for entire dataframe.
|
|
1676
1679
|
"""
|
|
1677
|
-
if
|
|
1680
|
+
if cidx == -1:
|
|
1678
1681
|
# Show statistics for entire dataframe
|
|
1679
|
-
self.app.push_screen(StatisticsScreen(self,
|
|
1682
|
+
self.app.push_screen(StatisticsScreen(self, cidx=None))
|
|
1680
1683
|
else:
|
|
1681
|
-
# Show statistics for current column
|
|
1682
|
-
cidx = self.cursor_col_idx
|
|
1683
|
-
self.app.push_screen(StatisticsScreen(self,
|
|
1684
|
+
# Show statistics for current column or specified column
|
|
1685
|
+
cidx = self.cursor_col_idx if cidx is None else cidx
|
|
1686
|
+
self.app.push_screen(StatisticsScreen(self, cidx=cidx))
|
|
1684
1687
|
|
|
1685
1688
|
def do_metadata_shape(self) -> None:
|
|
1686
1689
|
"""Show metadata about the dataframe (row and column counts)."""
|
|
@@ -3711,6 +3714,9 @@ class DataFrameTable(DataTable):
|
|
|
3711
3714
|
|
|
3712
3715
|
expr_str = "boolean list or series" if isinstance(expr, (list, pl.Series)) else str(expr)
|
|
3713
3716
|
|
|
3717
|
+
# Add to history
|
|
3718
|
+
self.add_history(f"Viewed rows by expression [$success]{expr_str}[/]")
|
|
3719
|
+
|
|
3714
3720
|
# Apply the filter expression
|
|
3715
3721
|
try:
|
|
3716
3722
|
df_filtered = lf.filter(expr).collect()
|
|
@@ -3722,12 +3728,10 @@ class DataFrameTable(DataTable):
|
|
|
3722
3728
|
|
|
3723
3729
|
matched_count = len(df_filtered)
|
|
3724
3730
|
if not matched_count:
|
|
3731
|
+
self.histories_undo.pop() # Remove last history entry
|
|
3725
3732
|
self.notify(f"No rows match the expression: [$success]{expr}[/]", title="View Rows", severity="warning")
|
|
3726
3733
|
return
|
|
3727
3734
|
|
|
3728
|
-
# Add to history
|
|
3729
|
-
self.add_history(f"Viewed rows by expression [$success]{expr_str}[/]")
|
|
3730
|
-
|
|
3731
3735
|
ok_rids = set(df_filtered[RID])
|
|
3732
3736
|
|
|
3733
3737
|
# Create a view of self.df as a copy
|
|
@@ -102,7 +102,7 @@ class TableScreen(ModalScreen):
|
|
|
102
102
|
if cidx_name_value is None:
|
|
103
103
|
return
|
|
104
104
|
cidx, col_name, col_value = cidx_name_value
|
|
105
|
-
self.log(f"Filtering or viewing by `{col_name} == {col_value}`")
|
|
105
|
+
# self.log(f"Filtering or viewing by `{col_name} == {col_value}`")
|
|
106
106
|
|
|
107
107
|
# Handle NULL values
|
|
108
108
|
if col_value == NULL:
|
|
@@ -115,7 +115,7 @@ class TableScreen(ModalScreen):
|
|
|
115
115
|
value_display = f"[$success]{col_value}[/]"
|
|
116
116
|
|
|
117
117
|
df_filtered = self.dftable.df.lazy().filter(expr).collect()
|
|
118
|
-
self.log(f"Filtered dataframe has {len(df_filtered)} rows")
|
|
118
|
+
# self.log(f"Filtered dataframe has {len(df_filtered)} rows")
|
|
119
119
|
|
|
120
120
|
ok_rids = set(df_filtered[RID].to_list())
|
|
121
121
|
if not ok_rids:
|
|
@@ -134,9 +134,45 @@ class TableScreen(ModalScreen):
|
|
|
134
134
|
else:
|
|
135
135
|
self.dftable.view_rows((expr, cidx, False, True))
|
|
136
136
|
|
|
137
|
-
# Dismiss the
|
|
137
|
+
# Dismiss the current modal screen
|
|
138
138
|
self.app.pop_screen()
|
|
139
139
|
|
|
140
|
+
def show_frequency(self, cidx_name_value: tuple[int, str, Any] | None) -> None:
|
|
141
|
+
"""Show frequency by the selected value.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
col_name_value: Tuple of (column_name, column_value) to filter/view by, or None.
|
|
145
|
+
"""
|
|
146
|
+
if cidx_name_value is None:
|
|
147
|
+
return
|
|
148
|
+
cidx, col_name, col_value = cidx_name_value
|
|
149
|
+
# self.log(f"Showing frequency for `{col_name} == {col_value}`")
|
|
150
|
+
|
|
151
|
+
# Do not dismiss the current modal screen so it can be returned to
|
|
152
|
+
# when frequency screen is closed.
|
|
153
|
+
# self.app.pop_screen()
|
|
154
|
+
|
|
155
|
+
# Show frequency screen
|
|
156
|
+
self.dftable.do_show_frequency(cidx)
|
|
157
|
+
|
|
158
|
+
def show_statistics(self, cidx_name_value: tuple[int, str, Any] | None) -> None:
|
|
159
|
+
"""Show frequency by the selected value.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
col_name_value: Tuple of (column_name, column_value) to filter/view by, or None.
|
|
163
|
+
"""
|
|
164
|
+
if cidx_name_value is None:
|
|
165
|
+
return
|
|
166
|
+
cidx, col_name, col_value = cidx_name_value
|
|
167
|
+
# self.log(f"Showing statistics for `{col_name} == {col_value}`")
|
|
168
|
+
|
|
169
|
+
# Do not dismiss the current modal screen so it can be returned to
|
|
170
|
+
# when frequency screen is closed.
|
|
171
|
+
# self.app.pop_screen()
|
|
172
|
+
|
|
173
|
+
# Show statistics screen
|
|
174
|
+
self.dftable.do_show_statistics(cidx)
|
|
175
|
+
|
|
140
176
|
|
|
141
177
|
class RowDetailScreen(TableScreen):
|
|
142
178
|
"""Modal screen to display a single row's details."""
|
|
@@ -175,10 +211,15 @@ class RowDetailScreen(TableScreen):
|
|
|
175
211
|
self.table.cursor_type = "row"
|
|
176
212
|
|
|
177
213
|
def on_key(self, event) -> None:
|
|
178
|
-
"""Handle key press events
|
|
214
|
+
"""Handle key press events on the row detail screen.
|
|
179
215
|
|
|
180
|
-
|
|
181
|
-
|
|
216
|
+
Supported keys:
|
|
217
|
+
- 'v': View the main table by the selected value.
|
|
218
|
+
- '"': Filter the main table by the selected value.
|
|
219
|
+
- '{': Move to the previous row.
|
|
220
|
+
- '}': Move to the next row.
|
|
221
|
+
- 'F': Show frequency for the selected value.
|
|
222
|
+
- 's': Show statistics for the selected value.
|
|
182
223
|
|
|
183
224
|
Args:
|
|
184
225
|
event: The key event object.
|
|
@@ -207,8 +248,17 @@ class RowDetailScreen(TableScreen):
|
|
|
207
248
|
self.dftable.move_cursor_to(self.ridx)
|
|
208
249
|
self.build_table()
|
|
209
250
|
event.stop()
|
|
251
|
+
elif event.key == "F":
|
|
252
|
+
# Show frequency for the selected value
|
|
253
|
+
self.show_frequency(self.get_cidx_name_value())
|
|
254
|
+
event.stop()
|
|
255
|
+
elif event.key == "s":
|
|
256
|
+
# Show statistics for the selected value
|
|
257
|
+
self.show_statistics(self.get_cidx_name_value())
|
|
258
|
+
event.stop()
|
|
210
259
|
|
|
211
260
|
def get_cidx_name_value(self) -> tuple[int, str, Any] | None:
|
|
261
|
+
"""Get the current column info."""
|
|
212
262
|
cidx = self.table.cursor_row
|
|
213
263
|
if cidx >= len(self.df.columns):
|
|
214
264
|
return None # Invalid row
|
|
@@ -224,9 +274,9 @@ class StatisticsScreen(TableScreen):
|
|
|
224
274
|
|
|
225
275
|
CSS = TableScreen.DEFAULT_CSS.replace("TableScreen", "StatisticsScreen")
|
|
226
276
|
|
|
227
|
-
def __init__(self, dftable: "DataFrameTable",
|
|
277
|
+
def __init__(self, dftable: "DataFrameTable", cidx: int | None = None):
|
|
228
278
|
super().__init__(dftable)
|
|
229
|
-
self.
|
|
279
|
+
self.cidx = cidx # None for dataframe statistics, otherwise column index
|
|
230
280
|
|
|
231
281
|
def on_mount(self) -> None:
|
|
232
282
|
"""Create the statistics table."""
|
|
@@ -236,7 +286,7 @@ class StatisticsScreen(TableScreen):
|
|
|
236
286
|
"""Build the statistics table."""
|
|
237
287
|
self.table.clear(columns=True)
|
|
238
288
|
|
|
239
|
-
if self.
|
|
289
|
+
if self.cidx is None:
|
|
240
290
|
# Dataframe statistics
|
|
241
291
|
self.build_dataframe_stats()
|
|
242
292
|
self.table.cursor_type = "column"
|
|
@@ -247,7 +297,7 @@ class StatisticsScreen(TableScreen):
|
|
|
247
297
|
|
|
248
298
|
def build_column_stats(self) -> None:
|
|
249
299
|
"""Build statistics for a single column."""
|
|
250
|
-
col_name = self.df.columns[self.
|
|
300
|
+
col_name = self.df.columns[self.cidx]
|
|
251
301
|
lf = self.df.lazy()
|
|
252
302
|
|
|
253
303
|
# Get column statistics
|
|
@@ -500,6 +550,25 @@ class MetaColumnScreen(TableScreen):
|
|
|
500
550
|
"""
|
|
501
551
|
self.build_table()
|
|
502
552
|
|
|
553
|
+
def on_key(self, event) -> None:
|
|
554
|
+
"""Handle key press events on the column metadata screen.
|
|
555
|
+
|
|
556
|
+
Supports keys:
|
|
557
|
+
- 'F': Show frequency for the selected value.
|
|
558
|
+
- 's': Show statistics for the selected value.
|
|
559
|
+
|
|
560
|
+
Args:
|
|
561
|
+
event: The key event object.
|
|
562
|
+
"""
|
|
563
|
+
if event.key == "F":
|
|
564
|
+
# Show frequency for the selected value
|
|
565
|
+
self.show_frequency(self.get_cidx_name_value())
|
|
566
|
+
event.stop()
|
|
567
|
+
elif event.key == "s":
|
|
568
|
+
# Show statistics for the selected value
|
|
569
|
+
self.show_statistics(self.get_cidx_name_value())
|
|
570
|
+
event.stop()
|
|
571
|
+
|
|
503
572
|
def build_table(self) -> None:
|
|
504
573
|
"""Build the column metadata table."""
|
|
505
574
|
self.table.clear(columns=True)
|
|
@@ -524,4 +593,15 @@ class MetaColumnScreen(TableScreen):
|
|
|
524
593
|
dc_str.format("Datetime" if str(col_type).startswith("Datetime") else col_type, style=dc.style),
|
|
525
594
|
)
|
|
526
595
|
|
|
527
|
-
self.table.cursor_type = "
|
|
596
|
+
self.table.cursor_type = "row"
|
|
597
|
+
|
|
598
|
+
def get_cidx_name_value(self) -> int | None:
|
|
599
|
+
"""Get the current column info."""
|
|
600
|
+
cidx = self.table.cursor_row
|
|
601
|
+
if cidx >= len(self.df.columns):
|
|
602
|
+
return None # Invalid row
|
|
603
|
+
|
|
604
|
+
col_name = self.df.columns[cidx]
|
|
605
|
+
col_value = None
|
|
606
|
+
|
|
607
|
+
return cidx, col_name, col_value
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/data_frame_help_panel.py
RENAMED
|
File without changes
|
{dataframe_textual-2.9.0 → dataframe_textual-2.10.0}/src/dataframe_textual/data_frame_viewer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|