base-aux 0.0.1__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.
Files changed (138) hide show
  1. base_aux/_NEW/__init__.py +22 -0
  2. base_aux/_NEW/main.py +53 -0
  3. base_aux/__init__.py +0 -0
  4. base_aux/alerts/__init__.py +20 -0
  5. base_aux/alerts/_examples.py +103 -0
  6. base_aux/alerts/base.py +266 -0
  7. base_aux/alerts/smtp.py +76 -0
  8. base_aux/alerts/telegram.py +45 -0
  9. base_aux/bits/__init__.py +19 -0
  10. base_aux/bits/bits.py +155 -0
  11. base_aux/buses/__init__.py +81 -0
  12. base_aux/buses/_examples.py +24 -0
  13. base_aux/buses/_explore.py +45 -0
  14. base_aux/buses/history.py +132 -0
  15. base_aux/buses/i2c_client.py +98 -0
  16. base_aux/buses/params_schema.py +149 -0
  17. base_aux/buses/parser.py +72 -0
  18. base_aux/buses/serial_client.py +1435 -0
  19. base_aux/buses/serial_derivatives.py +58 -0
  20. base_aux/buses/serial_server.py +505 -0
  21. base_aux/classes/__init__.py +210 -0
  22. base_aux/classes/annot_1_aux.py +150 -0
  23. base_aux/classes/annot_2_all_defined.py +71 -0
  24. base_aux/classes/annot_3_iter_values.py +44 -0
  25. base_aux/classes/annot_4_cls_keys_as_values.py +125 -0
  26. base_aux/classes/breeder_1_str_1_series.py +127 -0
  27. base_aux/classes/breeder_1_str_2_stack.py +182 -0
  28. base_aux/classes/breeder_2_objects.py +277 -0
  29. base_aux/classes/cmp.py +71 -0
  30. base_aux/classes/getattr_0_echo.py +62 -0
  31. base_aux/classes/getattr_1_aux.py +37 -0
  32. base_aux/classes/getattr_2_anycase.py +14 -0
  33. base_aux/classes/getattr_3_prefix_1_inst.py +123 -0
  34. base_aux/classes/getattr_3_prefix_2_cls.py +52 -0
  35. base_aux/classes/middle_group.py +213 -0
  36. base_aux/classes/number.py +280 -0
  37. base_aux/classes/singleton.py +206 -0
  38. base_aux/classes/singleton_examples.py +41 -0
  39. base_aux/classes/static.py +12 -0
  40. base_aux/classes/valid_0_aux.py +224 -0
  41. base_aux/classes/valid_1_base.py +323 -0
  42. base_aux/classes/valid_1_base_derivatives.py +65 -0
  43. base_aux/classes/valid_2_chains.py +104 -0
  44. base_aux/classes/valid_3_regexp.py +54 -0
  45. base_aux/classes/value_1_variants.py +139 -0
  46. base_aux/classes/value_2_unit.py +296 -0
  47. base_aux/cli/__init__.py +35 -0
  48. base_aux/cli/_examples.py +69 -0
  49. base_aux/cli/main.py +315 -0
  50. base_aux/funcs/__init__.py +98 -0
  51. base_aux/funcs/args.py +85 -0
  52. base_aux/funcs/arrays.py +64 -0
  53. base_aux/funcs/ensure.py +81 -0
  54. base_aux/funcs/iterables.py +147 -0
  55. base_aux/funcs/pytest_aux.py +218 -0
  56. base_aux/funcs/result_cum.py +168 -0
  57. base_aux/funcs/static.py +55 -0
  58. base_aux/funcs/strings.py +55 -0
  59. base_aux/funcs/value_0_explicit.py +96 -0
  60. base_aux/loggers/__init__.py +20 -0
  61. base_aux/loggers/main.py +187 -0
  62. base_aux/monitors/__init__.py +48 -0
  63. base_aux/monitors/_examples.py +71 -0
  64. base_aux/monitors/imap.py +205 -0
  65. base_aux/monitors/url_tag.py +227 -0
  66. base_aux/monitors/url_tag__derivatives.py +235 -0
  67. base_aux/objects/__init__.py +114 -0
  68. base_aux/objects/_examples.py +308 -0
  69. base_aux/objects/info.py +379 -0
  70. base_aux/objects/primitives.py +466 -0
  71. base_aux/objects/types.py +254 -0
  72. base_aux/privates/__init__.py +74 -0
  73. base_aux/privates/_examples.py +125 -0
  74. base_aux/privates/auto.py +38 -0
  75. base_aux/privates/base.py +187 -0
  76. base_aux/privates/csv.py +90 -0
  77. base_aux/privates/derivatives.py +26 -0
  78. base_aux/privates/env.py +48 -0
  79. base_aux/privates/ini.py +43 -0
  80. base_aux/privates/json.py +43 -0
  81. base_aux/privates/static.py +22 -0
  82. base_aux/pyqt/__init__.py +64 -0
  83. base_aux/pyqt/_explore.py +12 -0
  84. base_aux/pyqt/_from_t8.py +158 -0
  85. base_aux/pyqt/base.py +36 -0
  86. base_aux/pyqt/fonts.py +32 -0
  87. base_aux/pyqt/gui.py +943 -0
  88. base_aux/pyqt/hl.py +360 -0
  89. base_aux/pyqt/signals.py +35 -0
  90. base_aux/pyqt/th.py +84 -0
  91. base_aux/pyqt/tm.py +330 -0
  92. base_aux/requirements/__init__.py +75 -0
  93. base_aux/requirements/_examples.py +16 -0
  94. base_aux/requirements/pkgs.py +687 -0
  95. base_aux/requirements/strings.py +291 -0
  96. base_aux/requirements/versions.py +405 -0
  97. base_aux/servers/__init__.py +80 -0
  98. base_aux/servers/_examples.py +6 -0
  99. base_aux/servers/client_requests.py +226 -0
  100. base_aux/servers/server_aiohttp.py +261 -0
  101. base_aux/servers/server_fastapi.py +645 -0
  102. base_aux/servers/url.py +38 -0
  103. base_aux/testplans/DEVICES/__init__.py +0 -0
  104. base_aux/testplans/DEVICES/atc.py +47 -0
  105. base_aux/testplans/DEVICES/dut.py +34 -0
  106. base_aux/testplans/DEVICES/ptb.py +92 -0
  107. base_aux/testplans/TESTCASES/__init__.py +3 -0
  108. base_aux/testplans/TESTCASES/tc01_exist1_ptb.py +21 -0
  109. base_aux/testplans/TESTCASES/tc01_exist2_psu.py +20 -0
  110. base_aux/testplans/TESTCASES/tc0_groups.py +17 -0
  111. base_aux/testplans/TESTCASES/tc0_test_tcinst_startup_fail.py +15 -0
  112. base_aux/testplans/TESTCASES/tc1_direct.py +22 -0
  113. base_aux/testplans/TESTCASES/tc2_reverse.py +31 -0
  114. base_aux/testplans/TESTCASES/tc3_atc.py +34 -0
  115. base_aux/testplans/TESTCASES/tc4_dut_ptb.py +41 -0
  116. base_aux/testplans/TESTCASES/tc5_group_1.py +16 -0
  117. base_aux/testplans/TESTCASES/tc5_group_2.py +15 -0
  118. base_aux/testplans/TESTCASES/tc5_group_3.py +16 -0
  119. base_aux/testplans/__init__.py +87 -0
  120. base_aux/testplans/_explore.py +72 -0
  121. base_aux/testplans/api.py +109 -0
  122. base_aux/testplans/devices.py +118 -0
  123. base_aux/testplans/gui.py +289 -0
  124. base_aux/testplans/main.py +423 -0
  125. base_aux/testplans/models.py +63 -0
  126. base_aux/testplans/results.py +34 -0
  127. base_aux/testplans/tc.py +539 -0
  128. base_aux/testplans/tc_groups.py +69 -0
  129. base_aux/testplans/tc_types.py +11 -0
  130. base_aux/testplans/tm.py +277 -0
  131. base_aux/threads/__init__.py +27 -0
  132. base_aux/threads/_examples.py +32 -0
  133. base_aux/threads/main.py +215 -0
  134. base_aux-0.0.1.dist-info/LICENSE +22 -0
  135. base_aux-0.0.1.dist-info/METADATA +248 -0
  136. base_aux-0.0.1.dist-info/RECORD +138 -0
  137. base_aux-0.0.1.dist-info/WHEEL +5 -0
  138. base_aux-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,22 @@
1
+ # =====================================================================================================================
2
+ # VERSION = (0, 0, 1) # use import EXACT_OBJECTS! not *
3
+ # from .main import * # INcorrect
4
+ # from .main import EXACT_OBJECTS # CORRECT
5
+ # VERSION = (0, 0, 2) # del blank lines
6
+ # VERSION = (0, 0, 3) # separate all types/exx into static.py!
7
+
8
+
9
+ # =====================================================================================================================
10
+ # TEMPLATE
11
+ # from .static import (
12
+ # # TYPES
13
+ # # EXX
14
+ # )
15
+ # from .main import (
16
+ # # BASE
17
+ # # AUX
18
+ # )
19
+ # ---------------------------------------------------------------------------------------------------------------------
20
+
21
+
22
+ # =====================================================================================================================
base_aux/_NEW/main.py ADDED
@@ -0,0 +1,53 @@
1
+ import pathlib
2
+ from typing import *
3
+
4
+
5
+ # =====================================================================================================================
6
+ TYPE__PATH = Union[str, pathlib.Path]
7
+
8
+
9
+ # =====================================================================================================================
10
+ class NEW_CLASS____:
11
+ """
12
+ NOTE
13
+ ----
14
+
15
+ GOAL
16
+ ----
17
+
18
+ USEFUL IDEAS
19
+ ------------
20
+
21
+ CREATED SPECIALLY FOR
22
+ ---------------------
23
+ REPLACE:
24
+
25
+ CONSTRAINTS
26
+ -----------
27
+
28
+ BEST USAGE
29
+ ----------
30
+
31
+ SAME AS/OTHER VARIANTS
32
+ ----------------------
33
+ DIFFERENCE:
34
+
35
+ WHY NOT: 1?
36
+ ----------
37
+
38
+ WHY NOT: 2?
39
+ ----------
40
+
41
+ REFERENCE
42
+ ---------
43
+
44
+ """
45
+ def meth(self):
46
+ """
47
+ CREATED SPECIALLY FOR
48
+ ---------------------
49
+ """
50
+ pass
51
+
52
+
53
+ # =====================================================================================================================
base_aux/__init__.py ADDED
File without changes
@@ -0,0 +1,20 @@
1
+ # =====================================================================================================================
2
+ # VERSION = (0, 0, 1) # use import EXACT_OBJECTS! not *
3
+ # from .main import * # INcorerct
4
+ # from .main import EXACT_OBJECTS # CORERCT
5
+
6
+
7
+ # =====================================================================================================================
8
+ from .base import AlertBase
9
+ from .smtp import SmtpAddress, SmtpServers, AlertSmtp
10
+ from .telegram import RecipientTgID, AlertTelegram
11
+
12
+
13
+ # =====================================================================================================================
14
+ # FIXME: move to main!
15
+ class AlertSelect:
16
+ SMTP_DEF = AlertSmtp
17
+ TELEGRAM_DEF = AlertTelegram
18
+
19
+
20
+ # =====================================================================================================================
@@ -0,0 +1,103 @@
1
+ # =========================================================================================
2
+ ### 0. BEST PRACTICE
3
+ from base_aux.alerts import *
4
+
5
+ class AlertADX(AlertSelect.TELEGRAM_DEF):
6
+ pass
7
+
8
+ AlertADX("hello")
9
+ AlertADX("World")
10
+ AlertADX.threads_wait_all()
11
+
12
+ # =========================================================================================
13
+ # =========================================================================================
14
+ # =========================================================================================
15
+ ### AlertSmtp
16
+ #### 1. add new server if not exists
17
+ from base_aux.alerts import *
18
+
19
+
20
+ class SmtpServersMOD(SmtpServers):
21
+ EXAMPLE_RU: SmtpAddress = SmtpAddress("smtp.EXAMPLE.ru", 123)
22
+
23
+
24
+ class AlertSmtpMOD(AlertSmtp):
25
+ SERVER_SMTP: SmtpAddress = SmtpServersMOD.EXAMPLE_RU # or direct =SmtpAddress("smtp.EXAMPLE.ru", 123)
26
+
27
+ # =========================================================================================
28
+ #### 2. change authorisation data (see `privates` for details)
29
+ from base_aux.alerts import *
30
+ from base_aux.privates import *
31
+
32
+
33
+ class AlertSmtpMOD(AlertSmtp):
34
+ AUTH: PrivateAuto = PrivateAuto(_section="AUTH_EMAIL_MOD")
35
+
36
+ # =========================================================================================
37
+ #### 3. change other settings (see source for other not mentioned)
38
+ from base_aux.alerts import *
39
+
40
+
41
+ class AlertSmtpMOD(AlertSmtp):
42
+ RECONNECT_PAUSE: int = 60
43
+ RECONNECT_LIMIT: int = 10
44
+
45
+ TIMEOUT_RATELIMIT: int = 600
46
+
47
+ RECIPIENT_SPECIAL: str = "my_address_2@mail.ru"
48
+
49
+ # =========================================================================================
50
+ #### 4. send
51
+ # if no mods
52
+ from base_aux.alerts import *
53
+
54
+ AlertSmtp(_subj_name="Hello", body="World!")
55
+
56
+ # with mods
57
+ from base_aux.alerts import *
58
+
59
+
60
+ class AlertSmtpMOD(AlertSmtp):
61
+ pass # changed
62
+
63
+
64
+ AlertSmtpMOD(_subj_name="Hello", body="World!")
65
+
66
+ # =========================================================================================
67
+ #### 5. using in class with saving alert object
68
+ from base_aux.alerts import *
69
+
70
+ class AlertSmtpMOD(AlertSmtp):
71
+ pass # changed
72
+
73
+ class MyMonitor:
74
+ ALERT = AlertSmtpMOD
75
+
76
+ monitor = MyMonitor()
77
+ monitor.ALERT("Hello")
78
+
79
+ # =========================================================================================
80
+ # =========================================================================================
81
+ ### AlertTelegram
82
+ # All idea is similar to AlertSmtp.
83
+
84
+ # add auth data
85
+ # add pv.json or do smth else (for details see privates.PrivateJsonTgBotAddress)
86
+ # json
87
+ {
88
+ "TG_ID": {"MyTgID": 1234567890},
89
+ "TGBOT_DEF": {
90
+ "LINK_ID": "@my_bot_20230916",
91
+ "NAME": "my_bot",
92
+ "TOKEN": "9876543210xxxxxxxxxxxxxxxxxxxxxxxxx"
93
+ }
94
+ }
95
+
96
+ # =========================================================================================
97
+ from base_aux.alerts import *
98
+
99
+ class MyMonitor:
100
+ ALERT = AlertTelegram
101
+
102
+ monitor = MyMonitor()
103
+ monitor.ALERT("Hello")
@@ -0,0 +1,266 @@
1
+ import time
2
+ from typing import *
3
+
4
+ from PyQt5.QtCore import QThread
5
+
6
+ import smtplib
7
+ import telebot
8
+
9
+
10
+ # =====================================================================================================================
11
+ class _AlertInterface:
12
+ """Interface for Alerts
13
+
14
+ RULES:
15
+ - if some method cant exists (like for telegram) - just return True!
16
+ - Dont return None!
17
+ - Dont use Try sentences inside - it will be applied in upper logic!
18
+ - Decide inside if it was success or not, and return conclusion True/False only.
19
+ """
20
+ def _connect_unsafe(self) -> Union[bool, NoReturn]:
21
+ """establish connection to source
22
+ """
23
+ return True
24
+
25
+ def _login_unsafe(self) -> Union[bool, NoReturn]:
26
+ """authorise to source
27
+ """
28
+ return True
29
+
30
+ def _send_unsafe(self) -> Union[bool, NoReturn]:
31
+ """send msg
32
+ """
33
+ return True
34
+
35
+ def _msg_compose(self) -> Union[str, 'MIMEMultipart']:
36
+ """generate msg from existed data in attributes (passed before on init)
37
+ """
38
+ pass
39
+
40
+ def _recipient_self_get(self) -> str:
41
+ """RECIPIENT SelfSending, get from obvious class objects!
42
+ """
43
+ pass
44
+
45
+
46
+ # =====================================================================================================================
47
+ class AlertBase(_AlertInterface, QThread): # REM: DONT ADD SINGLETON!!! SNMP WILL NOT WORK!!! and calling logic will be not simle!
48
+ """Base class for Alert objects.
49
+
50
+ FEATURE:
51
+ - send msg,
52
+ - threading
53
+ - daemons
54
+ - collect all active threads
55
+ - wait all spawned threads finished
56
+
57
+ :ivar SUBJECT_PREFIX: default prefix for subject
58
+ :ivar SUBJECT_NAME: default name for subject
59
+ :ivar body: actual msg body for alert
60
+ :ivar _subtype: it used to change subtype only in smtp (http)
61
+
62
+ :ivar BODY_TIMESTAMP_USE: append timestamp into the body
63
+ :ivar TIMESTAMP: initiation timestamp for created instance
64
+
65
+ :ivar RECONNECT_LIMIT: how many times it will try to reconnect, after - just close object
66
+ :ivar RECONNECT_PAUSE: pause between reconnecting in seconds
67
+
68
+ :ivar RECIPIENT_SPECIAL: recipient for sending msg
69
+ None - if selfSending!
70
+
71
+ :ivar _conn: actual connection object
72
+ :ivar _result: result for alert state
73
+ None - in process,
74
+ False - finished UnSuccess,
75
+ True - finished success!
76
+
77
+ :ivar _threads_active: spawned (only active) threads
78
+ """
79
+ # SETTINGS ------------------------------------
80
+ SUBJECT_PREFIX: Optional[str] = "[ALERT]"
81
+ SUBJECT_NAME: Optional[str] = None
82
+ body: Union[None, str, dict] = None
83
+ _subtype: Optional[str] = "plain"
84
+
85
+ BODY_TIMESTAMP_USE: bool = True
86
+ TIMESTAMP: str = None
87
+
88
+ TIMEOUT_SEND: float = 1.2
89
+
90
+ RECONNECT_LIMIT: int = 10
91
+ RECONNECT_PAUSE: int = 60
92
+ # TIMEOUT_RATELIMIT: int = 600 # when EXX 451, b'Ratelimit exceeded
93
+
94
+ RECIPIENT_SPECIAL: Optional[Any] = None
95
+
96
+ # AUX -----------------------------------------
97
+ _conn: Union[None, smtplib.SMTP_SSL, telebot.TeleBot] = None
98
+ _result: Optional[bool] = None
99
+
100
+ _threads_active: Set['AlertBase'] = set()
101
+
102
+ # =================================================================================================================
103
+ def __init__(self, body: Optional[Any] = None, _subj_name: Optional[str] = None, _subtype: Optional[str] = None):
104
+ """Send msg
105
+
106
+ :param body: define msg body
107
+ None - just for research! (maybe deprecated!)
108
+ :param _subj_name: reuse new subject name instead of default
109
+ :param _subtype: reuse new _subtype instead of default
110
+ """
111
+ super().__init__(daemon=True)
112
+ self.TIMESTAMP = time.strftime("%Y.%m.%d %H:%M:%S")
113
+
114
+ # self._mutex: threading.Lock = threading.Lock()
115
+ self.SUBJECT_NAME = _subj_name or self.SUBJECT_NAME
116
+ self._subtype = _subtype or self._subtype
117
+
118
+ # BODY ---------------
119
+ if body is not None:
120
+ body = str(body)
121
+ if self.BODY_TIMESTAMP_USE:
122
+ body += f"\n{self.TIMESTAMP}"
123
+ self.body = body
124
+
125
+ self.start()
126
+
127
+ # =================================================================================================================
128
+ def RECIPIENT(self) -> str:
129
+ """RECIPIENT actual/final
130
+ """
131
+ return self.RECIPIENT_SPECIAL or self._recipient_self_get()
132
+
133
+ @property
134
+ def SUBJECT(self) -> str:
135
+ """final msg subject, composed with name and prefix.
136
+ """
137
+ if self.SUBJECT_NAME is None:
138
+ self.SUBJECT_NAME = self.NAME
139
+ return self.SUBJECT_PREFIX + self.SUBJECT_NAME
140
+
141
+ @classmethod
142
+ @property
143
+ def NAME(cls) -> str:
144
+ """name for AlertClass.
145
+ Accustom ourselves to name you classes recognisable without adding new one redundant attributes.
146
+ """
147
+ return cls.__name__
148
+
149
+ # =================================================================================================================
150
+ def start(self):
151
+ """this is just add ability to collect started threads in class
152
+ """
153
+ self.__class__._threads_active.add(self)
154
+ super().start()
155
+
156
+ def _thread_finished(self):
157
+ """del thread object from collection.
158
+ called then thread finished.
159
+ """
160
+ self.__class__._threads_active.discard(self)
161
+
162
+ @classmethod
163
+ def threads_wait_all(cls):
164
+ """wait while all spawned active threads will finished.
165
+ """
166
+ try:
167
+ time.sleep(1)
168
+ while cls._threads_active:
169
+ list(cls._threads_active)[0].wait()
170
+ except:
171
+ pass
172
+
173
+ def result_wait(self) -> Optional[bool]:
174
+ """wait for finish thread and get succession result.
175
+ Created for tests mainly! but you can use!
176
+ """
177
+ self.wait()
178
+ return self._result
179
+
180
+ # =================================================================================================================
181
+ def _conn__check_exists(self) -> bool:
182
+ """check if connection object exists
183
+ """
184
+ return self._conn is not None
185
+
186
+ def _conn__disconnect(self) -> None:
187
+ """disconnect connection object
188
+ """
189
+ if self._conn:
190
+ self._conn.quit()
191
+ self._conn__clear()
192
+
193
+ def _conn__clear(self) -> None:
194
+ """del connection object
195
+ """
196
+ self._conn = None
197
+
198
+ def _connect(self) -> Optional[bool]:
199
+ """create connection object
200
+ """
201
+ result = None
202
+ if not self._conn__check_exists():
203
+ print(f"TRY _connect {self.__class__.__name__}")
204
+ try:
205
+ if self._connect_unsafe():
206
+ print("[READY] connect")
207
+
208
+ except Exception as exx:
209
+ print(f"[CRITICAL] CONNECT [{exx!r}]")
210
+ self._conn__clear()
211
+
212
+ if self._conn__check_exists():
213
+ try:
214
+ result = self._login_unsafe()
215
+ if result:
216
+ print("[READY] login")
217
+ except Exception as exx:
218
+ print(f"[CRITICAL] LOGIN [{exx!r}]")
219
+ self._conn__clear()
220
+
221
+ print("="*100)
222
+ print("="*100)
223
+ print("="*100)
224
+ print()
225
+
226
+ return result
227
+
228
+ # =================================================================================================================
229
+ def run(self) -> None:
230
+ """main logic which manage started thread
231
+ """
232
+ counter = 0
233
+ while not self._conn__check_exists() and counter <= self.RECONNECT_LIMIT:
234
+ counter += 1
235
+ if not self._connect():
236
+ print(f"[WARNING]try [{counter=}]")
237
+ print("=" * 100)
238
+ print()
239
+ time.sleep(self.RECONNECT_PAUSE)
240
+
241
+ print("[Try send", "-" * 80)
242
+ print(self._msg_compose())
243
+ print("Try send]", "-" * 80)
244
+
245
+ if self._conn__check_exists():
246
+ try:
247
+ result = self._send_unsafe()
248
+ if result:
249
+ print("[READY] send")
250
+ self._result = True
251
+ except Exception as exx:
252
+ msg = f"[CRITICAL]unexpected [{exx!r}]"
253
+ print(msg)
254
+ self._conn__clear()
255
+
256
+ print()
257
+ print()
258
+ print()
259
+
260
+ if self._result is None:
261
+ self._result = False
262
+
263
+ self._thread_finished()
264
+
265
+
266
+ # =====================================================================================================================
@@ -0,0 +1,76 @@
1
+ from .base import *
2
+
3
+ import time
4
+ from typing import *
5
+
6
+ import smtplib
7
+ from email.mime.text import MIMEText
8
+ from email.mime.multipart import MIMEMultipart
9
+
10
+ from base_aux.privates import *
11
+
12
+
13
+ # =====================================================================================================================
14
+ # TODO: cant solve not to use always connecting - tried many variants!
15
+ # make decision - use only one ability to send - only by instantiating!
16
+ # always will connecting! but always in threads! so dont mind!
17
+
18
+
19
+ # =====================================================================================================================
20
+ class SmtpAddress(NamedTuple):
21
+ """class for keeping connection parameters/settings for exact smtp server
22
+
23
+ :ivar ADDR: smtp server address like "smtp.mail.ru"
24
+ :ivar PORT: smtp server port like 465
25
+ """
26
+ ADDR: str
27
+ PORT: int
28
+
29
+
30
+ class SmtpServers:
31
+ """well known servers addresses.
32
+
33
+ Here we must collect servers like MilRu/GmailCom, and not to create it in any new project.
34
+ """
35
+ MAIL_RU: SmtpAddress = SmtpAddress("smtp.mail.ru", 465)
36
+
37
+
38
+ # =====================================================================================================================
39
+ class AlertSmtp(AlertBase):
40
+ """SMTP realisation for sending msg (email).
41
+ """
42
+ # SETTINGS ------------------------------------
43
+ SERVER_SMTP: SmtpAddress = SmtpServers.MAIL_RU
44
+ AUTH: PrivateAuth = PrivateAuto(_section="AUTH_EMAIL_DEF")
45
+ TIMEOUT_SEND = 5
46
+
47
+ # AUX -----------------------------------------
48
+ _conn: smtplib.SMTP_SSL
49
+
50
+ def _connect_unsafe(self) -> Union[bool, NoReturn]:
51
+ self._conn = smtplib.SMTP_SSL(self.SERVER_SMTP.ADDR, self.SERVER_SMTP.PORT, timeout=self.TIMEOUT_SEND)
52
+ return True
53
+
54
+ def _login_unsafe(self) -> Union[bool, NoReturn]:
55
+ response = self._conn.login(self.AUTH.USER, self.AUTH.PWD)
56
+ print(response)
57
+ print("=" * 100)
58
+ return response and response[0] in [235, 503]
59
+
60
+ def _send_unsafe(self) -> Union[bool, NoReturn]:
61
+ self._conn.send_message(self._msg_compose())
62
+ return True
63
+
64
+ def _msg_compose(self) -> MIMEMultipart:
65
+ msg = MIMEMultipart()
66
+ msg["From"] = self.AUTH.USER
67
+ msg["To"] = self.RECIPIENT_SPECIAL or self.AUTH.USER
68
+ msg['Subject'] = self.SUBJECT
69
+ msg.attach(MIMEText(self.body, _subtype=self._subtype))
70
+ return msg
71
+
72
+ def _recipient_self_get(self) -> str:
73
+ return self.AUTH.USER
74
+
75
+
76
+ # =====================================================================================================================
@@ -0,0 +1,45 @@
1
+ from .base import *
2
+
3
+ import time
4
+ from typing import *
5
+
6
+ import telebot
7
+
8
+ from base_aux.privates import *
9
+
10
+
11
+ # =====================================================================================================================
12
+ class RecipientTgID(PrivateAuto):
13
+ """Object to get telegram RecipientId
14
+ """
15
+ SECTION = "TG_ID"
16
+ MyTgID: str
17
+
18
+
19
+ # =====================================================================================================================
20
+ class AlertTelegram(AlertBase):
21
+ """realisation for sending Telegram msg
22
+ """
23
+ # SETTINGS ------------------------------------
24
+ SERVER_TG: PrivateTgBotAddressAuto = PrivateTgBotAddressAuto(_section="TGBOT_DEF")
25
+
26
+ # AUX -----------------------------------------
27
+ _conn: telebot.TeleBot
28
+
29
+ def _connect_unsafe(self) -> Union[bool, NoReturn]:
30
+ self._conn = telebot.TeleBot(token=self.SERVER_TG.TOKEN)
31
+ return True
32
+
33
+ def _send_unsafe(self) -> Union[bool, NoReturn]:
34
+ self._conn.send_message(chat_id=self.RECIPIENT, text=self._msg_compose())
35
+ return True
36
+
37
+ def _msg_compose(self) -> str:
38
+ msg = f"{self.SUBJECT}\n{self.body}"
39
+ return msg
40
+
41
+ def _recipient_self_get(self) -> str:
42
+ return RecipientTgID().MyTgID
43
+
44
+
45
+ # =====================================================================================================================
@@ -0,0 +1,19 @@
1
+ # =====================================================================================================================
2
+ # VERSION = (0, 0, 1) # use import EXACT_OBJECTS! not *
3
+ # from .main import * # INcorrect
4
+ # from .main import EXACT_OBJECTS # CORRECT
5
+
6
+
7
+ # =====================================================================================================================
8
+ from .bits import (
9
+ # BASE
10
+ Bitfield, Flags, Bits,
11
+
12
+ # AUX
13
+
14
+ # EXX
15
+ Exx_BitsNoSize, Exx_BitsOutOfRange,
16
+ )
17
+
18
+
19
+ # =====================================================================================================================