easy-utils-dev 2.139__py3-none-any.whl → 2.140__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.
- easy_utils_dev/debugger-C-PF4PAMMP.py +486 -0
- easy_utils_dev/debugger.py +9 -0
- easy_utils_dev/temp_memory.py +15 -8
- easy_utils_dev/wsnoclib.py +18 -6
- {easy_utils_dev-2.139.dist-info → easy_utils_dev-2.140.dist-info}/METADATA +8 -6
- {easy_utils_dev-2.139.dist-info → easy_utils_dev-2.140.dist-info}/RECORD +8 -7
- {easy_utils_dev-2.139.dist-info → easy_utils_dev-2.140.dist-info}/WHEEL +1 -1
- {easy_utils_dev-2.139.dist-info → easy_utils_dev-2.140.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from logging.handlers import RotatingFileHandler
|
|
6
|
+
from .utils import getRandomKey , convert_mb_to_bytes , getTimestamp , start_thread
|
|
7
|
+
from .custom_env import custom_env , setupEnvironment
|
|
8
|
+
from .Events import EventEmitter
|
|
9
|
+
from threading import Thread
|
|
10
|
+
from time import sleep
|
|
11
|
+
|
|
12
|
+
gEvent = EventEmitter()
|
|
13
|
+
logging.addLevelName(25, "SCREEN")
|
|
14
|
+
|
|
15
|
+
def setGlobalHomePath( path ) :
|
|
16
|
+
env = custom_env()
|
|
17
|
+
env['debugger_homepath'] = path
|
|
18
|
+
gEvent.dispatchEvent('update_home_path')
|
|
19
|
+
|
|
20
|
+
def setGlobalDisableOnScreen(on_screen=False) :
|
|
21
|
+
env = custom_env()
|
|
22
|
+
env['debugger_on_screen'] = on_screen
|
|
23
|
+
if not on_screen :
|
|
24
|
+
gEvent.dispatchEvent('disable_global_printing')
|
|
25
|
+
else :
|
|
26
|
+
gEvent.dispatchEvent('enable_global_printing')
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def setGlobalDebugLevel(level='info') :
|
|
30
|
+
env = custom_env()
|
|
31
|
+
env['debugger_global_level'] = level
|
|
32
|
+
gEvent.dispatchEvent('update_debug_level')
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class DEBUGGER:
|
|
36
|
+
def __init__(self
|
|
37
|
+
, name
|
|
38
|
+
, level='info',
|
|
39
|
+
fullSyntax=True,
|
|
40
|
+
onscreen=True,
|
|
41
|
+
log_rotation=3,
|
|
42
|
+
homePath=None,
|
|
43
|
+
id=getRandomKey(9) ,
|
|
44
|
+
global_debugger=None,
|
|
45
|
+
disable_log_write=False,
|
|
46
|
+
file_name=None,
|
|
47
|
+
seperate_files=True
|
|
48
|
+
):
|
|
49
|
+
env = custom_env()
|
|
50
|
+
setupEnvironment( 'debugger' )
|
|
51
|
+
debugger_on_screen = env.get('debugger_on_screen' , True)
|
|
52
|
+
env['debugger_on_screen'] = debugger_on_screen
|
|
53
|
+
self.env = env
|
|
54
|
+
self.events = gEvent
|
|
55
|
+
self.debuggerLabel = f"{name}"
|
|
56
|
+
self.logger = logging.getLogger(self.debuggerLabel)
|
|
57
|
+
self.set_level(level)
|
|
58
|
+
self.file_handler_class=None
|
|
59
|
+
self.LOG_SIZE_THRESHOLD_IN_BYTES = 10 * 1024 * 1024
|
|
60
|
+
self.BACKUP_COUNT = log_rotation
|
|
61
|
+
self.homePath = homePath
|
|
62
|
+
self.lastAbsoluteHomePath= None
|
|
63
|
+
self.fullSyntax=fullSyntax
|
|
64
|
+
self.onScreen= onscreen
|
|
65
|
+
self.id = id
|
|
66
|
+
self.how_many_times_write= 0
|
|
67
|
+
self.stream_service = None
|
|
68
|
+
if not env['debugger'].get(name) :
|
|
69
|
+
self.console = console_handler = logging.StreamHandler()
|
|
70
|
+
else :
|
|
71
|
+
self.console = console_handler = env['debugger'].get(name).console
|
|
72
|
+
if not self.logger.hasHandlers() :
|
|
73
|
+
self.logger.addHandler(self.console)
|
|
74
|
+
self.name = name
|
|
75
|
+
self.rotate_disabled=False
|
|
76
|
+
self.isInPyinstaller = False
|
|
77
|
+
self.log_iterations=0
|
|
78
|
+
self.log_iterations_threshold = 200
|
|
79
|
+
self.global_debugger = global_debugger
|
|
80
|
+
self.isLogWriteDisabled = disable_log_write
|
|
81
|
+
self.type = "CUSTOM_DEBUGGER"
|
|
82
|
+
self.seperate_files=seperate_files
|
|
83
|
+
if fullSyntax :
|
|
84
|
+
f = f"[%(asctime)s]-[{self.name}]-[%(levelname)s]: %(message)s"
|
|
85
|
+
else :
|
|
86
|
+
f = f"[{self.name}]-[%(levelname)s]: %(message)s"
|
|
87
|
+
self.syntax = f
|
|
88
|
+
self.formatter = logging.Formatter(f , datefmt='%Y-%m-%d %H:%M:%S' )
|
|
89
|
+
self.filename = file_name
|
|
90
|
+
path = self.homepath(homePath)
|
|
91
|
+
if not env['debugger'].get(name) :
|
|
92
|
+
console_handler.setFormatter(self.formatter)
|
|
93
|
+
if not disable_log_write :
|
|
94
|
+
if not env['debugger'].get(name) :
|
|
95
|
+
self.file_handler_class = self.createRotateFileHandler(path)
|
|
96
|
+
if onscreen :
|
|
97
|
+
self.enable_print()
|
|
98
|
+
elif not onscreen :
|
|
99
|
+
self.disable_print()
|
|
100
|
+
self.events.addEventListener('disable_global_printing' , self.disable_print )
|
|
101
|
+
self.events.addEventListener('enable_global_printing' , self.enable_print )
|
|
102
|
+
self.events.addEventListener('update_home_path' , self.updateGlobalHomePath )
|
|
103
|
+
self.events.addEventListener('update_debug_level' , self.updateGlobalSetLevel )
|
|
104
|
+
if env['debugger'].get(name) :
|
|
105
|
+
self = env['debugger'].get(name)
|
|
106
|
+
else:
|
|
107
|
+
env['debugger'][id] = self
|
|
108
|
+
env['debugger'][name] = self
|
|
109
|
+
if not env.get('debugger_on_screen' , True ) :
|
|
110
|
+
self.disable_print()
|
|
111
|
+
if env.get('debugger_on_screen' , True ) :
|
|
112
|
+
self.enable_print()
|
|
113
|
+
if os.environ.get("EASY_UTILS_DEBUG_LEVEL") :
|
|
114
|
+
EASY_UTILS_DEBUG_LEVEL = os.environ.get("EASY_UTILS_DEBUG_LEVEL")
|
|
115
|
+
if not EASY_UTILS_DEBUG_LEVEL.lower() in ['info' , 'debug' , 'warning' , 'error' , 'critical'] :
|
|
116
|
+
self.logger.error(f'EASY_UTILS_DEBUG_LEVEL ENV must be one of [info,debug,warning,error,critical] | Current Env Variable Is "{EASY_UTILS_DEBUG_LEVEL}". Skipping ')
|
|
117
|
+
else :
|
|
118
|
+
self.set_level(EASY_UTILS_DEBUG_LEVEL)
|
|
119
|
+
if os.environ.get("EASY_UTILS_ENABLE_PRINT" , '' ).lower() == 'true' :
|
|
120
|
+
self.enable_print()
|
|
121
|
+
|
|
122
|
+
def switch_full_syntax(self , toggle) :
|
|
123
|
+
if toggle :
|
|
124
|
+
f = f"[%(asctime)s]-[{self.name}]-[%(levelname)s]: %(message)s"
|
|
125
|
+
else :
|
|
126
|
+
f = f"[{self.name}]-[%(levelname)s]: %(message)s"
|
|
127
|
+
self.syntax = f
|
|
128
|
+
self.formatter = logging.Formatter(f , datefmt='%Y-%m-%d %H:%M:%S' )
|
|
129
|
+
self.console.setFormatter(self.formatter)
|
|
130
|
+
|
|
131
|
+
def custom_log_syntax(self , syntax) :
|
|
132
|
+
'''
|
|
133
|
+
f"[%(asctime)s]-[{self.name}]-[%(levelname)s]: %(message)s"
|
|
134
|
+
'''
|
|
135
|
+
f = syntax
|
|
136
|
+
self.syntax = f
|
|
137
|
+
self.formatter = logging.Formatter(f , datefmt='%Y-%m-%d %H:%M:%S' )
|
|
138
|
+
self.console.setFormatter(self.formatter)
|
|
139
|
+
|
|
140
|
+
def updateGlobalHomePath(self ) :
|
|
141
|
+
if not self.isLogWriteDisabled :
|
|
142
|
+
getFromEnv = self.env.get('debugger_homepath' , None )
|
|
143
|
+
self.homepath(getFromEnv)
|
|
144
|
+
if getFromEnv :
|
|
145
|
+
self.file_handler_class = self.createRotateFileHandler(self.homePath)
|
|
146
|
+
|
|
147
|
+
def updateGlobalSetLevel( self ) :
|
|
148
|
+
self.set_level(self.env['debugger_global_level'])
|
|
149
|
+
|
|
150
|
+
def advertiseGlobalDebugLevel(self , level) :
|
|
151
|
+
setGlobalDebugLevel(level)
|
|
152
|
+
|
|
153
|
+
def disable_rotate(self) :
|
|
154
|
+
self.rotate_disabled = True
|
|
155
|
+
|
|
156
|
+
def enable_rotate(self) :
|
|
157
|
+
self.rotate_disabled = False
|
|
158
|
+
|
|
159
|
+
def createRotateFileHandler( self , path ) :
|
|
160
|
+
old = self.file_handler_class
|
|
161
|
+
if old :
|
|
162
|
+
self.logger.removeHandler(old)
|
|
163
|
+
file_handler = RotatingFileHandler(path , maxBytes=self.LOG_SIZE_THRESHOLD_IN_BYTES , backupCount=self.BACKUP_COUNT , delay=True )
|
|
164
|
+
self.file_handler= file_handler.setFormatter(self.formatter)
|
|
165
|
+
self.logger.addHandler(file_handler)
|
|
166
|
+
return file_handler
|
|
167
|
+
|
|
168
|
+
def update_log_iterantions_threshold(self,threshold : int ):
|
|
169
|
+
'''
|
|
170
|
+
set value when rotation should be checked. when every on_log function called.
|
|
171
|
+
by default rotation will be checked every 200 on_log function call.
|
|
172
|
+
'''
|
|
173
|
+
self.log_iterations_threshold = threshold
|
|
174
|
+
|
|
175
|
+
def updateGlobalDebugger(self , logger ) :
|
|
176
|
+
'''
|
|
177
|
+
this function pass the log message to other logger to write the same log message to it.
|
|
178
|
+
logger must be debugger class.
|
|
179
|
+
'''
|
|
180
|
+
if logger.type != 'CUSTOM_DEBUGGER' :
|
|
181
|
+
raise Exception(f'Invalid logger type. must pass debugger class.')
|
|
182
|
+
self.global_debugger = logger
|
|
183
|
+
|
|
184
|
+
def getStreamServiceUrlPath(self) :
|
|
185
|
+
return self.streampath
|
|
186
|
+
|
|
187
|
+
def getStreamService(self) :
|
|
188
|
+
return self.stream_service
|
|
189
|
+
|
|
190
|
+
def isStreamServiceAvailable(self) :
|
|
191
|
+
if self.stream_service :
|
|
192
|
+
return True
|
|
193
|
+
return False
|
|
194
|
+
|
|
195
|
+
def addStreamService( self , socketio , streampath='/debugger/stream/log' ) :
|
|
196
|
+
"""
|
|
197
|
+
This function takes a live socketio server. it emit the log message using default path which is /debugger/stream/log
|
|
198
|
+
"""
|
|
199
|
+
self.stream_service = socketio
|
|
200
|
+
self.streampath = streampath
|
|
201
|
+
|
|
202
|
+
def updateLogName( self , name ) :
|
|
203
|
+
self.name = name
|
|
204
|
+
|
|
205
|
+
def disable_log_write(self) :
|
|
206
|
+
'''
|
|
207
|
+
this function is used to disable the log write to file. if onScreen is enabled, logs will be displayed only on screen.
|
|
208
|
+
'''
|
|
209
|
+
self.isLogWriteDisabled = True
|
|
210
|
+
if self.file_handler_class :
|
|
211
|
+
self.logger.removeHandler(self.file_handler_class)
|
|
212
|
+
|
|
213
|
+
def enable_log_write(self) :
|
|
214
|
+
self.createRotateFileHandler(self.homePath)
|
|
215
|
+
|
|
216
|
+
def manage_file_rotation(self, record ) :
|
|
217
|
+
handler = self.get_rotate_handler()
|
|
218
|
+
if handler.shouldRollover(record) :
|
|
219
|
+
handler.doRollover()
|
|
220
|
+
self.log_iterations = 0
|
|
221
|
+
|
|
222
|
+
def get_rotate_handler(self) :
|
|
223
|
+
return self.file_handler_class
|
|
224
|
+
|
|
225
|
+
def change_log_size(self, size) -> bool:
|
|
226
|
+
'''
|
|
227
|
+
change the size of each log file rotation.
|
|
228
|
+
default is 10M
|
|
229
|
+
size should be passed as MB
|
|
230
|
+
'''
|
|
231
|
+
size = convert_mb_to_bytes(size)
|
|
232
|
+
self.LOG_SIZE_THRESHOLD_IN_BYTES = size
|
|
233
|
+
handler = self.get_rotate_handler()
|
|
234
|
+
handler.maxBytes = size
|
|
235
|
+
return True
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def checks_in_bg(self) :
|
|
239
|
+
while True :
|
|
240
|
+
if self.env.get('GLOBAL_DEBUGGER_STREAM_SERVICE') :
|
|
241
|
+
self.addStreamService(socketio=self.env.get('GLOBAL_DEBUGGER_STREAM_SERVICE'))
|
|
242
|
+
if self.env.get('debugger_global_level' , None) :
|
|
243
|
+
self.set_level( level=self.env.get('debugger_global_level') )
|
|
244
|
+
if not self.env.get('debugger_on_screen' , True ) :
|
|
245
|
+
self.disable_print()
|
|
246
|
+
if self.env.get('debugger_on_screen' , True ) :
|
|
247
|
+
self.enable_print()
|
|
248
|
+
if os.environ.get("EASY_UTILS_DEBUG_LEVEL") :
|
|
249
|
+
EASY_UTILS_DEBUG_LEVEL = os.environ.get("EASY_UTILS_DEBUG_LEVEL")
|
|
250
|
+
if not EASY_UTILS_DEBUG_LEVEL.lower() in ['info' , 'debug' , 'warning' , 'error' , 'critical'] :
|
|
251
|
+
self.logger.error(f'EASY_UTILS_DEBUG_LEVEL ENV must be one of [info,debug,warning,error,critical] | Current Env Variable Is "{EASY_UTILS_DEBUG_LEVEL}". Skipping ')
|
|
252
|
+
else :
|
|
253
|
+
self.set_level(EASY_UTILS_DEBUG_LEVEL)
|
|
254
|
+
self.updateGlobalHomePath()
|
|
255
|
+
if os.environ.get("EASY_UTILS_ENABLE_PRINT" , '' ).lower() == 'true' :
|
|
256
|
+
self.enable_print()
|
|
257
|
+
sleep(5)
|
|
258
|
+
|
|
259
|
+
def close(self) :
|
|
260
|
+
try :
|
|
261
|
+
logging.shutdown()
|
|
262
|
+
except :
|
|
263
|
+
pass
|
|
264
|
+
|
|
265
|
+
def homepath(self , path=None ) :
|
|
266
|
+
env = custom_env()
|
|
267
|
+
getFromEnv = env.get('debugger_homepath' , None )
|
|
268
|
+
if getFromEnv is not None :
|
|
269
|
+
self.homePath = getFromEnv
|
|
270
|
+
else :
|
|
271
|
+
if path is not None :
|
|
272
|
+
if self.homePath and '.log' in str(self.homePath):
|
|
273
|
+
self.lastAbsoluteHomePath= self.homePath
|
|
274
|
+
self.homePath = path
|
|
275
|
+
else :
|
|
276
|
+
self.homePath = os.path.join(os.getcwd() , 'debug')
|
|
277
|
+
if not os.path.exists( self.homePath ) :
|
|
278
|
+
try :
|
|
279
|
+
os.makedirs( self.homePath )
|
|
280
|
+
except :
|
|
281
|
+
pass
|
|
282
|
+
if self.filename :
|
|
283
|
+
self.homePath = os.path.join( self.homePath, f'{self.filename}.log' )
|
|
284
|
+
else :
|
|
285
|
+
self.homePath = os.path.join( self.homePath, f'{self.name}.log' )
|
|
286
|
+
return self.homePath
|
|
287
|
+
|
|
288
|
+
def get_current_levels(self):
|
|
289
|
+
"""
|
|
290
|
+
Returns a list of log levels that will be printed based on the current logging level.
|
|
291
|
+
"""
|
|
292
|
+
levels_order = [
|
|
293
|
+
('debug', logging.DEBUG),
|
|
294
|
+
('info', logging.INFO),
|
|
295
|
+
('warning', logging.WARNING),
|
|
296
|
+
('error', logging.ERROR),
|
|
297
|
+
('critical', logging.CRITICAL),
|
|
298
|
+
]
|
|
299
|
+
# Optional custom level
|
|
300
|
+
if hasattr(logging, 'SCREEN'):
|
|
301
|
+
levels_order.append(('screen', logging.SCREEN))
|
|
302
|
+
current_level = self.logger.level
|
|
303
|
+
# Return all levels with numeric value >= current_level
|
|
304
|
+
return [name for name, value in levels_order if value >= current_level]
|
|
305
|
+
|
|
306
|
+
def enable_print(self) :
|
|
307
|
+
self.onScreen = True
|
|
308
|
+
self.logger.addHandler(self.console)
|
|
309
|
+
|
|
310
|
+
def disable_print(self) :
|
|
311
|
+
self.onScreen = False
|
|
312
|
+
self.logger.removeHandler(self.console)
|
|
313
|
+
|
|
314
|
+
def changeHomePath( self , path ) :
|
|
315
|
+
p = self.homepath(path)
|
|
316
|
+
self.file_handler_class = self.createRotateFileHandler(p)
|
|
317
|
+
if self.lastAbsoluteHomePath :
|
|
318
|
+
os.remove(self.lastAbsoluteHomePath)
|
|
319
|
+
|
|
320
|
+
def isGlobalDebuggerDefined(self) :
|
|
321
|
+
if self.global_debugger :
|
|
322
|
+
return True
|
|
323
|
+
else :
|
|
324
|
+
return False
|
|
325
|
+
|
|
326
|
+
def set_level(self, level : str):
|
|
327
|
+
if 'info' in level.lower() : lvl = logging.INFO
|
|
328
|
+
elif 'warn' in level.lower() : lvl = logging.WARNING
|
|
329
|
+
elif 'warning' in level.lower() : lvl = logging.WARNING
|
|
330
|
+
elif 'critical' in level.lower() : lvl = logging.CRITICAL
|
|
331
|
+
elif 'debug' in level.lower() : lvl = logging.DEBUG
|
|
332
|
+
elif 'error' in level.lower() : lvl = logging.ERROR
|
|
333
|
+
elif 'screen' in level.lower() : lvl = logging.SCREEN
|
|
334
|
+
else : raise ValueError('Unknown level, not one of [info,warn,warning,critical,debug,error,screen]')
|
|
335
|
+
self.currentDebugLevel = level
|
|
336
|
+
self.logger.setLevel(lvl)
|
|
337
|
+
|
|
338
|
+
def get_current_debug_level(self) :
|
|
339
|
+
return self.currentDebugLevel
|
|
340
|
+
|
|
341
|
+
def get_logger(self) :
|
|
342
|
+
return self.logger
|
|
343
|
+
|
|
344
|
+
def before_log(self , message , level) :
|
|
345
|
+
|
|
346
|
+
def __call_thread__() :
|
|
347
|
+
if not level in self.get_current_levels() :
|
|
348
|
+
return
|
|
349
|
+
if self.isStreamServiceAvailable() :
|
|
350
|
+
d = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
351
|
+
streamUrl = self.getStreamServiceUrlPath()
|
|
352
|
+
self.stream_service.emit( streamUrl , {
|
|
353
|
+
'message' : message ,
|
|
354
|
+
'level' : level ,
|
|
355
|
+
'msg' : message,
|
|
356
|
+
'date' : d ,
|
|
357
|
+
'id' : self.id,
|
|
358
|
+
'formate' : 'json' ,
|
|
359
|
+
'source' : self.name ,
|
|
360
|
+
'getTimestamp' : getTimestamp()
|
|
361
|
+
})
|
|
362
|
+
try :
|
|
363
|
+
t= Thread(target=__call_thread__)
|
|
364
|
+
# t.daemon=True
|
|
365
|
+
t.start()
|
|
366
|
+
except :
|
|
367
|
+
__call_thread__()
|
|
368
|
+
|
|
369
|
+
params = {
|
|
370
|
+
'screen' : True ,
|
|
371
|
+
'file': True
|
|
372
|
+
}
|
|
373
|
+
if self.onScreen and self.env['debugger_on_screen'] == True :
|
|
374
|
+
params['screen'] = True
|
|
375
|
+
else :
|
|
376
|
+
params['screen'] = False
|
|
377
|
+
return params
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def info(self, message , external_debugger=None,source=None):
|
|
381
|
+
def __call__(message) :
|
|
382
|
+
if source :
|
|
383
|
+
message = f'[{source}]-{message}'
|
|
384
|
+
self.before_log(message , 'info')
|
|
385
|
+
self.logger.info(message)
|
|
386
|
+
if self.isGlobalDebuggerDefined() :
|
|
387
|
+
self.global_debugger.info(message)
|
|
388
|
+
if external_debugger :
|
|
389
|
+
external_debugger.info(message)
|
|
390
|
+
try :
|
|
391
|
+
r=Thread(target=__call__,args=[message])
|
|
392
|
+
r.daemon=True
|
|
393
|
+
r.start()
|
|
394
|
+
r.join()
|
|
395
|
+
except :
|
|
396
|
+
__call__(message)
|
|
397
|
+
|
|
398
|
+
def debug(self, message , external_debugger=None,source=None):
|
|
399
|
+
def __call__(message) :
|
|
400
|
+
if source :
|
|
401
|
+
message = f'[{source}]-{message}'
|
|
402
|
+
self.before_log(message , 'debug')
|
|
403
|
+
self.logger.debug(message)
|
|
404
|
+
if self.isGlobalDebuggerDefined() :
|
|
405
|
+
self.global_debugger.debug(message)
|
|
406
|
+
if external_debugger :
|
|
407
|
+
external_debugger.debug(message)
|
|
408
|
+
try :
|
|
409
|
+
r=Thread(target=__call__,args=[message])
|
|
410
|
+
r.daemon=True
|
|
411
|
+
r.start()
|
|
412
|
+
r.join()
|
|
413
|
+
except :
|
|
414
|
+
__call__(message)
|
|
415
|
+
|
|
416
|
+
def warning(self, message , external_debugger=None,source=None):
|
|
417
|
+
def __call__(message) :
|
|
418
|
+
if source :
|
|
419
|
+
message = f'[{source}]-{message}'
|
|
420
|
+
self.before_log(message , 'warning')
|
|
421
|
+
self.logger.warning(message)
|
|
422
|
+
if self.isGlobalDebuggerDefined() :
|
|
423
|
+
self.global_debugger.warning(message)
|
|
424
|
+
if external_debugger :
|
|
425
|
+
external_debugger.warning(message)
|
|
426
|
+
try :
|
|
427
|
+
r=Thread(target=__call__,args=[message])
|
|
428
|
+
r.daemon=True
|
|
429
|
+
r.start()
|
|
430
|
+
r.join()
|
|
431
|
+
except :
|
|
432
|
+
__call__(message)
|
|
433
|
+
|
|
434
|
+
def error(self, message,external_debugger=None,source=None):
|
|
435
|
+
def __call__(message) :
|
|
436
|
+
if source :
|
|
437
|
+
message = f'[{source}]-{message}'
|
|
438
|
+
self.before_log(message , 'error')
|
|
439
|
+
self.logger.error(message)
|
|
440
|
+
if self.isGlobalDebuggerDefined() :
|
|
441
|
+
self.global_debugger.error(message)
|
|
442
|
+
if external_debugger :
|
|
443
|
+
external_debugger.error(message)
|
|
444
|
+
try :
|
|
445
|
+
r=Thread(target=__call__,args=[message])
|
|
446
|
+
r.daemon=True
|
|
447
|
+
r.start()
|
|
448
|
+
r.join()
|
|
449
|
+
except :
|
|
450
|
+
__call__(message)
|
|
451
|
+
|
|
452
|
+
def critical(self, message,external_debugger=None,source=None):
|
|
453
|
+
def __call__() :
|
|
454
|
+
if source :
|
|
455
|
+
message = f'[{source}]-{message}'
|
|
456
|
+
self.before_log(message , 'critical')
|
|
457
|
+
self.logger.critical(message)
|
|
458
|
+
if self.isGlobalDebuggerDefined() :
|
|
459
|
+
self.global_debugger.critical(message)
|
|
460
|
+
if external_debugger :
|
|
461
|
+
external_debugger.critical(message)
|
|
462
|
+
try :
|
|
463
|
+
r=Thread(target=__call__,args=[message])
|
|
464
|
+
r.daemon=True
|
|
465
|
+
r.start()
|
|
466
|
+
r.join()
|
|
467
|
+
except :
|
|
468
|
+
__call__(message)
|
|
469
|
+
|
|
470
|
+
def screen(self, message,external_debugger=None,source=None):
|
|
471
|
+
def __call__() :
|
|
472
|
+
if source :
|
|
473
|
+
message = f'[{source}]-{message}'
|
|
474
|
+
self.before_log(message , 'critical')
|
|
475
|
+
print(f"{self.syntax}")
|
|
476
|
+
if self.isGlobalDebuggerDefined() :
|
|
477
|
+
self.global_debugger.critical(message)
|
|
478
|
+
if external_debugger :
|
|
479
|
+
external_debugger.critical(message)
|
|
480
|
+
try :
|
|
481
|
+
r=Thread(target=__call__,args=[message])
|
|
482
|
+
r.daemon=True
|
|
483
|
+
r.start()
|
|
484
|
+
r.join()
|
|
485
|
+
except :
|
|
486
|
+
__call__(message)
|
easy_utils_dev/debugger.py
CHANGED
|
@@ -128,6 +128,15 @@ class DEBUGGER:
|
|
|
128
128
|
self.formatter = logging.Formatter(f , datefmt='%Y-%m-%d %H:%M:%S' )
|
|
129
129
|
self.console.setFormatter(self.formatter)
|
|
130
130
|
|
|
131
|
+
def custom_log_syntax(self , syntax) :
|
|
132
|
+
'''
|
|
133
|
+
f"[%(asctime)s]-[{self.name}]-[%(levelname)s]: %(message)s"
|
|
134
|
+
'''
|
|
135
|
+
f = syntax
|
|
136
|
+
self.syntax = f
|
|
137
|
+
self.formatter = logging.Formatter(f , datefmt='%Y-%m-%d %H:%M:%S' )
|
|
138
|
+
self.console.setFormatter(self.formatter)
|
|
139
|
+
|
|
131
140
|
def updateGlobalHomePath(self ) :
|
|
132
141
|
if not self.isLogWriteDisabled :
|
|
133
142
|
getFromEnv = self.env.get('debugger_homepath' , None )
|
easy_utils_dev/temp_memory.py
CHANGED
|
@@ -17,21 +17,28 @@ class TemporaryMemory :
|
|
|
17
17
|
sleep(5)
|
|
18
18
|
now = getTimestamp()
|
|
19
19
|
for key, value in list(self.store.items()) :
|
|
20
|
-
if
|
|
21
|
-
if value.get('
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
if value.get('removeTimestamp') :
|
|
21
|
+
if now >= value.get('removeTimestamp' , 0) :
|
|
22
|
+
if value.get('store_deleted_key' , False) :
|
|
23
|
+
self.deletions.append(key)
|
|
24
|
+
self.delete(key)
|
|
24
25
|
|
|
25
26
|
def delete(self , key ) :
|
|
26
|
-
|
|
27
|
+
try :
|
|
28
|
+
del self.store[key]
|
|
29
|
+
except :
|
|
30
|
+
pass
|
|
27
31
|
gc.collect()
|
|
28
32
|
|
|
29
|
-
def get(self , key ) :
|
|
30
|
-
return self.store.get(key , {}).get('item')
|
|
33
|
+
def get(self , key , default=None ) :
|
|
34
|
+
return self.store.get(key , {}).get('item' , default)
|
|
31
35
|
|
|
32
36
|
def save(self, item , custom_key=None ,auto_destroy_period=60 , store_deleted_key=True) :
|
|
33
37
|
now = getTimestamp()
|
|
34
|
-
|
|
38
|
+
if auto_destroy_period :
|
|
39
|
+
later = getTimestamp(after_seconds=auto_destroy_period)
|
|
40
|
+
else :
|
|
41
|
+
later = None
|
|
35
42
|
if not custom_key :
|
|
36
43
|
custom_key = f"{getTimestamp()}-{generateToken(iter=4)}".upper()
|
|
37
44
|
self.store[custom_key] = {
|
easy_utils_dev/wsnoclib.py
CHANGED
|
@@ -80,6 +80,7 @@ class WSNOCLIB :
|
|
|
80
80
|
self.refresh_inprogress = False
|
|
81
81
|
self.kafka = kafka
|
|
82
82
|
self.refresh_thread = None
|
|
83
|
+
self.token_refresh_count = 0
|
|
83
84
|
self.session = WSNOCSession(self)
|
|
84
85
|
if register_atexit :
|
|
85
86
|
atexit.register(self.goodbye)
|
|
@@ -135,7 +136,7 @@ class WSNOCLIB :
|
|
|
135
136
|
data = {
|
|
136
137
|
"grant_type": "client_credentials"
|
|
137
138
|
}
|
|
138
|
-
r = self.session.post(url = URL , headers=headers , auth=BAuth(self.username, self.password), json=data)
|
|
139
|
+
r = self.session.post(url = URL , headers=headers , auth=BAuth(self.username, self.password), json=data , retries=5)
|
|
139
140
|
if not r.ok :
|
|
140
141
|
self.logger.debug(f'fail message {r.text}')
|
|
141
142
|
raise Exception(f'Failed to authenticate WSNOC. Return status code : {r.status_code}')
|
|
@@ -200,6 +201,7 @@ class WSNOCLIB :
|
|
|
200
201
|
if self.kafka.enable_auto_refresh :
|
|
201
202
|
self.renewSubscription()
|
|
202
203
|
self.kafka.refresh_inprogress = False
|
|
204
|
+
self.token_refresh_count += 1
|
|
203
205
|
self.runAutoRefreshThread()
|
|
204
206
|
|
|
205
207
|
def kafka_connect( self ,
|
|
@@ -704,17 +706,18 @@ class WSNOCSession(requests.Session):
|
|
|
704
706
|
self._wsnoc = wsnoc
|
|
705
707
|
self.verify = False
|
|
706
708
|
self.retries = 0
|
|
709
|
+
self.debug_this_request = False
|
|
707
710
|
self.skip_hold_for_token_refresh = False
|
|
708
711
|
|
|
709
712
|
def rebuild_auth(self, prepared_request, response):
|
|
710
713
|
return
|
|
711
714
|
|
|
712
|
-
def hold_for_token_refresh(self, url) :
|
|
715
|
+
def hold_for_token_refresh(self, url=None) :
|
|
713
716
|
while self._wsnoc.refresh_inprogress :
|
|
714
|
-
self._wsnoc.logger.
|
|
715
|
-
sleep(.
|
|
717
|
+
self._wsnoc.logger.info(f'Waiting for token refresh. {url if url else "No URL"}')
|
|
718
|
+
sleep(.5)
|
|
716
719
|
|
|
717
|
-
def request(self, method, url , retries=0 , skip_hold_for_token_refresh=False , **kwargs):
|
|
720
|
+
def request(self, method, url , retries=0 , skip_hold_for_token_refresh=False , debug_this_request=False , **kwargs):
|
|
718
721
|
self._wsnoc.logger.debug(f'[{method}] : {url}')
|
|
719
722
|
if not skip_hold_for_token_refresh :
|
|
720
723
|
self.hold_for_token_refresh(url)
|
|
@@ -726,12 +729,21 @@ class WSNOCSession(requests.Session):
|
|
|
726
729
|
request_headers['Authorization'] = token
|
|
727
730
|
kwargs['headers'] = request_headers
|
|
728
731
|
request = super().request(method, url, **kwargs )
|
|
732
|
+
if debug_this_request :
|
|
733
|
+
self._wsnoc.logger.info(f'''
|
|
734
|
+
[DEBUG] [{method}] : {url}
|
|
735
|
+
[DEBUG] Headers: {request_headers}
|
|
736
|
+
[DEBUG] Body: {kwargs.get('data' , {})}
|
|
737
|
+
[DEBUG] Response: {request.text}
|
|
738
|
+
[DEBUG] OK: {request.ok}
|
|
739
|
+
[DEBUG] Method: {request.request.method}
|
|
740
|
+
''')
|
|
729
741
|
for i in range(retries) :
|
|
730
742
|
if request.ok :
|
|
731
743
|
break
|
|
732
744
|
if not request.ok :
|
|
733
745
|
sleep(1)
|
|
734
|
-
self.hold_for_token_refresh()
|
|
746
|
+
self.hold_for_token_refresh(url)
|
|
735
747
|
request = super().request(method, url, **kwargs )
|
|
736
748
|
self._wsnoc.logger.debug(f'[Try-{i}] [{method}] : {url}- {request.status_code}')
|
|
737
749
|
self._wsnoc.logger.info(f'[{method}] : {url} - [{request.status_code}]')
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
2
|
-
Name:
|
|
3
|
-
Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: easy_utils_dev
|
|
3
|
+
Version: 2.140
|
|
4
4
|
Keywords: python3
|
|
5
5
|
Classifier: Programming Language :: Python :: 3
|
|
6
6
|
Requires-Dist: psutil
|
|
7
7
|
Requires-Dist: ping3
|
|
8
8
|
Requires-Dist: flask
|
|
9
|
-
Requires-Dist:
|
|
9
|
+
Requires-Dist: flask_cors
|
|
10
10
|
Requires-Dist: xmltodict
|
|
11
11
|
Requires-Dist: paramiko
|
|
12
12
|
Requires-Dist: oracledb
|
|
13
13
|
Requires-Dist: requests
|
|
14
|
-
Requires-Dist:
|
|
14
|
+
Requires-Dist: flask_socketio
|
|
15
15
|
Requires-Dist: python-dotenv
|
|
16
16
|
Requires-Dist: gevent
|
|
17
17
|
Requires-Dist: pyzipper
|
|
18
18
|
Requires-Dist: pyjwt
|
|
19
19
|
Requires-Dist: authlib
|
|
20
20
|
Requires-Dist: kafka-python
|
|
21
|
-
|
|
21
|
+
Dynamic: classifier
|
|
22
|
+
Dynamic: keywords
|
|
23
|
+
Dynamic: requires-dist
|
|
@@ -8,7 +8,8 @@ easy_utils_dev/brevosmtp.py,sha256=A5n13MnVQnDuSjYQ91-MLftmqfg3VQ-36Zqw9OtoTB4,3
|
|
|
8
8
|
easy_utils_dev/check_license.py,sha256=C8vKXwaduoF3FSuDJ-J_j5jStNNyUdS-mOdLNfsCjmc,4825
|
|
9
9
|
easy_utils_dev/cplib.py,sha256=TPCFNQh4jYSGsm_CrMdivmD3G5B1rprco2O4B0BSnzo,19570
|
|
10
10
|
easy_utils_dev/custom_env.py,sha256=vxrjikpSNJlKfoBE-ef88UExlpXucUe-HcwHMn3gfB0,1510
|
|
11
|
-
easy_utils_dev/debugger.py,sha256=
|
|
11
|
+
easy_utils_dev/debugger-C-PF4PAMMP.py,sha256=5GmZU1l9R3CSZVIGff-l-gYaf-imJGSGTsh-cxNz6og,18637
|
|
12
|
+
easy_utils_dev/debugger.py,sha256=5GmZU1l9R3CSZVIGff-l-gYaf-imJGSGTsh-cxNz6og,18637
|
|
12
13
|
easy_utils_dev/easy_oracle.py,sha256=Jyc3HSl6eyLayjS8NoE4GOaf8otQlonR5_qOg2h1DjE,2157
|
|
13
14
|
easy_utils_dev/encryptor.py,sha256=f5Zjn0DGtXCyhldpVnBtfcTb4h4Wp0eQPHusEYwIags,1512
|
|
14
15
|
easy_utils_dev/ept.py,sha256=X-Z0_XCNfKK1TxQZquPMBqo3ZuxnK4TvWAYPnBUMlPI,25363
|
|
@@ -23,15 +24,15 @@ easy_utils_dev/openid_server.py,sha256=_odeg6omuizSUEJLtbAVn2PnG9vkcUAQ7rU3K5yXk
|
|
|
23
24
|
easy_utils_dev/optics_utils.py,sha256=G-hFX2iiUCSJjk7BICBRGvVoDq0IBONLZSjagoB5FMg,964
|
|
24
25
|
easy_utils_dev/require_auth.py,sha256=UsYAxfLX5wda6hd0nfLR_tl0bGQ4DYIpaTowsYSku-E,881
|
|
25
26
|
easy_utils_dev/simple_sqlite.py,sha256=J-mcTUnHmAn0eCPD8j-WEoA19uzHRXJ4YRJsyx9B-do,13113
|
|
26
|
-
easy_utils_dev/temp_memory.py,sha256=
|
|
27
|
+
easy_utils_dev/temp_memory.py,sha256=0Dx_vNUSFQRMtJZNT8tUZXubcG7T6jxevw2WYuGmVe8,1658
|
|
27
28
|
easy_utils_dev/uiserver.py,sha256=d9jImwgSURMH4MIU4Zkro2b20cAbuV8rO_If42FVyZ4,6826
|
|
28
29
|
easy_utils_dev/utils.py,sha256=BmVnbxc336c6WTeDFcEHN6Mavt7fJrIEyK4GXODV3gI,13345
|
|
29
30
|
easy_utils_dev/winserviceapi.py,sha256=2ZP6jaSt1-5vEJYXqwBhwX-1-eQ3V3YzntsoOoko2cw,18804
|
|
30
|
-
easy_utils_dev/wsnoclib.py,sha256=
|
|
31
|
+
easy_utils_dev/wsnoclib.py,sha256=kqkOkiafXnrIgdlV__3uyrAoqxG5dmIHnwqm0EkwS2U,33457
|
|
31
32
|
easy_utils_dev/wsselib.py,sha256=YweScnoAAH_t29EeIjBpkQ6HtX0Rp9mQudRsRce2SE8,7920
|
|
32
33
|
easy_utils_dev/ept_sql/create_dirs.sql,sha256=KWfX-Nc6lvr_BC-P6O97NE0idoPW4GNKUKUCgonJhto,3508
|
|
33
34
|
easy_utils_dev/ept_sql/create_ept_tables.sql,sha256=WDHyIyeReV8_QaYBPIpSy-lto3OKvZtex1tWs-FPURQ,67737
|
|
34
|
-
easy_utils_dev-2.
|
|
35
|
-
easy_utils_dev-2.
|
|
36
|
-
easy_utils_dev-2.
|
|
37
|
-
easy_utils_dev-2.
|
|
35
|
+
easy_utils_dev-2.140.dist-info/METADATA,sha256=11wRCPmmDl1s7jptVfwy-_ru_jnkTn2nJMcJ-dM07uM,572
|
|
36
|
+
easy_utils_dev-2.140.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
37
|
+
easy_utils_dev-2.140.dist-info/top_level.txt,sha256=7vBsrpq7NmilkdU3YUvfd5iVDNBaT07u_-ut4F7zc7A,15
|
|
38
|
+
easy_utils_dev-2.140.dist-info/RECORD,,
|
|
File without changes
|