lyrpy 2025.0.1__py3-none-any.whl → 2025.0.2__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.

Potentially problematic release.


This version of lyrpy might be problematic. Click here for more details.

Files changed (109) hide show
  1. SRC/LIB/__init__.py +21 -0
  2. SRC/lyrpy/LUConsole.py +402 -0
  3. SRC/lyrpy/LUConst.py +358 -0
  4. SRC/lyrpy/LUDateTime.py +205 -0
  5. SRC/lyrpy/LUDecotators.py +417 -0
  6. SRC/lyrpy/LUDict.py +116 -0
  7. SRC/lyrpy/LUDoc.py +62 -0
  8. SRC/lyrpy/LUErrors.py +79 -0
  9. SRC/lyrpy/LUFile.py +1228 -0
  10. SRC/lyrpy/LUFileUtils.py +501 -0
  11. SRC/lyrpy/LULog.py +2324 -0
  12. SRC/lyrpy/LUNetwork.py +277 -0
  13. SRC/lyrpy/LUNumUtils.py +305 -0
  14. SRC/lyrpy/LUObjects.py +208 -0
  15. SRC/lyrpy/LUObjectsYT.py +846 -0
  16. SRC/lyrpy/LUParserARG.py +364 -0
  17. SRC/lyrpy/LUParserINI.py +376 -0
  18. SRC/lyrpy/LUParserREG.py +514 -0
  19. SRC/lyrpy/LUProc.py +110 -0
  20. SRC/lyrpy/LUQThread.py +141 -0
  21. SRC/lyrpy/LUQTimer.py +197 -0
  22. SRC/lyrpy/LUSheduler.py +941 -0
  23. SRC/lyrpy/LUStrDecode.py +223 -0
  24. SRC/lyrpy/LUStrUtils.py +633 -0
  25. SRC/lyrpy/LUSupport.py +124 -0
  26. SRC/lyrpy/LUTelegram.py +428 -0
  27. SRC/lyrpy/LUThread.py +177 -0
  28. SRC/lyrpy/LUTimer.py +141 -0
  29. SRC/lyrpy/LUVersion.py +383 -0
  30. SRC/lyrpy/LUYouTube.py +203 -0
  31. SRC/lyrpy/LUos.py +807 -0
  32. SRC/lyrpy/LUsys.py +47 -0
  33. SRC/lyrpy/__init__.py +21 -0
  34. SRC/lyrpy/__main__.py +20 -0
  35. __SRC/LIB/__init__.py +0 -0
  36. __SRC/LIB/lyrpy/LUConsole.py +402 -0
  37. __SRC/LIB/lyrpy/LUConst.py +358 -0
  38. __SRC/LIB/lyrpy/LUDateTime.py +205 -0
  39. __SRC/LIB/lyrpy/LUDecotators.py +417 -0
  40. __SRC/LIB/lyrpy/LUDict.py +116 -0
  41. __SRC/LIB/lyrpy/LUDoc.py +62 -0
  42. __SRC/LIB/lyrpy/LUErrors.py +79 -0
  43. __SRC/LIB/lyrpy/LUFile.py +1228 -0
  44. __SRC/LIB/lyrpy/LUFileUtils.py +501 -0
  45. __SRC/LIB/lyrpy/LULog.py +2324 -0
  46. __SRC/LIB/lyrpy/LUNetwork.py +277 -0
  47. __SRC/LIB/lyrpy/LUNumUtils.py +305 -0
  48. __SRC/LIB/lyrpy/LUObjects.py +208 -0
  49. __SRC/LIB/lyrpy/LUObjectsYT.py +846 -0
  50. __SRC/LIB/lyrpy/LUParserARG.py +364 -0
  51. __SRC/LIB/lyrpy/LUParserINI.py +376 -0
  52. __SRC/LIB/lyrpy/LUParserREG.py +514 -0
  53. __SRC/LIB/lyrpy/LUProc.py +110 -0
  54. __SRC/LIB/lyrpy/LUQThread.py +141 -0
  55. __SRC/LIB/lyrpy/LUQTimer.py +197 -0
  56. __SRC/LIB/lyrpy/LUSheduler.py +941 -0
  57. __SRC/LIB/lyrpy/LUStrDecode.py +223 -0
  58. __SRC/LIB/lyrpy/LUStrUtils.py +633 -0
  59. __SRC/LIB/lyrpy/LUSupport.py +124 -0
  60. __SRC/LIB/lyrpy/LUTelegram.py +428 -0
  61. __SRC/LIB/lyrpy/LUThread.py +177 -0
  62. __SRC/LIB/lyrpy/LUTimer.py +141 -0
  63. __SRC/LIB/lyrpy/LUVersion.py +383 -0
  64. __SRC/LIB/lyrpy/LUYouTube.py +203 -0
  65. __SRC/LIB/lyrpy/LUos.py +807 -0
  66. __SRC/LIB/lyrpy/LUsys.py +47 -0
  67. __SRC/LIB/lyrpy/__init__.py +21 -0
  68. __SRC/LIB/lyrpy/__main__.py +20 -0
  69. __SRC/__init__.py +0 -0
  70. ____src/__init__.py +0 -0
  71. ____src/lyrpy/LUConsole.py +402 -0
  72. ____src/lyrpy/LUConst.py +358 -0
  73. ____src/lyrpy/LUDateTime.py +205 -0
  74. ____src/lyrpy/LUDecotators.py +417 -0
  75. ____src/lyrpy/LUDict.py +116 -0
  76. ____src/lyrpy/LUDoc.py +62 -0
  77. ____src/lyrpy/LUErrors.py +79 -0
  78. ____src/lyrpy/LUFile.py +1228 -0
  79. ____src/lyrpy/LUFileUtils.py +501 -0
  80. ____src/lyrpy/LULog.py +2324 -0
  81. ____src/lyrpy/LUNetwork.py +277 -0
  82. ____src/lyrpy/LUNumUtils.py +305 -0
  83. ____src/lyrpy/LUObjects.py +208 -0
  84. ____src/lyrpy/LUObjectsYT.py +846 -0
  85. ____src/lyrpy/LUParserARG.py +364 -0
  86. ____src/lyrpy/LUParserINI.py +376 -0
  87. ____src/lyrpy/LUParserREG.py +514 -0
  88. ____src/lyrpy/LUProc.py +110 -0
  89. ____src/lyrpy/LUQThread.py +141 -0
  90. ____src/lyrpy/LUQTimer.py +197 -0
  91. ____src/lyrpy/LUSheduler.py +941 -0
  92. ____src/lyrpy/LUStrDecode.py +223 -0
  93. ____src/lyrpy/LUStrUtils.py +633 -0
  94. ____src/lyrpy/LUSupport.py +124 -0
  95. ____src/lyrpy/LUTelegram.py +428 -0
  96. ____src/lyrpy/LUThread.py +177 -0
  97. ____src/lyrpy/LUTimer.py +141 -0
  98. ____src/lyrpy/LUVersion.py +383 -0
  99. ____src/lyrpy/LUYouTube.py +203 -0
  100. ____src/lyrpy/LUos.py +807 -0
  101. ____src/lyrpy/LUsys.py +47 -0
  102. ____src/lyrpy/__init__.py +21 -0
  103. ____src/lyrpy/__main__.py +20 -0
  104. {lyrpy-2025.0.1.dist-info → lyrpy-2025.0.2.dist-info}/METADATA +1 -1
  105. lyrpy-2025.0.2.dist-info/RECORD +145 -0
  106. lyrpy-2025.0.1.dist-info/RECORD +0 -43
  107. {lyrpy-2025.0.1.dist-info → lyrpy-2025.0.2.dist-info}/WHEEL +0 -0
  108. {lyrpy-2025.0.1.dist-info → lyrpy-2025.0.2.dist-info}/licenses/LICENSE +0 -0
  109. {lyrpy-2025.0.1.dist-info → lyrpy-2025.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,417 @@
1
+ """LUsys.py"""
2
+ # -*- coding: UTF-8 -*-
3
+ __annotations__ = """
4
+ =======================================================
5
+ Copyright (c) 2023-2024
6
+ Author:
7
+ Lisitsin Y.R.
8
+ Project:
9
+ LU_PY
10
+ Python (LU)
11
+ Module:
12
+ LUDecotators.py
13
+
14
+ =======================================================
15
+ """
16
+
17
+ #------------------------------------------
18
+ # БИБЛИОТЕКИ python
19
+ #------------------------------------------
20
+ import time
21
+ from functools import wraps
22
+ import smtplib
23
+ import traceback
24
+ from email.mime.text import MIMEText
25
+
26
+ #------------------------------------------
27
+ # БИБЛИОТЕКИ сторонние
28
+ #------------------------------------------
29
+
30
+ #------------------------------------------
31
+ # БИБЛИОТЕКИ LU
32
+ #------------------------------------------
33
+ import lyrpy.LULog as LULog
34
+
35
+ #---------------------------------------------------------------
36
+ # TIMING
37
+ #---------------------------------------------------------------
38
+ def TIMING(func):
39
+ #beginfunction
40
+
41
+ def wrapper(*args, **kwargs):
42
+ #beginfunction
43
+ start_time = time.time()
44
+ result = func(*args, **kwargs)
45
+ end_time = time.time()
46
+ s = f"Функция {func.__name__} работала {end_time - start_time} секунд..."
47
+ LULog.LoggerAdd (LULog.LoggerTOOLS, LULog.DEBUGTEXT, s)
48
+ return result
49
+ #endfunction
50
+
51
+ return wrapper
52
+ #endfunction
53
+
54
+ #---------------------------------------------------------------
55
+ # retry
56
+ #---------------------------------------------------------------
57
+ """
58
+ 1. Декоратор retry
59
+ В проектах по обработке данных и разработке программного обеспечения очень много случаев, когда мы зависим от внешних систем. Не всё всегда находятся под нашим контролем.
60
+ Иногда происходят неожиданное событие, во время которых нам бы хотелось, чтобы внешняя система сама исправляла возникнувшие ошибки и перезапускалась.
61
+ Я предпочитаю реализовывать эту логику с помощью декоратора retry, который позволяет повторно выполнять программу через N-ное количество времени.
62
+ """
63
+ def retry(max_tries=3, delay_seconds=1):
64
+ def decorator_retry(func):
65
+ @wraps(func)
66
+ def wrapper_retry(*args, **kwargs):
67
+ tries = 0
68
+ while tries < max_tries:
69
+ try:
70
+ return func(*args, **kwargs)
71
+ except Exception as e:
72
+ tries += 1
73
+ if tries == max_tries:
74
+ raise e
75
+ time.sleep(delay_seconds)
76
+ return wrapper_retry
77
+ return decorator_retry
78
+ @retry(max_tries=5, delay_seconds=2)
79
+ def call_dummy_api():
80
+ response = None
81
+ # response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
82
+ return response
83
+ #endfunction
84
+
85
+ #---------------------------------------------------------------
86
+ # memoize
87
+ #---------------------------------------------------------------
88
+ """
89
+ 2. Результаты функции кэширования
90
+ Некоторые части нашего кода редко меняют своё поведение. Тем не менее, если такое всё-таки произойдёт, это может отнять большую часть наших вычислительных мощностей. В таких ситуациях мы можем использовать декоратор для кэширования вызовов функций
91
+ Функция будет запущена только один раз, если входные данные совпадают. При каждом последующем запуске результаты будут извлекаться из кэша. Следовательно, нам не нужно будет постоянно выполнять дорогостоящие вычисления.
92
+ """
93
+ def memoize(func):
94
+ cache = {}
95
+ def wrapper(*args):
96
+ if args in cache:
97
+ return cache[args]
98
+ else:
99
+ result = func(*args)
100
+ cache[args] = result
101
+ return result
102
+ return wrapper
103
+ #endfunction
104
+
105
+ #---------------------------------------------------------------
106
+ # email_on_failure
107
+ #---------------------------------------------------------------
108
+ """
109
+ 5. Декоратор Notification
110
+ Наконец, очень полезным декоратором в производственных системах является декоратор Notification.
111
+ Ещё раз, даже при нескольких повторных попытках хорошо протестированная кодовая база может потерпеть неудачу. И когда это произойдет, нам нужно сообщить кому-нибудь об этом, чтобы принять быстрые меры.
112
+ Это не ново, если вы когда-либо создавали конвейер данных и надеялись, что он всегда будет работать без перебоев.
113
+ Следующий декоратор отправляет электронное письмо всякий раз, когда выполнение внутренней функции завершается неудачей. В вашем случае это не обязательно должно быть уведомление по электронной почте. Вы можете настроить его для отправки уведомлений Teams / slack:
114
+ """
115
+ def email_on_failure (sender_email, password, recipient_email):
116
+ def decorator (func):
117
+ def wrapper (*args, **kwargs):
118
+ try:
119
+ return func (*args, **kwargs)
120
+ except Exception as e:
121
+ # format the error message and traceback
122
+ err_msg = f"Error: {str (e)}\n\nTraceback:\n{traceback.format_exc ()}"
123
+
124
+ # create the email message
125
+ message = MIMEText (err_msg)
126
+ message ['Subject'] = f"{func.__name__} failed"
127
+ message ['From'] = sender_email
128
+ message ['To'] = recipient_email
129
+
130
+ # send the email
131
+ with smtplib.SMTP_SSL ('smtp.gmail.com', 465) as smtp:
132
+ smtp.login (sender_email, password)
133
+ smtp.sendmail (sender_email, recipient_email, message.as_string ())
134
+
135
+ # re-raise the exception
136
+ raise
137
+
138
+ return wrapper
139
+ return decorator
140
+ #endfunction
141
+
142
+ #---------------------------------------------------------------
143
+ # my_function
144
+ #---------------------------------------------------------------
145
+ @email_on_failure (sender_email = 'your_email@gmail.com', password = 'your_password',
146
+ recipient_email = 'recipient_email@gmail.com')
147
+ def my_function ():
148
+ # code that might fail
149
+ ...
150
+ #endfunction
151
+
152
+ #---------------------------------------------------------------
153
+ # timeit
154
+ #---------------------------------------------------------------
155
+ """
156
+ To overcome this, created the @timeit decorator which allows you to measure the execution time of the method/function by just adding the @timeit decorator on the method.
157
+ @timeit decorator:
158
+ """
159
+ def timeit(method):
160
+ def timed(*args, **kw):
161
+ ts = time.time()
162
+ result = method(*args, **kw)
163
+ te = time.time()
164
+ if 'log_time' in kw:
165
+ name = kw.get('log_name', method.__name__.upper())
166
+ kw['log_time'][name] = int((te - ts) * 1000)
167
+ else:
168
+ print ('%r %2.2f ms' % (method.__name__, (te - ts) * 1000))
169
+ return result
170
+ return timed
171
+ #endfunction
172
+
173
+ #---------------------------------------------------------------
174
+ # get_all_employee_details
175
+ #---------------------------------------------------------------
176
+ # Adding decorator to the method
177
+ @timeit
178
+ def get_all_employee_details(**kwargs):
179
+ print ('employee details')
180
+ # The code will look like this after removing the redundant code.
181
+ # logtime_data = {}
182
+ # employees = Employee.get_all_employee_details(log_time=logtime_data)
183
+ # Hurray!! All that messy code is gone and now it looks simple and clear.
184
+ # log_time and log_name are optional. Make use of them accordingly when needed.
185
+
186
+ #---------------------------------------------------------------
187
+ # timeit
188
+ #---------------------------------------------------------------
189
+ def timeit(func):
190
+ @wraps(func)
191
+ def timeit_wrapper(*args, **kwargs):
192
+ start_time = time.perf_counter()
193
+ result = func(*args, **kwargs)
194
+ end_time = time.perf_counter()
195
+ total_time = end_time - start_time
196
+ print(f'Function {func.__name__}{args} {kwargs} Took {total_time:.4f} seconds')
197
+ return result
198
+ return timeit_wrapper
199
+ #endfunction
200
+
201
+ @timeit
202
+ def calculate_something(num):
203
+ """
204
+ Simple function that returns sum of all numbers up to the square of num.
205
+ """
206
+ total = sum((x for x in range(0, num**2)))
207
+ return total
208
+ #endfunction
209
+
210
+ class Calculator:
211
+ @timeit
212
+ def calculate_something(self, num):
213
+ """
214
+ an example function that returns sum of all numbers up to the square of num
215
+ """
216
+ total = sum((x for x in range(0, num**2)))
217
+ return total
218
+
219
+ def __repr__(self):
220
+ return f'calc_object:{id(self)}'
221
+
222
+ #---------------------------------------------------------------
223
+ #
224
+ #---------------------------------------------------------------
225
+ """
226
+ 01.Свойства @property
227
+ Декоратор @property облегчает создание свойств в классах Python. Свойства выглядят как обычные атрибуты (поля) класса, но при их чтении вызывается геттер (getter), при записи – сеттер (setter), а при удалении – делитер (deleter). Геттер и делитер опциональны.
228
+
229
+ 02.Статические и классовые методы
230
+ Методы могут быть не только у экземпляра класса, но и у самого класса, которые вызываются без какого-то экземпляра (без self). Декораторы @staticmethod и @classmethod как раз делают метод таким (статическим или классовым). Эти декораторы встроены и видны без import.
231
+
232
+ Статический метод – это способ поместить функцию в класс, если она логически относится к этому классу. Статический метод ничего не знает о классе, из которого его вызвали.
233
+
234
+ class Foo:
235
+ @staticmethod
236
+ def help():
237
+ print('help for Foo class')
238
+ Foo.help()
239
+
240
+ Классовый метод напротив знает, из какого класса его вызывают. Он принимает неявный первый аргумент (обычно его зовут cls), который содержит вызывающий класс. Классовые методы прекрасно подходят, когда нужно учесть иерархию наследования. Пример: метод group создает список из нескольких людей. Причем для Person – список Person, а для Worker – список Worker. Со @staticmethod такое бы не вышло:
241
+
242
+ class Person:
243
+ @classmethod
244
+ def group(cls, n):
245
+ # cls именно тот класс, который вызвал
246
+ return [cls() for _ in range(n)]
247
+ def __repr__(self):
248
+ return 'Person'
249
+ class Worker(Person):
250
+ def __repr__(self):
251
+ return 'Worker'
252
+ print(Person.group(3))
253
+ # [Person, Person, Person]
254
+ print(Worker.group(2))
255
+ # [Worker, Worker]
256
+
257
+ 03.@contextmanager
258
+ Этот декоратор позволяет получить из генератора – контекст менеджер. Находится в стандартном модуле contextlib. Пример открытие файла.
259
+
260
+ from contextlib import contextmanager
261
+ @contextmanager
262
+ def my_open(name, mode='r'):
263
+ # тут код для получения ресурса
264
+ f = open(name, mode)
265
+ print('Файл открыт:', name)
266
+ try:
267
+ yield f
268
+ finally:
269
+ # Code to release resource, e.g.:
270
+ f.close()
271
+ print('Файл закрыт:', name)
272
+ # использование
273
+ with my_open('1.txt', 'w') as f:
274
+ f.write('Hello')
275
+ f.fooooo() # <- error
276
+ # Файл открыт: 1.txt
277
+ # Traceback (most recent call last):
278
+ # Файл закрыт: 1.txt
279
+
280
+ В этом генераторе есть единственный yield – он возвращает как раз нужный ресурс. Все, что до него – код захвата ресурса (будет выполнен в методе __enter__), например, открытие файла. Мы оборачиваем yield в try/finally, чтобы если даже в блоке кода with произойдет ошибка, то исключение выбросится из yield, но код закрытия файла в блоке finally будет выполнен в любом случае. Код закрытия выполняется в методе __exit__ менеджера контекста.
281
+
282
+ Асинхронная версия этого декоратора – @asynccontextmanager. Пример:
283
+
284
+ from contextlib import asynccontextmanager
285
+ @asynccontextmanager
286
+ async def get_connection():
287
+ conn = await acquire_db_connection()
288
+ try:
289
+ yield conn
290
+ finally:
291
+ await release_db_connection(conn)
292
+ # использование
293
+ async def get_all_users():
294
+ async with get_connection() as conn:
295
+ return conn.query('SELECT ...')
296
+
297
+ @functools.wraps
298
+ Декоратор @functools.wraps полезен при разработке других декораторов. Передает имя, документацию и прочую мета-информацию из декорируемой функции к ее обертке. Подробнее в статье про декораторы.
299
+
300
+ @atexit.register
301
+ Декоратор @atexit.register регистрирует функцию для вызова ее при завершении работы процесса Python.
302
+
303
+ import atexit
304
+ @atexit.register
305
+ def goodbye():
306
+ print("You are now leaving the Python sector.")
307
+ Измерение времени @timeit
308
+ Переходим к самописным декораторам.
309
+
310
+ Этот декоратор измеряет время выполнения функции, которую декорирует.
311
+
312
+ import time
313
+ from functools import wraps
314
+ def timeit(method):
315
+ @wraps(method)
316
+ def timed(*args, **kw):
317
+ ts = time.monotonic()
318
+ result = method(*args, **kw)
319
+ te = time.monotonic()
320
+ ms = (te - ts) * 1000
321
+ all_args = ', '.join(tuple(f'{a!r}' for a in args)
322
+ + tuple(f'{k}={v!r}' for k, v in kw.items()))
323
+ print(f'{method.__name__}({all_args}): {ms:2.2f} ms')
324
+ return result
325
+ return timed
326
+ # использование:
327
+ @timeit
328
+ def slow_func(x, y, sleep):
329
+ time.sleep(sleep)
330
+ return x + y
331
+ slow_func(10, 20, sleep=2)
332
+ # печатает: slow_func(10, 20, sleep=2): 2004.65 ms
333
+
334
+ Как видите, нам не нужно вмешиваться в код функции, не нужно каждый раз писать измеритель времени, декоратор отлично экономит нашу работу: надо измерить время – дописали @timeit и видим все, как на ладони.
335
+
336
+ Повторитель
337
+ Повторяет вызов функции n раз, возвращает последний результат.
338
+
339
+ from functools import wraps
340
+ def repeat(_func=None, *, num_times=2):
341
+ def decorator_repeat(func):
342
+ @wraps(func)
343
+ def wrapper_repeat(*args, **kwargs):
344
+ value = None
345
+ for _ in range(num_times):
346
+ value = func(*args, **kwargs)
347
+ return value
348
+ return wrapper_repeat
349
+ if _func is None:
350
+ return decorator_repeat
351
+ else:
352
+ return decorator_repeat(_func)
353
+ @repeat(num_times=5)
354
+ def foo():
355
+ print('текст')
356
+ """
357
+
358
+ """
359
+ Замедлитель
360
+ Замедляет исполнение функции на нужное число секунд. Бывает полезно для отладки.
361
+
362
+ from functools import wraps
363
+ import time
364
+ def slow_down(seconds=1):
365
+ def _slow_down(func):
366
+ # Sleep 1 second before calling the function
367
+ @wraps(func)
368
+ def wrapper_slow_down(*args, **kwargs):
369
+ time.sleep(seconds)
370
+ return func(*args, **kwargs)
371
+ return wrapper_slow_down
372
+ return _slow_down
373
+ @slow_down(seconds=0.5)
374
+ def foo():
375
+ print('foo')
376
+ def bar():
377
+ foo() # каждый foo по полсекунды
378
+ foo()
379
+
380
+ Помощник для отладки
381
+ Этот декоратор будет логгировать все вызовы функции и печатать ее аргументы и возвращаемое значение.
382
+
383
+ from functools import wraps
384
+ # Печатает сигнатуру вызова и возвращаемое значение
385
+ import functools
386
+ def debug(func):
387
+ @wraps(func)
388
+ def wrapper_debug(*args, **kwargs):
389
+ args_repr = [repr(a) for a in args]
390
+ kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()]
391
+ signature = ", ".join(args_repr + kwargs_repr)
392
+ print(f"Calling {func.__name__}({signature})")
393
+ value = func(*args, **kwargs)
394
+ print(f"{func.__name__!r} returned {value!r}")
395
+ return value
396
+ return wrapper_debug
397
+ @debug
398
+ def testee(x, y):
399
+ print(x + y)
400
+ """
401
+
402
+
403
+ #------------------------------------------
404
+ def main ():
405
+ #beginfunction
406
+ print('main LUDecotators.py ...')
407
+ #endfunction
408
+
409
+ #------------------------------------------
410
+ #
411
+ #------------------------------------------
412
+ #beginmodule
413
+ if __name__ == "__main__":
414
+ main()
415
+ #endif
416
+
417
+ #endmodule
SRC/lyrpy/LUDict.py ADDED
@@ -0,0 +1,116 @@
1
+ """LUDict.py"""
2
+ # -*- coding: UTF-8 -*-
3
+ __annotations__ = """
4
+ =======================================================
5
+ Copyright (c) 2023-2024
6
+ Author:
7
+ Lisitsin Y.R.
8
+ Project:
9
+ LU_PY
10
+ Python (LU)
11
+ Module:
12
+ LUDict.py
13
+
14
+ =======================================================
15
+ """
16
+
17
+ #------------------------------------------
18
+ # БИБЛИОТЕКИ python
19
+ #------------------------------------------
20
+ import sys
21
+
22
+ #------------------------------------------
23
+ # БИБЛИОТЕКИ сторонние
24
+ #------------------------------------------
25
+ import json
26
+
27
+ #------------------------------------------
28
+ # БИБЛИОТЕКИ LU
29
+ #------------------------------------------
30
+
31
+ """
32
+ data = {}
33
+ data ['people'] = []
34
+ data ['people'].append ({
35
+ 'name': 'Scott',
36
+ 'website': 'pythonist.ru',
37
+ 'from': 'Nebraska'
38
+ })
39
+ data ['people'].append ({
40
+ 'name': 'Larry',
41
+ 'website': 'pythonist.ru',
42
+ 'from': 'Michigan'
43
+ })
44
+ data ['people'].append ({
45
+ 'name': 'Tim',
46
+ 'website': 'pythonist.ru',
47
+ 'from': 'Alabama'
48
+ })
49
+ """
50
+
51
+ #---------------------------------------------------------------
52
+ # PrintDict
53
+ #---------------------------------------------------------------
54
+ def PrintDict (ADict: dict):
55
+ """PrintDict"""
56
+ #beginfunction
57
+
58
+ # LResult = AARGS.get (AARGName).get (AARGValue)
59
+
60
+ for key, value in ADict.items():
61
+ # print(key, value)
62
+ try:
63
+ print("key:\t" + key)
64
+ # ADict (value)
65
+ except AttributeError:
66
+ print("value:\t" + str(value))
67
+ #endtry
68
+ #endfor
69
+ #endfunction
70
+
71
+ #---------------------------------------------------------------
72
+ # SaveDictJSON
73
+ #---------------------------------------------------------------
74
+ def SaveDictJSON (ADict, AFileName):
75
+ """SaveDictJSON"""
76
+ #beginfunction
77
+ with open (AFileName, 'w') as LFileDictJSON:
78
+ json.dump (ADict, LFileDictJSON)
79
+ #endwith
80
+ #endfunction
81
+
82
+ #---------------------------------------------------------------
83
+ # SaveDictSTR
84
+ #---------------------------------------------------------------
85
+ def SaveDictSTR (ADict, AFileName):
86
+ """SaveDictSTR"""
87
+ #beginfunction
88
+ LDict = json.dumps (ADict, ensure_ascii = False, indent = 4)
89
+ # Save a reference to the original standard output
90
+ original_stdout = sys.stdout
91
+ with open (AFileName, 'w') as LFileDictSTR:
92
+ # Change the standard output to the file we created.
93
+ sys.stdout = LFileDictSTR
94
+ print (LDict)
95
+ #endwith
96
+ # Reset the standard output to its original value
97
+ sys.stdout = original_stdout
98
+ #endfunction
99
+
100
+ #---------------------------------------------------------------
101
+ #
102
+ #---------------------------------------------------------------
103
+ def main ():
104
+ #beginfunction
105
+ print('main LUDict.py...')
106
+ #endfunction
107
+
108
+ #------------------------------------------
109
+ #
110
+ #------------------------------------------
111
+ #beginmodule
112
+ if __name__ == "__main__":
113
+ main()
114
+ #endif
115
+
116
+ #endmodule
SRC/lyrpy/LUDoc.py ADDED
@@ -0,0 +1,62 @@
1
+ """LUDoc.py"""
2
+ # -*- coding: UTF-8 -*-
3
+ __annotations__ = """
4
+ ------------------------------------------------------
5
+ Copyright (c) 2023-2024
6
+ Author:
7
+ Lisitsin Y.R.
8
+ Project:
9
+ LU_PY
10
+ Python (LU)
11
+ Module:
12
+ LUDoc.py
13
+
14
+ ------------------------------------------------------
15
+ """
16
+
17
+ #------------------------------------------
18
+ # БИБЛИОТЕКИ python
19
+ #------------------------------------------
20
+ #import sys
21
+
22
+ #------------------------------------------
23
+ # БИБЛИОТЕКИ сторонние
24
+ #------------------------------------------
25
+
26
+ #------------------------------------------
27
+ # БИБЛИОТЕКИ LU
28
+ #------------------------------------------
29
+ import lyrpy.LULog as LULog
30
+
31
+ #---------------------------------------------------------------
32
+ # PrintInfoObject
33
+ #---------------------------------------------------------------
34
+ def PrintInfoObject (AObject):
35
+ #beginfunction
36
+ # print (sys._getframe (0).f_code.co_name, '...')
37
+ # print (inspect.currentframe().f_code.co_name, '...')
38
+ # print (inspect.stack () [0] [3], '...')
39
+ # print (traceback.extract_stack () [-1].name, '...')
40
+ s = f'{AObject}'
41
+ #LULog.LoggerAdd (LULog.LoggerTOOLS, LULog.DEBUGTEXT, s)
42
+ print (s)
43
+ #endfunction
44
+
45
+ #---------------------------------------------------------------
46
+ # main
47
+ #---------------------------------------------------------------
48
+ def main ():
49
+ #beginfunction
50
+ print('main LUDoc.py...')
51
+ ...
52
+ #endfunction
53
+
54
+ #------------------------------------------
55
+ #
56
+ #------------------------------------------
57
+ #beginmodule
58
+ if __name__ == "__main__":
59
+ main()
60
+ #endif
61
+
62
+ #endmodule
SRC/lyrpy/LUErrors.py ADDED
@@ -0,0 +1,79 @@
1
+ """LUErrors.py"""
2
+ # -*- coding: UTF-8 -*-
3
+ __annotations__ = """
4
+ =======================================================
5
+ Copyright (c) 2023-2024
6
+ Author:
7
+ Lisitsin Y.R.
8
+ Project:
9
+ LU_PY
10
+ Python (LU)
11
+ Module:
12
+ LUErrors.py
13
+
14
+ =======================================================
15
+ """
16
+
17
+ #------------------------------------------
18
+ # БИБЛИОТЕКИ python
19
+ #------------------------------------------
20
+
21
+ #------------------------------------------
22
+ # БИБЛИОТЕКИ сторонние
23
+ #------------------------------------------
24
+
25
+ #---------------------------------------------------------------
26
+ # class LUFileError_FileERROR
27
+ #---------------------------------------------------------------
28
+ class LUFileError_FileERROR(Exception):
29
+ """Ошибки в модуле LUFile при обработке файла"""
30
+ """
31
+ Атрибуты:
32
+ AFileName:
33
+ AMessage: объяснение ошибки
34
+ """
35
+
36
+ def __init__(self, AFileName: str, AMessage="Файл не существует."):
37
+ self.__FFileName: str = AFileName
38
+ self.__FMessage: str = AMessage
39
+ super().__init__(self.__FMessage)
40
+
41
+ # переопределяем метод '__str__'
42
+ def __str__(self):
43
+ return f'{self.__FFileName} -> {self.__FMessage}'
44
+
45
+ #--------------------------------------------------
46
+ # @property Message
47
+ #--------------------------------------------------
48
+ # getter
49
+ @property
50
+ def Message(self):
51
+ #beginfunction
52
+ return self.__FMessage
53
+ #endfunction
54
+ @Message.setter
55
+ def Message(self, Value: str):
56
+ #beginfunction
57
+ self.__FMessage: str = Value
58
+ #endfunction
59
+
60
+ #endclass
61
+
62
+ #------------------------------------------
63
+ # main
64
+ #------------------------------------------
65
+ def main ():
66
+ #beginfunction
67
+ print('main LUEditors.py ...')
68
+ #endfunction
69
+
70
+ #------------------------------------------
71
+ #
72
+ #------------------------------------------
73
+ #beginmodule
74
+ if __name__ == "__main__":
75
+ main()
76
+ #endif
77
+
78
+ #endmodule
79
+