tksheet 7.4.5__py3-none-any.whl → 7.4.6__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/__init__.py +1 -1
- tksheet/column_headers.py +28 -28
- tksheet/constants.py +4 -3
- tksheet/find_window.py +8 -8
- tksheet/formatters.py +39 -39
- tksheet/functions.py +53 -57
- tksheet/main_table.py +153 -122
- tksheet/other_classes.py +11 -11
- tksheet/row_index.py +27 -27
- tksheet/sheet.py +99 -110
- tksheet/sorting.py +19 -18
- tksheet/text_editor.py +9 -9
- tksheet/tksheet_types.py +187 -0
- tksheet/top_left_rectangle.py +13 -12
- {tksheet-7.4.5.dist-info → tksheet-7.4.6.dist-info}/METADATA +1 -1
- tksheet-7.4.6.dist-info/RECORD +22 -0
- tksheet-7.4.5.dist-info/RECORD +0 -22
- {tksheet-7.4.5.dist-info → tksheet-7.4.6.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.4.5.dist-info → tksheet-7.4.6.dist-info}/WHEEL +0 -0
- {tksheet-7.4.5.dist-info → tksheet-7.4.6.dist-info}/top_level.txt +0 -0
tksheet/functions.py
CHANGED
@@ -10,7 +10,7 @@ from collections import deque
|
|
10
10
|
from collections.abc import Callable, Generator, Hashable, Iterable, Iterator, Sequence
|
11
11
|
from difflib import SequenceMatcher
|
12
12
|
from itertools import islice, repeat
|
13
|
-
from typing import Literal
|
13
|
+
from typing import Any, Literal
|
14
14
|
|
15
15
|
from .colors import color_map
|
16
16
|
from .constants import align_value_error, symbols_set
|
@@ -202,7 +202,7 @@ def recursive_bind(widget: tk.Misc, event: str, callback: Callable) -> None:
|
|
202
202
|
recursive_bind(child, event, callback)
|
203
203
|
|
204
204
|
|
205
|
-
def tksheet_type_error(kwarg: str, valid_types: list[str], not_type:
|
205
|
+
def tksheet_type_error(kwarg: str, valid_types: list[str], not_type: Any) -> str:
|
206
206
|
valid_types = ", ".join(f"{type_}" for type_ in valid_types)
|
207
207
|
return f"Argument '{kwarg}' must be one of the following types: {valid_types}, not {type(not_type)}."
|
208
208
|
|
@@ -213,7 +213,7 @@ def new_tk_event(keysym: str) -> tk.Event:
|
|
213
213
|
return event
|
214
214
|
|
215
215
|
|
216
|
-
def event_has_char_key(event:
|
216
|
+
def event_has_char_key(event: Any) -> bool:
|
217
217
|
return (
|
218
218
|
event and hasattr(event, "char") and (event.char.isalpha() or event.char.isdigit() or event.char in symbols_set)
|
219
219
|
)
|
@@ -232,7 +232,7 @@ def event_opens_dropdown_or_checkbox(event=None) -> bool:
|
|
232
232
|
)
|
233
233
|
|
234
234
|
|
235
|
-
def dropdown_search_function(search_for: str, data: Iterable[
|
235
|
+
def dropdown_search_function(search_for: str, data: Iterable[Any]) -> None | int:
|
236
236
|
search_for = search_for.lower()
|
237
237
|
search_len = len(search_for)
|
238
238
|
if not search_len:
|
@@ -281,16 +281,16 @@ def float_to_int(f: int | float) -> int | float:
|
|
281
281
|
|
282
282
|
def event_dict(
|
283
283
|
name: str = None,
|
284
|
-
sheet:
|
284
|
+
sheet: Any = None,
|
285
285
|
widget: tk.Canvas | None = None,
|
286
286
|
boxes: None | dict | tuple = None,
|
287
287
|
cells_table: None | dict = None,
|
288
288
|
cells_header: None | dict = None,
|
289
289
|
cells_index: None | dict = None,
|
290
290
|
selected: None | tuple = None,
|
291
|
-
data:
|
291
|
+
data: Any = None,
|
292
292
|
key: None | str = None,
|
293
|
-
value:
|
293
|
+
value: Any = None,
|
294
294
|
loc: None | int | tuple[int] = None,
|
295
295
|
row: None | int = None,
|
296
296
|
column: None | int = None,
|
@@ -366,7 +366,8 @@ def stored_event_dict(d: DotDict) -> DotDict:
|
|
366
366
|
def len_to_idx(n: int) -> int:
|
367
367
|
if n < 1:
|
368
368
|
return 0
|
369
|
-
|
369
|
+
else:
|
370
|
+
return n - 1
|
370
371
|
|
371
372
|
|
372
373
|
def b_index(sorted_seq: Sequence[int], num_to_index: int) -> int:
|
@@ -376,13 +377,15 @@ def b_index(sorted_seq: Sequence[int], num_to_index: int) -> int:
|
|
376
377
|
"""
|
377
378
|
if (idx := bisect_left(sorted_seq, num_to_index)) == len(sorted_seq) or sorted_seq[idx] != num_to_index:
|
378
379
|
raise ValueError(f"{num_to_index} is not in Sequence")
|
379
|
-
|
380
|
+
else:
|
381
|
+
return idx
|
380
382
|
|
381
383
|
|
382
384
|
def try_b_index(sorted_seq: Sequence[int], num_to_index: int) -> int | None:
|
383
385
|
if (idx := bisect_left(sorted_seq, num_to_index)) == len(sorted_seq) or sorted_seq[idx] != num_to_index:
|
384
386
|
return None
|
385
|
-
|
387
|
+
else:
|
388
|
+
return idx
|
386
389
|
|
387
390
|
|
388
391
|
def bisect_in(sorted_seq: Sequence[int], num: int) -> bool:
|
@@ -399,27 +402,20 @@ def push_n(num: int, sorted_seq: Sequence[int]) -> int:
|
|
399
402
|
if num < sorted_seq[0]:
|
400
403
|
return num
|
401
404
|
else:
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
while lo < hi:
|
412
|
-
mid = (lo + hi) // 2
|
413
|
-
if sorted_seq[mid] < num + mid + 1:
|
414
|
-
lo = mid + 1
|
415
|
-
else:
|
416
|
-
hi = mid
|
417
|
-
return num + lo
|
405
|
+
hi = len(sorted_seq)
|
406
|
+
lo = 0
|
407
|
+
while lo < hi:
|
408
|
+
mid = (lo + hi) // 2
|
409
|
+
if sorted_seq[mid] < num + mid + 1:
|
410
|
+
lo = mid + 1
|
411
|
+
else:
|
412
|
+
hi = mid
|
413
|
+
return num + lo
|
418
414
|
|
419
415
|
|
420
416
|
def get_dropdown_kwargs(
|
421
|
-
values: list[
|
422
|
-
set_value:
|
417
|
+
values: list[Any] | None = None,
|
418
|
+
set_value: Any = None,
|
423
419
|
state: str = "normal",
|
424
420
|
redraw: bool = True,
|
425
421
|
selection_function: Callable | None = None,
|
@@ -477,7 +473,7 @@ def get_checkbox_dict(**kwargs) -> dict:
|
|
477
473
|
}
|
478
474
|
|
479
475
|
|
480
|
-
def is_iterable(o:
|
476
|
+
def is_iterable(o: Any) -> bool:
|
481
477
|
if isinstance(o, str):
|
482
478
|
return False
|
483
479
|
try:
|
@@ -499,7 +495,7 @@ def int_x_tuple(i: AnyIter[int] | int) -> tuple[int]:
|
|
499
495
|
return tuple(i)
|
500
496
|
|
501
497
|
|
502
|
-
def unpack(t: tuple[
|
498
|
+
def unpack(t: tuple[Any] | tuple[AnyIter[Any]]) -> tuple[Any]:
|
503
499
|
if not len(t):
|
504
500
|
return t
|
505
501
|
if is_iterable(t[0]) and len(t) == 1:
|
@@ -507,11 +503,11 @@ def unpack(t: tuple[object] | tuple[AnyIter[object]]) -> tuple[object]:
|
|
507
503
|
return t
|
508
504
|
|
509
505
|
|
510
|
-
def is_type_int(o:
|
506
|
+
def is_type_int(o: Any) -> bool:
|
511
507
|
return isinstance(o, int) and not isinstance(o, bool)
|
512
508
|
|
513
509
|
|
514
|
-
def force_bool(o:
|
510
|
+
def force_bool(o: Any) -> bool:
|
515
511
|
try:
|
516
512
|
return to_bool(o)
|
517
513
|
except Exception:
|
@@ -702,8 +698,8 @@ def cell_right_within_box(
|
|
702
698
|
|
703
699
|
|
704
700
|
def get_last(
|
705
|
-
it: AnyIter[
|
706
|
-
) ->
|
701
|
+
it: AnyIter[Any],
|
702
|
+
) -> Any:
|
707
703
|
if hasattr(it, "__reversed__"):
|
708
704
|
try:
|
709
705
|
return next(reversed(it))
|
@@ -716,7 +712,7 @@ def get_last(
|
|
716
712
|
return None
|
717
713
|
|
718
714
|
|
719
|
-
def index_exists(seq: Sequence[
|
715
|
+
def index_exists(seq: Sequence[Any], index: int) -> bool:
|
720
716
|
try:
|
721
717
|
seq[index]
|
722
718
|
return True
|
@@ -733,10 +729,10 @@ def add_to_displayed(displayed: list[int], to_add: Iterable[int]) -> list[int]:
|
|
733
729
|
|
734
730
|
|
735
731
|
def move_elements_by_mapping(
|
736
|
-
seq: list[
|
732
|
+
seq: list[Any],
|
737
733
|
new_idxs: dict[int, int],
|
738
734
|
old_idxs: dict[int, int] | None = None,
|
739
|
-
) -> list[
|
735
|
+
) -> list[Any]:
|
740
736
|
# move elements of a list around
|
741
737
|
# displacing other elements based on mapping
|
742
738
|
# new_idxs = {old index: new index, ...}
|
@@ -748,10 +744,10 @@ def move_elements_by_mapping(
|
|
748
744
|
|
749
745
|
|
750
746
|
def move_elements_by_mapping_gen(
|
751
|
-
seq: list[
|
747
|
+
seq: list[Any],
|
752
748
|
new_idxs: dict[int, int],
|
753
749
|
old_idxs: dict[int, int] | None = None,
|
754
|
-
) -> Generator[
|
750
|
+
) -> Generator[Any]:
|
755
751
|
if old_idxs is None:
|
756
752
|
old_idxs = dict(zip(new_idxs.values(), new_idxs))
|
757
753
|
remaining_values = (e for i, e in enumerate(seq) if i not in new_idxs)
|
@@ -759,10 +755,10 @@ def move_elements_by_mapping_gen(
|
|
759
755
|
|
760
756
|
|
761
757
|
def move_elements_to(
|
762
|
-
seq: list[
|
758
|
+
seq: list[Any],
|
763
759
|
move_to: int,
|
764
760
|
to_move: list[int],
|
765
|
-
) -> list[
|
761
|
+
) -> list[Any]:
|
766
762
|
return move_elements_by_mapping(
|
767
763
|
seq,
|
768
764
|
*get_new_indexes(
|
@@ -791,14 +787,14 @@ def get_new_indexes(
|
|
791
787
|
|
792
788
|
|
793
789
|
def insert_items(
|
794
|
-
seq: list[
|
795
|
-
to_insert: dict[int,
|
790
|
+
seq: list[Any],
|
791
|
+
to_insert: dict[int, Any],
|
796
792
|
seq_len_func: Callable | None = None,
|
797
|
-
) -> list[
|
793
|
+
) -> list[Any]:
|
798
794
|
"""
|
799
|
-
seq: list[
|
795
|
+
seq: list[Any]
|
800
796
|
to_insert: keys are ints sorted in reverse, representing list indexes to insert items.
|
801
|
-
Values are any
|
797
|
+
Values are any, e.g. {1: 200, 0: 200}
|
802
798
|
"""
|
803
799
|
if to_insert:
|
804
800
|
if seq_len_func and next(iter(to_insert)) >= len(seq) + len(to_insert):
|
@@ -809,11 +805,11 @@ def insert_items(
|
|
809
805
|
|
810
806
|
|
811
807
|
def del_placeholder_dict_key(
|
812
|
-
d: dict[Hashable,
|
808
|
+
d: dict[Hashable, Any],
|
813
809
|
k: Hashable,
|
814
|
-
v:
|
810
|
+
v: Any,
|
815
811
|
p: tuple = (),
|
816
|
-
) -> dict[Hashable,
|
812
|
+
) -> dict[Hashable, Any]:
|
817
813
|
if p in d:
|
818
814
|
del d[p]
|
819
815
|
d[k] = v
|
@@ -994,7 +990,7 @@ def is_last_cell(
|
|
994
990
|
return row == end_row - 1 and col == end_col - 1
|
995
991
|
|
996
992
|
|
997
|
-
def zip_fill_2nd_value(x: AnyIter[
|
993
|
+
def zip_fill_2nd_value(x: AnyIter[Any], o: Any) -> Generator[Any, Any]:
|
998
994
|
return zip(x, repeat(o))
|
999
995
|
|
1000
996
|
|
@@ -1011,7 +1007,7 @@ def str_to_int(s: str) -> int | None:
|
|
1011
1007
|
|
1012
1008
|
def gen_formatted(
|
1013
1009
|
options: dict,
|
1014
|
-
formatter:
|
1010
|
+
formatter: Any = None,
|
1015
1011
|
) -> Generator[tuple[int, int]] | Generator[int]:
|
1016
1012
|
if formatter is None:
|
1017
1013
|
return (k for k, dct in options.items() if "format" in dct)
|
@@ -1060,7 +1056,7 @@ def span_dict(
|
|
1060
1056
|
convert: Callable | None = None,
|
1061
1057
|
undo: bool = False,
|
1062
1058
|
emit_event: bool = False,
|
1063
|
-
widget:
|
1059
|
+
widget: Any = None,
|
1064
1060
|
) -> Span:
|
1065
1061
|
d: Span = Span(
|
1066
1062
|
from_r=from_r,
|
@@ -1087,7 +1083,7 @@ def span_dict(
|
|
1087
1083
|
|
1088
1084
|
|
1089
1085
|
def coords_to_span(
|
1090
|
-
widget:
|
1086
|
+
widget: Any,
|
1091
1087
|
from_r: int | None = None,
|
1092
1088
|
from_c: int | None = None,
|
1093
1089
|
upto_r: int | None = None,
|
@@ -1122,7 +1118,7 @@ def key_to_span(
|
|
1122
1118
|
| Sequence[Sequence[int | None, int | None], Sequence[int | None, int | None]]
|
1123
1119
|
),
|
1124
1120
|
spans: dict[str, Span],
|
1125
|
-
widget:
|
1121
|
+
widget: Any = None,
|
1126
1122
|
) -> Span:
|
1127
1123
|
if isinstance(key, Span):
|
1128
1124
|
return key
|
@@ -1623,7 +1619,7 @@ def add_to_options(
|
|
1623
1619
|
options: dict,
|
1624
1620
|
coords: int | tuple[int, int],
|
1625
1621
|
key: str,
|
1626
|
-
value:
|
1622
|
+
value: Any,
|
1627
1623
|
) -> dict:
|
1628
1624
|
if coords not in options:
|
1629
1625
|
options[coords] = {}
|
@@ -1694,14 +1690,14 @@ def mod_span(
|
|
1694
1690
|
return to_set_to
|
1695
1691
|
|
1696
1692
|
|
1697
|
-
def mod_span_widget(span: Span, widget:
|
1693
|
+
def mod_span_widget(span: Span, widget: Any) -> Span:
|
1698
1694
|
span.widget = widget
|
1699
1695
|
return span
|
1700
1696
|
|
1701
1697
|
|
1702
1698
|
def mod_event_val(
|
1703
1699
|
event_data: EventDataDict,
|
1704
|
-
val:
|
1700
|
+
val: Any,
|
1705
1701
|
loc: Loc | None = None,
|
1706
1702
|
row: int | None = None,
|
1707
1703
|
column: int | None = None,
|