tksheet 7.4.0__tar.gz → 7.4.1__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.0/tksheet.egg-info → tksheet-7.4.1}/PKG-INFO +1 -4
  2. {tksheet-7.4.0 → tksheet-7.4.1}/README.md +0 -3
  3. {tksheet-7.4.0 → tksheet-7.4.1}/pyproject.toml +1 -1
  4. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/__init__.py +1 -1
  5. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/main_table.py +40 -28
  6. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/sorting.py +13 -95
  7. {tksheet-7.4.0 → tksheet-7.4.1/tksheet.egg-info}/PKG-INFO +1 -4
  8. {tksheet-7.4.0 → tksheet-7.4.1}/LICENSE.txt +0 -0
  9. {tksheet-7.4.0 → tksheet-7.4.1}/setup.cfg +0 -0
  10. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/colors.py +0 -0
  11. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/column_headers.py +0 -0
  12. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/constants.py +0 -0
  13. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/find_window.py +0 -0
  14. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/formatters.py +0 -0
  15. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/functions.py +0 -0
  16. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/other_classes.py +0 -0
  17. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/row_index.py +0 -0
  18. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/sheet.py +0 -0
  19. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/sheet_options.py +0 -0
  20. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/text_editor.py +0 -0
  21. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/themes.py +0 -0
  22. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/tksheet_types.py +0 -0
  23. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet/top_left_rectangle.py +0 -0
  24. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet.egg-info/SOURCES.txt +0 -0
  25. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet.egg-info/dependency_links.txt +0 -0
  26. {tksheet-7.4.0 → tksheet-7.4.1}/tksheet.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tksheet
3
- Version: 7.4.0
3
+ Version: 7.4.1
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
@@ -82,8 +82,6 @@ License-File: LICENSE.txt
82
82
  </tbody>
83
83
  </table>
84
84
 
85
- This library is maintained with the help of **[others](https://github.com/ragardner/tksheet/graphs/contributors)**. If you would like to contribute please read this [help section](https://github.com/ragardner/tksheet/wiki/Version-7#contributing).
86
-
87
85
  ## **Features**
88
86
 
89
87
  - Smoothly display and modify tabular data
@@ -95,7 +93,6 @@ This library is maintained with the help of **[others](https://github.com/ragard
95
93
  - [Expand row heights and column widths](https://github.com/ragardner/tksheet/wiki/Version-7#table-functionality-and-bindings)
96
94
  - [Change fonts and font size (not for individual cells)](https://github.com/ragardner/tksheet/wiki/Version-7#text-font-and-alignment)
97
95
  - [Change any colors in the sheet](https://github.com/ragardner/tksheet/wiki/Version-7#sheet-appearance)
98
-
99
96
  - [Dropdown boxes](https://github.com/ragardner/tksheet/wiki/Version-7#dropdown-boxes)
100
97
  - [Check boxes](https://github.com/ragardner/tksheet/wiki/Version-7#check-boxes)
101
98
  - [Progress bars](https://github.com/ragardner/tksheet/wiki/Version-7#progress-bars)
@@ -39,8 +39,6 @@
39
39
  </tbody>
40
40
  </table>
41
41
 
42
- This library is maintained with the help of **[others](https://github.com/ragardner/tksheet/graphs/contributors)**. If you would like to contribute please read this [help section](https://github.com/ragardner/tksheet/wiki/Version-7#contributing).
43
-
44
42
  ## **Features**
45
43
 
46
44
  - Smoothly display and modify tabular data
@@ -52,7 +50,6 @@ This library is maintained with the help of **[others](https://github.com/ragard
52
50
  - [Expand row heights and column widths](https://github.com/ragardner/tksheet/wiki/Version-7#table-functionality-and-bindings)
53
51
  - [Change fonts and font size (not for individual cells)](https://github.com/ragardner/tksheet/wiki/Version-7#text-font-and-alignment)
54
52
  - [Change any colors in the sheet](https://github.com/ragardner/tksheet/wiki/Version-7#sheet-appearance)
55
-
56
53
  - [Dropdown boxes](https://github.com/ragardner/tksheet/wiki/Version-7#dropdown-boxes)
57
54
  - [Check boxes](https://github.com/ragardner/tksheet/wiki/Version-7#check-boxes)
58
55
  - [Progress bars](https://github.com/ragardner/tksheet/wiki/Version-7#progress-bars)
@@ -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.0"
9
+ version = "7.4.1"
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.0"
7
+ __version__ = "7.4.1"
8
8
 
9
9
  from .colors import (
10
10
  color_map,
@@ -275,31 +275,21 @@ class MainTable(tk.Canvas):
275
275
  self.all_columns_displayed = True
276
276
  self.all_rows_displayed = True
277
277
  self.align = kwargs["align"]
278
-
279
- self.PAR.ops.table_font = [
278
+ self.PAR.ops.table_font = FontTuple(
280
279
  self.PAR.ops.table_font[0],
281
- int(self.PAR.ops.table_font[1] * kwargs["zoom"] / 100),
280
+ max(1, int(self.PAR.ops.table_font[1] * kwargs["zoom"] / 100)),
282
281
  self.PAR.ops.table_font[2],
283
- ]
284
-
285
- self.PAR.ops.index_font = [
282
+ )
283
+ self.PAR.ops.index_font = FontTuple(
286
284
  self.PAR.ops.index_font[0],
287
- int(self.PAR.ops.index_font[1] * kwargs["zoom"] / 100),
285
+ max(1, int(self.PAR.ops.index_font[1] * kwargs["zoom"] / 100)),
288
286
  self.PAR.ops.index_font[2],
289
- ]
290
-
291
- self.PAR.ops.header_font = [
287
+ )
288
+ self.PAR.ops.header_font = FontTuple(
292
289
  self.PAR.ops.header_font[0],
293
- int(self.PAR.ops.header_font[1] * kwargs["zoom"] / 100),
290
+ max(1, int(self.PAR.ops.header_font[1] * kwargs["zoom"] / 100)),
294
291
  self.PAR.ops.header_font[2],
295
- ]
296
- for fnt in (self.PAR.ops.table_font, self.PAR.ops.index_font, self.PAR.ops.header_font):
297
- if fnt[1] < 1:
298
- fnt[1] = 1
299
- self.PAR.ops.table_font = FontTuple(*self.PAR.ops.table_font)
300
- self.PAR.ops.index_font = FontTuple(*self.PAR.ops.index_font)
301
- self.PAR.ops.header_font = FontTuple(*self.PAR.ops.header_font)
302
-
292
+ )
303
293
  self.txt_measure_canvas = tk.Canvas(self)
304
294
  self.txt_measure_canvas_text = self.txt_measure_canvas.create_text(0, 0, text="", font=self.PAR.ops.table_font)
305
295
 
@@ -1155,7 +1145,7 @@ class MainTable(tk.Canvas):
1155
1145
  if ctr:
1156
1146
  event_data = self.add_rows(
1157
1147
  rows=rows,
1158
- index=index,
1148
+ index=index if isinstance(self._row_index, list) and self._row_index else {},
1159
1149
  row_heights=row_heights,
1160
1150
  event_data=event_data,
1161
1151
  mod_event_boxes=False,
@@ -1205,7 +1195,7 @@ class MainTable(tk.Canvas):
1205
1195
  if ctr:
1206
1196
  event_data = self.add_columns(
1207
1197
  columns=columns,
1208
- header=headers,
1198
+ header=headers if isinstance(self._headers, list) and self._headers else {},
1209
1199
  column_widths=column_widths,
1210
1200
  event_data=event_data,
1211
1201
  mod_event_boxes=False,
@@ -5009,8 +4999,11 @@ class MainTable(tk.Canvas):
5009
4999
  event_data = self.new_event_dict("add_columns", state=True)
5010
5000
  if not try_binding(self.extra_begin_insert_cols_rc_func, event_data, "begin_add_columns"):
5011
5001
  return
5002
+ columns, headers, widths = self.get_args_for_add_columns(data_ins_col, displayed_ins_col, numcols)
5012
5003
  event_data = self.add_columns(
5013
- *self.get_args_for_add_columns(data_ins_col, displayed_ins_col, numcols),
5004
+ columns=columns,
5005
+ header=headers if isinstance(self._headers, list) and self._headers else {},
5006
+ column_widths=widths,
5014
5007
  event_data=event_data,
5015
5008
  )
5016
5009
  if self.undo_enabled:
@@ -5138,8 +5131,11 @@ class MainTable(tk.Canvas):
5138
5131
  event_data = self.new_event_dict("add_rows", state=True)
5139
5132
  if not try_binding(self.extra_begin_insert_rows_rc_func, event_data, "begin_add_rows"):
5140
5133
  return
5134
+ rows, index, heights = self.get_args_for_add_rows(data_ins_row, displayed_ins_row, numrows)
5141
5135
  event_data = self.add_rows(
5142
- *self.get_args_for_add_rows(data_ins_row, displayed_ins_row, numrows),
5136
+ rows=rows,
5137
+ index=index if isinstance(self._row_index, list) and self._row_index else {},
5138
+ row_heights=heights,
5143
5139
  event_data=event_data,
5144
5140
  )
5145
5141
  if self.undo_enabled:
@@ -5346,12 +5342,22 @@ class MainTable(tk.Canvas):
5346
5342
  return event_data
5347
5343
  if not ext and not try_binding(self.extra_begin_del_cols_rc_func, event_data, "begin_delete_columns"):
5348
5344
  return
5345
+ if self.all_columns_displayed:
5346
+ data_columns = columns
5347
+ disp_columns = columns
5348
+ else:
5349
+ if data_indexes:
5350
+ data_columns = columns
5351
+ disp_columns = data_to_displayed_idxs(data_columns, self.displayed_columns)
5352
+ else:
5353
+ data_columns = [self.displayed_columns[c] for c in columns]
5354
+ disp_columns = columns
5349
5355
  event_data = self.delete_columns_displayed(
5350
- data_to_displayed_idxs(columns, self.MT.displayed_columns) if data_indexes else columns,
5356
+ disp_columns,
5351
5357
  event_data,
5352
5358
  )
5353
5359
  event_data = self.delete_columns_data(
5354
- columns if data_indexes or self.all_columns_displayed else [self.displayed_columns[c] for c in columns],
5360
+ data_columns,
5355
5361
  event_data,
5356
5362
  )
5357
5363
  if undo and self.undo_enabled:
@@ -5425,10 +5431,16 @@ class MainTable(tk.Canvas):
5425
5431
  return
5426
5432
  if not ext and not try_binding(self.extra_begin_del_rows_rc_func, event_data, "begin_delete_rows"):
5427
5433
  return
5428
- if data_indexes or self.all_rows_displayed:
5434
+ if self.all_rows_displayed:
5429
5435
  data_rows = rows
5436
+ disp_rows = rows
5430
5437
  else:
5431
- data_rows = [self.displayed_rows[r] for r in rows]
5438
+ if data_indexes:
5439
+ data_rows = rows
5440
+ disp_rows = data_to_displayed_idxs(data_rows, self.displayed_rows)
5441
+ else:
5442
+ data_rows = [self.displayed_rows[r] for r in rows]
5443
+ disp_rows = rows
5432
5444
  if self.PAR.ops.treeview:
5433
5445
  data_rows = sorted(
5434
5446
  chain(
@@ -5441,7 +5453,7 @@ class MainTable(tk.Canvas):
5441
5453
  )
5442
5454
  )
5443
5455
  event_data = self.delete_rows_displayed(
5444
- data_to_displayed_idxs(data_rows, self.displayed_rows) if self.PAR.ops.treeview or data_indexes else rows,
5456
+ disp_rows,
5445
5457
  event_data,
5446
5458
  )
5447
5459
  event_data = self.delete_rows_data(
@@ -1,9 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- import re
4
- import unittest
5
3
  from collections.abc import Callable, Generator
6
4
  from datetime import datetime
5
+ from re import finditer
7
6
 
8
7
  from .other_classes import Node
9
8
  from .tksheet_types import AnyIter
@@ -59,8 +58,6 @@ def natural_sort_key(item: object) -> tuple[int, object]:
59
58
  - Strings with natural sorting for embedded numbers and dates
60
59
  - Unknown types treated as strings or left at the end
61
60
 
62
- With love from Grok ❤️
63
-
64
61
  Args:
65
62
  item: Any Python object to be sorted.
66
63
 
@@ -68,39 +65,42 @@ def natural_sort_key(item: object) -> tuple[int, object]:
68
65
  A tuple or value that can be used for sorting.
69
66
  """
70
67
  if item is None:
71
- return (0, "")
68
+ return (0,)
72
69
 
73
70
  elif isinstance(item, bool):
74
71
  return (1, item)
75
72
 
76
73
  elif isinstance(item, (int, float)):
77
- return (2, (item,)) # Tuple to ensure float and int are sorted together
74
+ return (2, item)
78
75
 
79
76
  elif isinstance(item, datetime):
80
77
  return (3, item.timestamp())
81
78
 
82
79
  elif isinstance(item, str):
83
- # Check if the whole string is a date
84
80
  for date_format in date_formats:
85
81
  try:
86
- # Use the same sort order as for datetime objects
87
82
  return (3, datetime.strptime(item, date_format).timestamp())
88
83
  except ValueError:
89
84
  continue
90
85
 
91
- # Check if the whole string is a number
92
86
  try:
93
- return (4, float(item))
87
+ return (2, float(item))
94
88
  except Exception:
95
- # Proceed with natural sorting
96
- return (5, tuple(int(text) if text.isdigit() else text.lower() for text in re.split(r"(\d+)", item)))
89
+ n = []
90
+ s = []
91
+ for match in finditer(r"\d+|[^\d\s]+", item):
92
+ if (m := match.group()).isdigit():
93
+ n.append(int(m))
94
+ else:
95
+ s.append(m.lower())
96
+ return (5, s, n)
97
97
 
98
98
  else:
99
99
  # For unknown types, attempt to convert to string, or place at end
100
100
  try:
101
101
  return (6, f"{item}".lower())
102
102
  except Exception:
103
- return (7, item) # If conversion fails, place at the very end
103
+ return (7, item)
104
104
 
105
105
 
106
106
  def sort_selection(
@@ -285,85 +285,3 @@ def sort_tree_view(
285
285
  new_index += 1
286
286
 
287
287
  return sorted_nodes, mapping
288
-
289
-
290
- class TestNaturalSort(unittest.TestCase):
291
- def test_none_first(self):
292
- self.assertEqual(natural_sort_key(None), (0, ""))
293
-
294
- def test_booleans_order(self):
295
- self.assertLess(natural_sort_key(False), natural_sort_key(True))
296
-
297
- def test_numbers_order(self):
298
- self.assertLess(natural_sort_key(5), natural_sort_key(10))
299
- self.assertLess(natural_sort_key(5.5), natural_sort_key(6))
300
-
301
- def test_datetime_order(self):
302
- dt1 = datetime(2023, 1, 1)
303
- dt2 = datetime(2023, 1, 2)
304
- self.assertLess(natural_sort_key(dt1), natural_sort_key(dt2))
305
-
306
- def test_string_natural_sort(self):
307
- items = ["item2", "item10", "item1"]
308
- sorted_items = sorted(items, key=natural_sort_key)
309
- self.assertEqual(sorted_items, ["item1", "item2", "item10"])
310
-
311
- def test_date_string_recognition(self):
312
- # Test various date formats
313
- date_str1 = "01/01/2023"
314
- date_str2 = "2023-01-01"
315
- date_str3 = "Jan 1, 2023"
316
-
317
- dt = datetime(2023, 1, 1)
318
-
319
- self.assertEqual(natural_sort_key(date_str1)[0], 3)
320
- self.assertEqual(natural_sort_key(date_str2)[0], 3)
321
- self.assertEqual(natural_sort_key(date_str3)[0], 3)
322
- self.assertEqual(natural_sort_key(date_str1)[1], natural_sort_key(dt)[1]) # Timestamps should match
323
-
324
- def test_unknown_types(self):
325
- # Here we use a custom class for testing unknown types
326
- class Unknown:
327
- pass
328
-
329
- unknown = Unknown()
330
- self.assertEqual(natural_sort_key(unknown)[0], 5) # Success case, string conversion works
331
-
332
- def test_unknown_types_failure(self):
333
- # Create an object where string conversion fails
334
- class Unconvertible:
335
- def __str__(self):
336
- raise Exception("String conversion fails")
337
-
338
- def __repr__(self):
339
- raise Exception("String conversion fails")
340
-
341
- unconvertible = Unconvertible()
342
- self.assertEqual(natural_sort_key(unconvertible)[0], 6) # Failure case, string conversion fails
343
-
344
-
345
- def test_sort_selection():
346
- # Test case 1: Mixed types, no reverse
347
- data1 = [[1, "b"], [3, "a"]]
348
- sorted_data1 = sort_selection(data1)
349
- print(f"Test 1 - No reverse: {data1} -> {sorted_data1}")
350
-
351
- # Test case 2: Mixed types, with reverse
352
- data2 = [[1, "b"], [3, "a"]]
353
- sorted_data2 = sort_selection(data2, reverse=True)
354
- print(f"Test 2 - With reverse: {data2} -> {sorted_data2}")
355
-
356
- # Test case 3: All numbers
357
- data3 = [[2, 1], [4, 3]]
358
- sorted_data3 = sort_selection(data3)
359
- print(f"Test 3 - All numbers: {data3} -> {sorted_data3}")
360
-
361
- # Test case 4: With None values
362
- data4 = [[None, "b"], ["a", None]]
363
- sorted_data4 = sort_selection(data4)
364
- print(f"Test 4 - With None: {data4} -> {sorted_data4}")
365
-
366
-
367
- if __name__ == "__main__":
368
- test_sort_selection()
369
- unittest.main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tksheet
3
- Version: 7.4.0
3
+ Version: 7.4.1
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
@@ -82,8 +82,6 @@ License-File: LICENSE.txt
82
82
  </tbody>
83
83
  </table>
84
84
 
85
- This library is maintained with the help of **[others](https://github.com/ragardner/tksheet/graphs/contributors)**. If you would like to contribute please read this [help section](https://github.com/ragardner/tksheet/wiki/Version-7#contributing).
86
-
87
85
  ## **Features**
88
86
 
89
87
  - Smoothly display and modify tabular data
@@ -95,7 +93,6 @@ This library is maintained with the help of **[others](https://github.com/ragard
95
93
  - [Expand row heights and column widths](https://github.com/ragardner/tksheet/wiki/Version-7#table-functionality-and-bindings)
96
94
  - [Change fonts and font size (not for individual cells)](https://github.com/ragardner/tksheet/wiki/Version-7#text-font-and-alignment)
97
95
  - [Change any colors in the sheet](https://github.com/ragardner/tksheet/wiki/Version-7#sheet-appearance)
98
-
99
96
  - [Dropdown boxes](https://github.com/ragardner/tksheet/wiki/Version-7#dropdown-boxes)
100
97
  - [Check boxes](https://github.com/ragardner/tksheet/wiki/Version-7#check-boxes)
101
98
  - [Progress bars](https://github.com/ragardner/tksheet/wiki/Version-7#progress-bars)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes