dataframe-textual 1.9.0__py3-none-any.whl → 2.2.2__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.
@@ -119,9 +119,6 @@ class YesNoScreen(ModalScreen):
119
119
  maybe: Optional Maybe button text/dict. Defaults to None.
120
120
  no: Text or dict for the No button. If None, hides the No button. Defaults to "No".
121
121
  on_yes_callback: Optional callable that takes no args and returns the value to dismiss with when Yes is pressed. Defaults to None.
122
-
123
- Returns:
124
- None
125
122
  """
126
123
  super().__init__()
127
124
  self.title = title
@@ -295,32 +292,26 @@ class SaveFileScreen(YesNoScreen):
295
292
 
296
293
  CSS = YesNoScreen.DEFAULT_CSS.replace("YesNoScreen", "SaveFileScreen")
297
294
 
298
- def __init__(
299
- self, filename: str, title: str = "Save to File", all_tabs: bool | None = None, multi_tab: bool = False
300
- ):
301
- self.all_tabs = all_tabs or (all_tabs is None and multi_tab)
295
+ def __init__(self, filename: str, save_all: bool = False, tab_count: int = 1):
296
+ self.save_all = save_all
302
297
  super().__init__(
303
- title=title,
304
- label="Enter filename",
298
+ title="Save to File",
299
+ label="Filename",
305
300
  input=filename,
306
- yes="Save",
307
- maybe="Save All Tabs" if self.all_tabs else None,
301
+ yes=f"Save {tab_count} Tabs" if self.save_all else "Save Current Tab" if tab_count > 1 else "Save",
308
302
  no="Cancel",
309
303
  on_yes_callback=self.handle_save,
310
- on_maybe_callback=self.handle_save,
311
304
  )
312
305
 
313
306
  def handle_save(self):
314
307
  if self.input:
315
308
  input_filename = self.input.value.strip()
316
309
  if input_filename:
317
- return input_filename, self.all_tabs
310
+ return input_filename, self.save_all, True # Overwrite prompt
318
311
  else:
319
312
  self.notify("Filename cannot be empty", title="Save", severity="error")
320
313
  return None
321
314
 
322
- return None
323
-
324
315
 
325
316
  class ConfirmScreen(YesNoScreen):
326
317
  """Modal screen to ask for confirmation."""
@@ -359,7 +350,7 @@ class EditCellScreen(YesNoScreen):
359
350
 
360
351
  # Input
361
352
  df_value = df.item(ridx, cidx)
362
- self.input_value = "" if df_value is None else str(df_value).strip()
353
+ self.input_value = NULL if df_value is None else str(df_value)
363
354
 
364
355
  super().__init__(
365
356
  title="Edit Cell",
@@ -373,20 +364,20 @@ class EditCellScreen(YesNoScreen):
373
364
 
374
365
  def _validate_input(self) -> None:
375
366
  """Validate and save the edited value."""
376
- new_value_str = self.input.value.strip()
367
+ new_value_str = self.input.value # Do not strip to preserve spaces
377
368
 
378
369
  # Handle empty input
379
370
  if not new_value_str:
380
- new_value = None
371
+ new_value = ""
381
372
  self.notify(
382
- "Empty value provided. If you want to clear the cell, press [$accent]x[/].",
383
- title="Edit",
373
+ "Empty value provided. If you want to clear the cell, press [$accent]Delete[/].",
374
+ title="Edit Cell",
384
375
  severity="warning",
385
376
  )
386
377
  # Check if value changed
387
378
  elif new_value_str == self.input_value:
388
379
  new_value = None
389
- self.notify("No changes made", title="Edit", severity="warning")
380
+ self.notify("No changes made", title="Edit Cell", severity="warning")
390
381
  else:
391
382
  # Parse and validate based on column dtype
392
383
  try:
@@ -394,7 +385,7 @@ class EditCellScreen(YesNoScreen):
394
385
  except Exception as e:
395
386
  self.notify(
396
387
  f"Failed to convert [$accent]{new_value_str}[/] to [$error]{self.dtype}[/]: {str(e)}",
397
- title="Edit",
388
+ title="Edit Cell",
398
389
  severity="error",
399
390
  )
400
391
  return None
@@ -477,7 +468,7 @@ class SearchScreen(YesNoScreen):
477
468
 
478
469
  def _validate_input(self) -> tuple[str, int, bool, bool]:
479
470
  """Validate the input and return it."""
480
- term = self.input.value.strip()
471
+ term = self.input.value # Do not strip to preserve spaces
481
472
 
482
473
  if not term:
483
474
  self.notify("Term cannot be empty", title=self.title, severity="error")
@@ -494,13 +485,13 @@ class FilterScreen(YesNoScreen):
494
485
 
495
486
  CSS = YesNoScreen.DEFAULT_CSS.replace("YesNoScreen", "FilterScreen")
496
487
 
497
- def __init__(self, df: pl.DataFrame, cidx: int, input_value: str | None = None):
488
+ def __init__(self, df: pl.DataFrame, cidx: int, term: str | None = None):
498
489
  self.df = df
499
490
  self.cidx = cidx
500
491
  super().__init__(
501
492
  title="Filter by Expression",
502
493
  label="e.g., NULL, $1 > 50, $name == 'text', $_ > 100, $a < $b, $_.str.contains('sub')",
503
- input=input_value,
494
+ input=term,
504
495
  checkbox="Match Nocase",
505
496
  checkbox2="Match Whole",
506
497
  on_yes_callback=self._get_input,
@@ -508,7 +499,7 @@ class FilterScreen(YesNoScreen):
508
499
 
509
500
  def _get_input(self) -> tuple[str, int, bool, bool]:
510
501
  """Get input."""
511
- term = self.input.value.strip()
502
+ term = self.input.value # Do not strip to preserve spaces
512
503
  match_nocase = self.checkbox.value
513
504
  match_whole = self.checkbox2.value
514
505
 
@@ -583,14 +574,14 @@ class EditColumnScreen(YesNoScreen):
583
574
  self.df = df
584
575
  super().__init__(
585
576
  title="Edit Column",
586
- label=f"by value or Polars expression, e.g., abc, pl.lit(7), {NULL}, $_ * 2, $1 + $2, $_.str.to_uppercase(), pl.arange(0, pl.len())",
577
+ label=f"By value or Polars expression, e.g., abc, pl.lit(7), {NULL}, $_ * 2, $1 + $2, $_.str.to_uppercase(), pl.arange(0, pl.len())",
587
578
  input="$_",
588
579
  on_yes_callback=self._get_input,
589
580
  )
590
581
 
591
582
  def _get_input(self) -> tuple[str, int]:
592
583
  """Get input."""
593
- term = self.input.value.strip()
584
+ term = self.input.value # Do not strip to preserve spaces
594
585
  return term, self.cidx
595
586
 
596
587
 
@@ -606,19 +597,19 @@ class AddColumnScreen(YesNoScreen):
606
597
  self.existing_columns = set(df.columns)
607
598
  super().__init__(
608
599
  title="Add Column",
609
- label="Enter column name",
610
- input="Link" if link else "Column name",
611
- label2="Enter link template, e.g., https://example.com/$_/id/$1, PC/compound/$cid"
600
+ label="Column name",
601
+ input="Link" if link else "New column",
602
+ label2="Link template, e.g., https://example.com/$1/id/$_, PC/compound/$cid"
612
603
  if link
613
- else "Enter value or Polars expression, e.g., abc, pl.lit(123), NULL, $_ * 2, $1 + $total, $_.str.to_uppercase(), pl.concat_str($_, pl.lit('-suffix'))",
614
- input2="Link template" if link else "Column value or expression",
604
+ else "Value or Polars expression, e.g., abc, pl.lit(123), NULL, $_ * 2, $1 + $total, $_ + '_suffix', $_.str.to_uppercase()",
605
+ input2="Link template" if link else "Value or expression",
615
606
  on_yes_callback=self._get_input,
616
607
  )
617
608
 
618
609
  def _get_input(self) -> tuple[int, str, str] | None:
619
610
  """Validate and return the new column configuration."""
620
611
  col_name = self.input.value.strip()
621
- term = self.input2.value.strip()
612
+ term = self.input2.value # Do not strip to preserve spaces
622
613
 
623
614
  # Validate column name
624
615
  if not col_name:
@@ -680,7 +671,11 @@ class FindReplaceScreen(YesNoScreen):
680
671
  CSS = YesNoScreen.DEFAULT_CSS.replace("YesNoScreen", "ReplaceScreen")
681
672
 
682
673
  def __init__(self, dftable: "DataFrameTable", title: str = "Find and Replace"):
683
- term_find = str(dftable.cursor_value)
674
+ if (cursor_value := dftable.cursor_value) is None:
675
+ term_find = NULL
676
+ else:
677
+ term_find = str(cursor_value)
678
+
684
679
  super().__init__(
685
680
  title=title,
686
681
  label="Find",
@@ -698,8 +693,8 @@ class FindReplaceScreen(YesNoScreen):
698
693
 
699
694
  def _get_input(self) -> tuple[str, str, bool, bool, bool]:
700
695
  """Get input."""
701
- term_find = self.input.value.strip()
702
- term_replace = self.input2.value.strip()
696
+ term_find = self.input.value # Do not strip to preserve spaces
697
+ term_replace = self.input2.value # Do not strip to preserve spaces
703
698
  match_nocase = self.checkbox.value
704
699
  match_whole = self.checkbox2.value
705
700
  replace_all = False
@@ -708,8 +703,8 @@ class FindReplaceScreen(YesNoScreen):
708
703
 
709
704
  def _get_input_replace_all(self) -> tuple[str, str, bool, bool, bool]:
710
705
  """Get input for 'Replace All'."""
711
- term_find = self.input.value.strip()
712
- term_replace = self.input2.value.strip()
706
+ term_find = self.input.value # Do not strip to preserve spaces
707
+ term_replace = self.input2.value # Do not strip to preserve spaces
713
708
  match_nocase = self.checkbox.value
714
709
  match_whole = self.checkbox2.value
715
710
  replace_all = True