sysnet-pyutils 1.0.7__tar.gz → 1.1.0__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.
- {sysnet_pyutils-1.0.7/sysnet_pyutils.egg-info → sysnet_pyutils-1.1.0}/PKG-INFO +23 -2
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/README.md +20 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/pyproject.toml +1 -1
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/requirements.txt +2 -0
- sysnet_pyutils-1.1.0/sysnet_pyutils/data_utils.py +323 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/ident.py +4 -4
- sysnet_pyutils-1.1.0/sysnet_pyutils/models/__init__.py +10 -0
- sysnet_pyutils-1.1.0/sysnet_pyutils/models/general.py +262 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/utils.py +145 -71
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0/sysnet_pyutils.egg-info}/PKG-INFO +23 -2
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils.egg-info/SOURCES.txt +4 -1
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils.egg-info/requires.txt +1 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/LICENSE +0 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/setup.cfg +0 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/__init__.py +0 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/barcode.py +0 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/domino.py +0 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/geo.py +0 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/log.py +0 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/ses.py +0 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/tools.py +0 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils.egg-info/dependency_links.txt +0 -0
- {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: sysnet-pyutils
|
3
|
-
Version: 1.0
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: Python Utilities
|
5
5
|
Author-email: Data Developer <info@sysnet.cz>
|
6
6
|
Project-URL: Homepage, https://github.com/SYSNET-CZ/pyutils
|
@@ -21,6 +21,7 @@ Requires-Dist: xmltodict>=0.13.0
|
|
21
21
|
Requires-Dist: boto3>=1.34.34
|
22
22
|
Requires-Dist: botocore>=1.34.34
|
23
23
|
Requires-Dist: pymongo>=4.7.2
|
24
|
+
Requires-Dist: pydantic>=2.10.6
|
24
25
|
|
25
26
|
# sysnet-pyutils
|
26
27
|
|
@@ -311,6 +312,26 @@ Vhodné pro MongoDB pro ukládání položek typu datum.
|
|
311
312
|
* #### S konfiguračním souborem YAML se nyní pracuje v _UTF-8_
|
312
313
|
|
313
314
|
* #### Nová třída _LoggedObject_
|
315
|
+
--------------------------------------------------------------------------------------------------------------------------------
|
316
|
+
|
317
|
+
### verze 1.0.8
|
318
|
+
|
319
|
+
* #### Nové utility pro práci s daty JSON _data_utils_
|
320
|
+
--------------------------------------------------------------------------------------------------------------------------------
|
321
|
+
|
322
|
+
#### is_valid_email(email: str) -> bool:
|
323
|
+
Kontrola validity emailové adresy
|
324
|
+
* param email: hodnota
|
325
|
+
* return: True/False
|
326
|
+
--------------------------------------------------------------------------------------------------------------------------------
|
327
|
+
|
328
|
+
### verze 1.1.0
|
329
|
+
|
330
|
+
* #### Přidán obecný datový slovník SYSNET do balíku models.general
|
331
|
+
|
332
|
+
Datový slovník je vytvořen pomocí pydantic a je plně kompatibilní s FastAPI.
|
333
|
+
Obsahuje základní datové typy, které se používají ve všech aplikacích SYSNET.
|
334
|
+
|
314
335
|
|
315
336
|
|
316
337
|
## Systémové proměnné
|
@@ -287,6 +287,26 @@ Vhodné pro MongoDB pro ukládání položek typu datum.
|
|
287
287
|
* #### S konfiguračním souborem YAML se nyní pracuje v _UTF-8_
|
288
288
|
|
289
289
|
* #### Nová třída _LoggedObject_
|
290
|
+
--------------------------------------------------------------------------------------------------------------------------------
|
291
|
+
|
292
|
+
### verze 1.0.8
|
293
|
+
|
294
|
+
* #### Nové utility pro práci s daty JSON _data_utils_
|
295
|
+
--------------------------------------------------------------------------------------------------------------------------------
|
296
|
+
|
297
|
+
#### is_valid_email(email: str) -> bool:
|
298
|
+
Kontrola validity emailové adresy
|
299
|
+
* param email: hodnota
|
300
|
+
* return: True/False
|
301
|
+
--------------------------------------------------------------------------------------------------------------------------------
|
302
|
+
|
303
|
+
### verze 1.1.0
|
304
|
+
|
305
|
+
* #### Přidán obecný datový slovník SYSNET do balíku models.general
|
306
|
+
|
307
|
+
Datový slovník je vytvořen pomocí pydantic a je plně kompatibilní s FastAPI.
|
308
|
+
Obsahuje základní datové typy, které se používají ve všech aplikacích SYSNET.
|
309
|
+
|
290
310
|
|
291
311
|
|
292
312
|
## Systémové proměnné
|
@@ -0,0 +1,323 @@
|
|
1
|
+
from datetime import date, datetime
|
2
|
+
from typing import Union, List, Any
|
3
|
+
|
4
|
+
import pytz
|
5
|
+
|
6
|
+
from utils import is_valid_email, TZ
|
7
|
+
|
8
|
+
|
9
|
+
def get_dict_value(data: dict, item_name: str) -> Union[Any, None]:
|
10
|
+
"""
|
11
|
+
Extrahuje hodnotu ze slovníku. Používá se pro load dat JSON do objektů
|
12
|
+
|
13
|
+
:param data: Slovník s daty JSON
|
14
|
+
:param item_name: Název položky
|
15
|
+
:return: Hodnota
|
16
|
+
"""
|
17
|
+
if data is None or item_name in [None, '']:
|
18
|
+
return None
|
19
|
+
if item_name in data:
|
20
|
+
return data[item_name]
|
21
|
+
return None
|
22
|
+
|
23
|
+
|
24
|
+
def get_dict_value_string(data: dict, item_name: str) -> str:
|
25
|
+
"""
|
26
|
+
Extrahuje textovou hodnotu ze slovníku. Pokud je vstupní hodnota None, vrací prázdný string.
|
27
|
+
|
28
|
+
:param data: Slovník s daty JSON
|
29
|
+
:param item_name: Název položky
|
30
|
+
:return: Hodnota
|
31
|
+
"""
|
32
|
+
out = ''
|
33
|
+
if data is None or item_name in [None, '']:
|
34
|
+
return out
|
35
|
+
v = get_dict_value(data, item_name)
|
36
|
+
if v not in [None, '']:
|
37
|
+
out = str(v)
|
38
|
+
return out
|
39
|
+
|
40
|
+
|
41
|
+
def get_dict_value_email(data: dict, item_name: str) -> Union[Any, None]:
|
42
|
+
"""
|
43
|
+
Extrahuje emailovou adresu ze slovníku.
|
44
|
+
|
45
|
+
:param data: Slovník s daty JSON
|
46
|
+
:param item_name: Název položky
|
47
|
+
:return: Hodnota
|
48
|
+
"""
|
49
|
+
if data is None or item_name in [None, '']:
|
50
|
+
return None
|
51
|
+
out = get_dict_value(data, item_name)
|
52
|
+
if not is_valid_email(out):
|
53
|
+
return None
|
54
|
+
return out
|
55
|
+
|
56
|
+
|
57
|
+
def get_dict_value_bool(data: dict, item_name: str) -> bool:
|
58
|
+
"""
|
59
|
+
Extrahuje logickou hodnotu ze slovníku
|
60
|
+
|
61
|
+
:param data: Slovník s daty JSON
|
62
|
+
:param item_name: Název položky
|
63
|
+
:return: Hodnota
|
64
|
+
"""
|
65
|
+
if data is None or item_name in [None, '']:
|
66
|
+
return False
|
67
|
+
v = get_dict_value(data, item_name)
|
68
|
+
if v in [None, '']:
|
69
|
+
return False
|
70
|
+
if v.lower() in ('true', '1', 't'):
|
71
|
+
return True
|
72
|
+
return False
|
73
|
+
|
74
|
+
|
75
|
+
def get_dict_value_int(data: dict, item_name: str, spare_item_name: Union[str, None] = None) -> int:
|
76
|
+
"""
|
77
|
+
Extrahuje celočíselnou hodnotu ze slovníku. Pokud nenajde hlavní položku, hledá záložní.
|
78
|
+
|
79
|
+
:param data: Slovník s daty JSON
|
80
|
+
:param item_name: Název položky
|
81
|
+
:param spare_item_name: Název záložní položky
|
82
|
+
:return: Hodnota
|
83
|
+
"""
|
84
|
+
if data is None or item_name in [None, '']:
|
85
|
+
return 0
|
86
|
+
v = get_dict_value(data, item_name)
|
87
|
+
out = 0
|
88
|
+
if v is not None:
|
89
|
+
try:
|
90
|
+
out = int(v)
|
91
|
+
except (ValueError, TypeError):
|
92
|
+
out = 0
|
93
|
+
if (out == 0) and (spare_item_name is not None):
|
94
|
+
v1 = get_dict_value(data, spare_item_name)
|
95
|
+
if v1 is not None:
|
96
|
+
try:
|
97
|
+
out = int(v1)
|
98
|
+
except (ValueError, TypeError):
|
99
|
+
out = 0
|
100
|
+
return out
|
101
|
+
|
102
|
+
|
103
|
+
def get_dict_value_list(data: dict, item_name: str, spare_item_name: str = None) -> Union[List[str], None]:
|
104
|
+
v = get_dict_value(data, item_name)
|
105
|
+
if v in [None, '']:
|
106
|
+
v = get_dict_value(data, spare_item_name)
|
107
|
+
if v in [None, '']:
|
108
|
+
return None
|
109
|
+
out = [i.strip() for i in v[1:-1].replace('"',"").split(';')]
|
110
|
+
if len(out) == 1 and out[0] == '':
|
111
|
+
out = []
|
112
|
+
return out
|
113
|
+
|
114
|
+
|
115
|
+
def get_dict_value_float(data: dict, item_name: str, spare_item_name: str = None) -> Union[float, None]:
|
116
|
+
v = get_dict_value(data, item_name)
|
117
|
+
out: float = float(0)
|
118
|
+
if v is not None:
|
119
|
+
try:
|
120
|
+
if isinstance(v, str):
|
121
|
+
v = v.replace(',', '.')
|
122
|
+
out = float(v)
|
123
|
+
except (ValueError, TypeError):
|
124
|
+
out = float(0)
|
125
|
+
if (out == float(0)) and (spare_item_name is not None):
|
126
|
+
v1 = get_dict_value(data, spare_item_name)
|
127
|
+
if v1 is not None:
|
128
|
+
try:
|
129
|
+
out = float(v1)
|
130
|
+
except (ValueError, TypeError):
|
131
|
+
out = float(0)
|
132
|
+
return out
|
133
|
+
|
134
|
+
|
135
|
+
def get_dict_value_date(data: dict, item_name: str) -> Union[date, None]:
|
136
|
+
"""
|
137
|
+
Konvertuje ISO nebo český formát do data
|
138
|
+
|
139
|
+
:param data:
|
140
|
+
:param item_name:
|
141
|
+
:return:
|
142
|
+
"""
|
143
|
+
v = get_dict_value(data, item_name)
|
144
|
+
if v is None:
|
145
|
+
return None
|
146
|
+
out = convert_iso_to_date(v)
|
147
|
+
if out is None:
|
148
|
+
out = convert_cz_to_date(v)
|
149
|
+
return out
|
150
|
+
|
151
|
+
|
152
|
+
def convert_iso_to_date(text: str) -> Union[date, None]:
|
153
|
+
try:
|
154
|
+
out = date.fromisoformat(text)
|
155
|
+
return out
|
156
|
+
except (ValueError, TypeError):
|
157
|
+
return None
|
158
|
+
|
159
|
+
|
160
|
+
def convert_iso_to_datetime(text: str) -> Union[datetime, None]:
|
161
|
+
try:
|
162
|
+
out = datetime.fromisoformat(text)
|
163
|
+
local_tz = pytz.timezone(TZ)
|
164
|
+
out = out.astimezone(local_tz)
|
165
|
+
return out
|
166
|
+
except (ValueError, TypeError):
|
167
|
+
return None
|
168
|
+
|
169
|
+
|
170
|
+
def convert_cz_to_date(text: str) -> Union[date, None]:
|
171
|
+
try:
|
172
|
+
out = datetime.strptime(text, '%d.%m.%Y').date()
|
173
|
+
return out
|
174
|
+
except (ValueError, TypeError):
|
175
|
+
return None
|
176
|
+
|
177
|
+
|
178
|
+
def convert_cz_to_datetime(text: str) -> Union[datetime, None]:
|
179
|
+
try:
|
180
|
+
out = datetime.strptime(text, '%d.%m.%Y %H:%M:%S')
|
181
|
+
local_tz = pytz.timezone(TZ)
|
182
|
+
out = out.astimezone(local_tz)
|
183
|
+
return out
|
184
|
+
except (ValueError, TypeError):
|
185
|
+
return None
|
186
|
+
|
187
|
+
|
188
|
+
def get_dict_value_datetime(data: dict, item_name: str) -> Union[datetime, None]:
|
189
|
+
"""
|
190
|
+
Konvertuje ISO nebo český formát do datatime
|
191
|
+
|
192
|
+
:param data:
|
193
|
+
:param item_name:
|
194
|
+
:return:
|
195
|
+
"""
|
196
|
+
v = get_dict_value(data, item_name)
|
197
|
+
out = None
|
198
|
+
if v is None:
|
199
|
+
return None
|
200
|
+
try:
|
201
|
+
if isinstance(v, datetime):
|
202
|
+
return v
|
203
|
+
elif isinstance(v, date):
|
204
|
+
gmt_tz = pytz.timezone('GMT')
|
205
|
+
return datetime(year=v.year, month=v.month, day=v.day, tzinfo=gmt_tz)
|
206
|
+
elif isinstance(v, str):
|
207
|
+
out = convert_iso_to_datetime(v)
|
208
|
+
if out is None:
|
209
|
+
out = convert_cz_to_datetime(v)
|
210
|
+
return out
|
211
|
+
except (ValueError, TypeError):
|
212
|
+
return None
|
213
|
+
|
214
|
+
|
215
|
+
def get_object_attr(obj: Any, attr: str) -> Union[Any, None]:
|
216
|
+
"""
|
217
|
+
Získa hodnotu atributu z datového objektu
|
218
|
+
|
219
|
+
:param obj:
|
220
|
+
:param attr:
|
221
|
+
:return:
|
222
|
+
"""
|
223
|
+
if obj is None:
|
224
|
+
return None
|
225
|
+
if hasattr(obj, attr):
|
226
|
+
return getattr(obj, attr)
|
227
|
+
return None
|
228
|
+
|
229
|
+
|
230
|
+
def get_dict_item_value_list(data: dict, item_name: str, alt_item_names: List[str] = None) -> Union[list, None]:
|
231
|
+
out = []
|
232
|
+
v = get_dict_item_value(data=data, item_name=item_name, alt_item_names=alt_item_names, blank=False)
|
233
|
+
if v is None:
|
234
|
+
return out
|
235
|
+
if isinstance(v, list):
|
236
|
+
out = v
|
237
|
+
else:
|
238
|
+
out.append(v)
|
239
|
+
return out
|
240
|
+
|
241
|
+
|
242
|
+
def get_dict_item_value(data: dict, item_name: str, alt_item_names: List[str] = None, blank=True) -> Union[Any, None]:
|
243
|
+
out = None
|
244
|
+
if blank:
|
245
|
+
out = ''
|
246
|
+
if (data is None) or (item_name is None):
|
247
|
+
return out
|
248
|
+
if item_name in data:
|
249
|
+
out = data[item_name]
|
250
|
+
elif alt_item_names is not None:
|
251
|
+
if alt_item_names:
|
252
|
+
for name in alt_item_names:
|
253
|
+
if name in data:
|
254
|
+
out = data[name]
|
255
|
+
break
|
256
|
+
return out
|
257
|
+
|
258
|
+
|
259
|
+
def get_dict_code_value_list(data: dict, item_name_code: str, item_name_value: str) -> Union[list[tuple[Any, Any]], None]:
|
260
|
+
"""
|
261
|
+
Vrátí z dvojice položek slovníku tuple code/value
|
262
|
+
|
263
|
+
:param data:
|
264
|
+
:param item_name_code:
|
265
|
+
:param item_name_value:
|
266
|
+
:return:
|
267
|
+
"""
|
268
|
+
codes = get_dict_value_list(data, item_name_code)
|
269
|
+
values = get_dict_value_list(data, item_name_value)
|
270
|
+
if not codes or not values:
|
271
|
+
return None
|
272
|
+
if len(codes) != len(values):
|
273
|
+
return None
|
274
|
+
out = []
|
275
|
+
i = 0
|
276
|
+
for c in codes:
|
277
|
+
v = values[i]
|
278
|
+
i += 1
|
279
|
+
out.append((c,v))
|
280
|
+
return out
|
281
|
+
|
282
|
+
def adjust_datetime_to_utc(date_value: Union[date, datetime], for_store: bool = False) -> Union[datetime, date]:
|
283
|
+
"""
|
284
|
+
Nastavení času pro uložení. Použije se časová zóna UTF
|
285
|
+
|
286
|
+
:param date_value: Datová hodnota
|
287
|
+
:param for_store: Pro uložení (převede se vždy na datetime)
|
288
|
+
:return: nastavená hodnota
|
289
|
+
"""
|
290
|
+
if date_value in [None, '']:
|
291
|
+
return date_value
|
292
|
+
if for_store:
|
293
|
+
if isinstance(date_value, date):
|
294
|
+
return datetime(year=date_value.year, month=date_value.month, day=date_value.day, tzinfo=pytz.UTC)
|
295
|
+
if isinstance(date_value, datetime):
|
296
|
+
if date_value.tzinfo is None:
|
297
|
+
date_value.replace(tzinfo=pytz.UTC)
|
298
|
+
return date(year=date_value.year, month=date_value.month, day=date_value.day)
|
299
|
+
return date_value
|
300
|
+
|
301
|
+
|
302
|
+
def dict_convert_date_to_str(data: dict):
|
303
|
+
"""
|
304
|
+
Rekurzivně převede všechny časové položky ve slovníku na ISO text
|
305
|
+
|
306
|
+
:param data: dictionary
|
307
|
+
:return:
|
308
|
+
"""
|
309
|
+
if isinstance(data, dict):
|
310
|
+
for k, v in data.items():
|
311
|
+
if isinstance(v, datetime):
|
312
|
+
if v.tzinfo is None:
|
313
|
+
v_gmt = v.replace(tzinfo=pytz.utc)
|
314
|
+
else:
|
315
|
+
v_gmt = v.astimezone(pytz.utc)
|
316
|
+
data[k] = v_gmt.strftime('%Y-%m-%dT%H:%M:%SZ')
|
317
|
+
elif isinstance(v, dict):
|
318
|
+
dict_convert_date_to_str(v)
|
319
|
+
elif isinstance(v, list):
|
320
|
+
for item in v:
|
321
|
+
dict_convert_date_to_str(item)
|
322
|
+
else:
|
323
|
+
pass
|
@@ -53,7 +53,7 @@ def generate_tiny_uuid():
|
|
53
53
|
return out[-ID_LENGTH:]
|
54
54
|
|
55
55
|
|
56
|
-
def generate_id12(three_char_prefix):
|
56
|
+
def generate_id12(three_char_prefix: str) -> str:
|
57
57
|
"""
|
58
58
|
Vygeneruje 12místný alfanumerický identifikátor s pevným prefixem
|
59
59
|
|
@@ -70,7 +70,7 @@ def generate_id12(three_char_prefix):
|
|
70
70
|
return correct_pid(out)
|
71
71
|
|
72
72
|
|
73
|
-
def check_pid(pid):
|
73
|
+
def check_pid(pid: str) -> bool:
|
74
74
|
"""
|
75
75
|
Kontroluje správnost PID pomocí kontrolního součtu
|
76
76
|
|
@@ -88,7 +88,7 @@ def check_pid(pid):
|
|
88
88
|
return out
|
89
89
|
|
90
90
|
|
91
|
-
def correct_pid(pid):
|
91
|
+
def correct_pid(pid: str) -> str:
|
92
92
|
"""
|
93
93
|
Opraví PID do korektní podoby. Doplní kontrolní součet.
|
94
94
|
|
@@ -103,7 +103,7 @@ def correct_pid(pid):
|
|
103
103
|
return out
|
104
104
|
|
105
105
|
|
106
|
-
def generate_pid():
|
106
|
+
def generate_pid() -> str:
|
107
107
|
"""
|
108
108
|
Vybeneruje nový PID
|
109
109
|
|