invesytoolbox 0.0.22__tar.gz → 0.0.24__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.
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/HISTORY.md +12 -0
- {invesytoolbox-0.0.22/src/invesytoolbox.egg-info → invesytoolbox-0.0.24}/PKG-INFO +15 -3
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/setup.cfg +2 -2
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox/itb_data.py +102 -22
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox/itb_date_time.py +11 -1
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox/itb_email_phone.py +1 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox/itb_html.py +1 -1
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox/itb_text_name.py +50 -2
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24/src/invesytoolbox.egg-info}/PKG-INFO +15 -3
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/tests/test_data.py +50 -9
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/tests/test_text_name.py +33 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/LICENSE.txt +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/README.md +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/setup.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox/__init__.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox/itb_locales.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox/itb_restricted_python.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox/itb_security.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox/itb_www.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox.egg-info/SOURCES.txt +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox.egg-info/dependency_links.txt +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox.egg-info/requires.txt +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox.egg-info/top_level.txt +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/tests/__init__.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/tests/test_date_time.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/tests/test_email_phone.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/tests/test_html.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/tests/test_locales.py +0 -0
- {invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/tests/test_www.py +0 -0
@@ -1,4 +1,16 @@
|
|
1
1
|
# History
|
2
|
+
## 0.0.24 (2024-09-29)
|
3
|
+
**timezone** can be passed as an argument to **dictlist_2datatypes** and **dict_2datatypes**
|
4
|
+
|
5
|
+
## 0.0.23 (2024-07-22)
|
6
|
+
* **adjust_spaces_on_punctuation**: inserts narrow (or normal spaces) for certain languages
|
7
|
+
* **value_2datatype**:
|
8
|
+
- default fmt changed to None (hopefully it doesn't break somewhere, but this is necessary)
|
9
|
+
- 'pendulum' is now an option for the parameter
|
10
|
+
- default for parameter **fmt** changed to None (this is necessary for the new pendulum conversion in **value_2datatype** to work) for
|
11
|
+
- **dict_2datatypes**
|
12
|
+
- **dictlist_2datatypes**
|
13
|
+
|
2
14
|
## 0.0.22 (2023-10-14)
|
3
15
|
* **normalize_name** and **could_be_a_name** now have the boolean parameter *lastname* that indicates that a single-word name is to be treated as a last name, not a first name.
|
4
16
|
* **get_locale**: locale can be only the language, without the country.
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: invesytoolbox
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.24
|
4
4
|
Summary: Tools for Python scripts or terminal
|
5
5
|
Home-page: https://gitlab.com/Rastaf/invesytoolbox
|
6
6
|
Author: Georg Pfolz
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
17
17
|
Classifier: License :: OSI Approved :: MIT License
|
18
18
|
Classifier: Operating System :: OS Independent
|
19
|
-
Requires-Python:
|
19
|
+
Requires-Python: <3.12,>=3.7
|
20
20
|
Description-Content-Type: text/markdown
|
21
21
|
License-File: LICENSE.txt
|
22
22
|
Requires-Dist: bs4
|
@@ -44,6 +44,18 @@ That's also why all date and time functions also take into account the old DateT
|
|
44
44
|
The documentation can be found [here](https://rastaf.gitlab.io/invesytoolbox/).
|
45
45
|
|
46
46
|
# History
|
47
|
+
## 0.0.24 (2024-09-29)
|
48
|
+
**timezone** can be passed as an argument to **dictlist_2datatypes** and **dict_2datatypes**
|
49
|
+
|
50
|
+
## 0.0.23 (2024-07-22)
|
51
|
+
* **adjust_spaces_on_punctuation**: inserts narrow (or normal spaces) for certain languages
|
52
|
+
* **value_2datatype**:
|
53
|
+
- default fmt changed to None (hopefully it doesn't break somewhere, but this is necessary)
|
54
|
+
- 'pendulum' is now an option for the parameter
|
55
|
+
- default for parameter **fmt** changed to None (this is necessary for the new pendulum conversion in **value_2datatype** to work) for
|
56
|
+
- **dict_2datatypes**
|
57
|
+
- **dictlist_2datatypes**
|
58
|
+
|
47
59
|
## 0.0.22 (2023-10-14)
|
48
60
|
* **normalize_name** and **could_be_a_name** now have the boolean parameter *lastname* that indicates that a single-word name is to be treated as a last name, not a first name.
|
49
61
|
* **get_locale**: locale can be only the language, without the country.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[metadata]
|
2
2
|
name = invesytoolbox
|
3
|
-
version = 0.0.
|
3
|
+
version = 0.0.24
|
4
4
|
author = Georg Pfolz
|
5
5
|
author_email = georg.pfolz@invesy.at
|
6
6
|
description = Tools for Python scripts or terminal
|
@@ -26,7 +26,7 @@ classifiers =
|
|
26
26
|
package_dir =
|
27
27
|
= src
|
28
28
|
packages = find:
|
29
|
-
python_requires = >=3.7
|
29
|
+
python_requires = >=3.7,<3.12
|
30
30
|
install_requires =
|
31
31
|
bs4
|
32
32
|
babel
|
@@ -8,6 +8,7 @@ from typing import Union, List, Dict, Any, Optional
|
|
8
8
|
import DateTime
|
9
9
|
import datetime
|
10
10
|
import vobject
|
11
|
+
import pendulum
|
11
12
|
from dateutil.parser import parse
|
12
13
|
from itb_date_time import convert_datetime, str_to_date, str_to_DT, get_dateformat
|
13
14
|
from itb_email_phone import process_phonenumber
|
@@ -35,12 +36,10 @@ def any_2boolean(
|
|
35
36
|
def dict_from_dict_list(
|
36
37
|
dict_list: List[dict],
|
37
38
|
key: str,
|
38
|
-
single_value: Optional[
|
39
|
+
single_value: Optional[str] = None,
|
39
40
|
include_key: Optional[bool] = False
|
40
41
|
) -> dict:
|
41
|
-
"""Create a dictionary from a list of dictionaries
|
42
|
-
|
43
|
-
.. note:: The annotated return type is not true if a single_value argument is given.
|
42
|
+
""" Create a dictionary from a list of dictionaries
|
44
43
|
|
45
44
|
:param dictList: the list of dictionaries to be converted
|
46
45
|
:param key: the key of the dictionaries to use as key for the new dictionary.
|
@@ -70,7 +69,7 @@ def create_vcard(
|
|
70
69
|
data: Dict[str, str],
|
71
70
|
returning: str = 'vcard'
|
72
71
|
) -> str:
|
73
|
-
"""create a vCard from a dictionary
|
72
|
+
""" create a vCard from a dictionary
|
74
73
|
|
75
74
|
.. note:: The serialized vcard has Windows line-breaks, which is fine, I guess
|
76
75
|
.. note:: colons in notes are escaped in vobject
|
@@ -134,7 +133,7 @@ def dict_2unicode(
|
|
134
133
|
d: Dict[Union[str, bytes], Any],
|
135
134
|
encoding: str = 'utf-8'
|
136
135
|
) -> dict:
|
137
|
-
"""
|
136
|
+
""" Convert all keys and values in a dictionary from bytes to unicode
|
138
137
|
|
139
138
|
All keys and values are changed from bytes to unicode, if applicable.
|
140
139
|
Other data types are left unchaged, including other compound data types.
|
@@ -156,9 +155,29 @@ def dict_2datatypes(
|
|
156
155
|
convert_keys: bool = False,
|
157
156
|
convert_to_unicode: bool = False,
|
158
157
|
dt: str = 'datetime',
|
159
|
-
fmt: str =
|
158
|
+
fmt: str = None,
|
159
|
+
timezone: str = 'local'
|
160
160
|
) -> Dict[Any, Any]:
|
161
|
-
"""
|
161
|
+
""" Convert all data of a dictionary to specific (json metadata) or guessed types
|
162
|
+
|
163
|
+
:param d: dictionary
|
164
|
+
:param metadata: dictionary containing types for the keys:
|
165
|
+
- boolean
|
166
|
+
- int
|
167
|
+
- float
|
168
|
+
- date
|
169
|
+
- datetime: date and time
|
170
|
+
- time: conversion or not based on dt
|
171
|
+
:param convert_keys: convert keys to unicode
|
172
|
+
:param convert_to_unicode: convert all bytes to unicode in the process
|
173
|
+
:param dt: - datetime or dt
|
174
|
+
- DateTime or DT
|
175
|
+
- ignore or string
|
176
|
+
- pendulum
|
177
|
+
- default: datetime, because it's Python's default
|
178
|
+
:param fmt: format for datetime parsing
|
179
|
+
:param timezone: default is 'local', other options are 'UTC' or 'Europe/Vienna'
|
180
|
+
"""
|
162
181
|
|
163
182
|
if convert_keys:
|
164
183
|
return {
|
@@ -173,7 +192,8 @@ def dict_2datatypes(
|
|
173
192
|
key=key,
|
174
193
|
convert_to_unicode=convert_to_unicode,
|
175
194
|
dt=dt,
|
176
|
-
fmt=fmt
|
195
|
+
fmt=fmt,
|
196
|
+
timezone=timezone
|
177
197
|
)
|
178
198
|
for key, val in d.items()
|
179
199
|
} # dict comprehension
|
@@ -185,7 +205,8 @@ def dict_2datatypes(
|
|
185
205
|
key=key,
|
186
206
|
convert_to_unicode=convert_to_unicode,
|
187
207
|
dt=dt,
|
188
|
-
fmt=fmt
|
208
|
+
fmt=fmt,
|
209
|
+
timezone=timezone
|
189
210
|
)
|
190
211
|
for key, val in d.items()
|
191
212
|
} # dict comprehension
|
@@ -197,15 +218,38 @@ def dictlist_2datatypes(
|
|
197
218
|
convert_keys: bool = False,
|
198
219
|
convert_to_unicode: bool = False,
|
199
220
|
dt: str = 'datetime',
|
200
|
-
fmt: str =
|
221
|
+
fmt: str = None,
|
222
|
+
timezone: str = 'local'
|
201
223
|
) -> list:
|
224
|
+
""" Convert all data of a list of dictionaries to specific (json metadata) or guessed types
|
225
|
+
|
226
|
+
:param dictList: list of dictionaries
|
227
|
+
:param metadata: dictionary containing types for the keys:
|
228
|
+
- boolean
|
229
|
+
- int
|
230
|
+
- float
|
231
|
+
- date
|
232
|
+
- datetime: date and time
|
233
|
+
- time: conversion or not based on dt
|
234
|
+
:param convert_keys: convert keys to unicode
|
235
|
+
:param convert_to_unicode: convert all bytes to unicode in the process
|
236
|
+
:param dt: - datetime or dt
|
237
|
+
- DateTime or DT
|
238
|
+
- ignore or string
|
239
|
+
- pendulum
|
240
|
+
- default: datetime, because it's Python's default
|
241
|
+
:param fmt: format for datetime parsing
|
242
|
+
:param timezone: default is 'local', other options are 'UTC' or 'Europe/Vienna'
|
243
|
+
"""
|
202
244
|
return [
|
203
245
|
dict_2datatypes(
|
204
246
|
d=dic,
|
205
247
|
metadata=metadata,
|
206
248
|
convert_keys=convert_keys,
|
207
249
|
convert_to_unicode=convert_to_unicode,
|
208
|
-
dt=dt
|
250
|
+
dt=dt,
|
251
|
+
fmt=fmt,
|
252
|
+
timezone=timezone
|
209
253
|
)
|
210
254
|
for dic
|
211
255
|
in dictlist
|
@@ -258,17 +302,18 @@ def value_2datatype(
|
|
258
302
|
convert_to_unicode: bool = False,
|
259
303
|
encoding: str = 'utf-8',
|
260
304
|
dt: str = 'datetime',
|
261
|
-
fmt: str =
|
262
|
-
|
305
|
+
fmt: str = None,
|
306
|
+
timezone: str = 'local'
|
263
307
|
) -> Union[str, int, float]:
|
264
308
|
""" Convert a value to a datatype
|
265
309
|
|
266
310
|
this function has two modes:
|
267
311
|
|
268
|
-
1.
|
312
|
+
1. a type is provided for the conversion
|
269
313
|
2. it makes educated guesses in converting a string
|
270
314
|
|
271
315
|
:param value:
|
316
|
+
:param typ: type for the conversion
|
272
317
|
:param metadata: dictionary containing types for the keys:
|
273
318
|
- boolean
|
274
319
|
- int
|
@@ -281,7 +326,10 @@ def value_2datatype(
|
|
281
326
|
:param encoding: if bytes are present, use this encoding to convert them to unicode
|
282
327
|
:param dt: - datetime or dt
|
283
328
|
- DateTime or DT
|
329
|
+
- ignore or string
|
330
|
+
- pendulum
|
284
331
|
- default: datetime, because it's Python's default
|
332
|
+
:param timezone: default is 'local', other options are 'UTC' or 'Europe/Vienna'
|
285
333
|
"""
|
286
334
|
if typ:
|
287
335
|
if typ == 'boolean':
|
@@ -311,6 +359,17 @@ def value_2datatype(
|
|
311
359
|
value,
|
312
360
|
datefmt='international'
|
313
361
|
) + 0.5 # to avoid day-shifting due to timezones, use 12am
|
362
|
+
elif dt == 'pendulum':
|
363
|
+
if fmt:
|
364
|
+
p_dt = pendulum.from_format(value, fmt)
|
365
|
+
else:
|
366
|
+
p_dt = pendulum.parse(value)
|
367
|
+
|
368
|
+
if p_dt.tzinfo == 'UTC' and timezone == 'local':
|
369
|
+
return p_dt.in_tz(pendulum.local_timezone())
|
370
|
+
elif timezone:
|
371
|
+
return p_dt.in_tz(timezone)
|
372
|
+
return p_dt.date()
|
314
373
|
elif dt in ('ignore', 'string'):
|
315
374
|
return value
|
316
375
|
else:
|
@@ -327,6 +386,17 @@ def value_2datatype(
|
|
327
386
|
)
|
328
387
|
except DateTime.interfaces.SyntaxError:
|
329
388
|
return value
|
389
|
+
elif dt == 'pendulum':
|
390
|
+
if fmt:
|
391
|
+
p_dt = pendulum.from_format(value, fmt)
|
392
|
+
else:
|
393
|
+
p_dt = pendulum.parse(value)
|
394
|
+
|
395
|
+
if p_dt.tzinfo == 'UTC' and timezone == 'local':
|
396
|
+
return p_dt.in_tz(pendulum.local_timezone())
|
397
|
+
elif timezone:
|
398
|
+
return p_dt.in_tz(timezone)
|
399
|
+
return p_dt
|
330
400
|
elif dt in ('ignore', 'string'):
|
331
401
|
return value
|
332
402
|
else:
|
@@ -339,7 +409,6 @@ def value_2datatype(
|
|
339
409
|
return value # DT: return the string
|
340
410
|
|
341
411
|
else:
|
342
|
-
|
343
412
|
if isinstance(value, (bool, int, float)):
|
344
413
|
return value
|
345
414
|
|
@@ -373,12 +442,7 @@ def value_2datatype(
|
|
373
442
|
datestring=value,
|
374
443
|
checkonly=True
|
375
444
|
):
|
376
|
-
if '
|
377
|
-
return convert_datetime(
|
378
|
-
date=value,
|
379
|
-
convert_to=dt
|
380
|
-
)
|
381
|
-
elif dt in ('datetime', 'dt'):
|
445
|
+
if dt in ('datetime', 'dt'):
|
382
446
|
return str_to_date(
|
383
447
|
datestring=value
|
384
448
|
)
|
@@ -386,6 +450,22 @@ def value_2datatype(
|
|
386
450
|
return str_to_DT(
|
387
451
|
datestring=value
|
388
452
|
)
|
453
|
+
elif dt == 'pendulum':
|
454
|
+
if fmt:
|
455
|
+
p_dt = pendulum.from_format(value, fmt)
|
456
|
+
else:
|
457
|
+
p_dt = pendulum.parse(value)
|
458
|
+
|
459
|
+
if p_dt.tzinfo == 'UTC' and timezone == 'local':
|
460
|
+
return p_dt.in_tz(pendulum.local_timezone())
|
461
|
+
elif timezone:
|
462
|
+
return p_dt.in_tz(timezone)
|
463
|
+
return p_dt
|
464
|
+
else:
|
465
|
+
return convert_datetime(
|
466
|
+
date=value,
|
467
|
+
convert_to=dt
|
468
|
+
)
|
389
469
|
|
390
470
|
except Exception:
|
391
471
|
# in case it's a subset of datetime_chars but not a date or datetime or time
|
@@ -37,6 +37,8 @@ def is_valid_datetime_string(
|
|
37
37
|
a conflict with 4-digit year values, it is considered invalid
|
38
38
|
|
39
39
|
:param returning: can return a tuple
|
40
|
+
|
41
|
+
.. note:: This does not work with ISO8601 strings! (returns False)
|
40
42
|
"""
|
41
43
|
return str_to_dt(
|
42
44
|
datestring=datestring,
|
@@ -57,6 +59,14 @@ def get_dateformat(
|
|
57
59
|
:todo: times!
|
58
60
|
:raises ValueError: if an invalid datetime or DateTime string is provided
|
59
61
|
"""
|
62
|
+
# first let's check for ISO8601 strings
|
63
|
+
if checkonly:
|
64
|
+
try:
|
65
|
+
pendulum.parse(datestring)
|
66
|
+
return True
|
67
|
+
except pendulum.parsing.exceptions.ParserError:
|
68
|
+
pass # don't return False, because it may be a valid date string
|
69
|
+
|
60
70
|
timefmt = ''
|
61
71
|
if ' ' in datestring:
|
62
72
|
try:
|
@@ -225,7 +235,7 @@ def str_to_pendulum(
|
|
225
235
|
if not fmt:
|
226
236
|
return pendulum.parse(datestring)
|
227
237
|
else:
|
228
|
-
return pendulum.
|
238
|
+
return pendulum.from_format(datestring, fmt)
|
229
239
|
|
230
240
|
|
231
241
|
def str_to_date(
|
@@ -15,7 +15,7 @@ def prettify_html(
|
|
15
15
|
|
16
16
|
.. note:: This function is needed for Zope Python Scripts
|
17
17
|
because even if bs4 can be imported, prettify throws
|
18
|
-
an Unauthorized error in
|
18
|
+
an Unauthorized error in Restricted Python
|
19
19
|
"""
|
20
20
|
|
21
21
|
return BeautifulSoup(html, "html.parser").prettify()
|
@@ -14,7 +14,7 @@ from nameparser import HumanName
|
|
14
14
|
d = gender.Detector(case_sensitive=False)
|
15
15
|
|
16
16
|
|
17
|
-
|
17
|
+
CHAR_NB_MAP = {
|
18
18
|
'a': ('a', '4', '@'),
|
19
19
|
'b': ('b', '6', '8', 'I3', '13', '!3'),
|
20
20
|
'c': ('c', '('),
|
@@ -43,6 +43,54 @@ char_nb_map = {
|
|
43
43
|
'z': ('z', '2', '7_')
|
44
44
|
}
|
45
45
|
|
46
|
+
# regex pattern
|
47
|
+
LANG_PUNCT_SPACES = {
|
48
|
+
'fr': {
|
49
|
+
'regex': r'([!?:;%])',
|
50
|
+
'narrow': '\u202f\\1',
|
51
|
+
'normal': r' \1'
|
52
|
+
},
|
53
|
+
'es': {
|
54
|
+
'regex': r'([¿¡])',
|
55
|
+
'narrow': '\\1\u202f',
|
56
|
+
'normal': r'\1 '
|
57
|
+
},
|
58
|
+
'ro': {
|
59
|
+
'regex': r'([!?:;])',
|
60
|
+
'narrow': '\u202f\\1',
|
61
|
+
'normal': r' \1'
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
def adjust_spaces_on_punctuation(
|
66
|
+
text: str,
|
67
|
+
language: str,
|
68
|
+
space: str = 'narrow'
|
69
|
+
):
|
70
|
+
"""
|
71
|
+
Adjust spaces before or after punctuation marks according to the language.
|
72
|
+
By default the narrow space (\u202f) is used for adjustments.
|
73
|
+
"""
|
74
|
+
# Step 1: Remove existing spaces before the punctuation
|
75
|
+
text = re.sub(r'\s+([!?:;%\),.])', r'\1', text)
|
76
|
+
|
77
|
+
lang_data = LANG_PUNCT_SPACES.get(language)
|
78
|
+
|
79
|
+
if lang_data:
|
80
|
+
# Step 2: Add a narrow space (\u202f) before the punctuation
|
81
|
+
try:
|
82
|
+
text = re.sub(
|
83
|
+
lang_data['regex'],
|
84
|
+
lang_data[space],
|
85
|
+
text
|
86
|
+
)
|
87
|
+
except re.error as e:
|
88
|
+
raise Exception(f"Error in regex for language {language}: {e}")
|
89
|
+
else:
|
90
|
+
# Original behavior for other languages
|
91
|
+
text = re.sub(r'\s+([,.!?;:\)])', r'\1', text)
|
92
|
+
return text
|
93
|
+
|
46
94
|
|
47
95
|
def and_list(
|
48
96
|
elements: list,
|
@@ -202,7 +250,7 @@ def leet(
|
|
202
250
|
if not c.isalnum():
|
203
251
|
continue # without counting
|
204
252
|
|
205
|
-
c = random.choice(
|
253
|
+
c = random.choice(CHAR_NB_MAP[c])
|
206
254
|
|
207
255
|
if not random.randrange(change_uppercase):
|
208
256
|
c = c.upper()
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: invesytoolbox
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.24
|
4
4
|
Summary: Tools for Python scripts or terminal
|
5
5
|
Home-page: https://gitlab.com/Rastaf/invesytoolbox
|
6
6
|
Author: Georg Pfolz
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
17
17
|
Classifier: License :: OSI Approved :: MIT License
|
18
18
|
Classifier: Operating System :: OS Independent
|
19
|
-
Requires-Python:
|
19
|
+
Requires-Python: <3.12,>=3.7
|
20
20
|
Description-Content-Type: text/markdown
|
21
21
|
License-File: LICENSE.txt
|
22
22
|
Requires-Dist: bs4
|
@@ -44,6 +44,18 @@ That's also why all date and time functions also take into account the old DateT
|
|
44
44
|
The documentation can be found [here](https://rastaf.gitlab.io/invesytoolbox/).
|
45
45
|
|
46
46
|
# History
|
47
|
+
## 0.0.24 (2024-09-29)
|
48
|
+
**timezone** can be passed as an argument to **dictlist_2datatypes** and **dict_2datatypes**
|
49
|
+
|
50
|
+
## 0.0.23 (2024-07-22)
|
51
|
+
* **adjust_spaces_on_punctuation**: inserts narrow (or normal spaces) for certain languages
|
52
|
+
* **value_2datatype**:
|
53
|
+
- default fmt changed to None (hopefully it doesn't break somewhere, but this is necessary)
|
54
|
+
- 'pendulum' is now an option for the parameter
|
55
|
+
- default for parameter **fmt** changed to None (this is necessary for the new pendulum conversion in **value_2datatype** to work) for
|
56
|
+
- **dict_2datatypes**
|
57
|
+
- **dictlist_2datatypes**
|
58
|
+
|
47
59
|
## 0.0.22 (2023-10-14)
|
48
60
|
* **normalize_name** and **could_be_a_name** now have the boolean parameter *lastname* that indicates that a single-word name is to be treated as a last name, not a first name.
|
49
61
|
* **get_locale**: locale can be only the language, without the country.
|
@@ -8,18 +8,21 @@ import sys
|
|
8
8
|
import unittest
|
9
9
|
import datetime
|
10
10
|
import DateTime
|
11
|
+
import pendulum
|
11
12
|
from dateutil.parser import parse
|
12
13
|
|
13
14
|
sys.path.append(".")
|
14
15
|
|
15
|
-
from itb_data import
|
16
|
-
any_2boolean,
|
17
|
-
create_vcard,
|
18
|
-
dict_2unicode,
|
19
|
-
dict_2datatypes,
|
20
|
-
dict_from_dict_list,
|
21
|
-
dictlist_2datatypes,
|
22
|
-
sort_dictlist
|
16
|
+
from itb_data import (
|
17
|
+
any_2boolean,
|
18
|
+
create_vcard,
|
19
|
+
dict_2unicode,
|
20
|
+
dict_2datatypes,
|
21
|
+
dict_from_dict_list,
|
22
|
+
dictlist_2datatypes,
|
23
|
+
sort_dictlist,
|
24
|
+
value_2datatype
|
25
|
+
)
|
23
26
|
|
24
27
|
dict_list = [
|
25
28
|
{'a': 1, 'b': 2, 'c': 5},
|
@@ -154,6 +157,9 @@ END:VCARD
|
|
154
157
|
|
155
158
|
|
156
159
|
class TestData(unittest.TestCase):
|
160
|
+
# verbose, show complete diff
|
161
|
+
maxDiff = None
|
162
|
+
|
157
163
|
def test_any_2boolean(self):
|
158
164
|
for a, b in test_boolean.items():
|
159
165
|
self.assertEqual(
|
@@ -260,7 +266,28 @@ class TestData(unittest.TestCase):
|
|
260
266
|
)
|
261
267
|
|
262
268
|
def test_value_2datatype(self):
|
263
|
-
|
269
|
+
# this is already tested extensively in test_dict_2datatypes
|
270
|
+
# so we just test pendulum here
|
271
|
+
print('test_value_2datatype: this should result in pendulum datetimes')
|
272
|
+
value = '01.04.2022 10:32'
|
273
|
+
fmt = 'DD.MM.YYYY HH:mm'
|
274
|
+
|
275
|
+
p = value_2datatype(
|
276
|
+
value=value,
|
277
|
+
typ='datetime',
|
278
|
+
dt='pendulum',
|
279
|
+
fmt=fmt
|
280
|
+
)
|
281
|
+
print(value, '→', p, p.tzinfo)
|
282
|
+
|
283
|
+
value = '2024-04-01T10:32:00'
|
284
|
+
|
285
|
+
p = value_2datatype(
|
286
|
+
value=value,
|
287
|
+
dt='pendulum'
|
288
|
+
)
|
289
|
+
print(value, '→', p, p.tzinfo)
|
290
|
+
|
264
291
|
|
265
292
|
def test_sort_dictlist(self):
|
266
293
|
sorted_dict_list = sort_dictlist(
|
@@ -297,6 +324,10 @@ class TestData(unittest.TestCase):
|
|
297
324
|
)
|
298
325
|
|
299
326
|
def test_dictlist_2datatypes(self):
|
327
|
+
# print('dict_for_testing', dict_for_testing)
|
328
|
+
# print('dict_for_testing_datatyped_unicoded', dict_for_testing_datatyped_unicoded)
|
329
|
+
|
330
|
+
|
300
331
|
dictlist_for_testing = [
|
301
332
|
dict_for_testing,
|
302
333
|
dict_for_testing,
|
@@ -323,6 +354,16 @@ class TestData(unittest.TestCase):
|
|
323
354
|
dictlist_tested_datatyped
|
324
355
|
)
|
325
356
|
|
357
|
+
dictlist_pendulum = dictlist_2datatypes(
|
358
|
+
dictlist=dictlist_for_testing,
|
359
|
+
convert_keys=True,
|
360
|
+
convert_to_unicode=True,
|
361
|
+
dt='pendulum',
|
362
|
+
fmt='DD.MM.YYYY'
|
363
|
+
)
|
364
|
+
|
365
|
+
print('dictlist_pendulum', dictlist_pendulum)
|
366
|
+
|
326
367
|
|
327
368
|
if __name__ == '__main__':
|
328
369
|
unittest.main()
|
@@ -11,6 +11,7 @@ import random
|
|
11
11
|
sys.path.append(".")
|
12
12
|
|
13
13
|
from itb_text_name import (
|
14
|
+
adjust_spaces_on_punctuation,
|
14
15
|
and_list,
|
15
16
|
capitalize_name,
|
16
17
|
get_gender,
|
@@ -295,8 +296,40 @@ reference_names_sorted = [
|
|
295
296
|
|
296
297
|
lower_text = 'das ist ein Beispiel-Text, der kapitalisiert werden kann.'
|
297
298
|
|
299
|
+
# Language Texts (for adjusting spaces on the indentation)
|
300
|
+
punct_texts = {
|
301
|
+
'de': "Hallo Welt ! Wie geht es Ihnen ? Ich hoffe, Sie haben einen schönen Tag : Das Wetter ist herrlich . Wussten Sie, dass 75 % aller Statistiken erfunden sind?",
|
302
|
+
'en': "Hello world ! How are you today ? I hope you're having a great day : The weather is lovely . Did you know that 80 % of all statistics are made up?",
|
303
|
+
'fr': "Bonjour le monde! Comment allez-vous aujourd'hui? J'espère que vous passez une bonne journée: Le temps est magnifique . Saviez-vous que 85% des statistiques sont inventées?",
|
304
|
+
'es': "¡Hola mundo! ¿Cómo estás hoy ? Espero que tengas un buen día : El clima es hermoso. ¿Sabías que el 90 % de las estadísticas son inventadas ?",
|
305
|
+
'ro': "Salut lume! Cum ești azi? Sper că ai o zi bună: Vremea este minunată.Știai că 95 % din statistici sunt inventate?"
|
306
|
+
}
|
307
|
+
|
308
|
+
punct_texts_corrected = {
|
309
|
+
'de': "Hallo Welt! Wie geht es Ihnen? Ich hoffe, Sie haben einen schönen Tag: Das Wetter ist herrlich. Wussten Sie, dass 75% aller Statistiken erfunden sind?",
|
310
|
+
'en': "Hello world! How are you today? I hope you're having a great day: The weather is lovely. Did you know that 80% of all statistics are made up?",
|
311
|
+
'fr': "Bonjour le monde\u202f! Comment allez-vous aujourd'hui\u202f? J'espère que vous passez une bonne journée\u202f: Le temps est magnifique. Saviez-vous que 85\u202f% des statistiques sont inventées\u202f?",
|
312
|
+
'es': "¡\u202fHola mundo! ¿\u202fCómo estás hoy? Espero que tengas un buen día: El clima es hermoso. ¿\u202fSabías que el 90% de las estadísticas son inventadas?",
|
313
|
+
'ro': "Salut lume\u202f! Cum ești azi\u202f? Sper că ai o zi bună\u202f: Vremea este minunată.Știai că 95% din statistici sunt inventate\u202f?"
|
314
|
+
}
|
298
315
|
|
299
316
|
class TestTextName(unittest.TestCase):
|
317
|
+
def test_adjust_spaces_on_punctuation(self):
|
318
|
+
for lang, text in punct_texts.items():
|
319
|
+
print(f'Language: {lang}')
|
320
|
+
try:
|
321
|
+
corrected_text = adjust_spaces_on_punctuation(
|
322
|
+
text = text,
|
323
|
+
language = lang
|
324
|
+
)
|
325
|
+
except Exception as e:
|
326
|
+
print(f'Error: {e}')
|
327
|
+
raise AssertionError(f'Error: {e}')
|
328
|
+
self.assertEqual(
|
329
|
+
corrected_text,
|
330
|
+
punct_texts_corrected[lang]
|
331
|
+
)
|
332
|
+
|
300
333
|
def test_and_list(self):
|
301
334
|
a_list = [1, 'Georg', 'Haus', True]
|
302
335
|
correct_str = '1, Georg, Haus and True'
|
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
|
{invesytoolbox-0.0.22 → invesytoolbox-0.0.24}/src/invesytoolbox.egg-info/dependency_links.txt
RENAMED
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
|