easy-utils-dev 2.140__tar.gz → 2.141__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.

Potentially problematic release.


This version of easy-utils-dev might be problematic. Click here for more details.

Files changed (44) hide show
  1. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/PKG-INFO +1 -1
  2. easy_utils_dev-2.141/easy_utils_dev/uiserver.py +227 -0
  3. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev.egg-info/PKG-INFO +1 -1
  4. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/setup.py +1 -1
  5. easy_utils_dev-2.140/easy_utils_dev/uiserver.py +0 -193
  6. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/MANIFEST.in +0 -0
  7. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/EasySsh.py +0 -0
  8. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/Events.py +0 -0
  9. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/FastQueue.py +0 -0
  10. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/NameObject.py +0 -0
  11. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/__init__.py +0 -0
  12. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/abortable.py +0 -0
  13. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/brevosmtp.py +0 -0
  14. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/check_license.py +0 -0
  15. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/cplib.py +0 -0
  16. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/custom_env.py +0 -0
  17. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/debugger-C-PF4PAMMP.py +0 -0
  18. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/debugger.py +0 -0
  19. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/easy_oracle.py +0 -0
  20. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/encryptor.py +0 -0
  21. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/ept.py +0 -0
  22. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/ept_sql/create_dirs.sql +0 -0
  23. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/ept_sql/create_ept_tables.sql +0 -0
  24. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/exceptions.py +0 -0
  25. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/filescompressor.py +0 -0
  26. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/generate_license.py +0 -0
  27. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/keycloakapi.py +0 -0
  28. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/lralib.py +0 -0
  29. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/ne1830PSS.py +0 -0
  30. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/nsp_kafka.py +0 -0
  31. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/openid_server.py +0 -0
  32. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/optics_utils.py +0 -0
  33. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/require_auth.py +0 -0
  34. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/simple_sqlite.py +0 -0
  35. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/temp_memory.py +0 -0
  36. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/utils.py +0 -0
  37. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/winserviceapi.py +0 -0
  38. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/wsnoclib.py +0 -0
  39. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev/wsselib.py +0 -0
  40. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev.egg-info/SOURCES.txt +0 -0
  41. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev.egg-info/dependency_links.txt +0 -0
  42. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev.egg-info/requires.txt +0 -0
  43. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/easy_utils_dev.egg-info/top_level.txt +0 -0
  44. {easy_utils_dev-2.140 → easy_utils_dev-2.141}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easy_utils_dev
3
- Version: 2.140
3
+ Version: 2.141
4
4
  Keywords: python3
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Requires-Dist: psutil
@@ -0,0 +1,227 @@
1
+ import copy
2
+ import gc
3
+ import time
4
+ from werkzeug.serving import ThreadedWSGIServer
5
+ from easy_utils_dev.utils import getRandomKey , generateToken , getTimestamp
6
+ from flask_socketio import SocketIO
7
+ from engineio.async_drivers import gevent
8
+ from flask_cors import CORS
9
+ import logging , os
10
+ from flask import jsonify, request , current_app
11
+ from flask import Flask
12
+ from threading import Thread
13
+ import threading
14
+ from easy_utils_dev.custom_env import cenv
15
+ from easy_utils_dev.utils import kill_thread
16
+ from multiprocessing import Process
17
+ from werkzeug.serving import make_ssl_devcert
18
+ from time import sleep
19
+ from easy_utils_dev.utils import start_thread , getRandomKeysAndStr , mkdirs
20
+ from easy_utils_dev.temp_memory import TemporaryMemory
21
+
22
+ def getClassById( id ) :
23
+ return cenv[id]
24
+
25
+ def create_ssl(host,output) :
26
+ '''
27
+ host : is the IP/Adress of the server which servers the web-server
28
+ output: the output locaiton to generate the ssl certificate. it should end with filename without extension
29
+ '''
30
+ return make_ssl_devcert( output , host=host)
31
+
32
+ def clone_request(request):
33
+ """Return a plain dict clone of Flask request data."""
34
+ return {
35
+ "method": request.method,
36
+ "path": request.path,
37
+ "url": request.url,
38
+ "headers": dict(request.headers),
39
+ "args": request.args.to_dict(flat=False),
40
+ "form": request.form.to_dict(flat=False),
41
+ "json": request.get_json(silent=True),
42
+ "data": request.get_data(), # raw body bytes
43
+ "files": {k: v.filename for k, v in request.files.items()},
44
+ "remote_addr": request.remote_addr,
45
+ "cookies": request.cookies,
46
+ }
47
+
48
+ class AbortRequest :
49
+ def __init__(self, request ) :
50
+ self.request = clone_request(request)
51
+ self.abort_id = None
52
+ self.abortable = False
53
+ self.thread = None
54
+ self.cache = None
55
+ self.start_ts = getTimestamp()
56
+
57
+ def abort(self) :
58
+ kill_thread(self.thread)
59
+ self.cache.delete(self.abort_id)
60
+ try :
61
+ gc.collect()
62
+ except :
63
+ pass
64
+
65
+
66
+ class UISERVER :
67
+ def __init__(self ,
68
+ id=getRandomKey(n=15),
69
+ secretkey=generateToken(),
70
+ address='localhost',
71
+ port=5312 ,
72
+ https=False ,
73
+ ssl_crt=None,
74
+ ssl_key=None,
75
+ template_folder='templates/' ,
76
+ static_folder = 'templates/assets'
77
+ ,**kwargs
78
+ ) -> None:
79
+ self.id = id
80
+ self.static_folder = static_folder
81
+ self.app = app = Flask(self.id , template_folder=template_folder , static_folder=self.static_folder )
82
+ app.config['SECRET_KEY'] = secretkey
83
+ CORS(app,resources={r"/*":{"origins":"*"}})
84
+ self.address= address
85
+ self.port = port
86
+ self.thread = None
87
+ self.ssl_crt=ssl_crt
88
+ self.ssl_key=ssl_key
89
+ self.enable_test_url=True
90
+ self.abort_requests = {}
91
+ self.abort_base_url = '/request/abort'
92
+ if https :
93
+ self.httpProtocol = 'https'
94
+ else :
95
+ self.httpProtocol = 'http'
96
+ self.socketio = SocketIO(app , cors_allowed_origins="*" ,async_mode='threading' , engineio_logger=False , always_connect=True ,**kwargs )
97
+ cenv[id] = self
98
+ self.fullAddress = f"{self.httpProtocol}://{self.address}:{self.port}"
99
+ self.cache = TemporaryMemory()
100
+
101
+ def update_cert(self , crt, ssl ) :
102
+ self.ssl_crt=crt
103
+ self.ssl_key=ssl
104
+
105
+ def register_abortable_request(self , request , abort_id = None ) :
106
+ path = request.path
107
+ Abort = AbortRequest(request)
108
+ if not path.startswith(self.abort_base_url) :
109
+ if not abort_id :
110
+ if not request.headers.get('abortid') :
111
+ abort_id = getRandomKeysAndStr(n=20)
112
+ else :
113
+ abort_id = request.headers.get('abortid')
114
+
115
+ Abort.abort_id = abort_id
116
+ current_thread = threading.current_thread()
117
+ Abort.thread = current_thread
118
+ Abort.cache = self.cache
119
+ Abort.start_ts = getTimestamp()
120
+ self.cache.set( Abort , custom_key=abort_id , auto_destroy_period=120 , store_deleted_key=False )
121
+ return Abort
122
+
123
+ def start_before_request(self) :
124
+
125
+ @self.app.route(f'{self.abort_base_url}/<id>' , methods=['DELETE'])
126
+ def abort_request(id : str ) :
127
+ abort : AbortRequest = self.cache.get(id)
128
+ timestamp = getTimestamp()
129
+ if abort :
130
+ abort.abort()
131
+ for i in range(30) :
132
+ th = abort.thread
133
+ alive = th.is_alive()
134
+ if not alive :
135
+ break
136
+ time.sleep(.25)
137
+ return { 'status' : 200 , 'message' : 'Request aborted' , 'abort_timestamp' : timestamp , 'abort_id' : id , 'alive' : alive , 'url' : abort.request.get('path')}
138
+ else :
139
+ return { 'status' : 404 , 'message' : 'Request not found or request is not abortable. Check request headers for abortable flag.'}
140
+
141
+ @self.app.before_request
142
+ def before_request() :
143
+ abortable = request.headers.get('abortable')
144
+ if abortable :
145
+ abort = self.register_abortable_request(request)
146
+ request.abortable = True
147
+ request.abort_id = abort.abort_id
148
+ # check here if async in the headers
149
+ # if yes . i will trigger the function in thread
150
+ # start_tread(#how to get the target function here ? )
151
+ # now i want to return response to UI { status : 200 , message : 'request now in running bg' , abort_id : abort.abort_id }
152
+ # the flask function should not be called again
153
+ if request.headers.get('async') == 'false' :
154
+ target_func = current_app.view_functions.get(request.endpoint)
155
+ if not target_func:
156
+ return jsonify({"error": "Route not found"}), 404
157
+ th = start_thread(target=target_func, args=request.args, kwargs=request.form)
158
+ abort.thread = th
159
+ return {"status": 200, "message": "Request now in running bg", "abort_id": abort.abort_id} , 200
160
+
161
+ @self.app.after_request
162
+ def after_request(response) :
163
+ try :
164
+ if request.abortable :
165
+ response.headers['abortid'] = request.abort_id
166
+ response.headers['abortable'] = True
167
+ except :
168
+ response.headers['abortable'] = False
169
+ return response
170
+
171
+
172
+ def getInstance(self) :
173
+ return self.getFlask() , self.getSocketio() , self.getWsgi()
174
+
175
+ def getSocketio( self ):
176
+ return self.socketio
177
+
178
+ def getFlask( self ):
179
+ return self.app
180
+
181
+ def getWsgi(self) :
182
+ return self.wsgi_server
183
+
184
+ def shutdownUi(self) :
185
+ kill_thread(self.thread)
186
+ self.wsgi_server.server_close()
187
+ self.wsgi_server.shutdown()
188
+
189
+ def _wait_th(self , t ) :
190
+ t.join()
191
+
192
+ def thrStartUi(self , suppress_prints=True) :
193
+ if self.enable_test_url :
194
+ if not suppress_prints :
195
+ print(f'TEST URL GET-METHOD /connection/test/internal')
196
+ @self.app.route('/connection/test/internal' , methods=['GET'])
197
+ def test_connection():
198
+ return f"Status=200<br> ID={self.id}<br> one-time-token={getRandomKey(20)}"
199
+ if self.httpProtocol == 'http' :
200
+ con = None
201
+ elif self.httpProtocol == 'https' :
202
+ con=(self.ssl_crt , self.ssl_key)
203
+ self.wsgi_server = wsgi_server = ThreadedWSGIServer(
204
+ host = self.address ,
205
+ ssl_context=con,
206
+ # ssl_context=('ssl.crt', 'ssl.key'),
207
+ port = self.port,
208
+ app = self.app )
209
+ if not suppress_prints :
210
+ print(f"web-socket: {self.fullAddress}")
211
+ print(f"UI URL : {self.fullAddress}")
212
+ log = logging.getLogger('werkzeug')
213
+ log.setLevel(logging.ERROR)
214
+ wsgi_server.serve_forever()
215
+
216
+ def startUi(self ,daemon , suppress_prints=True) :
217
+ self.start_before_request()
218
+ self.thread = self.flaskprocess = Thread(target=self.thrStartUi , args=[suppress_prints])
219
+ self.flaskprocess.daemon = False
220
+ self.flaskprocess.start()
221
+ start_thread(target=self._wait_th , args=[self.thread] , daemon=daemon)
222
+ return self.thread
223
+
224
+ def stopUi(self) :
225
+ kill_thread(self.thread)
226
+ return True
227
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easy_utils_dev
3
- Version: 2.140
3
+ Version: 2.141
4
4
  Keywords: python3
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Requires-Dist: psutil
@@ -1,6 +1,6 @@
1
1
  from setuptools import setup, find_packages
2
2
 
3
- VERSION = '2.140'
3
+ VERSION = '2.141'
4
4
 
5
5
  # Setting up
6
6
  setup(
@@ -1,193 +0,0 @@
1
- from werkzeug.serving import ThreadedWSGIServer
2
- from easy_utils_dev.utils import getRandomKey , generateToken , getTimestamp
3
- from flask_socketio import SocketIO
4
- from engineio.async_drivers import gevent
5
- from engineio.async_drivers import threading
6
- from flask_cors import CORS
7
- import logging , os
8
- from flask import Flask
9
- from threading import Thread
10
- from easy_utils_dev.custom_env import cenv
11
- from easy_utils_dev.utils import kill_thread
12
- from multiprocessing import Process
13
- from werkzeug.serving import make_ssl_devcert
14
- from time import sleep
15
- from easy_utils_dev.utils import start_thread , getRandomKeysAndStr , mkdirs
16
-
17
- def getClassById( id ) :
18
- return cenv[id]
19
-
20
- def create_ssl(host,output) :
21
- '''
22
- host : is the IP/Adress of the server which servers the web-server
23
- output: the output locaiton to generate the ssl certificate. it should end with filename without extension
24
- '''
25
- return make_ssl_devcert( output , host=host)
26
-
27
-
28
-
29
- class Abort :
30
- def __init__(self, requestId=getRandomKeysAndStr(50)) :
31
- self.requestId = requestId
32
- self.result= None
33
- self.thread = None
34
- self.aborted=False
35
- self.response = {}
36
- self.error = False
37
- self.message = ''
38
- self.starttimestamp = getTimestamp()
39
- self.endtimestamp = 0
40
- self.kill = self.api_abort
41
- pass
42
-
43
-
44
- def abortable_process(self , operation , args=[] , kwargs={}) :
45
- def thread_run() :
46
- try :
47
- self.result = operation( *args, **kwargs )
48
- self.error = False
49
- self.message = ''
50
- self.endtimestamp = getTimestamp()
51
- except Exception as error :
52
- self.error = True
53
- self.message = str(error)
54
- thread = self.thread = start_thread( target = thread_run )
55
- while thread.is_alive() :
56
- sleep(.1)
57
- if self.aborted :
58
- self.response = {
59
- 'message' : 'request aborted.' ,
60
- 'id' : self.requestId ,
61
- 'status' : 405 ,
62
- 'result' : None,
63
- 'error' : self.error ,
64
- 'error_message' : '',
65
- 'starttimestamp' : self.starttimestamp,
66
- 'endtimestamp' : self.endtimestamp,
67
- 'aborted' : True,
68
- 'threadIsAlive' : thread.is_alive()
69
- }
70
- return self.response
71
- sleep(.2)
72
- self.response = {
73
- 'message' : 'request completed.' ,
74
- 'id' : self.requestId ,
75
- 'status' : 200 ,
76
- 'result' : self.result ,
77
- 'error' : self.error ,
78
- 'error_message' : self.message ,
79
- 'starttimestamp' : self.starttimestamp,
80
- 'endtimestamp' : self.endtimestamp,
81
- 'aborted' : False ,
82
- 'threadIsAlive' : thread.is_alive()
83
- }
84
- return self.response
85
-
86
-
87
- def api_abort(self) :
88
- self.endtimestamp = getTimestamp()
89
- kill_thread(self.thread)
90
- sleep(.5)
91
- self.aborted=True
92
-
93
-
94
- class UISERVER :
95
- def __init__(self ,
96
- id=getRandomKey(n=15),
97
- secretkey=generateToken(),
98
- address='localhost',
99
- port=5312 ,
100
- https=False ,
101
- ssl_crt=None,
102
- ssl_key=None,
103
- template_folder='templates/' ,
104
- static_folder = 'templates/assets'
105
- ,**kwargs
106
- ) -> None:
107
- self.id = id
108
- self.static_folder = static_folder
109
- self.app = app = Flask(self.id , template_folder=template_folder , static_folder=self.static_folder )
110
- app.config['SECRET_KEY'] = secretkey
111
- CORS(app,resources={r"/*":{"origins":"*"}})
112
- self.address= address
113
- self.port = port
114
- self.thread = None
115
- self.ssl_crt=ssl_crt
116
- self.ssl_key=ssl_key
117
- self.enable_test_url=True
118
- self.abort_requests = {}
119
- if https :
120
- self.httpProtocol = 'https'
121
- else :
122
- self.httpProtocol = 'http'
123
- self.socketio = SocketIO(app , cors_allowed_origins="*" ,async_mode='threading' , engineio_logger=False , always_connect=True ,**kwargs )
124
- cenv[id] = self
125
- self.fullAddress = f"{self.httpProtocol}://{self.address}:{self.port}"
126
-
127
- def update_cert(self , crt, ssl ) :
128
- self.ssl_crt=crt
129
- self.ssl_key=ssl
130
-
131
-
132
- def getAbort(self , id ) :
133
- result : Abort = self.abort_requests.get(id , Abort)
134
- return result
135
-
136
- def updateAbort( self , id , abort ) :
137
- self.abort_requests[id] = abort
138
-
139
- def getInstance(self) :
140
- return self.getFlask() , self.getSocketio() , self.getWsgi()
141
-
142
- def getSocketio( self ):
143
- return self.socketio
144
-
145
- def getFlask( self ):
146
- return self.app
147
-
148
- def getWsgi(self) :
149
- return self.wsgi_server
150
-
151
- def shutdownUi(self) :
152
- kill_thread(self.thread)
153
- self.wsgi_server.server_close()
154
- self.wsgi_server.shutdown()
155
-
156
- def _wait_th(self , t ) :
157
- t.join()
158
-
159
- def thrStartUi(self , suppress_prints=True) :
160
- if self.enable_test_url :
161
- if not suppress_prints :
162
- print(f'TEST URL GET-METHOD /connection/test/internal')
163
- @self.app.route('/connection/test/internal' , methods=['GET'])
164
- def test_connection():
165
- return f"Status=200<br> ID={self.id}<br> one-time-token={getRandomKey(20)}"
166
- if self.httpProtocol == 'http' :
167
- con = None
168
- elif self.httpProtocol == 'https' :
169
- con=(self.ssl_crt , self.ssl_key)
170
- self.wsgi_server = wsgi_server = ThreadedWSGIServer(
171
- host = self.address ,
172
- ssl_context=con,
173
- # ssl_context=('ssl.crt', 'ssl.key'),
174
- port = self.port,
175
- app = self.app )
176
- if not suppress_prints :
177
- print(f"web-socket: {self.fullAddress}")
178
- print(f"UI URL : {self.fullAddress}")
179
- log = logging.getLogger('werkzeug')
180
- log.setLevel(logging.ERROR)
181
- wsgi_server.serve_forever()
182
-
183
- def startUi(self ,daemon , suppress_prints=True) :
184
- self.thread = self.flaskprocess = Thread(target=self.thrStartUi , args=[suppress_prints])
185
- self.flaskprocess.daemon = False
186
- self.flaskprocess.start()
187
- start_thread(target=self._wait_th , args=[self.thread] , daemon=daemon)
188
- return self.thread
189
-
190
- def stopUi(self) :
191
- kill_thread(self.thread)
192
- return True
193
-
File without changes