tksheet 7.4.4__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 +84 -86
- tksheet/constants.py +4 -3
- tksheet/find_window.py +8 -8
- tksheet/formatters.py +58 -74
- tksheet/functions.py +65 -79
- tksheet/main_table.py +330 -448
- tksheet/other_classes.py +19 -25
- tksheet/row_index.py +114 -92
- tksheet/sheet.py +191 -208
- tksheet/sorting.py +23 -22
- tksheet/text_editor.py +18 -12
- tksheet/tksheet_types.py +187 -0
- tksheet/top_left_rectangle.py +18 -18
- {tksheet-7.4.4.dist-info → tksheet-7.4.6.dist-info}/METADATA +4 -2
- tksheet-7.4.6.dist-info/RECORD +22 -0
- {tksheet-7.4.4.dist-info → tksheet-7.4.6.dist-info}/WHEEL +1 -1
- tksheet-7.4.4.dist-info/RECORD +0 -22
- {tksheet-7.4.4.dist-info → tksheet-7.4.6.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.4.4.dist-info → tksheet-7.4.6.dist-info}/top_level.txt +0 -0
tksheet/formatters.py
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from collections.abc import Callable
|
4
|
+
from contextlib import suppress
|
5
|
+
from typing import Any
|
4
6
|
|
5
7
|
from .constants import falsy, nonelike, truthy
|
6
8
|
|
7
9
|
|
8
|
-
def is_none_like(o:
|
9
|
-
|
10
|
-
return True
|
11
|
-
return False
|
10
|
+
def is_none_like(o: Any) -> bool:
|
11
|
+
return (isinstance(o, str) and o.lower().replace(" ", "") in nonelike) or o in nonelike
|
12
12
|
|
13
13
|
|
14
|
-
def to_int(o:
|
14
|
+
def to_int(o: Any, **kwargs) -> int:
|
15
15
|
if isinstance(o, int):
|
16
16
|
return o
|
17
17
|
return int(float(o))
|
18
18
|
|
19
19
|
|
20
|
-
def to_float(o:
|
20
|
+
def to_float(o: Any, **kwargs) -> float:
|
21
21
|
if isinstance(o, float):
|
22
22
|
return o
|
23
23
|
return float(o)
|
24
24
|
|
25
25
|
|
26
|
-
def to_percentage(o:
|
26
|
+
def to_percentage(o: Any, **kwargs) -> float:
|
27
27
|
if isinstance(o, float):
|
28
28
|
return o
|
29
29
|
if isinstance(o, str) and o.endswith("%"):
|
@@ -31,7 +31,7 @@ def to_percentage(o: object, **kwargs) -> float:
|
|
31
31
|
return float(o)
|
32
32
|
|
33
33
|
|
34
|
-
def alt_to_percentage(o:
|
34
|
+
def alt_to_percentage(o: Any, **kwargs) -> float:
|
35
35
|
if isinstance(o, float):
|
36
36
|
return o
|
37
37
|
if isinstance(o, str) and o.endswith("%"):
|
@@ -39,21 +39,12 @@ def alt_to_percentage(o: object, **kwargs) -> float:
|
|
39
39
|
return float(o)
|
40
40
|
|
41
41
|
|
42
|
-
def to_bool(val:
|
42
|
+
def to_bool(val: Any, **kwargs) -> bool:
|
43
43
|
if isinstance(val, bool):
|
44
44
|
return val
|
45
|
-
if isinstance(val, str)
|
46
|
-
|
47
|
-
|
48
|
-
v = val
|
49
|
-
if "truthy" in kwargs:
|
50
|
-
_truthy = kwargs["truthy"]
|
51
|
-
else:
|
52
|
-
_truthy = truthy
|
53
|
-
if "falsy" in kwargs:
|
54
|
-
_falsy = kwargs["falsy"]
|
55
|
-
else:
|
56
|
-
_falsy = falsy
|
45
|
+
v = val.lower() if isinstance(val, str) else val
|
46
|
+
_truthy = kwargs.get("truthy", truthy)
|
47
|
+
_falsy = kwargs.get("falsy", falsy)
|
57
48
|
if v in _truthy:
|
58
49
|
return True
|
59
50
|
elif v in _falsy:
|
@@ -61,14 +52,14 @@ def to_bool(val: object, **kwargs) -> bool:
|
|
61
52
|
raise ValueError(f'Cannot map "{val}" to bool.')
|
62
53
|
|
63
54
|
|
64
|
-
def try_to_bool(o:
|
55
|
+
def try_to_bool(o: Any, **kwargs) -> Any:
|
65
56
|
try:
|
66
57
|
return to_bool(o)
|
67
58
|
except Exception:
|
68
59
|
return o
|
69
60
|
|
70
61
|
|
71
|
-
def is_bool_like(o:
|
62
|
+
def is_bool_like(o: Any, **kwargs) -> bool:
|
72
63
|
try:
|
73
64
|
to_bool(o)
|
74
65
|
return True
|
@@ -76,11 +67,11 @@ def is_bool_like(o: object, **kwargs) -> bool:
|
|
76
67
|
return False
|
77
68
|
|
78
69
|
|
79
|
-
def to_str(o:
|
70
|
+
def to_str(o: Any, **kwargs: dict) -> str:
|
80
71
|
return f"{o}"
|
81
72
|
|
82
73
|
|
83
|
-
def float_to_str(v:
|
74
|
+
def float_to_str(v: Any, **kwargs: dict) -> str:
|
84
75
|
if isinstance(v, float):
|
85
76
|
if v.is_integer():
|
86
77
|
return f"{int(v)}"
|
@@ -91,7 +82,7 @@ def float_to_str(v: object, **kwargs: dict) -> str:
|
|
91
82
|
return f"{v}"
|
92
83
|
|
93
84
|
|
94
|
-
def percentage_to_str(v:
|
85
|
+
def percentage_to_str(v: Any, **kwargs: dict) -> str:
|
95
86
|
if isinstance(v, (int, float)):
|
96
87
|
x = v * 100
|
97
88
|
if isinstance(x, float):
|
@@ -105,16 +96,16 @@ def percentage_to_str(v: object, **kwargs: dict) -> str:
|
|
105
96
|
return f"{v}%"
|
106
97
|
|
107
98
|
|
108
|
-
def alt_percentage_to_str(v:
|
99
|
+
def alt_percentage_to_str(v: Any, **kwargs: dict) -> str:
|
109
100
|
return f"{float_to_str(v)}%"
|
110
101
|
|
111
102
|
|
112
|
-
def bool_to_str(v:
|
103
|
+
def bool_to_str(v: Any, **kwargs: dict) -> str:
|
113
104
|
return f"{v}"
|
114
105
|
|
115
106
|
|
116
107
|
def int_formatter(
|
117
|
-
datatypes: tuple[
|
108
|
+
datatypes: tuple[Any] | Any = int,
|
118
109
|
format_function: Callable = to_int,
|
119
110
|
to_str_function: Callable = to_str,
|
120
111
|
**kwargs,
|
@@ -128,7 +119,7 @@ def int_formatter(
|
|
128
119
|
|
129
120
|
|
130
121
|
def float_formatter(
|
131
|
-
datatypes: tuple[
|
122
|
+
datatypes: tuple[Any] | Any = float,
|
132
123
|
format_function: Callable = to_float,
|
133
124
|
to_str_function: Callable = float_to_str,
|
134
125
|
decimals: int = 2,
|
@@ -144,7 +135,7 @@ def float_formatter(
|
|
144
135
|
|
145
136
|
|
146
137
|
def percentage_formatter(
|
147
|
-
datatypes: tuple[
|
138
|
+
datatypes: tuple[Any] | Any = float,
|
148
139
|
format_function: Callable = to_percentage,
|
149
140
|
to_str_function: Callable = percentage_to_str,
|
150
141
|
decimals: int = 2,
|
@@ -160,12 +151,12 @@ def percentage_formatter(
|
|
160
151
|
|
161
152
|
|
162
153
|
def bool_formatter(
|
163
|
-
datatypes: tuple[
|
154
|
+
datatypes: tuple[Any] | Any = bool,
|
164
155
|
format_function: Callable = to_bool,
|
165
156
|
to_str_function: Callable = bool_to_str,
|
166
|
-
invalid_value:
|
167
|
-
truthy_values: set[
|
168
|
-
falsy_values: set[
|
157
|
+
invalid_value: Any = "NA",
|
158
|
+
truthy_values: set[Any] = truthy,
|
159
|
+
falsy_values: set[Any] = falsy,
|
169
160
|
**kwargs,
|
170
161
|
) -> dict:
|
171
162
|
return formatter(
|
@@ -180,10 +171,10 @@ def bool_formatter(
|
|
180
171
|
|
181
172
|
|
182
173
|
def formatter(
|
183
|
-
datatypes: tuple[
|
174
|
+
datatypes: tuple[Any] | Any,
|
184
175
|
format_function: Callable,
|
185
176
|
to_str_function: Callable = to_str,
|
186
|
-
invalid_value:
|
177
|
+
invalid_value: Any = "NaN",
|
187
178
|
nullable: bool = True,
|
188
179
|
pre_format_function: Callable | None = None,
|
189
180
|
post_format_function: Callable | None = None,
|
@@ -191,48 +182,46 @@ def formatter(
|
|
191
182
|
**kwargs,
|
192
183
|
) -> dict:
|
193
184
|
return {
|
194
|
-
**
|
195
|
-
datatypes
|
196
|
-
format_function
|
197
|
-
to_str_function
|
198
|
-
invalid_value
|
199
|
-
nullable
|
200
|
-
pre_format_function
|
201
|
-
post_format_function
|
202
|
-
clipboard_function
|
203
|
-
|
185
|
+
**{
|
186
|
+
"datatypes": datatypes,
|
187
|
+
"format_function": format_function,
|
188
|
+
"to_str_function": to_str_function,
|
189
|
+
"invalid_value": invalid_value,
|
190
|
+
"nullable": nullable,
|
191
|
+
"pre_format_function": pre_format_function,
|
192
|
+
"post_format_function": post_format_function,
|
193
|
+
"clipboard_function": clipboard_function,
|
194
|
+
},
|
204
195
|
**kwargs,
|
205
196
|
}
|
206
197
|
|
207
198
|
|
208
199
|
def format_data(
|
209
|
-
value:
|
210
|
-
datatypes: tuple[
|
200
|
+
value: Any = "",
|
201
|
+
datatypes: tuple[Any] | Any = int,
|
211
202
|
nullable: bool = True,
|
212
203
|
pre_format_function: Callable | None = None,
|
213
204
|
format_function: Callable | None = to_int,
|
214
205
|
post_format_function: Callable | None = None,
|
215
206
|
**kwargs,
|
216
|
-
) ->
|
207
|
+
) -> Any:
|
217
208
|
if pre_format_function:
|
218
209
|
value = pre_format_function(value)
|
219
210
|
if nullable and is_none_like(value):
|
220
211
|
value = None
|
221
212
|
else:
|
222
|
-
|
213
|
+
with suppress(Exception):
|
223
214
|
value = format_function(value, **kwargs)
|
224
|
-
except Exception:
|
225
|
-
pass
|
226
215
|
if post_format_function and isinstance(value, datatypes):
|
227
216
|
value = post_format_function(value)
|
228
217
|
return value
|
229
218
|
|
230
219
|
|
231
220
|
def data_to_str(
|
232
|
-
value:
|
233
|
-
datatypes: tuple[
|
221
|
+
value: Any = "",
|
222
|
+
datatypes: tuple[Any] | Any = int,
|
234
223
|
nullable: bool = True,
|
235
|
-
invalid_value:
|
224
|
+
invalid_value: Any = "NaN",
|
236
225
|
to_str_function: Callable | None = None,
|
237
226
|
**kwargs,
|
238
227
|
) -> str:
|
@@ -243,13 +232,13 @@ def data_to_str(
|
|
243
232
|
return to_str_function(value, **kwargs)
|
244
233
|
|
245
234
|
|
246
|
-
def get_data_with_valid_check(value="", datatypes: tuple[()] | tuple[
|
235
|
+
def get_data_with_valid_check(value="", datatypes: tuple[()] | tuple[Any] | Any = (), invalid_value="NA"):
|
247
236
|
if isinstance(value, datatypes):
|
248
237
|
return value
|
249
238
|
return invalid_value
|
250
239
|
|
251
240
|
|
252
|
-
def get_clipboard_data(value:
|
241
|
+
def get_clipboard_data(value: Any = "", clipboard_function: Callable | None = None, **kwargs: dict) -> Any:
|
253
242
|
if clipboard_function is not None:
|
254
243
|
return clipboard_function(value, **kwargs)
|
255
244
|
if isinstance(value, (str, int, float, bool)):
|
@@ -260,9 +249,8 @@ def get_clipboard_data(value: object = "", clipboard_function: Callable | None =
|
|
260
249
|
class Formatter:
|
261
250
|
def __init__(
|
262
251
|
self,
|
263
|
-
value:
|
264
|
-
datatypes: tuple[
|
265
|
-
object=int,
|
252
|
+
value: Any,
|
253
|
+
datatypes: tuple[Any],
|
266
254
|
format_function: Callable = to_int,
|
267
255
|
to_str_function: Callable = to_str,
|
268
256
|
nullable: bool = True,
|
@@ -274,12 +262,10 @@ class Formatter:
|
|
274
262
|
) -> None:
|
275
263
|
if nullable:
|
276
264
|
if isinstance(datatypes, (list, tuple)):
|
277
|
-
datatypes = tuple(
|
265
|
+
datatypes = tuple(set(datatypes) | {type(None)})
|
278
266
|
else:
|
279
267
|
datatypes = (datatypes, type(None))
|
280
|
-
elif isinstance(datatypes, (list, tuple)) and type(None) in datatypes:
|
281
|
-
raise TypeError("Non-nullable cells cannot have NoneType as a datatype.")
|
282
|
-
elif datatypes is type(None):
|
268
|
+
elif isinstance(datatypes, (list, tuple)) and type(None) in datatypes or datatypes is type(None):
|
283
269
|
raise TypeError("Non-nullable cells cannot have NoneType as a datatype.")
|
284
270
|
self.kwargs = kwargs
|
285
271
|
self.valid_datatypes = datatypes
|
@@ -295,21 +281,19 @@ class Formatter:
|
|
295
281
|
except Exception:
|
296
282
|
self.value = f"{value}"
|
297
283
|
|
298
|
-
def __str__(self) ->
|
284
|
+
def __str__(self) -> Any:
|
299
285
|
if not self.valid():
|
300
286
|
return self.invalid_value
|
301
287
|
if self.value is None and self.nullable:
|
302
288
|
return ""
|
303
289
|
return self.to_str_function(self.value, **self.kwargs)
|
304
290
|
|
305
|
-
def valid(self, value:
|
291
|
+
def valid(self, value: Any = None) -> bool:
|
306
292
|
if value is None:
|
307
293
|
value = self.value
|
308
|
-
|
309
|
-
return True
|
310
|
-
return False
|
294
|
+
return isinstance(value, self.valid_datatypes)
|
311
295
|
|
312
|
-
def format_data(self, value:
|
296
|
+
def format_data(self, value: Any) -> Any:
|
313
297
|
if self.pre_format_function:
|
314
298
|
value = self.pre_format_function(value)
|
315
299
|
value = None if (self.nullable and is_none_like(value)) else self.format_function(value, **self.kwargs)
|
@@ -317,19 +301,19 @@ class Formatter:
|
|
317
301
|
value = self.post_format_function(value)
|
318
302
|
return value
|
319
303
|
|
320
|
-
def get_data_with_valid_check(self) ->
|
304
|
+
def get_data_with_valid_check(self) -> Any:
|
321
305
|
if self.valid():
|
322
306
|
return self.value
|
323
307
|
return self.invalid_value
|
324
308
|
|
325
|
-
def get_clipboard_data(self) ->
|
309
|
+
def get_clipboard_data(self) -> Any:
|
326
310
|
if self.clipboard_function is not None:
|
327
311
|
return self.clipboard_function(self.value, **self.kwargs)
|
328
312
|
if isinstance(self.value, (int, float, bool)):
|
329
313
|
return self.value
|
330
314
|
return self.__str__()
|
331
315
|
|
332
|
-
def __eq__(self, __value:
|
316
|
+
def __eq__(self, __value: Any) -> bool:
|
333
317
|
# in case of custom formatter class
|
334
318
|
# compare the values
|
335
319
|
try:
|