tksheet 7.4.19__tar.gz → 7.4.21__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.
Files changed (26) hide show
  1. {tksheet-7.4.19/tksheet.egg-info → tksheet-7.4.21}/PKG-INFO +1 -1
  2. {tksheet-7.4.19 → tksheet-7.4.21}/pyproject.toml +1 -1
  3. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/__init__.py +1 -1
  4. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/column_headers.py +10 -11
  5. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/functions.py +0 -2
  6. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/main_table.py +12 -17
  7. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/other_classes.py +40 -10
  8. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/row_index.py +14 -15
  9. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/sheet.py +0 -2
  10. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/top_left_rectangle.py +3 -4
  11. {tksheet-7.4.19 → tksheet-7.4.21/tksheet.egg-info}/PKG-INFO +1 -1
  12. {tksheet-7.4.19 → tksheet-7.4.21}/LICENSE.txt +0 -0
  13. {tksheet-7.4.19 → tksheet-7.4.21}/README.md +0 -0
  14. {tksheet-7.4.19 → tksheet-7.4.21}/setup.cfg +0 -0
  15. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/colors.py +0 -0
  16. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/constants.py +0 -0
  17. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/find_window.py +0 -0
  18. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/formatters.py +0 -0
  19. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/sheet_options.py +0 -0
  20. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/sorting.py +0 -0
  21. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/text_editor.py +0 -0
  22. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/themes.py +0 -0
  23. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet/tksheet_types.py +0 -0
  24. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet.egg-info/SOURCES.txt +0 -0
  25. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet.egg-info/dependency_links.txt +0 -0
  26. {tksheet-7.4.19 → tksheet-7.4.21}/tksheet.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tksheet
3
- Version: 7.4.19
3
+ Version: 7.4.21
4
4
  Summary: Tkinter table / sheet and treeview widget
5
5
  Author-email: ragardner <github@ragardner.simplelogin.com>
6
6
  License: Copyright (c) 2019 ragardner and open source contributors
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
  name = "tksheet"
7
7
  description = "Tkinter table / sheet and treeview widget"
8
8
  readme = "README.md"
9
- version = "7.4.19"
9
+ version = "7.4.21"
10
10
  authors = [{ name = "ragardner", email = "github@ragardner.simplelogin.com" }]
11
11
  requires-python = ">=3.8"
12
12
  license = {file = "LICENSE.txt"}
@@ -4,7 +4,7 @@
4
4
  tksheet - A Python tkinter table widget
5
5
  """
6
6
 
7
- __version__ = "7.4.19"
7
+ __version__ = "7.4.21"
8
8
 
9
9
  from .colors import (
10
10
  color_map,
@@ -326,7 +326,6 @@ class ColumnHeaders(tk.Canvas):
326
326
  x = self.canvasx(event.x)
327
327
  y = self.canvasy(event.y)
328
328
  mouse_over_resize = False
329
- mouse_over_selected = False
330
329
  if self.width_resizing_enabled:
331
330
  c = self.check_mouse_position_width_resizers(x, y)
332
331
  if c is not None:
@@ -353,16 +352,16 @@ class ColumnHeaders(tk.Canvas):
353
352
  self.rsz_h = None
354
353
  except Exception:
355
354
  self.rsz_h = None
356
- if not mouse_over_resize and self.MT.col_selected(self.MT.identify_col(event, allow_end=False)):
357
- mouse_over_selected = True
358
- if self.current_cursor != "hand2":
359
- self.config(cursor="hand2")
360
- self.current_cursor = "hand2"
361
- if not mouse_over_resize and not mouse_over_selected:
362
- if self.current_cursor != "":
363
- self.config(cursor="")
364
- self.current_cursor = ""
365
- self.MT.reset_resize_vars()
355
+ if not mouse_over_resize:
356
+ if self.MT.col_selected(self.MT.identify_col(event, allow_end=False)):
357
+ if self.current_cursor != "hand2":
358
+ self.config(cursor="hand2")
359
+ self.current_cursor = "hand2"
360
+ else:
361
+ if self.current_cursor != "":
362
+ self.config(cursor="")
363
+ self.current_cursor = ""
364
+ self.MT.reset_resize_vars()
366
365
  try_binding(self.extra_motion_func, event)
367
366
 
368
367
  def double_b1(self, event: Any) -> None:
@@ -2,7 +2,6 @@ from __future__ import annotations
2
2
 
3
3
  import csv
4
4
  import io
5
- import pickle
6
5
  import re
7
6
  import tkinter as tk
8
7
  from bisect import bisect_left
@@ -17,7 +16,6 @@ from .constants import align_value_error, symbols_set
17
16
  from .formatters import to_bool
18
17
  from .other_classes import DotDict, EventDataDict, Highlight, Loc, Span
19
18
 
20
- unpickle_obj = pickle.loads
21
19
  lines_re = re.compile(r"[^\n]+")
22
20
  ORD_A = ord("A")
23
21
 
@@ -73,7 +73,6 @@ from .functions import (
73
73
  len_to_idx,
74
74
  mod_event_val,
75
75
  mod_span,
76
- mod_span_widget,
77
76
  move_elements_by_mapping_gen,
78
77
  move_fast,
79
78
  new_tk_event,
@@ -83,7 +82,6 @@ from .functions import (
83
82
  span_idxs_post_move,
84
83
  stored_event_dict,
85
84
  try_binding,
86
- unpickle_obj,
87
85
  wrap_text,
88
86
  )
89
87
  from .other_classes import (
@@ -385,8 +383,8 @@ class MainTable(tk.Canvas):
385
383
 
386
384
  def basic_bindings(self, enable: bool = True) -> None:
387
385
  bindings = (
386
+ ("<Enter>", self, self.mouse_motion),
388
387
  ("<Configure>", self, self.window_configured),
389
- ("<Motion>", self, self.mouse_motion),
390
388
  ("<ButtonPress-1>", self, self.b1_press),
391
389
  ("<B1-Motion>", self, self.b1_motion),
392
390
  ("<ButtonRelease-1>", self, self.b1_release),
@@ -1528,7 +1526,7 @@ class MainTable(tk.Canvas):
1528
1526
  "displayed": {} if disp_new_idxs is None else disp_new_idxs,
1529
1527
  }
1530
1528
  event_data["options"] = self.copy_options()
1531
- event_data["named_spans"] = {k: span.pickle_self() for k, span in self.named_spans.items()}
1529
+ event_data["named_spans"] = {k: span.copy_self() for k, span in self.named_spans.items()}
1532
1530
 
1533
1531
  if move_widths and disp_new_idxs:
1534
1532
  self.set_col_positions(
@@ -1787,7 +1785,7 @@ class MainTable(tk.Canvas):
1787
1785
  "displayed": {} if disp_new_idxs is None else disp_new_idxs,
1788
1786
  }
1789
1787
  event_data["options"] = self.copy_options()
1790
- event_data["named_spans"] = {k: span.pickle_self() for k, span in self.named_spans.items()}
1788
+ event_data["named_spans"] = {k: span.copy_self() for k, span in self.named_spans.items()}
1791
1789
 
1792
1790
  if move_data:
1793
1791
  maxidx = len_to_idx(totalrows)
@@ -2081,9 +2079,7 @@ class MainTable(tk.Canvas):
2081
2079
  if "tagged_columns" in modification["options"]:
2082
2080
  self.tagged_columns = modification["options"]["tagged_columns"]
2083
2081
  if modification["named_spans"]:
2084
- self.named_spans = {
2085
- k: mod_span_widget(unpickle_obj(v), self.PAR) for k, v in modification["named_spans"].items()
2086
- }
2082
+ self.named_spans = modification["named_spans"]
2087
2083
  if modification["sheet_state"]:
2088
2084
  self.RI.tree_open_ids = modification["sheet_state"]["tree_open_ids"]
2089
2085
  self.row_positions = modification["sheet_state"]["row_positions"]
@@ -3559,9 +3555,8 @@ class MainTable(tk.Canvas):
3559
3555
  self.CH.rsz_h = None
3560
3556
 
3561
3557
  def mouse_motion(self, event: Any) -> None:
3562
- if self.current_cursor != "":
3563
- self.config(cursor="")
3564
- self.current_cursor = ""
3558
+ self.config(cursor="")
3559
+ self.current_cursor = ""
3565
3560
  self.reset_resize_vars()
3566
3561
  try_binding(self.extra_motion_func, event)
3567
3562
 
@@ -5468,7 +5463,7 @@ class MainTable(tk.Canvas):
5468
5463
  if not event_data:
5469
5464
  event_data = self.new_event_dict("delete_columns", state=True)
5470
5465
  event_data["options"] = self.copy_options()
5471
- event_data["named_spans"] = {k: span.pickle_self() for k, span in self.named_spans.items()}
5466
+ event_data["named_spans"] = {k: span.copy_self() for k, span in self.named_spans.items()}
5472
5467
  for i, datacn in enumerate(cols):
5473
5468
  for rn in range(len(self.data)):
5474
5469
  if datacn not in event_data["deleted"]["columns"]:
@@ -5558,7 +5553,7 @@ class MainTable(tk.Canvas):
5558
5553
  if not event_data:
5559
5554
  event_data = self.new_event_dict("delete_rows", state=True)
5560
5555
  event_data["options"] = self.copy_options()
5561
- event_data["named_spans"] = {k: span.pickle_self() for k, span in self.named_spans.items()}
5556
+ event_data["named_spans"] = {k: span.copy_self() for k, span in self.named_spans.items()}
5562
5557
 
5563
5558
  for i, datarn in enumerate(rows):
5564
5559
  event_data["deleted"]["rows"][datarn] = self.data.pop(datarn - i)
@@ -6183,7 +6178,7 @@ class MainTable(tk.Canvas):
6183
6178
  and can_width >= self.col_positions[-1] + self.PAR.ops.empty_horizontal
6184
6179
  and self.PAR.xscroll_showing
6185
6180
  ):
6186
- self.PAR.xscroll.grid_forget()
6181
+ self.PAR.xscroll.grid_remove()
6187
6182
  self.PAR.xscroll_showing = False
6188
6183
  elif (
6189
6184
  can_width < self.col_positions[-1] + self.PAR.ops.empty_horizontal
@@ -6191,10 +6186,10 @@ class MainTable(tk.Canvas):
6191
6186
  and not self.PAR.xscroll_disabled
6192
6187
  and can_height > 40
6193
6188
  ):
6194
- self.PAR.xscroll.grid(row=2, column=0, columnspan=2, sticky="nswe")
6189
+ self.PAR.xscroll.grid()
6195
6190
  self.PAR.xscroll_showing = True
6196
6191
  if can_height >= self.row_positions[-1] + self.PAR.ops.empty_vertical and self.PAR.yscroll_showing:
6197
- self.PAR.yscroll.grid_forget()
6192
+ self.PAR.yscroll.grid_remove()
6198
6193
  self.PAR.yscroll_showing = False
6199
6194
  elif (
6200
6195
  can_height < self.row_positions[-1] + self.PAR.ops.empty_vertical
@@ -6202,7 +6197,7 @@ class MainTable(tk.Canvas):
6202
6197
  and not self.PAR.yscroll_disabled
6203
6198
  and can_width > 40
6204
6199
  ):
6205
- self.PAR.yscroll.grid(row=0, column=2, rowspan=3, sticky="nswe")
6200
+ self.PAR.yscroll.grid()
6206
6201
  self.PAR.yscroll_showing = True
6207
6202
 
6208
6203
  def _overflow(
@@ -1,14 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
- import pickle
3
+ import copy
4
4
  import tkinter as tk
5
5
  from collections import namedtuple
6
6
  from collections.abc import Callable, Hashable, Iterator
7
- from functools import partial
8
7
  from typing import Any, Literal
9
8
 
10
- pickle_obj = partial(pickle.dumps, protocol=pickle.HIGHEST_PROTOCOL)
11
-
12
9
  FontTuple = namedtuple("FontTuple", "family size style")
13
10
  Box_nt = namedtuple(
14
11
  "Box_nt",
@@ -423,12 +420,45 @@ class Span(dict):
423
420
  cols = self.columns
424
421
  return Box_nt(rows.from_, cols.from_, rows.upto_, cols.upto_)
425
422
 
426
- def pickle_self(self) -> bytes:
427
- x = self["widget"]
428
- self["widget"] = None
429
- p = pickle_obj(self)
430
- self["widget"] = x
431
- return p
423
+ def copy_self(self) -> "Span":
424
+ # Create a new Span instance
425
+ span = Span()
426
+
427
+ # Iterate over all dictionary items to capture all attributes
428
+ for key, value in self.items():
429
+ if key == "widget":
430
+ # Tkinter widget: retain reference (do not copy)
431
+ span[key] = value
432
+ elif key == "kwargs":
433
+ # Handle kwargs, which may contain functions or lambdas
434
+ span[key] = {}
435
+ for k, v in value.items():
436
+ if callable(v):
437
+ # Functions/lambdas: shallow copy (immutable, but check for safety)
438
+ span[key][k] = v
439
+ else:
440
+ try:
441
+ # Deep copy non-callable items in kwargs
442
+ span[key][k] = copy.deepcopy(v)
443
+ except (TypeError, AttributeError):
444
+ # Handle non-copyable objects (e.g., complex closures or objects)
445
+ span[key][k] = v # Fallback to shallow copy
446
+ elif key == "convert" and callable(value):
447
+ # Convert is a callable: shallow copy (immutable)
448
+ span[key] = value
449
+ else:
450
+ # Deep copy other values to handle nested objects like DotDict
451
+ try:
452
+ span[key] = copy.deepcopy(value)
453
+ except (TypeError, AttributeError):
454
+ # Fallback for non-copyable objects
455
+ span[key] = value # Shallow copy as fallback
456
+
457
+ # Ensure widget is set if not already present (edge case)
458
+ if "widget" not in span and hasattr(self, "widget"):
459
+ span["widget"] = self["widget"]
460
+
461
+ return span
432
462
 
433
463
  __setattr__ = __setitem__
434
464
  __getattr__ = __getitem__
@@ -322,8 +322,7 @@ class RowIndex(tk.Canvas):
322
322
  x = self.canvasx(event.x)
323
323
  y = self.canvasy(event.y)
324
324
  mouse_over_resize = False
325
- mouse_over_selected = False
326
- if self.height_resizing_enabled and not mouse_over_resize:
325
+ if self.height_resizing_enabled:
327
326
  r = self.check_mouse_position_height_resizers(x, y)
328
327
  if r is not None:
329
328
  self.rsz_h, mouse_over_resize = r, True
@@ -358,19 +357,19 @@ class RowIndex(tk.Canvas):
358
357
  self.rsz_w = None
359
358
  except Exception:
360
359
  self.rsz_w = None
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.current_cursor != "hand2":
364
- self.config(cursor="hand2")
365
- self.current_cursor = "hand2"
366
- if not mouse_over_resize and not mouse_over_selected:
367
- if self.current_cursor != "":
368
- self.config(cursor="")
369
- self.current_cursor = ""
370
- self.MT.reset_resize_vars()
360
+ if not mouse_over_resize:
361
+ if self.MT.row_selected(self.MT.identify_row(event, allow_end=False)):
362
+ if self.current_cursor != "hand2":
363
+ self.config(cursor="hand2")
364
+ self.current_cursor = "hand2"
365
+ else:
366
+ if self.current_cursor != "":
367
+ self.config(cursor="")
368
+ self.current_cursor = ""
369
+ self.MT.reset_resize_vars()
371
370
  try_binding(self.extra_motion_func, event)
372
371
 
373
- def double_b1(self, event: Any):
372
+ def double_b1(self, event: Any) -> None:
374
373
  self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
375
374
  self.focus_set()
376
375
  if (
@@ -416,7 +415,7 @@ class RowIndex(tk.Canvas):
416
415
  self.mouse_motion(event)
417
416
  try_binding(self.extra_double_b1_func, event)
418
417
 
419
- def b1_press(self, event: Any):
418
+ def b1_press(self, event: Any) -> None:
420
419
  self.MT.unbind("<MouseWheel>")
421
420
  self.focus_set()
422
421
  self.closed_dropdown = self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
@@ -485,7 +484,7 @@ class RowIndex(tk.Canvas):
485
484
  self.toggle_select_row(r, redraw=True)
486
485
  try_binding(self.extra_b1_press_func, event)
487
486
 
488
- def b1_motion(self, event: Any):
487
+ def b1_motion(self, event: Any) -> None:
489
488
  x1, y1, x2, y2 = self.MT.get_canvas_visible_area()
490
489
  if self.height_resizing_enabled and self.rsz_h is not None and self.currently_resizing_height:
491
490
  y = self.canvasy(event.y)
@@ -446,7 +446,6 @@ class Sheet(tk.Frame):
446
446
  style=f"Sheet{self.unique_id}.Vertical.TScrollbar",
447
447
  )
448
448
  self.MT["yscrollcommand"] = self.yscroll.set
449
- self.RI["yscrollcommand"] = self.yscroll.set
450
449
  self.xscroll = ttk.Scrollbar(
451
450
  self,
452
451
  command=self.MT._xscrollbar,
@@ -454,7 +453,6 @@ class Sheet(tk.Frame):
454
453
  style=f"Sheet{self.unique_id}.Horizontal.TScrollbar",
455
454
  )
456
455
  self.MT["xscrollcommand"] = self.xscroll.set
457
- self.CH["xscrollcommand"] = self.xscroll.set
458
456
  self.show()
459
457
  if show_top_left is False or (show_top_left is None and (not show_row_index or not show_header)):
460
458
  self.hide("top_left")
@@ -4,6 +4,7 @@ import tkinter as tk
4
4
  from typing import Any
5
5
 
6
6
  from .constants import rc_binding
7
+ from .functions import try_binding
7
8
 
8
9
 
9
10
  class TopLeftRectangle(tk.Canvas):
@@ -198,10 +199,8 @@ class TopLeftRectangle(tk.Canvas):
198
199
  )
199
200
  self.coords(self.select_all_box, 0, 0, w - 5, h - 5)
200
201
 
201
- def mouse_motion(self, event: Any = None) -> None:
202
- self.MT.reset_mouse_motion_creations()
203
- if self.extra_motion_func is not None:
204
- self.extra_motion_func(event)
202
+ def mouse_motion(self, event: Any) -> None:
203
+ try_binding(self.extra_motion_func, event)
205
204
 
206
205
  def b1_press(self, event: Any = None) -> None:
207
206
  self.focus_set()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tksheet
3
- Version: 7.4.19
3
+ Version: 7.4.21
4
4
  Summary: Tkinter table / sheet and treeview widget
5
5
  Author-email: ragardner <github@ragardner.simplelogin.com>
6
6
  License: Copyright (c) 2019 ragardner and open source contributors
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes