2022-05-31 17:56:37 +00:00
|
|
|
|
|
|
|
import asyncio
|
|
|
|
import threading
|
|
|
|
import time
|
2022-10-25 15:33:50 +00:00
|
|
|
from queue import Queue
|
2022-05-31 17:56:37 +00:00
|
|
|
|
2022-11-01 13:22:55 +00:00
|
|
|
from .uv import UVLoop
|
2022-06-02 19:00:42 +00:00
|
|
|
|
2022-05-31 20:53:20 +00:00
|
|
|
|
|
|
|
def future_handler(future, loop, exception_handler, response):
|
|
|
|
try:
|
|
|
|
future.result()
|
|
|
|
return None
|
|
|
|
except Exception as error:
|
|
|
|
if hasattr(exception_handler, '__call__'):
|
|
|
|
exception_handler(loop, error, response)
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
#just log in console the error to call attention
|
|
|
|
print("Uncaught Exception: %s" % str(error))
|
|
|
|
if response != None:
|
|
|
|
response.write_status(500).end("Internal Error")
|
|
|
|
finally:
|
2022-10-26 01:08:13 +00:00
|
|
|
return None
|
|
|
|
return None
|
2022-05-31 20:53:20 +00:00
|
|
|
|
2022-05-31 17:56:37 +00:00
|
|
|
class Loop:
|
2022-05-31 20:53:20 +00:00
|
|
|
def __init__(self, exception_handler=None):
|
2022-05-31 17:56:37 +00:00
|
|
|
self.loop = asyncio.new_event_loop()
|
2022-06-02 19:00:42 +00:00
|
|
|
self.uv_loop = UVLoop()
|
2022-10-25 15:33:50 +00:00
|
|
|
self.queue = Queue()
|
|
|
|
|
2022-05-31 20:53:20 +00:00
|
|
|
if hasattr(exception_handler, '__call__'):
|
|
|
|
self.exception_handler = exception_handler
|
|
|
|
self.loop.set_exception_handler(lambda loop, context: exception_handler(loop, context, None))
|
|
|
|
else:
|
|
|
|
self.exception_handler = None
|
|
|
|
|
2022-05-31 17:56:37 +00:00
|
|
|
asyncio.set_event_loop(self.loop)
|
2022-06-02 19:00:42 +00:00
|
|
|
self.started = False
|
fixed UVLoop, and added better strategy to Loop, added post support, get_data(), get_json(), get_text(), get_cookie(), set_cookie(), pending x-www-form-urlencoded and form-data (maybe only with another package), added more options for keys in response, added fallback to None if decode fails in request, added on_writable and on_data events, pending try_end and stream examples, added upload and post examples
2022-06-03 21:53:42 +00:00
|
|
|
self.last_defer = False
|
2022-05-31 17:56:37 +00:00
|
|
|
|
2022-10-25 12:53:18 +00:00
|
|
|
def set_timeout(self, timeout, callback, user_data):
|
|
|
|
return self.uv_loop.create_timer(timeout, 0, callback, user_data)
|
|
|
|
|
2022-10-25 15:33:50 +00:00
|
|
|
def enqueue(self, callback, user_data):
|
|
|
|
self.queue.put((callback, user_data))
|
|
|
|
|
fixed UVLoop, and added better strategy to Loop, added post support, get_data(), get_json(), get_text(), get_cookie(), set_cookie(), pending x-www-form-urlencoded and form-data (maybe only with another package), added more options for keys in response, added fallback to None if decode fails in request, added on_writable and on_data events, pending try_end and stream examples, added upload and post examples
2022-06-03 21:53:42 +00:00
|
|
|
def create_future(self):
|
|
|
|
return self.loop.create_future()
|
|
|
|
|
2022-05-31 17:56:37 +00:00
|
|
|
def start(self):
|
2022-06-02 19:00:42 +00:00
|
|
|
self.started = True
|
2022-10-25 15:33:50 +00:00
|
|
|
#run asyncio once per tick
|
|
|
|
def tick(loop):
|
|
|
|
#only call one item of the queue per tick
|
|
|
|
if not loop.queue.empty():
|
|
|
|
(callback, user_data) = loop.queue.get(False)
|
|
|
|
callback(user_data)
|
|
|
|
loop.queue.task_done()
|
2022-11-06 10:22:10 +00:00
|
|
|
#run once asyncio
|
|
|
|
loop.run_once_asyncio()
|
|
|
|
|
2022-10-25 15:33:50 +00:00
|
|
|
#use check for calling asyncio once per tick
|
2022-11-06 10:25:07 +00:00
|
|
|
self.timer = self.uv_loop.create_timer(0, 1, tick, self)
|
2022-10-26 01:08:13 +00:00
|
|
|
# self.timer = self.uv_loop.create_check(tick, self)
|
fixed UVLoop, and added better strategy to Loop, added post support, get_data(), get_json(), get_text(), get_cookie(), set_cookie(), pending x-www-form-urlencoded and form-data (maybe only with another package), added more options for keys in response, added fallback to None if decode fails in request, added on_writable and on_data events, pending try_end and stream examples, added upload and post examples
2022-06-03 21:53:42 +00:00
|
|
|
|
2022-06-02 19:00:42 +00:00
|
|
|
def run(self):
|
|
|
|
self.uv_loop.run()
|
|
|
|
|
|
|
|
def run_once(self):
|
|
|
|
self.uv_loop.run_once()
|
|
|
|
|
|
|
|
def run_once_asyncio(self):
|
2022-10-26 01:08:13 +00:00
|
|
|
# with suppress(asyncio.CancelledError):
|
2022-06-02 19:00:42 +00:00
|
|
|
#run only one step
|
|
|
|
self.loop.call_soon(self.loop.stop)
|
|
|
|
self.loop.run_forever()
|
2022-10-26 01:08:13 +00:00
|
|
|
|
fixed UVLoop, and added better strategy to Loop, added post support, get_data(), get_json(), get_text(), get_cookie(), set_cookie(), pending x-www-form-urlencoded and form-data (maybe only with another package), added more options for keys in response, added fallback to None if decode fails in request, added on_writable and on_data events, pending try_end and stream examples, added upload and post examples
2022-06-03 21:53:42 +00:00
|
|
|
|
2022-05-31 17:56:37 +00:00
|
|
|
def stop(self):
|
2022-06-02 19:00:42 +00:00
|
|
|
if(self.started):
|
|
|
|
self.timer.stop()
|
|
|
|
self.started = False
|
|
|
|
#unbind run_once
|
|
|
|
#if is still running stops
|
|
|
|
if self.loop.is_running():
|
|
|
|
self.loop.stop()
|
|
|
|
|
fixed UVLoop, and added better strategy to Loop, added post support, get_data(), get_json(), get_text(), get_cookie(), set_cookie(), pending x-www-form-urlencoded and form-data (maybe only with another package), added more options for keys in response, added fallback to None if decode fails in request, added on_writable and on_data events, pending try_end and stream examples, added upload and post examples
2022-06-03 21:53:42 +00:00
|
|
|
self.last_defer = None
|
2022-05-31 17:56:37 +00:00
|
|
|
# Find all running tasks in main thread:
|
|
|
|
pending = asyncio.all_tasks(self.loop)
|
|
|
|
# Run loop until tasks done
|
|
|
|
self.loop.run_until_complete(asyncio.gather(*pending))
|
2022-06-02 19:00:42 +00:00
|
|
|
|
|
|
|
#Exposes native loop for uWS
|
|
|
|
def get_native_loop(self):
|
|
|
|
return self.uv_loop.get_native_loop()
|
2022-05-31 17:56:37 +00:00
|
|
|
|
2022-05-31 20:53:20 +00:00
|
|
|
def run_async(self, task, response=None):
|
2022-06-02 19:00:42 +00:00
|
|
|
#with run_once
|
|
|
|
future = asyncio.ensure_future(task, loop=self.loop)
|
|
|
|
|
|
|
|
#with threads
|
2022-05-31 20:53:20 +00:00
|
|
|
future.add_done_callback(lambda f: future_handler(f, self.loop, self.exception_handler, response))
|
fixed UVLoop, and added better strategy to Loop, added post support, get_data(), get_json(), get_text(), get_cookie(), set_cookie(), pending x-www-form-urlencoded and form-data (maybe only with another package), added more options for keys in response, added fallback to None if decode fails in request, added on_writable and on_data events, pending try_end and stream examples, added upload and post examples
2022-06-03 21:53:42 +00:00
|
|
|
#force asyncio run once to enable req in async functions before first await
|
|
|
|
self.run_once_asyncio()
|
2022-10-24 17:15:46 +00:00
|
|
|
|
2022-10-25 14:05:11 +00:00
|
|
|
#if response != None: #set auto cork
|
|
|
|
# response.needs_cork = True
|
2022-05-31 20:53:20 +00:00
|
|
|
return future
|
2022-06-01 23:00:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# if sys.version_info >= (3, 11)
|
|
|
|
# with asyncio.Runner(loop_factory=uvloop.new_event_loop) as runner:
|
|
|
|
# runner.run(main())
|
|
|
|
# else:
|
|
|
|
# uvloop.install()
|
|
|
|
# asyncio.run(main())
|