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.
Files changed (23) hide show
  1. {sysnet_pyutils-1.0.7/sysnet_pyutils.egg-info → sysnet_pyutils-1.1.0}/PKG-INFO +23 -2
  2. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/README.md +20 -0
  3. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/pyproject.toml +1 -1
  4. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/requirements.txt +2 -0
  5. sysnet_pyutils-1.1.0/sysnet_pyutils/data_utils.py +323 -0
  6. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/ident.py +4 -4
  7. sysnet_pyutils-1.1.0/sysnet_pyutils/models/__init__.py +10 -0
  8. sysnet_pyutils-1.1.0/sysnet_pyutils/models/general.py +262 -0
  9. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/utils.py +145 -71
  10. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0/sysnet_pyutils.egg-info}/PKG-INFO +23 -2
  11. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils.egg-info/SOURCES.txt +4 -1
  12. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils.egg-info/requires.txt +1 -0
  13. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/LICENSE +0 -0
  14. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/setup.cfg +0 -0
  15. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/__init__.py +0 -0
  16. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/barcode.py +0 -0
  17. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/domino.py +0 -0
  18. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/geo.py +0 -0
  19. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/log.py +0 -0
  20. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/ses.py +0 -0
  21. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils/tools.py +0 -0
  22. {sysnet_pyutils-1.0.7 → sysnet_pyutils-1.1.0}/sysnet_pyutils.egg-info/dependency_links.txt +0 -0
  23. {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
1
+ Metadata-Version: 2.2
2
2
  Name: sysnet-pyutils
3
- Version: 1.0.7
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é
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sysnet-pyutils"
7
- version = "1.0.7"
7
+ version = "1.1.0"
8
8
  authors = [
9
9
  { name="Data Developer", email="info@sysnet.cz" },
10
10
  ]
@@ -6,3 +6,5 @@ xmltodict>=0.13.0
6
6
  boto3>=1.34.34
7
7
  botocore>=1.34.34
8
8
  pymongo>=4.7.2
9
+
10
+ pydantic>=2.10.6
@@ -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
 
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ File name:
6
+ Author: "SYSNET s.r.o."<rjaeger@sysnet.cz>
7
+ Created:
8
+ Version: 1.0.0
9
+ Description:
10
+ """