tksheet 7.4.3__py3-none-any.whl → 7.4.5__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.
tksheet/other_classes.py CHANGED
@@ -105,9 +105,7 @@ class SpanRange:
105
105
  return reversed(range(self.from_, self.upto_))
106
106
 
107
107
  def __contains__(self, n: int) -> bool:
108
- if n >= self.from_ and n < self.upto_:
109
- return True
110
- return False
108
+ return n >= self.from_ and n < self.upto_
111
109
 
112
110
  def __eq__(self, v: SpanRange) -> bool:
113
111
  return self.from_ == v.from_ and self.upto_ == v.upto_
@@ -189,11 +187,13 @@ class Span(dict):
189
187
 
190
188
  def format(
191
189
  self,
192
- formatter_options: dict = {},
190
+ formatter_options: dict | None = None,
193
191
  formatter_class: object = None,
194
192
  redraw: bool = True,
195
193
  **kwargs,
196
194
  ) -> Span:
195
+ if formatter_options is None:
196
+ formatter_options = {}
197
197
  return self["widget"].format(
198
198
  self,
199
199
  formatter_options={"formatter": formatter_class, **formatter_options, **kwargs},
@@ -232,9 +232,9 @@ class Span(dict):
232
232
 
233
233
  def dropdown(
234
234
  self,
235
- values: list = [],
235
+ values: list[object] | None = None,
236
236
  edit_data: bool = True,
237
- set_values: dict[tuple[int, int], object] = {},
237
+ set_values: dict[tuple[int, int], object] | None = None,
238
238
  set_value: object = None,
239
239
  state: str = "normal",
240
240
  redraw: bool = True,
@@ -246,9 +246,9 @@ class Span(dict):
246
246
  ) -> Span:
247
247
  return self["widget"].dropdown(
248
248
  self,
249
- values=values,
249
+ values=[] if values is None else values,
250
250
  edit_data=edit_data,
251
- set_values=set_values,
251
+ set_values={} if set_values is None else set_values,
252
252
  set_value=set_value,
253
253
  state=state,
254
254
  redraw=redraw,
@@ -406,19 +406,13 @@ class Span(dict):
406
406
  @property
407
407
  def rows(self) -> SpanRange:
408
408
  rng_from_r = 0 if self["from_r"] is None else self["from_r"]
409
- if self["upto_r"] is None:
410
- rng_upto_r = self["widget"].total_rows()
411
- else:
412
- rng_upto_r = self["upto_r"]
409
+ rng_upto_r = self["widget"].total_rows() if self["upto_r"] is None else self["upto_r"]
413
410
  return SpanRange(rng_from_r, rng_upto_r)
414
411
 
415
412
  @property
416
413
  def columns(self) -> SpanRange:
417
414
  rng_from_c = 0 if self["from_c"] is None else self["from_c"]
418
- if self["upto_c"] is None:
419
- rng_upto_c = self["widget"].total_columns()
420
- else:
421
- rng_upto_c = self["upto_c"]
415
+ rng_upto_c = self["widget"].total_columns() if self["upto_c"] is None else self["upto_c"]
422
416
  return SpanRange(rng_from_c, rng_upto_c)
423
417
 
424
418
  @property
tksheet/row_index.py CHANGED
@@ -91,7 +91,7 @@ class RowIndex(tk.Canvas):
91
91
  self.rc_delete_row_enabled = False
92
92
  self.edit_cell_enabled = False
93
93
  self.visible_row_dividers = {}
94
- self.row_width_resize_bbox = tuple()
94
+ self.row_width_resize_bbox = ()
95
95
  self.rsz_w = None
96
96
  self.rsz_h = None
97
97
  self.currently_resizing_width = False
@@ -249,28 +249,32 @@ class RowIndex(tk.Canvas):
249
249
  def shift_b1_press(self, event: object) -> None:
250
250
  self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
251
251
  r = self.MT.identify_row(y=event.y)
252
- if (self.drag_and_drop_enabled or self.row_selection_enabled) and self.rsz_h is None and self.rsz_w is None:
253
- if r < len(self.MT.row_positions) - 1:
254
- r_selected = self.MT.row_selected(r)
255
- if not r_selected and self.row_selection_enabled:
256
- if self.MT.selected and self.MT.selected.type_ == "rows":
257
- r_to_sel, c_to_sel = self.MT.selected.row, self.MT.selected.column
258
- self.MT.deselect("all", redraw=False)
259
- self.being_drawn_item = self.MT.create_selection_box(
260
- *self.get_shift_select_box(r, r_to_sel), "rows"
261
- )
262
- self.MT.set_currently_selected(r_to_sel, c_to_sel, self.being_drawn_item)
263
- else:
264
- self.being_drawn_item = self.select_row(r, run_binding_func=False)
265
- self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
266
- sel_event = self.MT.get_select_event(being_drawn_item=self.being_drawn_item)
267
- try_binding(self.shift_selection_binding_func, sel_event)
268
- self.PAR.emit_event("<<SheetSelect>>", data=sel_event)
269
- elif r_selected:
270
- self.dragged_row = DraggedRowColumn(
271
- dragged=r,
272
- to_move=sorted(self.MT.get_selected_rows()),
252
+ if (
253
+ (self.drag_and_drop_enabled or self.row_selection_enabled)
254
+ and self.rsz_h is None
255
+ and self.rsz_w is None
256
+ and r < len(self.MT.row_positions) - 1
257
+ ):
258
+ r_selected = self.MT.row_selected(r)
259
+ if not r_selected and self.row_selection_enabled:
260
+ if self.MT.selected and self.MT.selected.type_ == "rows":
261
+ r_to_sel, c_to_sel = self.MT.selected.row, self.MT.selected.column
262
+ self.MT.deselect("all", redraw=False)
263
+ self.being_drawn_item = self.MT.create_selection_box(
264
+ *self.get_shift_select_box(r, r_to_sel), "rows"
273
265
  )
266
+ self.MT.set_currently_selected(r_to_sel, c_to_sel, self.being_drawn_item)
267
+ else:
268
+ self.being_drawn_item = self.select_row(r, run_binding_func=False)
269
+ self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
270
+ sel_event = self.MT.get_select_event(being_drawn_item=self.being_drawn_item)
271
+ try_binding(self.shift_selection_binding_func, sel_event)
272
+ self.PAR.emit_event("<<SheetSelect>>", data=sel_event)
273
+ elif r_selected:
274
+ self.dragged_row = DraggedRowColumn(
275
+ dragged=r,
276
+ to_move=sorted(self.MT.get_selected_rows()),
277
+ )
274
278
 
275
279
  def get_shift_select_box(self, r: int, min_r: int) -> tuple[int, int, int, int, str]:
276
280
  if r >= min_r:
@@ -354,12 +358,11 @@ class RowIndex(tk.Canvas):
354
358
  self.rsz_w = None
355
359
  except Exception:
356
360
  self.rsz_w = None
357
- if not mouse_over_resize:
358
- if self.MT.row_selected(self.MT.identify_row(event, allow_end=False)):
359
- mouse_over_selected = True
360
- if self.MT.current_cursor != "hand2":
361
- self.config(cursor="hand2")
362
- self.MT.current_cursor = "hand2"
361
+ if not mouse_over_resize and self.MT.row_selected(self.MT.identify_row(event, allow_end=False)):
362
+ mouse_over_selected = True
363
+ if self.MT.current_cursor != "hand2":
364
+ self.config(cursor="hand2")
365
+ self.MT.current_cursor = "hand2"
363
366
  if not mouse_over_resize and not mouse_over_selected:
364
367
  self.MT.reset_mouse_motion_creations()
365
368
  try_binding(self.extra_motion_func, event)
@@ -900,6 +903,8 @@ class RowIndex(tk.Canvas):
900
903
  rows = list(range(0, len(self.MT.row_positions) - 1))
901
904
  event_data = self.MT.new_event_dict("edit_table")
902
905
  try_binding(self.MT.extra_begin_sort_cells_func, event_data)
906
+ if key is None:
907
+ key = self.PAR.ops.sort_key
903
908
  for r in rows:
904
909
  datarn = self.MT.datarn(r)
905
910
  for c, val in enumerate(sort_row(self.MT.data[datarn], reverse=reverse, key=key)):
@@ -943,6 +948,8 @@ class RowIndex(tk.Canvas):
943
948
  return event_data
944
949
  row = self.MT.selected.row
945
950
  if try_binding(self.ri_extra_begin_sort_cols_func, event_data, "begin_move_columns"):
951
+ if key is None:
952
+ key = self.PAR.ops.sort_key
946
953
  sorted_indices, data_new_idxs = sort_columns_by_row(self.MT.data, row=row, reverse=reverse, key=key)
947
954
  disp_new_idxs = {}
948
955
  if self.MT.all_columns_displayed:
@@ -1227,7 +1234,7 @@ class RowIndex(tk.Canvas):
1227
1234
  def set_width_of_index_to_text(
1228
1235
  self,
1229
1236
  text: None | str = None,
1230
- only_rows: list = [],
1237
+ only_rows: list[int] | None = None,
1231
1238
  ) -> int:
1232
1239
  self.fix_index()
1233
1240
  w = self.ops.default_row_index_width
@@ -1241,7 +1248,7 @@ class RowIndex(tk.Canvas):
1241
1248
  if (tw := b[2] - b[0] + 10) > w:
1242
1249
  w = tw
1243
1250
  elif text is None:
1244
- w = self.get_index_text_width(only_rows=only_rows)
1251
+ w = self.get_index_text_width(only_rows=[] if only_rows is None else only_rows)
1245
1252
  if w > self.ops.max_index_width:
1246
1253
  w = int(self.ops.max_index_width)
1247
1254
  self.set_width(w, set_TL=True)
@@ -1637,9 +1644,8 @@ class RowIndex(tk.Canvas):
1637
1644
  row_pos_exists: bool,
1638
1645
  set_scrollregion: bool,
1639
1646
  ) -> bool:
1640
- if set_scrollregion:
1641
- if not self.configure_scrollregion(last_row_line_pos=last_row_line_pos):
1642
- return False
1647
+ if set_scrollregion and not self.configure_scrollregion(last_row_line_pos=last_row_line_pos):
1648
+ return False
1643
1649
  self.hidd_text.update(self.disp_text)
1644
1650
  self.disp_text = {}
1645
1651
  self.hidd_high.update(self.disp_high)
@@ -1979,7 +1985,7 @@ class RowIndex(tk.Canvas):
1979
1985
  self.text_editor.set_text(self.text_editor.get() + "" if not isinstance(text, str) else text)
1980
1986
  return False
1981
1987
  self.hide_text_editor()
1982
- if not self.MT.see(r=r, c=0, keep_yscroll=True, check_cell_visibility=True):
1988
+ if not self.MT.see(r, 0, keep_yscroll=True):
1983
1989
  self.MT.main_table_redraw_grid_and_text(True, True)
1984
1990
  x = 0
1985
1991
  y = self.MT.row_positions[r]
@@ -2424,16 +2430,18 @@ class RowIndex(tk.Canvas):
2424
2430
  self.MT._row_index[datarn] = value
2425
2431
 
2426
2432
  def input_valid_for_cell(self, datarn: int, value: object, check_readonly: bool = True) -> bool:
2427
- if check_readonly and self.get_cell_kwargs(datarn, key="readonly"):
2433
+ kwargs = self.get_cell_kwargs(datarn, key=None)
2434
+ if check_readonly and "readonly" in kwargs:
2428
2435
  return False
2429
- if self.get_cell_kwargs(datarn, key="checkbox"):
2436
+ elif "checkbox" in kwargs:
2430
2437
  return is_bool_like(value)
2431
- if self.cell_equal_to(datarn, value):
2432
- return False
2433
- kwargs = self.get_cell_kwargs(datarn, key="dropdown")
2434
- if kwargs and kwargs["validate_input"] and value not in kwargs["values"]:
2435
- return False
2436
- return True
2438
+ else:
2439
+ return not (
2440
+ self.cell_equal_to(datarn, value)
2441
+ or (kwargs := kwargs.get("dropdown", {}))
2442
+ and kwargs["validate_input"]
2443
+ and value not in kwargs["values"]
2444
+ )
2437
2445
 
2438
2446
  def cell_equal_to(self, datarn: int, value: object) -> bool:
2439
2447
  self.fix_index(datarn)
@@ -2495,12 +2503,13 @@ class RowIndex(tk.Canvas):
2495
2503
  if self.ops.treeview:
2496
2504
  iid = self.new_iid()
2497
2505
  return Node(text=iid, iid=iid, parent=self.get_row_parent(datarn))
2498
- if self.get_cell_kwargs(datarn, key="checkbox", cell=r_ops):
2506
+ kwargs = self.get_cell_kwargs(datarn, key=None, cell=r_ops)
2507
+ if "checkbox" in kwargs:
2499
2508
  return False
2500
- kwargs = self.get_cell_kwargs(datarn, key="dropdown", cell=r_ops)
2501
- if kwargs and kwargs["validate_input"] and kwargs["values"]:
2509
+ elif (kwargs := kwargs.get("dropdown", {})) and kwargs["validate_input"] and kwargs["values"]:
2502
2510
  return kwargs["values"][0]
2503
- return ""
2511
+ else:
2512
+ return ""
2504
2513
 
2505
2514
  def get_empty_index_seq(self, end: int, start: int = 0, r_ops: bool = True) -> list[object]:
2506
2515
  return [self.get_value_for_empty_cell(datarn, r_ops=r_ops) for datarn in range(start, end)]
@@ -2567,10 +2576,11 @@ class RowIndex(tk.Canvas):
2567
2576
  if redraw:
2568
2577
  self.MT.refresh()
2569
2578
 
2570
- def get_cell_kwargs(self, datarn: int, key: Hashable = "dropdown", cell: bool = True) -> dict:
2571
- if cell and datarn in self.cell_options and key in self.cell_options[datarn]:
2572
- return self.cell_options[datarn][key]
2573
- return {}
2579
+ def get_cell_kwargs(self, datarn: int, key: Hashable | None = "dropdown", cell: bool = True) -> dict:
2580
+ if cell and datarn in self.cell_options:
2581
+ return self.cell_options[datarn] if key is None else self.cell_options[datarn].get(key, {})
2582
+ else:
2583
+ return {}
2574
2584
 
2575
2585
  # Treeview Mode
2576
2586
 
@@ -2671,29 +2681,35 @@ class RowIndex(tk.Canvas):
2671
2681
  new_parent = node_change[1]
2672
2682
  move_to_index = node_change[2]
2673
2683
  if new_parent:
2674
- move_to_index = (
2675
- move_to_index if isinstance(move_to_index, int) else len(self.tree[new_parent].children)
2676
- )
2677
- move_to_row = self.tree_rns[new_parent] + max(
2678
- 0, min(move_to_index, len(self.tree[new_parent].children))
2684
+ if isinstance(move_to_index, int):
2685
+ move_to_index = min(move_to_index, len(self.tree[new_parent].children))
2686
+ else:
2687
+ move_to_index = len(self.tree[new_parent].children)
2688
+ move_to_row = self.tree_rns[new_parent]
2689
+ _find = move_to_index + 1 if new_parent == self.tree[item].parent else move_to_index
2690
+ move_to_row += _find + sum(
2691
+ self.num_descendants(cid) for cid in islice(self.tree[new_parent].children, _find)
2679
2692
  )
2693
+ insert_row = move_to_row + 1
2680
2694
  else:
2681
2695
  num_top_nodes = sum(1 for _ in self.gen_top_nodes())
2682
2696
  if move_to_index is None:
2683
2697
  move_to_row = self.PAR.top_index_row(num_top_nodes - 1)
2684
2698
  move_to_index = num_top_nodes
2699
+ insert_row = move_to_row
2685
2700
  else:
2686
2701
  move_to_row = self.PAR.top_index_row(move_to_index)
2702
+ insert_row = move_to_row
2687
2703
  if move_to_row is None:
2688
2704
  move_to_row = self.PAR.top_index_row(num_top_nodes - 1)
2689
2705
  move_to_index = num_top_nodes
2706
+ insert_row = move_to_row + 1
2690
2707
 
2691
2708
  move_to_iid = self.MT._row_index[move_to_row].iid
2692
- insert_row = move_to_row + 1
2693
2709
  disp_insert_row = None
2694
2710
 
2695
2711
  else:
2696
- iids = set(self.MT._row_index[r].iid for r in event_data["moved"]["rows"]["data"])
2712
+ iids = {self.MT._row_index[r].iid for r in event_data["moved"]["rows"]["data"]}
2697
2713
  iids_descendants = {iid: set(self.get_iid_descendants(iid)) for iid in iids}
2698
2714
 
2699
2715
  # remove descendants in iids to move
@@ -2715,10 +2731,7 @@ class RowIndex(tk.Canvas):
2715
2731
  # max_from = max(event_data.moved.rows)
2716
2732
  min_to = min(event_data["moved"]["rows"]["data"].values())
2717
2733
  max_to = max(event_data["moved"]["rows"]["data"].values())
2718
- if min_from <= min_to:
2719
- insert_row = max_to
2720
- else:
2721
- insert_row = min_to
2734
+ insert_row = max_to if min_from <= min_to else min_to
2722
2735
  move_to_iid = self.MT._row_index[insert_row].iid
2723
2736
 
2724
2737
  move_to_index = self.PAR.index(move_to_iid)
@@ -2733,14 +2746,14 @@ class RowIndex(tk.Canvas):
2733
2746
  event_data["moved"]["rows"]["displayed"] = {}
2734
2747
  if new_loc_is_displayed:
2735
2748
  if disp_insert_row is None:
2736
- if new_parent == self.tree[item].parent:
2749
+ if new_parent or insert_row > move_to_row:
2737
2750
  disp_insert_row = self.MT.disprn(self.tree_rns[move_to_iid]) + 1
2738
2751
  else:
2739
- disp_insert_row = self.MT.disprn(self.tree_rns[move_to_iid]) + 1
2752
+ disp_insert_row = self.MT.disprn(self.tree_rns[move_to_iid])
2740
2753
  if (disp_from_row := self.MT.try_disprn(self.tree_rns[item])) is not None:
2741
2754
  event_data["moved"]["rows"]["displayed"] = {disp_from_row: disp_insert_row}
2742
2755
  else:
2743
- event_data["moved"]["rows"]["displayed"] = {tuple(): disp_insert_row}
2756
+ event_data["moved"]["rows"]["displayed"] = {(): disp_insert_row}
2744
2757
 
2745
2758
  if any(self.move_pid_causes_recursive_loop(self.MT._row_index[r].iid, new_parent) for r in moved_rows):
2746
2759
  event_data["moved"]["rows"] = {}
@@ -2756,7 +2769,6 @@ class RowIndex(tk.Canvas):
2756
2769
  index=move_to_index,
2757
2770
  )
2758
2771
  move_to_index += 1
2759
-
2760
2772
  event_data["moved"]["rows"]["data"] = get_new_indexes(
2761
2773
  insert_row,
2762
2774
  event_data["moved"]["rows"]["data"],
@@ -2764,8 +2776,8 @@ class RowIndex(tk.Canvas):
2764
2776
  data_new_idxs = event_data["moved"]["rows"]["data"]
2765
2777
  data_old_idxs = dict(zip(data_new_idxs.values(), data_new_idxs))
2766
2778
 
2767
- if tuple() in event_data["moved"]["rows"]["displayed"]:
2768
- del event_data["moved"]["rows"]["displayed"][tuple()]
2779
+ if () in event_data["moved"]["rows"]["displayed"]:
2780
+ del event_data["moved"]["rows"]["displayed"][()]
2769
2781
 
2770
2782
  if event_data["moved"]["rows"]["displayed"]:
2771
2783
  event_data["moved"]["rows"]["displayed"] = get_new_indexes(
@@ -2782,7 +2794,6 @@ class RowIndex(tk.Canvas):
2782
2794
  if not undo_modification and data_new_idxs:
2783
2795
  if new_parent and (not self.PAR.item_displayed(new_parent) or new_parent not in self.tree_open_ids):
2784
2796
  self.PAR.hide_rows(set(data_new_idxs.values()), data_indexes=True)
2785
-
2786
2797
  if new_loc_is_displayed:
2787
2798
  self.PAR.show_rows(
2788
2799
  (r for r in data_new_idxs.values() if self.ancestors_all_open(self.MT._row_index[r].iid))
@@ -2835,7 +2846,7 @@ class RowIndex(tk.Canvas):
2835
2846
  row_ctr = next(reversed(mapping.values())) + 1
2836
2847
 
2837
2848
  if disp_mapping := event_data["moved"]["rows"]["displayed"]:
2838
- if tuple() in disp_mapping:
2849
+ if () in disp_mapping:
2839
2850
  disp_row_ctr = next(reversed(disp_mapping.values()))
2840
2851
  else:
2841
2852
  disp_row_ctr = next(reversed(disp_mapping.values())) + 1
@@ -2894,24 +2905,48 @@ class RowIndex(tk.Canvas):
2894
2905
 
2895
2906
  def ancestors_all_open(self, iid: str, stop_at: str = "") -> bool:
2896
2907
  if stop_at:
2897
- for iid in self.get_iid_ancestors(iid):
2898
- if iid == stop_at:
2908
+ for i in self.get_iid_ancestors(iid):
2909
+ if i == stop_at:
2899
2910
  return True
2900
- elif iid not in self.tree_open_ids:
2911
+ elif i not in self.tree_open_ids:
2901
2912
  return False
2902
2913
  return True
2903
2914
  return all(map(self.tree_open_ids.__contains__, self.get_iid_ancestors(iid)))
2904
2915
 
2905
2916
  def get_iid_ancestors(self, iid: str) -> Generator[str]:
2906
- if self.tree[iid].parent:
2907
- yield self.tree[iid].parent
2908
- yield from self.get_iid_ancestors(self.tree[iid].parent)
2917
+ current_iid = iid
2918
+ while self.tree[current_iid].parent:
2919
+ parent_iid = self.tree[current_iid].parent
2920
+ yield parent_iid
2921
+ current_iid = parent_iid
2909
2922
 
2910
2923
  def get_iid_descendants(self, iid: str, check_open: bool = False) -> Generator[str]:
2911
- for ciid in self.tree[iid].children:
2912
- yield ciid
2913
- if self.tree[ciid].children and (not check_open or ciid in self.tree_open_ids):
2914
- yield from self.get_iid_descendants(ciid, check_open)
2924
+ tree = self.tree
2925
+ stack = [iter(tree[iid].children)]
2926
+ while stack:
2927
+ top_iterator = stack[-1]
2928
+ try:
2929
+ ciid = next(top_iterator)
2930
+ yield ciid
2931
+ if tree[ciid].children and (not check_open or ciid in self.tree_open_ids):
2932
+ stack.append(iter(tree[ciid].children))
2933
+ except StopIteration:
2934
+ stack.pop()
2935
+
2936
+ def num_descendants(self, iid: str) -> int:
2937
+ tree = self.tree
2938
+ stack = [iter(tree[iid].children)]
2939
+ num = 0
2940
+ while stack:
2941
+ top_iterator = stack[-1]
2942
+ try:
2943
+ ciid = next(top_iterator)
2944
+ num += 1
2945
+ if tree[ciid].children:
2946
+ stack.append(iter(tree[ciid].children))
2947
+ except StopIteration:
2948
+ stack.pop()
2949
+ return num
2915
2950
 
2916
2951
  def items_parent(self, iid: str) -> str:
2917
2952
  if self.tree[iid].parent:
@@ -2959,9 +2994,7 @@ class RowIndex(tk.Canvas):
2959
2994
  def move_pid_causes_recursive_loop(self, to_move_iid: str, move_to_parent: str) -> bool:
2960
2995
  # if the parent the item is being moved under is one of the item's descendants
2961
2996
  # then it is a recursive loop
2962
- return to_move_iid == move_to_parent or any(
2963
- move_to_parent == diid for diid in self.get_iid_descendants(to_move_iid)
2964
- )
2997
+ return any(move_to_parent == diid for diid in self.get_iid_descendants(to_move_iid))
2965
2998
 
2966
2999
  def tree_build(
2967
3000
  self,
@@ -3075,5 +3108,5 @@ class RowIndex(tk.Canvas):
3075
3108
  {self.tree_rns[iid] for iid in self.PAR.get_children() if self.tree[iid].parent},
3076
3109
  deselect_all=False,
3077
3110
  data_indexes=True,
3078
- row_heights=False if row_heights is False else True,
3111
+ row_heights=row_heights is not False,
3079
3112
  )