ka-uts-com 1.0.0.240823__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.
- build/lib/dist/ka_uts_com-1.0.0.240823-py3-none-any.whl +0 -0
- build/lib/dist/ka_uts_com-1.0.0.240823.tar.gz +0 -0
- build/lib/ka_uts_com/__init__.py +0 -0
- build/lib/ka_uts_com/__version__.py +10 -0
- build/lib/ka_uts_com/aeq.py +87 -0
- build/lib/ka_uts_com/argv.py +49 -0
- build/lib/ka_uts_com/com.py +222 -0
- build/lib/ka_uts_com/data/__init__.py +0 -0
- build/lib/ka_uts_com/data/log.personal.yml +93 -0
- build/lib/ka_uts_com/data/log.standard.yml +86 -0
- build/lib/ka_uts_com/date.py +15 -0
- build/lib/ka_uts_com/fnc.py +37 -0
- build/lib/ka_uts_com/ioc.py +57 -0
- build/lib/ka_uts_com/log.py +63 -0
- build/lib/ka_uts_com/pacmod.py +111 -0
- build/lib/ka_uts_com/py.typed +0 -0
- build/lib/ka_uts_com/str.py +268 -0
- build/lib/ka_uts_com/timer.py +72 -0
- dist/ka_uts_com-1.0.0.240823-py3-none-any.whl +0 -0
- dist/ka_uts_com-1.0.0.240823.tar.gz +0 -0
- ka_uts_com/__init__.py +0 -0
- ka_uts_com/__version__.py +10 -0
- ka_uts_com/aeq.py +87 -0
- ka_uts_com/argv.py +49 -0
- ka_uts_com/com.py +222 -0
- ka_uts_com/data/__init__.py +0 -0
- ka_uts_com/data/log.personal.yml +93 -0
- ka_uts_com/data/log.standard.yml +86 -0
- ka_uts_com/date.py +15 -0
- ka_uts_com/fnc.py +37 -0
- ka_uts_com/ioc.py +57 -0
- ka_uts_com/log.py +63 -0
- ka_uts_com/pacmod.py +111 -0
- ka_uts_com/py.typed +0 -0
- ka_uts_com/str.py +268 -0
- ka_uts_com/timer.py +72 -0
- ka_uts_com-1.0.0.240823.dist-info/LICENSE.txt +19 -0
- ka_uts_com-1.0.0.240823.dist-info/METADATA +943 -0
- ka_uts_com-1.0.0.240823.dist-info/RECORD +41 -0
- ka_uts_com-1.0.0.240823.dist-info/WHEEL +5 -0
- ka_uts_com-1.0.0.240823.dist-info/top_level.txt +4 -0
Binary file
|
Binary file
|
File without changes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
__title__ = 'ka_uts_com'
|
2
|
+
__description__ = 'Communication Utilities.'
|
3
|
+
__url__ = 'https://ka-ut-com.readthedocs.io/en/latest'
|
4
|
+
__version__ = '1.0.0.240823'
|
5
|
+
__build__ = 0x022200
|
6
|
+
__author__ = 'Bernd Stroehle'
|
7
|
+
__author_email__ = 'bernd.stroehle@gmail.com'
|
8
|
+
__license__ = 'Apache-2.0'
|
9
|
+
__copyright__ = 'Copyright 2024 Bernd Stroehle'
|
10
|
+
__cake__ = u'\u2728 \U0001f370 \u2728'
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
# import orjson
|
4
|
+
# import traceback
|
5
|
+
|
6
|
+
from ka_uts_com.date import Date
|
7
|
+
from ka_uts_com.str import Str
|
8
|
+
|
9
|
+
from typing import Any, Dict, List
|
10
|
+
|
11
|
+
TN_Date = None | Any
|
12
|
+
|
13
|
+
T_Arr = List[Any]
|
14
|
+
T_Dic = Dict[Any, Any]
|
15
|
+
|
16
|
+
TN_Arr = None | T_Arr
|
17
|
+
TN_Dic = None | T_Dic
|
18
|
+
TN_Str = None | str
|
19
|
+
|
20
|
+
|
21
|
+
class Aeq:
|
22
|
+
""" Dictionary of Equates
|
23
|
+
"""
|
24
|
+
@classmethod
|
25
|
+
def sh_value(cls, key: str, value: Any, d_valid_parms: TN_Dic) -> Any:
|
26
|
+
|
27
|
+
# print(f"key = {key}, type(key) = {type(key)}")
|
28
|
+
# print(f"value = {value}, type(value) = {type(value)}")
|
29
|
+
if not d_valid_parms:
|
30
|
+
return value
|
31
|
+
_type: TN_Str = d_valid_parms.get(key)
|
32
|
+
# print(f"_type = {_type}")
|
33
|
+
if not _type:
|
34
|
+
return value
|
35
|
+
if isinstance(_type, str):
|
36
|
+
match _type:
|
37
|
+
case 'int':
|
38
|
+
value = int(value)
|
39
|
+
case 'bool':
|
40
|
+
value = Str.sh_boolean(value)
|
41
|
+
case 'dict':
|
42
|
+
value = Str.sh_dic(value)
|
43
|
+
case 'list':
|
44
|
+
value = Str.sh_arr(value)
|
45
|
+
case '%Y-%m-%d':
|
46
|
+
value = Date.sh(value, _type)
|
47
|
+
case '_':
|
48
|
+
match _type[0]:
|
49
|
+
case '[', '{':
|
50
|
+
_obj = Str.sh_dic(_type)
|
51
|
+
if value not in _obj:
|
52
|
+
msg = (f"parameter={key} value={value} is invalid; "
|
53
|
+
f"valid values are={_obj}")
|
54
|
+
raise Exception(msg)
|
55
|
+
|
56
|
+
# print(f"value = {value}, type(value) = {type(value)}")
|
57
|
+
return value
|
58
|
+
|
59
|
+
@classmethod
|
60
|
+
def sh_d_eq(cls, a_s_eq: T_Arr, d_valid_parms: TN_Dic) -> T_Dic:
|
61
|
+
|
62
|
+
d_eq = {}
|
63
|
+
_d_valid_parms = d_valid_parms
|
64
|
+
for s_eq in a_s_eq[1:]:
|
65
|
+
a_eq = s_eq.split('=')
|
66
|
+
if len(a_eq) == 1:
|
67
|
+
key = 'cmd'
|
68
|
+
value = a_eq[0]
|
69
|
+
if _d_valid_parms is not None:
|
70
|
+
if value in _d_valid_parms:
|
71
|
+
_d_valid_parms = _d_valid_parms[value]
|
72
|
+
else:
|
73
|
+
_valid_commands = list(_d_valid_parms.keys())
|
74
|
+
msg = (f"Wrong command: {value}; "
|
75
|
+
f"valid commands are: {_valid_commands}")
|
76
|
+
else:
|
77
|
+
key = a_eq[0]
|
78
|
+
value = a_eq[1]
|
79
|
+
|
80
|
+
if _d_valid_parms is not None:
|
81
|
+
if key not in _d_valid_parms:
|
82
|
+
msg = (f"Wrong parameter: {key}; "
|
83
|
+
f"valid parameters are: {_d_valid_parms}")
|
84
|
+
raise Exception(msg)
|
85
|
+
value = cls.sh_value(key, value, _d_valid_parms)
|
86
|
+
d_eq[key] = value
|
87
|
+
return d_eq
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
from ka_uts_com.pacmod import Pacmod
|
4
|
+
from ka_uts_com.aeq import Aeq
|
5
|
+
|
6
|
+
from typing import Any, Callable, Dict, List
|
7
|
+
|
8
|
+
T_Arr = List[Any]
|
9
|
+
T_Dic = Dict[Any, Any]
|
10
|
+
|
11
|
+
TN_Arr = None | T_Arr
|
12
|
+
TN_Dic = None | T_Dic
|
13
|
+
|
14
|
+
|
15
|
+
class Argv:
|
16
|
+
""" Manage Commandline Arguments
|
17
|
+
"""
|
18
|
+
@staticmethod
|
19
|
+
def set_by_pacmod(d_eq: T_Dic, root_cls) -> None:
|
20
|
+
""" set current pacmod dictionary
|
21
|
+
"""
|
22
|
+
tenant = d_eq.get('tenant')
|
23
|
+
d_eq['pacmod_curr'] = Pacmod.sh_d_pacmod(root_cls, tenant)
|
24
|
+
|
25
|
+
@staticmethod
|
26
|
+
def set_by_prof(d_eq: T_Dic, sh_prof: Callable | Any) -> None:
|
27
|
+
""" set current pacmod dictionary
|
28
|
+
"""
|
29
|
+
if callable(sh_prof):
|
30
|
+
d_eq['sh_prof'] = sh_prof()
|
31
|
+
else:
|
32
|
+
d_eq['sh_prof'] = sh_prof
|
33
|
+
|
34
|
+
@classmethod
|
35
|
+
def sh(cls, a_s_eq: T_Arr, **kwargs) -> T_Dic:
|
36
|
+
""" show equates dictionary
|
37
|
+
"""
|
38
|
+
# print(f"DoEq sh kwargs = {kwargs}")
|
39
|
+
root_cls = kwargs.get('root_cls')
|
40
|
+
d_valid_parms: TN_Dic = kwargs.get('d_parms')
|
41
|
+
# print(f"DoEq sh d_valid_parms = {d_valid_parms}")
|
42
|
+
|
43
|
+
d_eq = Aeq.sh_d_eq(a_s_eq, d_valid_parms)
|
44
|
+
|
45
|
+
cls.set_by_pacmod(d_eq, root_cls)
|
46
|
+
_sh_prof = kwargs.get('sh_prof')
|
47
|
+
cls.set_by_prof(d_eq, _sh_prof)
|
48
|
+
|
49
|
+
return d_eq
|
@@ -0,0 +1,222 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
import calendar
|
4
|
+
import logging
|
5
|
+
import logging.config
|
6
|
+
from logging import Logger
|
7
|
+
|
8
|
+
import os
|
9
|
+
import time
|
10
|
+
from datetime import datetime
|
11
|
+
|
12
|
+
from ka_uts_com.ioc import Yaml
|
13
|
+
from ka_uts_com.ioc import Jinja2
|
14
|
+
from ka_uts_com.pacmod import Pacmod
|
15
|
+
|
16
|
+
from typing import Any, Callable, List, Dict
|
17
|
+
|
18
|
+
T_Any = Any
|
19
|
+
T_Arr = List[Any]
|
20
|
+
T_Bool = bool
|
21
|
+
T_Dic = Dict[Any, Any]
|
22
|
+
|
23
|
+
TN_Arr = None | T_Arr
|
24
|
+
TN_Bool = None | bool
|
25
|
+
TN_Dic = None | T_Dic
|
26
|
+
TN_DT = None | datetime
|
27
|
+
|
28
|
+
|
29
|
+
class LogStandard:
|
30
|
+
"""Standard Logging
|
31
|
+
"""
|
32
|
+
sw_init: bool = False
|
33
|
+
cfg: T_Dic = {}
|
34
|
+
log: Logger = logging.getLogger('dummy_logger')
|
35
|
+
logfile: str = 'log.standard.yml'
|
36
|
+
|
37
|
+
@staticmethod
|
38
|
+
def read(pacmod: T_Dic, filename: str) -> Any:
|
39
|
+
"""Read log file path with jinja2
|
40
|
+
"""
|
41
|
+
# path: str = Pacmod.Path.Log.sh_cfg(filename=filename)
|
42
|
+
path: str = Pacmod.sh_path_cfg_log(filename=filename)
|
43
|
+
tenant: str = pacmod['tenant']
|
44
|
+
package: str = pacmod['package']
|
45
|
+
module: str = pacmod['module']
|
46
|
+
pid = Com.pid
|
47
|
+
ts: TN_DT = Com.ts_start
|
48
|
+
cfg = Jinja2.read(
|
49
|
+
path, tenant=tenant,
|
50
|
+
package=package, module=module,
|
51
|
+
pid=pid, ts=ts)
|
52
|
+
return cfg
|
53
|
+
|
54
|
+
@classmethod
|
55
|
+
def set_level(cls, sw_debug: bool) -> None:
|
56
|
+
"""Set static variable log level in log configuration handlers
|
57
|
+
"""
|
58
|
+
if sw_debug:
|
59
|
+
level = logging.DEBUG
|
60
|
+
else:
|
61
|
+
level = logging.INFO
|
62
|
+
cls.cfg['handlers']['main_debug_console']['level'] = level
|
63
|
+
cls.cfg['handlers']['main_debug_file']['level'] = level
|
64
|
+
|
65
|
+
@classmethod
|
66
|
+
def init(
|
67
|
+
cls, **kwargs) -> None:
|
68
|
+
cls.sw_init = True
|
69
|
+
cls.cfg = cls.read(Com.pacmod_curr, cls.logfile)
|
70
|
+
sw_debug: Any = kwargs.get('sw_debug')
|
71
|
+
cls.set_level(sw_debug)
|
72
|
+
logging.config.dictConfig(cls.cfg)
|
73
|
+
cls.log = logging.getLogger('main')
|
74
|
+
|
75
|
+
@classmethod
|
76
|
+
def sh(cls, **kwargs) -> Any:
|
77
|
+
if cls.sw_init:
|
78
|
+
return cls.log
|
79
|
+
cls.init(**kwargs)
|
80
|
+
return cls.log
|
81
|
+
|
82
|
+
|
83
|
+
class LogPersonal:
|
84
|
+
"""Personal Logging
|
85
|
+
"""
|
86
|
+
sw_init: bool = False
|
87
|
+
cfg: T_Dic = {}
|
88
|
+
logfile = 'log.person.yml'
|
89
|
+
log: Logger = logging.getLogger('dummy_logger')
|
90
|
+
|
91
|
+
@classmethod
|
92
|
+
def read(cls, pacmod: T_Dic, person: Any, filename: str) -> Any:
|
93
|
+
path: str = Pacmod.sh_path_cfg_log(filename=filename)
|
94
|
+
package: str = pacmod['package']
|
95
|
+
module: str = pacmod['module']
|
96
|
+
return Jinja2.read(
|
97
|
+
path, package=package, module=module, person=person,
|
98
|
+
pid=Com.pid, ts=Com.ts_start)
|
99
|
+
|
100
|
+
@classmethod
|
101
|
+
def set_level(cls, person: str, sw_debug: bool) -> None:
|
102
|
+
if sw_debug:
|
103
|
+
level = logging.DEBUG
|
104
|
+
else:
|
105
|
+
level = logging.INFO
|
106
|
+
cls.cfg['handlers'][f'{person}_debug_console']['level'] = level
|
107
|
+
cls.cfg['handlers'][f'{person}_debug_file']['level'] = level
|
108
|
+
|
109
|
+
@classmethod
|
110
|
+
def init(cls, pacmod: T_Dic, person: str, sw_debug: bool) -> None:
|
111
|
+
cls.cfg = cls.read(pacmod, person, cls.logfile)
|
112
|
+
cls.set_level(person, sw_debug)
|
113
|
+
logging.config.dictConfig(cls.cfg)
|
114
|
+
cls.log = logging.getLogger(person)
|
115
|
+
|
116
|
+
@classmethod
|
117
|
+
def sh(cls, **kwargs) -> Any:
|
118
|
+
if cls.sw_init:
|
119
|
+
return cls.log
|
120
|
+
cls.init(**kwargs)
|
121
|
+
return cls.log
|
122
|
+
|
123
|
+
|
124
|
+
class Cfg:
|
125
|
+
"""Configuration Class
|
126
|
+
"""
|
127
|
+
@classmethod
|
128
|
+
def init(cls, pacmod: T_Dic) -> TN_Dic:
|
129
|
+
""" the package data directory has to contain a __init__.py
|
130
|
+
file otherwise the objects notation {package}.data to
|
131
|
+
locate the package data directory is invalid
|
132
|
+
"""
|
133
|
+
_dic: TN_Dic = Yaml.read(Pacmod.sh_path_cfg_yaml(pacmod))
|
134
|
+
return _dic
|
135
|
+
|
136
|
+
|
137
|
+
class Mgo:
|
138
|
+
"""Mongo DB Class
|
139
|
+
"""
|
140
|
+
client = None
|
141
|
+
|
142
|
+
|
143
|
+
class App:
|
144
|
+
"""Aplication Class
|
145
|
+
"""
|
146
|
+
sw_init: T_Bool = False
|
147
|
+
httpmod: T_Any = None
|
148
|
+
sw_replace_keys: TN_Bool = None
|
149
|
+
keys: TN_Arr = None
|
150
|
+
reqs: T_Dic = {}
|
151
|
+
app: T_Dic = {}
|
152
|
+
|
153
|
+
@classmethod
|
154
|
+
def init(cls, **kwargs) -> Any:
|
155
|
+
cls.sw_init = True
|
156
|
+
cls.httpmod = kwargs.get('httpmod')
|
157
|
+
cls.sw_replace_keys = kwargs.get('sw_replace_keys', False)
|
158
|
+
try:
|
159
|
+
if cls.sw_replace_keys:
|
160
|
+
pacmod = kwargs.get('pacmod_curr')
|
161
|
+
# cls.keys = Yaml.read(Pacmod.Pmd.sh_path_keys(pacmod))
|
162
|
+
cls.keys = Yaml.read(Pacmod.sh_path_keys_yaml(pacmod))
|
163
|
+
except Exception as e:
|
164
|
+
if Com.Log is not None:
|
165
|
+
fnc_error: Callable = Com.Log.error
|
166
|
+
fnc_error(e, exc_info=True)
|
167
|
+
raise
|
168
|
+
return cls
|
169
|
+
|
170
|
+
@classmethod
|
171
|
+
def sh(cls, **kwargs) -> Any:
|
172
|
+
if cls.sw_init:
|
173
|
+
return cls
|
174
|
+
cls.init(**kwargs)
|
175
|
+
return cls
|
176
|
+
|
177
|
+
|
178
|
+
class Exit:
|
179
|
+
"""Exit Class
|
180
|
+
"""
|
181
|
+
sw_critical: bool = False
|
182
|
+
sw_stop: bool = False
|
183
|
+
sw_interactive: bool = False
|
184
|
+
|
185
|
+
|
186
|
+
class Com:
|
187
|
+
"""Communication Class
|
188
|
+
"""
|
189
|
+
sw_init: bool = False
|
190
|
+
cfg: TN_Dic = None
|
191
|
+
pid = None
|
192
|
+
pacmod_curr: T_Dic = {}
|
193
|
+
|
194
|
+
ts_start: None | datetime = None
|
195
|
+
ts_end: None | datetime = None
|
196
|
+
ts_etime: None | datetime = None
|
197
|
+
d_timer: Dict = {}
|
198
|
+
|
199
|
+
# Log = None
|
200
|
+
Log: Logger = logging.getLogger('dummy_logger')
|
201
|
+
App = None
|
202
|
+
Exit = Exit
|
203
|
+
|
204
|
+
@classmethod
|
205
|
+
def init(cls, **kwargs):
|
206
|
+
""" set log and application (module) configuration
|
207
|
+
"""
|
208
|
+
if cls.sw_init:
|
209
|
+
return
|
210
|
+
cls.sw_init = True
|
211
|
+
|
212
|
+
cls.pacmod_curr = kwargs.get('pacmod_curr')
|
213
|
+
cls.ts_start = calendar.timegm(time.gmtime())
|
214
|
+
cls.pid = os.getpid()
|
215
|
+
|
216
|
+
cls.cfg = Cfg.init(cls.pacmod_curr)
|
217
|
+
log_type = kwargs.get('log_type', 'standard')
|
218
|
+
if log_type == 'standard':
|
219
|
+
cls.Log = LogStandard.sh(**kwargs)
|
220
|
+
else:
|
221
|
+
cls.Log = LogPersonal.sh(**kwargs)
|
222
|
+
cls.App = App.sh(**kwargs)
|
File without changes
|
@@ -0,0 +1,93 @@
|
|
1
|
+
version: 1
|
2
|
+
|
3
|
+
disable_existing_loggers: False
|
4
|
+
|
5
|
+
root:
|
6
|
+
level: DEBUG
|
7
|
+
handlers:
|
8
|
+
- debug_console
|
9
|
+
- debug_file
|
10
|
+
|
11
|
+
loggers:
|
12
|
+
|
13
|
+
# main logger
|
14
|
+
main:
|
15
|
+
level: 'NOTSET'
|
16
|
+
handlers:
|
17
|
+
- debug_console
|
18
|
+
- debug_file
|
19
|
+
- info_file
|
20
|
+
- error_file
|
21
|
+
|
22
|
+
# person logger
|
23
|
+
person:
|
24
|
+
level: NOTSET
|
25
|
+
handlers:
|
26
|
+
- debug_console
|
27
|
+
- debug_file
|
28
|
+
- info_file
|
29
|
+
- error_file
|
30
|
+
|
31
|
+
handlers:
|
32
|
+
|
33
|
+
debug_console:
|
34
|
+
class: 'logging.StreamHandler'
|
35
|
+
level: DEBUG
|
36
|
+
formatter: debug
|
37
|
+
stream: 'ext://sys.stderr'
|
38
|
+
|
39
|
+
debug_file:
|
40
|
+
class: 'logging.FileHandler'
|
41
|
+
level: DEBUG
|
42
|
+
formatter: error
|
43
|
+
filename: 'debug.log'
|
44
|
+
mode: 'a'
|
45
|
+
|
46
|
+
# info_rotating_file_handler:
|
47
|
+
# class: 'logging.handlers.RotatingFileHandler'
|
48
|
+
# level: INFO
|
49
|
+
# formatter: info
|
50
|
+
# filename: 'info.rotating.log'
|
51
|
+
# mode: 'a'
|
52
|
+
# maxBytes: 1048576 # 1MB
|
53
|
+
# backupCount: 10
|
54
|
+
# encoding: utf8
|
55
|
+
|
56
|
+
info_file:
|
57
|
+
class: 'logging.FileHandler'
|
58
|
+
level: INFO
|
59
|
+
formatter: info
|
60
|
+
filename: 'info.log'
|
61
|
+
mode: 'a'
|
62
|
+
|
63
|
+
error_file:
|
64
|
+
class: 'logging.FileHandler'
|
65
|
+
level: ERROR
|
66
|
+
formatter: error
|
67
|
+
filename: 'error.log'
|
68
|
+
mode: 'a'
|
69
|
+
|
70
|
+
critical_mail:
|
71
|
+
class: 'logging.handlers.SMTPHandler'
|
72
|
+
level: CRITICAL
|
73
|
+
formatter: critical
|
74
|
+
mailhost : localhost
|
75
|
+
fromaddr: 'monitoring@domain.com'
|
76
|
+
toaddrs:
|
77
|
+
- 'dev@domain.com'
|
78
|
+
- 'qa@domain.com'
|
79
|
+
subject: 'Critical error with application name'
|
80
|
+
|
81
|
+
formatters:
|
82
|
+
|
83
|
+
info:
|
84
|
+
format: '%(asctime)s-%(levelname)s-%(name)s::%(module)s|%(lineno)s:: %(message)s'
|
85
|
+
debug:
|
86
|
+
format: '%(asctime)-15s %(levelname)s-%(name)s-%(process)d::%(module)s.%(funcName)s|%(lineno)s:: %(message)s'
|
87
|
+
datefmt: '%Y-%m-%d %H:%M:%S'
|
88
|
+
error:
|
89
|
+
format: '%(asctime)-15s %(levelname)s-%(name)s-%(process)d::%(module)s.%(funcName)s|%(lineno)s:: %(message)s'
|
90
|
+
datefmt: '%Y-%m-%d %H:%M:%S'
|
91
|
+
critical:
|
92
|
+
format: '%(asctime)-15s %(levelname)s-%(name)s-%(process)d::%(module)s.%(funcName)s|%(lineno)s:: %(message)s'
|
93
|
+
datefmt: '%Y-%m-%d %H:%M:%S'
|
@@ -0,0 +1,86 @@
|
|
1
|
+
version: 1
|
2
|
+
|
3
|
+
disable_existing_loggers: False
|
4
|
+
|
5
|
+
# root:
|
6
|
+
# level: DEBUG
|
7
|
+
# handlers:
|
8
|
+
# - debug_console
|
9
|
+
# - debug_file
|
10
|
+
|
11
|
+
loggers:
|
12
|
+
|
13
|
+
# main logger
|
14
|
+
main:
|
15
|
+
# level: NOTSET
|
16
|
+
level: DEBUG
|
17
|
+
handlers:
|
18
|
+
- main_debug_console
|
19
|
+
- main_debug_file
|
20
|
+
- main_info_file
|
21
|
+
- main_error_file
|
22
|
+
|
23
|
+
handlers:
|
24
|
+
|
25
|
+
main_debug_console:
|
26
|
+
class: 'logging.StreamHandler'
|
27
|
+
level: DEBUG
|
28
|
+
formatter: main_debug
|
29
|
+
stream: 'ext://sys.stderr'
|
30
|
+
|
31
|
+
# main_info_rotating_file_handler:
|
32
|
+
# class: 'logging.handlers.RotatingFileHandler'
|
33
|
+
# level: INFO
|
34
|
+
# formatter: info
|
35
|
+
# filename: 'info.rotating.log'
|
36
|
+
# mode: 'a'
|
37
|
+
# maxBytes: 1048576 # 1MB
|
38
|
+
# backupCount: 10
|
39
|
+
# encoding: utf8
|
40
|
+
|
41
|
+
main_debug_file:
|
42
|
+
class: 'logging.FileHandler'
|
43
|
+
level: DEBUG
|
44
|
+
formatter: main_error
|
45
|
+
filename: '/data/{{tenant}}/RUN/{{package}}/{{module}}/debs/debs_{{pid}}_{{ts}}.log'
|
46
|
+
mode: 'a'
|
47
|
+
|
48
|
+
main_info_file:
|
49
|
+
class: 'logging.FileHandler'
|
50
|
+
level: INFO
|
51
|
+
formatter: main_info
|
52
|
+
filename: '/data/{{tenant}}/RUN/{{package}}/{{module}}/logs/logs_{{pid}}_{{ts}}.log'
|
53
|
+
mode: 'a'
|
54
|
+
|
55
|
+
main_error_file:
|
56
|
+
class: 'logging.FileHandler'
|
57
|
+
level: ERROR
|
58
|
+
formatter: main_error
|
59
|
+
filename: '/data/{{tenant}}/RUN/{{package}}/{{module}}/errs/errs_{{pid}}_{{ts}}.log'
|
60
|
+
mode: 'a'
|
61
|
+
|
62
|
+
main_critical_mail:
|
63
|
+
class: 'logging.handlers.SMTPHandler'
|
64
|
+
level: CRITICAL
|
65
|
+
formatter: main_critical
|
66
|
+
mailhost : localhost
|
67
|
+
fromaddr: 'monitoring@domain.com'
|
68
|
+
toaddrs:
|
69
|
+
- 'dev@domain.com'
|
70
|
+
- 'qa@domain.com'
|
71
|
+
subject: 'Critical error with application name'
|
72
|
+
|
73
|
+
|
74
|
+
formatters:
|
75
|
+
|
76
|
+
main_info:
|
77
|
+
format: '%(asctime)s-%(levelname)s-%(name)s::%(module)s|%(lineno)s:: %(message)s'
|
78
|
+
main_debug:
|
79
|
+
format: '%(asctime)-15s %(levelname)s-%(name)s-%(process)d::%(module)s.%(funcName)s|%(lineno)s:: %(message)s'
|
80
|
+
datefmt: '%Y-%m-%d %H:%M:%S'
|
81
|
+
main_error:
|
82
|
+
format: '%(asctime)-15s %(levelname)s-%(name)s-%(process)d::%(module)s.%(funcName)s|%(lineno)s:: %(message)s'
|
83
|
+
datefmt: '%Y-%m-%d %H:%M:%S'
|
84
|
+
main_critical:
|
85
|
+
format: '%(asctime)-15s %(levelname)s-%(name)s-%(process)d::%(module)s.%(funcName)s|%(lineno)s:: %(message)s'
|
86
|
+
datefmt: '%Y-%m-%d %H:%M:%S'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
from datetime import date
|
3
|
+
|
4
|
+
T_Date = date
|
5
|
+
TN_Date = None | T_Date
|
6
|
+
TN_Str = None | str
|
7
|
+
|
8
|
+
|
9
|
+
class Date:
|
10
|
+
|
11
|
+
@staticmethod
|
12
|
+
def sh(datestring: TN_Str, fmt: str) -> TN_Date:
|
13
|
+
if not datestring:
|
14
|
+
return None
|
15
|
+
return datetime.strptime(datestring, fmt).date()
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
from typing import Any, Callable, Dict
|
4
|
+
|
5
|
+
T_Dic = Dict[Any, Any]
|
6
|
+
T_DicStr2Callable = Dict[str, Callable]
|
7
|
+
|
8
|
+
TN_Str = None | str
|
9
|
+
TN_Callable = None | Callable
|
10
|
+
|
11
|
+
|
12
|
+
class Fnc:
|
13
|
+
""" Manage Functions
|
14
|
+
"""
|
15
|
+
@staticmethod
|
16
|
+
def sh(d_key2fnc: T_DicStr2Callable, key: TN_Str) -> Callable:
|
17
|
+
if not key:
|
18
|
+
msg = f"key {key} is None or empty string"
|
19
|
+
raise Exception(msg)
|
20
|
+
_fnc: TN_Callable = d_key2fnc.get(key)
|
21
|
+
if not _fnc:
|
22
|
+
msg = f"key {key} is not defined in function table {d_key2fnc}"
|
23
|
+
raise Exception(msg)
|
24
|
+
else:
|
25
|
+
return _fnc
|
26
|
+
|
27
|
+
@staticmethod
|
28
|
+
def ex(d_key2fnc: T_DicStr2Callable, key: TN_Str, kwargs: T_Dic) -> None:
|
29
|
+
if not key:
|
30
|
+
msg = f"key {key} is None or empty string"
|
31
|
+
raise Exception(msg)
|
32
|
+
_fnc: TN_Callable = d_key2fnc.get(key)
|
33
|
+
if not _fnc:
|
34
|
+
msg = f"key {key} is not defined in function table {d_key2fnc}"
|
35
|
+
raise Exception(msg)
|
36
|
+
else:
|
37
|
+
_fnc(kwargs)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
import jinja2
|
4
|
+
import os
|
5
|
+
import yaml
|
6
|
+
|
7
|
+
from typing import Any, Dict
|
8
|
+
|
9
|
+
T_Dic = Dict[Any, Any]
|
10
|
+
|
11
|
+
TN_Any = None | Any
|
12
|
+
|
13
|
+
|
14
|
+
class Yaml:
|
15
|
+
|
16
|
+
""" Manage Object to Yaml file affilitation
|
17
|
+
"""
|
18
|
+
@staticmethod
|
19
|
+
def load_with_safeloader(string: str) -> None | Any:
|
20
|
+
_obj = yaml.load(string, Loader=yaml.SafeLoader)
|
21
|
+
return _obj
|
22
|
+
|
23
|
+
@staticmethod
|
24
|
+
def read(path: str) -> TN_Any:
|
25
|
+
with open(path) as fd:
|
26
|
+
# The Loader parameter handles the conversion from YAML
|
27
|
+
# scalar values to Python object format
|
28
|
+
_obj = yaml.load(fd, Loader=yaml.SafeLoader)
|
29
|
+
return _obj
|
30
|
+
return None
|
31
|
+
|
32
|
+
|
33
|
+
class Jinja2:
|
34
|
+
""" Manage Object to Json file affilitation
|
35
|
+
"""
|
36
|
+
@staticmethod
|
37
|
+
def read_template(
|
38
|
+
path: str) -> Any:
|
39
|
+
dir, file = os.path.split(path)
|
40
|
+
env = jinja2.Environment(loader=jinja2.FileSystemLoader(dir))
|
41
|
+
return env.get_template(file)
|
42
|
+
|
43
|
+
@classmethod
|
44
|
+
def read(
|
45
|
+
cls, path: str, **kwargs):
|
46
|
+
try:
|
47
|
+
# read jinja template from file
|
48
|
+
template = cls.read_template(path)
|
49
|
+
|
50
|
+
# render template as yaml string
|
51
|
+
template_rendered = template.render(**kwargs)
|
52
|
+
|
53
|
+
# parse yaml string as dictionary
|
54
|
+
dic = Yaml.load_with_safeloader(template_rendered)
|
55
|
+
return dic
|
56
|
+
except Exception:
|
57
|
+
raise
|