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/sheet_options.py CHANGED
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from .constants import USER_OS, ctrl_key
4
4
  from .other_classes import DotDict, FontTuple
5
+ from .sorting import fast_sort_key, natural_sort_key, version_sort_key # noqa: F401
5
6
  from .themes import theme_light_blue
6
7
 
7
8
 
@@ -255,5 +256,6 @@ def new_sheet_options() -> DotDict:
255
256
  "max_row_height": float("inf"),
256
257
  "max_index_width": float("inf"),
257
258
  "show_top_left": None,
259
+ "sort_key": natural_sort_key,
258
260
  }
259
261
  )
tksheet/sorting.py CHANGED
@@ -3,12 +3,12 @@ from __future__ import annotations
3
3
  from collections.abc import Callable, Generator, Iterable, Iterator
4
4
  from datetime import datetime
5
5
  from pathlib import Path
6
- from re import finditer
6
+ from re import split
7
7
 
8
8
  AnyIter = Iterable | Iterator
9
9
 
10
10
  # Possible date formats to try for the entire string
11
- date_formats = [
11
+ date_formats = (
12
12
  # Common formats
13
13
  "%d/%m/%Y", # Day/Month/Year
14
14
  "%m/%d/%Y", # Month/Day/Year (US format)
@@ -24,7 +24,8 @@ date_formats = [
24
24
  "%m,%d,%Y", # Month,Day,Year
25
25
  "%Y,%m,%d", # Year,Month,Day
26
26
  "%d %m %Y", # Day Month Year (with space)
27
- "%m %d %Y", # Month Day Year
27
+ "%m %d %Y", # Month Day Year (with space)
28
+ "%Y %d %m", # Year Month Day (with space)
28
29
  # With month names
29
30
  "%d %b %Y", # Day Abbreviated Month Year
30
31
  "%b %d, %Y", # Abbreviated Month Day, Year
@@ -42,59 +43,228 @@ date_formats = [
42
43
  "%d/%m/%y %H:%M", # Day/Month/Year Hour:Minute
43
44
  "%m/%d/%y %H:%M", # Month/Day/Year Hour:Minute
44
45
  "%Y-%m-%d %H:%M:%S", # Year-Month-Day Hour:Minute:Second
45
- ]
46
+ )
46
47
 
47
48
 
48
- def natural_sort_key(item: object) -> tuple[int, ...]:
49
+ def _string_fallback(item: str) -> tuple[int, ...]:
50
+ """
51
+ In order to have reasonable file path sorting:
52
+ - Split by path separators
53
+ - Determine depth, more separators more depth
54
+ - Deal with every dir by splitting by digits
55
+ - Deal with file name by splitting by digits
56
+ """
57
+ components = split(r"[/\\]", item)
58
+ if components[-1]:
59
+ return (
60
+ 5,
61
+ len(components),
62
+ tuple(int(e) if e.isdigit() else e.lower() for comp in components[:-1] for e in split(r"(\d+)", comp) if e),
63
+ tuple(int(e) if e.isdigit() else e.lower() for e in split(r"(\d+)", components[-1])),
64
+ )
65
+ else:
66
+ return (
67
+ 5,
68
+ len(components),
69
+ tuple(int(e) if e.isdigit() else e.lower() for comp in components[:-1] for e in split(r"(\d+)", comp) if e),
70
+ (),
71
+ )
72
+
73
+
74
+ def version_sort_key(item: object) -> tuple[int, ...]:
49
75
  """
50
76
  A key for natural sorting of various Python types.
51
77
 
78
+ - Won't convert strings to floats
79
+ - Will sort string version numbers
80
+
52
81
  0. None
53
- 1. bool
54
- 2. int, float
55
- 3. datetime
56
- 4. empty strings
57
- 5. strings (including paths as POSIX strings)
58
- 6. unknown objects with __str__
59
- 7. unknown objects
82
+ 1. Empty strings
83
+ 2. bool
84
+ 3. int, float
85
+ 4. datetime (inc. strings that are dates)
86
+ 5. strings (including string file paths and paths as POSIX strings) & unknown objects with __str__
87
+ 6. unknown objects
60
88
  """
61
- if item is None:
89
+ if isinstance(item, str):
90
+ if item:
91
+ for date_format in date_formats:
92
+ try:
93
+ return (4, datetime.strptime(item, date_format).timestamp())
94
+ except ValueError:
95
+ continue
96
+ # the same as _string_fallback
97
+ components = split(r"[/\\]", item)
98
+ if components[-1]:
99
+ return (
100
+ 5,
101
+ len(components),
102
+ tuple(
103
+ int(e) if e.isdigit() else e.lower()
104
+ for comp in components[:-1]
105
+ for e in split(r"(\d+)", comp)
106
+ if e
107
+ ),
108
+ tuple(int(e) if e.isdigit() else e.lower() for e in split(r"(\d+)", components[-1])),
109
+ )
110
+ else:
111
+ return (
112
+ 5,
113
+ len(components),
114
+ tuple(
115
+ int(e) if e.isdigit() else e.lower()
116
+ for comp in components[:-1]
117
+ for e in split(r"(\d+)", comp)
118
+ if e
119
+ ),
120
+ (),
121
+ )
122
+ else:
123
+ return (1, item)
124
+
125
+ elif item is None:
62
126
  return (0,)
63
127
 
64
128
  elif isinstance(item, bool):
65
- return (1, item)
129
+ return (2, item)
66
130
 
67
131
  elif isinstance(item, (int, float)):
68
- return (2, item)
132
+ return (3, item)
69
133
 
70
134
  elif isinstance(item, datetime):
71
- return (3, item.timestamp())
135
+ return (4, item.timestamp())
72
136
 
73
- elif isinstance(item, str):
74
- if not item:
75
- return (4, item)
137
+ elif isinstance(item, Path):
138
+ return _string_fallback(item.as_posix())
139
+
140
+ else:
141
+ try:
142
+ return _string_fallback(f"{item}")
143
+ except Exception:
144
+ return (6, item)
145
+
146
+
147
+ def natural_sort_key(item: object) -> tuple[int, ...]:
148
+ """
149
+ A key for natural sorting of various Python types.
150
+
151
+ - Won't sort string version numbers
152
+ - Will convert strings to floats
153
+ - Will sort strings that are file paths
154
+
155
+ 0. None
156
+ 1. Empty strings
157
+ 2. bool
158
+ 3. int, float (inc. strings that are numbers)
159
+ 4. datetime (inc. strings that are dates)
160
+ 5. strings (including string file paths and paths as POSIX strings) & unknown objects with __str__
161
+ 6. unknown objects
162
+ """
163
+ if isinstance(item, str):
164
+ if item:
165
+ for date_format in date_formats:
166
+ try:
167
+ return (4, datetime.strptime(item, date_format).timestamp())
168
+ except ValueError:
169
+ continue
76
170
 
77
- for date_format in date_formats:
78
171
  try:
79
- return (3, datetime.strptime(item, date_format).timestamp())
172
+ return (3, float(item))
80
173
  except ValueError:
81
- continue
174
+ # the same as _string_fallback
175
+ components = split(r"[/\\]", item)
176
+ if components[-1]:
177
+ return (
178
+ 5,
179
+ len(components),
180
+ tuple(
181
+ int(e) if e.isdigit() else e.lower()
182
+ for comp in components[:-1]
183
+ for e in split(r"(\d+)", comp)
184
+ if e
185
+ ),
186
+ tuple(int(e) if e.isdigit() else e.lower() for e in split(r"(\d+)", components[-1])),
187
+ )
188
+ else:
189
+ return (
190
+ 5,
191
+ len(components),
192
+ tuple(
193
+ int(e) if e.isdigit() else e.lower()
194
+ for comp in components[:-1]
195
+ for e in split(r"(\d+)", comp)
196
+ if e
197
+ ),
198
+ (),
199
+ )
200
+ else:
201
+ return (1, item)
202
+
203
+ elif item is None:
204
+ return (0,)
205
+
206
+ elif isinstance(item, bool):
207
+ return (2, item)
208
+
209
+ elif isinstance(item, (int, float)):
210
+ return (3, item)
211
+
212
+ elif isinstance(item, datetime):
213
+ return (4, item.timestamp())
214
+
215
+ elif isinstance(item, Path):
216
+ return _string_fallback(item.as_posix())
217
+
218
+ else:
82
219
  try:
83
- return (2, float(item))
220
+ return _string_fallback(f"{item}")
84
221
  except Exception:
85
- pass
222
+ return (6, item)
223
+
224
+
225
+ def fast_sort_key(item: object) -> tuple[int, ...]:
226
+ """
227
+ A faster key for natural sorting of various Python types.
228
+
229
+ - Won't sort strings that are dates very well
230
+ - Won't convert strings to floats
231
+ - Won't sort string file paths very well
232
+ - Will do ok with string version numbers
86
233
 
87
- return (5, item.lower(), tuple(int(match.group()) for match in finditer(r"\d+", item)))
234
+ 0. None
235
+ 1. Empty strings
236
+ 2. bool
237
+ 3. int, float
238
+ 4. datetime
239
+ 5. strings (including paths as POSIX strings) & unknown objects with __str__
240
+ 6. unknown objects
241
+ """
242
+ if isinstance(item, str):
243
+ if item:
244
+ return (5, tuple(int(e) if e.isdigit() else e.lower() for e in split(r"(\d+)", item)))
245
+ else:
246
+ return (1, item)
247
+
248
+ elif item is None:
249
+ return (0,)
250
+
251
+ elif isinstance(item, bool):
252
+ return (2, item)
253
+
254
+ elif isinstance(item, (int, float)):
255
+ return (3, item)
256
+
257
+ elif isinstance(item, datetime):
258
+ return (4, item.timestamp())
88
259
 
89
260
  elif isinstance(item, Path):
90
- posix_str = item.as_posix()
91
- return (5, posix_str.lower(), tuple(int(match.group()) for match in finditer(r"\d+", posix_str)))
261
+ return _string_fallback(item.as_posix())
92
262
 
93
263
  else:
94
264
  try:
95
- return (6, f"{item}".lower())
265
+ return _string_fallback(f"{item}")
96
266
  except Exception:
97
- return (7, item)
267
+ return (6, item)
98
268
 
99
269
 
100
270
  def sort_selection(
@@ -223,7 +393,7 @@ def sort_columns_by_row(
223
393
  unsorted_part = [elem for idx, elem in enumerate(row_data) if idx not in sort_indices_set]
224
394
  new_data.append(sorted_part + unsorted_part)
225
395
 
226
- return sort_indices, {old: new for old, new in zip(range(len(data[row])), sort_indices)}
396
+ return sort_indices, dict(zip(range(len(data[row])), sort_indices))
227
397
 
228
398
 
229
399
  def _sort_node_children(
@@ -247,14 +417,15 @@ def sort_tree_view(
247
417
  _row_index: list[object],
248
418
  tree_rns: dict[str, int],
249
419
  tree: dict[str, object],
250
- key: Callable = natural_sort_key,
420
+ key: Callable | None = None,
251
421
  reverse: bool = False,
252
422
  ) -> tuple[list[object], dict[int, int]]:
253
423
  if not _row_index or not tree_rns or not tree:
254
424
  return [], {}
255
425
 
256
426
  if key is None:
257
- key = natural_sort_key
427
+ # prefer version_sort_key for iid names
428
+ key = version_sort_key
258
429
 
259
430
  # Create the index map and sorted nodes list
260
431
  mapping = {}
@@ -281,38 +452,80 @@ def sort_tree_view(
281
452
  return sorted_nodes, mapping
282
453
 
283
454
 
284
- # def test_natural_sort_key():
285
- # test_items = [
286
- # None,
287
- # False,
288
- # True,
289
- # 5,
290
- # 3.14,
291
- # datetime(2023, 1, 1),
292
- # "abc123",
293
- # "123abc",
294
- # "abc123def",
295
- # "998zzz",
296
- # "10-01-2023",
297
- # "01-10-2023",
298
- # "fi1le_0.txt",
299
- # "file_2.txt",
300
- # "file_10.txt",
301
- # "file_1.txt",
302
- # "path/to/file_2.txt",
303
- # "path/to/file_10.txt",
304
- # "path/to/file_1.txt",
305
- # "/another/path/file_2.log",
306
- # "/another/path/file_10.log",
307
- # "/another/path/file_1.log",
308
- # "C:\\Windows\\System32\\file_2.dll",
309
- # "C:\\Windows\\System32\\file_10.dll",
310
- # "C:\\Windows\\System32\\file_1.dll",
311
- # ]
312
- # print("Sort objects:", [natural_sort_key(e) for e in test_items])
313
- # sorted_items = sorted(test_items, key=natural_sort_key)
314
- # print("\nNatural Sort Order:", sorted_items)
315
-
316
-
317
455
  # if __name__ == "__main__":
318
- # test_natural_sort_key()
456
+ # test_cases = {
457
+ # "Filenames": ["file10.txt", "file2.txt", "file1.txt"],
458
+ # "Versions": ["1.10", "1.2", "1.9", "1.21"],
459
+ # "Mixed": ["z1.doc", "z10.doc", "z2.doc", "z100.doc"],
460
+ # "Paths": [
461
+ # "/folder/file.txt",
462
+ # "/folder/file (1).txt",
463
+ # "/folder (1)/file.txt",
464
+ # "/folder (10)/file.txt",
465
+ # "/dir/subdir/file1.txt",
466
+ # "/dir/subdir/file10.txt",
467
+ # "/dir/subdir/file2.txt",
468
+ # "/dir/file.txt",
469
+ # "/dir/sub/file123.txt",
470
+ # "/dir/sub/file12.txt",
471
+ # # New challenging cases
472
+ # "/a/file.txt",
473
+ # "/a/file1.txt",
474
+ # "/a/b/file.txt",
475
+ # "/a/b/file1.txt",
476
+ # "/x/file-v1.2.txt",
477
+ # "/x/file-v1.10.txt",
478
+ # # My own new challenging cases
479
+ # "/a/zzzzz.txt",
480
+ # "/a/b/a.txt",
481
+ # ],
482
+ # "Case": ["Apple", "banana", "Corn", "apple", "Banana", "corn"],
483
+ # "Leading Zeros": ["001", "010", "009", "100"],
484
+ # "Complex": ["x-1-y-10", "x-1-y-2", "x-2-y-1", "x-10-y-1"],
485
+ # "Lengths": ["2 ft 9 in", "2 ft 10 in", "10 ft 1 in", "10 ft 2 in"],
486
+ # "Floats": [
487
+ # "1.5",
488
+ # "1.25",
489
+ # "1.025",
490
+ # "10.5",
491
+ # "-10.2",
492
+ # "-2.5",
493
+ # "5.7",
494
+ # "-1.25",
495
+ # "0.0",
496
+ # "1.5e3",
497
+ # "2.5e2",
498
+ # "1.23e4",
499
+ # "1e-2",
500
+ # "file1.2.txt",
501
+ # "file1.5.txt",
502
+ # "file1.10.txt",
503
+ # ],
504
+ # "Strings": [
505
+ # "123abc",
506
+ # "abc123",
507
+ # "123abc456",
508
+ # "abc123def",
509
+ # ],
510
+ # }
511
+
512
+ # print("FAST SORT KEY:")
513
+
514
+ # for name, data in test_cases.items():
515
+ # sorted1 = sorted(data, key=fast_sort_key)
516
+ # print(f"\n{name}:")
517
+ # print(sorted1)
518
+
519
+ # print("\nNATURAL SORT KEY:")
520
+
521
+ # for name, data in test_cases.items():
522
+ # sorted1 = sorted(data, key=natural_sort_key)
523
+ # print(f"\n{name}:")
524
+ # print(sorted1)
525
+
526
+ # print("\nVERSION SORT KEY:")
527
+
528
+ # for name, data in test_cases.items():
529
+ # sorted1 = sorted(data, key=version_sort_key)
530
+ # print(f"\n{name}:")
531
+ # print(sorted1)
tksheet/text_editor.py CHANGED
@@ -111,9 +111,15 @@ class TextEditorTkText(tk.Text):
111
111
  ):
112
112
  self.tag_add("align", 1.0, "end")
113
113
  self.event_generate("<<TextModified>>")
114
- if args and len(args) > 1 and args[1] != "\n" and args != ("1.0", "end"):
115
- if self.yview() != (0.0, 1.0) and self.newline_bindng is not None:
116
- self.newline_bindng(check_lines=False)
114
+ if (
115
+ args
116
+ and len(args) > 1
117
+ and args[1] != "\n"
118
+ and args != ("1.0", "end")
119
+ and self.yview() != (0.0, 1.0)
120
+ and self.newline_bindng is not None
121
+ ):
122
+ self.newline_bindng(check_lines=False)
117
123
  return result
118
124
 
119
125
  def rc(self, event: object) -> None:
@@ -220,12 +220,11 @@ class TopLeftRectangle(tk.Canvas):
220
220
  self.PAR.ops.default_row_index_width,
221
221
  set_TL=True,
222
222
  )
223
- elif rect[0] == self.rh_box:
224
- if self.CH.height_resizing_enabled:
225
- self.CH.set_height(
226
- self.MT.get_default_header_height(),
227
- set_TL=True,
228
- )
223
+ elif rect[0] == self.rh_box and self.CH.height_resizing_enabled:
224
+ self.CH.set_height(
225
+ self.MT.get_default_header_height(),
226
+ set_TL=True,
227
+ )
229
228
  self.MT.main_table_redraw_grid_and_text(
230
229
  redraw_header=True,
231
230
  redraw_row_index=True,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tksheet
3
- Version: 7.4.3
3
+ Version: 7.4.5
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
@@ -24,7 +24,9 @@ License: Copyright (c) 2019 ragardner and open source contributors
24
24
  SOFTWARE.
25
25
 
26
26
  Project-URL: Homepage, https://github.com/ragardner/tksheet
27
- Project-URL: Bug Reports, https://github.com/ragardner/tksheet/issues
27
+ Project-URL: Documentation, https://github.com/ragardner/tksheet/wiki/Version-7
28
+ Project-URL: Changelog, https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md
29
+ Project-URL: Issues, https://github.com/ragardner/tksheet/issues
28
30
  Project-URL: Funding, https://github.com/ragardner
29
31
  Keywords: tkinter,table,widget,tree,treeview,sheet,grid,tk
30
32
  Classifier: Development Status :: 5 - Production/Stable
@@ -0,0 +1,22 @@
1
+ tksheet/__init__.py,sha256=DBwinDqYjK3FjcSqsMWT72Ew9gnVODLENV3h5GMYLd0,2313
2
+ tksheet/colors.py,sha256=dHhmdFuQDlwohDHsAfT9VdrKoSl_R33L72a3HCin5zo,51591
3
+ tksheet/column_headers.py,sha256=SSDDxSsfVwgg81R2eS4LZoRTfLWixIT_tIBrcZFfXDE,103240
4
+ tksheet/constants.py,sha256=YzomMDH38tPCk3XgbmtYebx_8RIJklD2wpeCUCCJnC0,3906
5
+ tksheet/find_window.py,sha256=JfkgpGluSng3bKMBneDNQg-AJmBcmCW7JIhtYbSUZaE,8036
6
+ tksheet/formatters.py,sha256=eKOX69mUXjkSHMqOMeda0nzMgb88Q05qjZBFCIlZmKc,10239
7
+ tksheet/functions.py,sha256=W2gNUQRFCCZH0gYCNECdl9-HZrhnEMYnxHEY9yl13uw,53058
8
+ tksheet/main_table.py,sha256=OzNnHRcg4JIPuG4Wx5KWe8ZNR0uwVV_78kK1uS9cksg,352912
9
+ tksheet/other_classes.py,sha256=2dMTcH21lDGXXLOO6DmT8HgrhdDOjFC-vo-RlLIv-yk,16603
10
+ tksheet/row_index.py,sha256=1KuU-_7k1Ci97v8RgKT-oSf5wolrQ72-vI8iB3spKo0,134283
11
+ tksheet/sheet.py,sha256=0CqGOrAK8THnyLkvUu3nCP5lubb2AqtNDXeJ7I7XcMI,283928
12
+ tksheet/sheet_options.py,sha256=A_cJEc6XirLO8YrWQHfb10lK2VhGbz28_3XgrKx3TfM,9753
13
+ tksheet/sorting.py,sha256=PGTQBaHyxc4TJ_gws44w9TsX2WSMavdOXN5119YhdZg,16851
14
+ tksheet/text_editor.py,sha256=czGlcJDV9o_jPS4nOlvpjOOs0wkVnK4cGI7PubMMElU,7426
15
+ tksheet/themes.py,sha256=AoNAxibnQi04MN0Zpbn9-kyDnkiiV8TDNWP9FYjpuf0,18473
16
+ tksheet/tksheet_types.py,sha256=8JQVlA6N9jEZTEAytbcyuhOGuNE4fUPxYhTqoidxEE0,588
17
+ tksheet/top_left_rectangle.py,sha256=WHf2FnId1QJ4q2vy9AbMIjAaP-6s9erPqSU5duN9giw,8569
18
+ tksheet-7.4.5.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
19
+ tksheet-7.4.5.dist-info/METADATA,sha256=4gWTvamk5QyT2W7WI1o73xGqjDvCg38zHgTiDHylvnY,8005
20
+ tksheet-7.4.5.dist-info/WHEEL,sha256=nn6H5-ilmfVryoAQl3ZQ2l8SH5imPWFpm1A5FgEuFV4,91
21
+ tksheet-7.4.5.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
22
+ tksheet-7.4.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (75.8.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,22 +0,0 @@
1
- tksheet/__init__.py,sha256=6xbeTomYvgJaGjRKmHAS1YW24Tmc5ZcR7_YmeyJvDnY,2280
2
- tksheet/colors.py,sha256=dHhmdFuQDlwohDHsAfT9VdrKoSl_R33L72a3HCin5zo,51591
3
- tksheet/column_headers.py,sha256=ZfHLhXEKe8M9ggf3nzg252DBVH_NRtQichtTF7pisIc,103245
4
- tksheet/constants.py,sha256=PkvAtdYXSOiOO5zuxqrObvGIVV2sEE0enN8YLhI8zCc,3922
5
- tksheet/find_window.py,sha256=JfkgpGluSng3bKMBneDNQg-AJmBcmCW7JIhtYbSUZaE,8036
6
- tksheet/formatters.py,sha256=21ZkMaDIJNUtjvtlAbPl8Y19I9nDxue-JJegw6hblz8,10551
7
- tksheet/functions.py,sha256=BDCCKdOUF9FRDq9GF7HmRXaZ22PYRDySlo6WLvyZtVA,52806
8
- tksheet/main_table.py,sha256=ChMaI_t5rDwfc5pStG5pxKhqWwKnauJGxa_hoTXq478,357778
9
- tksheet/other_classes.py,sha256=ADybikLipEG4NABXx8bGVAovJJhWcomQOWTorzS1CPU,16581
10
- tksheet/row_index.py,sha256=R6tCsfXnPbblnSU1tvse_fCjx2DG0U-vx-XaiAPdZs0,133195
11
- tksheet/sheet.py,sha256=6hHI_W0rmuV6l2C2jd3fa9pgnNx3kW9k6rY0qqEq-Wg,284585
12
- tksheet/sheet_options.py,sha256=7q5T55sZe_elA3MCP0VnbX_f0Euo425aw4uSoPXteoA,9624
13
- tksheet/sorting.py,sha256=qLusdRmqDUBkcEgK3WcYbFjIJmXNBoDhR-D2yrWC-BI,9895
14
- tksheet/text_editor.py,sha256=ZLVF-0WxDin5qUAJ5r7dmsdwvhyEoxw0PlPvi_AGNPE,7328
15
- tksheet/themes.py,sha256=AoNAxibnQi04MN0Zpbn9-kyDnkiiV8TDNWP9FYjpuf0,18473
16
- tksheet/tksheet_types.py,sha256=8JQVlA6N9jEZTEAytbcyuhOGuNE4fUPxYhTqoidxEE0,588
17
- tksheet/top_left_rectangle.py,sha256=KhTT-rBUwQTgaHjSwL83cL5_71k2L1B7gxkSxZlTSK8,8598
18
- tksheet-7.4.3.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
19
- tksheet-7.4.3.dist-info/METADATA,sha256=36JytEf6SmrgwlyWLnvv1SLYumrDvxH4wDERw-cxTXE,7839
20
- tksheet-7.4.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
21
- tksheet-7.4.3.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
22
- tksheet-7.4.3.dist-info/RECORD,,