dataframe-textual 2.1.0__py3-none-any.whl → 2.2.0__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/__main__.py +4 -0
- dataframe_textual/common.py +4 -0
- dataframe_textual/data_frame_table.py +15 -1
- dataframe_textual/data_frame_viewer.py +20 -1
- {dataframe_textual-2.1.0.dist-info → dataframe_textual-2.2.0.dist-info}/METADATA +1 -1
- dataframe_textual-2.2.0.dist-info/RECORD +14 -0
- dataframe_textual-2.1.0.dist-info/RECORD +0 -14
- {dataframe_textual-2.1.0.dist-info → dataframe_textual-2.2.0.dist-info}/WHEEL +0 -0
- {dataframe_textual-2.1.0.dist-info → dataframe_textual-2.2.0.dist-info}/entry_points.txt +0 -0
- {dataframe_textual-2.1.0.dist-info → dataframe_textual-2.2.0.dist-info}/licenses/LICENSE +0 -0
dataframe_textual/__main__.py
CHANGED
|
@@ -46,6 +46,9 @@ def cli() -> argparse.Namespace:
|
|
|
46
46
|
parser.add_argument(
|
|
47
47
|
"-I", "--no-inference", action="store_true", help="Do not infer data types when reading CSV/TSV"
|
|
48
48
|
)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
"-t", "--truncate-ragged-lines", action="store_true", help="Truncate ragged lines when reading CSV/TSV"
|
|
51
|
+
)
|
|
49
52
|
parser.add_argument("-E", "--ignore-errors", action="store_true", help="Ignore errors when reading CSV/TSV")
|
|
50
53
|
parser.add_argument(
|
|
51
54
|
"-c", "--comment-prefix", nargs="?", const="#", help="Comment lines are skipped when reading CSV/TSV"
|
|
@@ -94,6 +97,7 @@ def main() -> None:
|
|
|
94
97
|
skip_rows_after_header=args.skip_rows_after_header,
|
|
95
98
|
null_values=args.null,
|
|
96
99
|
ignore_errors=args.ignore_errors,
|
|
100
|
+
truncate_ragged_lines=args.truncate_ragged_lines,
|
|
97
101
|
)
|
|
98
102
|
app = DataFrameViewer(*sources)
|
|
99
103
|
app.run()
|
dataframe_textual/common.py
CHANGED
|
@@ -484,6 +484,7 @@ def load_dataframe(
|
|
|
484
484
|
skip_rows_after_header: int = 0,
|
|
485
485
|
null_values: list[str] | None = None,
|
|
486
486
|
ignore_errors: bool = False,
|
|
487
|
+
truncate_ragged_lines: bool = False,
|
|
487
488
|
) -> list[Source]:
|
|
488
489
|
"""Load DataFrames from file specifications.
|
|
489
490
|
|
|
@@ -548,6 +549,7 @@ def load_dataframe(
|
|
|
548
549
|
skip_rows_after_header=skip_rows_after_header,
|
|
549
550
|
null_values=null_values,
|
|
550
551
|
ignore_errors=ignore_errors,
|
|
552
|
+
truncate_ragged_lines=truncate_ragged_lines,
|
|
551
553
|
)
|
|
552
554
|
)
|
|
553
555
|
|
|
@@ -624,6 +626,7 @@ def load_file(
|
|
|
624
626
|
schema_overrides: dict[str, pl.DataType] | None = None,
|
|
625
627
|
null_values: list[str] | None = None,
|
|
626
628
|
ignore_errors: bool = False,
|
|
629
|
+
truncate_ragged_lines: bool = False,
|
|
627
630
|
) -> list[Source]:
|
|
628
631
|
"""Load a single file.
|
|
629
632
|
|
|
@@ -678,6 +681,7 @@ def load_file(
|
|
|
678
681
|
schema_overrides=schema_overrides,
|
|
679
682
|
null_values=null_values,
|
|
680
683
|
ignore_errors=ignore_errors,
|
|
684
|
+
truncate_ragged_lines=truncate_ragged_lines,
|
|
681
685
|
)
|
|
682
686
|
data.append(Source(lf, filename, filepath.stem))
|
|
683
687
|
elif file_format in ("xlsx", "xls", "excel"):
|
|
@@ -110,6 +110,20 @@ class ReplaceState:
|
|
|
110
110
|
done: bool = False # Whether the replace operation is complete
|
|
111
111
|
|
|
112
112
|
|
|
113
|
+
def add_rid_column(df: pl.DataFrame) -> pl.DataFrame:
|
|
114
|
+
"""Add internal row index as last column to the dataframe if not already present.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
df: The Polars DataFrame to modify.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
The modified DataFrame with the internal row index column added.
|
|
121
|
+
"""
|
|
122
|
+
if RID not in df.columns:
|
|
123
|
+
df = df.lazy().with_row_index(RID).select(pl.exclude(RID), RID).collect()
|
|
124
|
+
return df
|
|
125
|
+
|
|
126
|
+
|
|
113
127
|
class DataFrameTable(DataTable):
|
|
114
128
|
"""Custom DataTable to highlight row/column labels based on cursor position."""
|
|
115
129
|
|
|
@@ -321,7 +335,7 @@ class DataFrameTable(DataTable):
|
|
|
321
335
|
super().__init__(**kwargs)
|
|
322
336
|
|
|
323
337
|
# DataFrame state
|
|
324
|
-
self.dataframe = df
|
|
338
|
+
self.dataframe = add_rid_column(df) # Original dataframe
|
|
325
339
|
self.df = self.dataframe # Internal/working dataframe
|
|
326
340
|
self.filename = filename or "untitled.csv" # Current filename
|
|
327
341
|
self.tabname = tabname or Path(filename).stem # Tab name
|
|
@@ -279,6 +279,14 @@ class DataFrameViewer(App):
|
|
|
279
279
|
def action_duplicate_tab(self) -> None:
|
|
280
280
|
"""Duplicate the currently active tab.
|
|
281
281
|
|
|
282
|
+
Creates a copy of the current tab with the same data and filename.
|
|
283
|
+
The new tab is named with '_copy' suffix and inserted after the current tab.
|
|
284
|
+
"""
|
|
285
|
+
self.do_duplicate_tab()
|
|
286
|
+
|
|
287
|
+
def do_duplicate_tab(self) -> None:
|
|
288
|
+
"""Duplicate the currently active tab.
|
|
289
|
+
|
|
282
290
|
Creates a copy of the current tab with the same data and filename.
|
|
283
291
|
The new tab is named with '_copy' suffix and inserted after the current tab.
|
|
284
292
|
"""
|
|
@@ -320,6 +328,17 @@ class DataFrameViewer(App):
|
|
|
320
328
|
Cycles through tabs by the specified offset. With offset=1, moves to next tab.
|
|
321
329
|
With offset=-1, moves to previous tab. Wraps around when reaching edges.
|
|
322
330
|
|
|
331
|
+
Args:
|
|
332
|
+
offset: Number of tabs to advance (+1 for next, -1 for previous). Defaults to 1.
|
|
333
|
+
"""
|
|
334
|
+
self.do_next_tab(offset)
|
|
335
|
+
|
|
336
|
+
def do_next_tab(self, offset: int = 1) -> None:
|
|
337
|
+
"""Switch to the next tab or previous tab.
|
|
338
|
+
|
|
339
|
+
Cycles through tabs by the specified offset. With offset=1, moves to next tab.
|
|
340
|
+
With offset=-1, moves to previous tab. Wraps around when reaching edges.
|
|
341
|
+
|
|
323
342
|
Args:
|
|
324
343
|
offset: Number of tabs to advance (+1 for next, -1 for previous). Defaults to 1.
|
|
325
344
|
"""
|
|
@@ -478,7 +497,7 @@ class DataFrameViewer(App):
|
|
|
478
497
|
"""Handle the "save before closing?" confirmation."""
|
|
479
498
|
if result:
|
|
480
499
|
# User wants to save - close after save dialog opens
|
|
481
|
-
active_table.do_save_to_file(
|
|
500
|
+
active_table.do_save_to_file(task_after_save="close_tab")
|
|
482
501
|
elif result is None:
|
|
483
502
|
# User cancelled - do nothing
|
|
484
503
|
return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dataframe-textual
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.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
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
dataframe_textual/__init__.py,sha256=E53fW1spQRA4jW9grxSqPEmoe9zofzr6twdveMbt_W8,1310
|
|
2
|
+
dataframe_textual/__main__.py,sha256=xXeUA2EqVhufPkTbvv6MOCt3_ESHBH3PsCE--07a0ww,3613
|
|
3
|
+
dataframe_textual/common.py,sha256=ZDhAT13UCgwtQborPbcHboX956A6N-m1-YvCpZHFtwY,28108
|
|
4
|
+
dataframe_textual/data_frame_help_panel.py,sha256=UEtj64XsVRdtLzuwOaITfoEQUkAfwFuvpr5Npip5WHs,3381
|
|
5
|
+
dataframe_textual/data_frame_table.py,sha256=sxs2AZ6UUmiPc6yf503Vvj3FoASgcQuDSec17pN1I80,149069
|
|
6
|
+
dataframe_textual/data_frame_viewer.py,sha256=fyrMSH2dFxc3h3HkJSaT1jBCQyoUUstGVXXPSG6wyjA,23099
|
|
7
|
+
dataframe_textual/sql_screen.py,sha256=P3j1Fv45NIKEYo9adb7NPod54FaU-djFIvCUMMHbvjY,7534
|
|
8
|
+
dataframe_textual/table_screen.py,sha256=XPzJI6FXjwnxtQSMTmluygwkYM-0-Lx3v9o-MuL6bMg,19071
|
|
9
|
+
dataframe_textual/yes_no_screen.py,sha256=NI7Zt3rETDWYiT5CH_FDy7sIWkZ7d7LquaZZbX79b2g,26400
|
|
10
|
+
dataframe_textual-2.2.0.dist-info/METADATA,sha256=yf7TJe5fHtrSlTl6nI3PkpzE80aTW-zuJKsBbZ0q0pQ,29160
|
|
11
|
+
dataframe_textual-2.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
12
|
+
dataframe_textual-2.2.0.dist-info/entry_points.txt,sha256=R_GoooOxcq6ab4RaHiVoZ4zrZJ-phMcGmlL2rwqncW8,107
|
|
13
|
+
dataframe_textual-2.2.0.dist-info/licenses/LICENSE,sha256=AVTg0gk1X-LHI-nnHlAMDQetrwuDZK4eypgSMDO46Yc,1069
|
|
14
|
+
dataframe_textual-2.2.0.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
dataframe_textual/__init__.py,sha256=E53fW1spQRA4jW9grxSqPEmoe9zofzr6twdveMbt_W8,1310
|
|
2
|
-
dataframe_textual/__main__.py,sha256=vgHjpSsHBF34UN46iMgu_EiebZUzxWwJZ_ngOU3nQvI,3412
|
|
3
|
-
dataframe_textual/common.py,sha256=gpNNY5ZePJkJPf-YoLSCHKaBpdXQ1yW2iSKYV6zZYUo,27908
|
|
4
|
-
dataframe_textual/data_frame_help_panel.py,sha256=UEtj64XsVRdtLzuwOaITfoEQUkAfwFuvpr5Npip5WHs,3381
|
|
5
|
-
dataframe_textual/data_frame_table.py,sha256=pPddPOa3hV3voCf3_9botg0jeNcPdWsN7Oiw5vKdMdU,148701
|
|
6
|
-
dataframe_textual/data_frame_viewer.py,sha256=pX1xU3REQnMMEHapYKmr_FH1hFGExqTrOjjFWBx7dtg,22406
|
|
7
|
-
dataframe_textual/sql_screen.py,sha256=P3j1Fv45NIKEYo9adb7NPod54FaU-djFIvCUMMHbvjY,7534
|
|
8
|
-
dataframe_textual/table_screen.py,sha256=XPzJI6FXjwnxtQSMTmluygwkYM-0-Lx3v9o-MuL6bMg,19071
|
|
9
|
-
dataframe_textual/yes_no_screen.py,sha256=NI7Zt3rETDWYiT5CH_FDy7sIWkZ7d7LquaZZbX79b2g,26400
|
|
10
|
-
dataframe_textual-2.1.0.dist-info/METADATA,sha256=6RZnWlkm6mWKnQNMUTUGBeklOFYXQgWtd1lOJmz5oX0,29160
|
|
11
|
-
dataframe_textual-2.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
12
|
-
dataframe_textual-2.1.0.dist-info/entry_points.txt,sha256=R_GoooOxcq6ab4RaHiVoZ4zrZJ-phMcGmlL2rwqncW8,107
|
|
13
|
-
dataframe_textual-2.1.0.dist-info/licenses/LICENSE,sha256=AVTg0gk1X-LHI-nnHlAMDQetrwuDZK4eypgSMDO46Yc,1069
|
|
14
|
-
dataframe_textual-2.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|