easy-utils-dev 2.94__tar.gz → 2.140__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. easy_utils_dev-2.140/MANIFEST.in +1 -0
  2. easy_utils_dev-2.140/PKG-INFO +23 -0
  3. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/EasySsh.py +1 -1
  4. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/FastQueue.py +27 -6
  5. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/__init__.py +3 -1
  6. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/check_license.py +14 -9
  7. easy_utils_dev-2.140/easy_utils_dev/debugger-C-PF4PAMMP.py +486 -0
  8. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/debugger.py +81 -28
  9. easy_utils_dev-2.140/easy_utils_dev/ept.py +655 -0
  10. easy_utils_dev-2.140/easy_utils_dev/ept_sql/create_dirs.sql +82 -0
  11. easy_utils_dev-2.140/easy_utils_dev/ept_sql/create_ept_tables.sql +3559 -0
  12. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/exceptions.py +8 -0
  13. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/generate_license.py +11 -4
  14. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/ne1830PSS.py +235 -102
  15. easy_utils_dev-2.140/easy_utils_dev/nsp_kafka.py +240 -0
  16. easy_utils_dev-2.140/easy_utils_dev/openid_server.py +71 -0
  17. easy_utils_dev-2.140/easy_utils_dev/require_auth.py +21 -0
  18. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/simple_sqlite.py +76 -31
  19. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/temp_memory.py +15 -8
  20. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/uiserver.py +5 -1
  21. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/utils.py +2 -1
  22. easy_utils_dev-2.140/easy_utils_dev/wsnoclib.py +774 -0
  23. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/wsselib.py +0 -1
  24. easy_utils_dev-2.140/easy_utils_dev.egg-info/PKG-INFO +23 -0
  25. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev.egg-info/SOURCES.txt +9 -1
  26. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev.egg-info/requires.txt +2 -0
  27. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/setup.py +5 -2
  28. easy_utils_dev-2.94/PKG-INFO +0 -5
  29. easy_utils_dev-2.94/easy_utils_dev/wsnoclib.py +0 -526
  30. easy_utils_dev-2.94/easy_utils_dev.egg-info/PKG-INFO +0 -5
  31. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/Events.py +0 -0
  32. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/NameObject.py +0 -0
  33. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/abortable.py +0 -0
  34. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/brevosmtp.py +0 -0
  35. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/cplib.py +0 -0
  36. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/custom_env.py +0 -0
  37. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/easy_oracle.py +0 -0
  38. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/encryptor.py +0 -0
  39. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/filescompressor.py +0 -0
  40. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/keycloakapi.py +0 -0
  41. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/lralib.py +0 -0
  42. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/optics_utils.py +0 -0
  43. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev/winserviceapi.py +0 -0
  44. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev.egg-info/dependency_links.txt +0 -0
  45. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/easy_utils_dev.egg-info/top_level.txt +0 -0
  46. {easy_utils_dev-2.94 → easy_utils_dev-2.140}/setup.cfg +0 -0
@@ -0,0 +1 @@
1
+ recursive-include easy_utils_dev/ept_sql *.sql
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: easy_utils_dev
3
+ Version: 2.140
4
+ Keywords: python3
5
+ Classifier: Programming Language :: Python :: 3
6
+ Requires-Dist: psutil
7
+ Requires-Dist: ping3
8
+ Requires-Dist: flask
9
+ Requires-Dist: flask_cors
10
+ Requires-Dist: xmltodict
11
+ Requires-Dist: paramiko
12
+ Requires-Dist: oracledb
13
+ Requires-Dist: requests
14
+ Requires-Dist: flask_socketio
15
+ Requires-Dist: python-dotenv
16
+ Requires-Dist: gevent
17
+ Requires-Dist: pyzipper
18
+ Requires-Dist: pyjwt
19
+ Requires-Dist: authlib
20
+ Requires-Dist: kafka-python
21
+ Dynamic: classifier
22
+ Dynamic: keywords
23
+ Dynamic: requires-dist
@@ -69,7 +69,7 @@ class CREATESSH :
69
69
  ch.disconnect = disconnect
70
70
  return ch
71
71
 
72
- def ssh_execute(self ,command , merge_output=False , hide_output=False) :
72
+ def ssh_execute(self ,command , merge_output=False , hide_output=True) :
73
73
  self.logger.info(f"executing {command}")
74
74
  try :
75
75
  stdin_ , stdout_ , stderr_ = self.ssh.exec_command(command)
@@ -24,11 +24,12 @@ class FastQueue :
24
24
  actionArgs = task['actionArgs']
25
25
  onComplete = task['onComplete']
26
26
  onFailure = task['onFailure']
27
- onFailureArgs = task['onFailureArgs']
28
- onCompleteArgs = task['onCompleteArgs']
27
+ onFailureArgs : dict = task['onFailureArgs']
28
+ onCompleteArgs : dict = task['onCompleteArgs']
29
29
  onSuccess = task['onSuccess']
30
- onSuccessArgs = task['onSuccessArgs']
30
+ onSuccessArgs : dict = task['onSuccessArgs']
31
31
  supressError = task['supressError']
32
+ isSuccess= False
32
33
  result = None
33
34
  try:
34
35
  task['running'] = True
@@ -36,18 +37,38 @@ class FastQueue :
36
37
  task['result'] = result
37
38
  task['completed'] = True
38
39
  task['running'] = False
40
+ task['error'] = None
41
+ task['traceback'] = None
42
+ isSuccess = True
39
43
  if onSuccess :
40
- onSuccess(result , **onSuccessArgs)
44
+ for key , value in task.items() :
45
+ onSuccessArgs.update({ key : value })
46
+ onSuccessArgs.update({'_task' : task })
47
+ onSuccessArgs.update({'result' : result })
48
+ onSuccessArgs.update({'isSuccess' : True })
49
+ onSuccess(**onSuccessArgs)
41
50
  except Exception as e:
51
+ task['error'] = e
52
+ task['traceback']= traceback
42
53
  if onFailure :
43
- onFailure(**onFailureArgs,traceback=traceback.format_exc(),error=str(e))
54
+ onFailureArgs.update({'_task' : task })
55
+ for key , value in task.items() :
56
+ onFailureArgs.update({ key : value })
57
+ onFailureArgs.update({'traceback' : traceback })
58
+ onFailureArgs.update({'error' : e })
59
+ onFailureArgs.update({'isSuccess' : False })
60
+ onFailure(**onFailureArgs)
44
61
  if not supressError :
45
62
  print(traceback.format_exc())
46
63
  task['completed'] = True
47
64
  task['result'] = None
48
65
  task['running'] = False
66
+ onCompleteArgs.update({'_task' : task })
67
+ onCompleteArgs.update({'isSuccess' : isSuccess })
68
+ for key , value in task.items() :
69
+ onCompleteArgs.update({ key : value })
49
70
  if onComplete :
50
- onComplete(result , **onCompleteArgs)
71
+ onComplete(**onCompleteArgs)
51
72
  self.removeFromQueue(task_id)
52
73
  if 'exception' in task and not supressError :
53
74
  raise task['exception']
@@ -20,4 +20,6 @@ from .exceptions import *
20
20
  from .temp_memory import TemporaryMemory
21
21
  from .easy_oracle import *
22
22
  from .abortable import *
23
- from .filescompressor import *
23
+ from .filescompressor import *
24
+ from .require_auth import require_permission
25
+ from .ept import *
@@ -3,6 +3,7 @@ import hashlib
3
3
  import base64 , subprocess , sys
4
4
  from datetime import datetime
5
5
  from .generate_license import generate_license
6
+ import os
6
7
 
7
8
  def get_delta_days(date_str):
8
9
  try :
@@ -23,14 +24,18 @@ def verify_license(license_key, appname, uuid=None, level="basic",return_dict=Fa
23
24
  # print(f'appname={appname}')
24
25
  # print(f'uuid={uuid}')
25
26
  # print(f'level={level}')
26
- if len(key.split('||')) != 2 :
27
+ features=None
28
+ if len(key.split('||')) == 3 :
29
+ features=key.split('||')[2]
30
+ os.environ.update({'LICENSEKEY_FEATURES' : features })
31
+ # print(features)
32
+ if len(key.split('||')) < 1 :
27
33
  if exit_on_failure :
28
34
  sys.exit(f'Invalid license file')
29
35
  if return_dict :
30
- return {'status' : 400 , 'message' : "400_INVALID_LICENSE_FILE" }
36
+ return {'status' : 400 , 'message' : "400_INVALID_LICENSE_FILE" , "features" : features }
31
37
  else :
32
38
  return "400_INVALID_LICENSE_FILE"
33
-
34
39
  license_key = key.split('||')[0].replace('\n' , '')
35
40
  expire_date = key.split('||')[1].replace('\n', '')
36
41
  if disable_expire_days_warn :
@@ -45,7 +50,7 @@ def verify_license(license_key, appname, uuid=None, level="basic",return_dict=Fa
45
50
  if exit_on_failure :
46
51
  sys.exit("400_NOT_SUPPORTED_OS")
47
52
  elif return_dict :
48
- return {'status' : 400 , 'message' : "400_NOT_SUPPORTED_OS" }
53
+ return {'status' : 400 , 'message' : "400_NOT_SUPPORTED_OS" , 'features' : features }
49
54
  return "400_NOT_SUPPORTED_OS"
50
55
 
51
56
  if open_all :
@@ -60,7 +65,7 @@ def verify_license(license_key, appname, uuid=None, level="basic",return_dict=Fa
60
65
  if exit_on_failure :
61
66
  sys.exit(f'400_INCORRECT_LICENSE_FORMAT')
62
67
  if return_dict :
63
- return {'status' : 400 , 'message' : "400_INCORRECT_FORMAT" }
68
+ return {'status' : 400 , 'message' : "400_INCORRECT_FORMAT" , 'features' : features }
64
69
  return "400_INCORRECT_FORMAT"
65
70
  # Convert expected_license_key to bytes
66
71
  expected_key_bytes = base64.b64decode(expected_license_key)
@@ -74,16 +79,16 @@ def verify_license(license_key, appname, uuid=None, level="basic",return_dict=Fa
74
79
  if exit_on_failure :
75
80
  sys.exit(f'License is expired.')
76
81
  if return_dict :
77
- return {'status' : 400 , 'message' : "400_EXPIRED" }
82
+ return {'status' : 400 , 'message' : "400_EXPIRED" , 'features' : features }
78
83
  return "400_EXPIRED"
79
84
  if return_dict :
80
- return {'status' : 200 , 'message' : "200_LICENSE_IS_VALID"}
85
+ return {'status' : 200 , 'message' : "200_LICENSE_IS_VALID" , 'features' : features }
81
86
  return "200"
82
87
  else:
83
88
  if exit_on_failure :
84
- sys.exit(f'License is not valid. license key is not correct.')
89
+ sys.exit(f'License is not valid. license key is not correct.')
85
90
  if return_dict :
86
- return {'status' : 400 , 'message' : "400_LICENSE_NOT_VALID" }
91
+ return {'status' : 400 , 'message' : "400_LICENSE_NOT_VALID" , 'features' : features }
87
92
  return "400_LICENSE_NOT_VALID."
88
93
 
89
94
  def main():
@@ -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)