mirror of https://github.com/nocturn9x/giambio.git
Added context manager functionality and other related features
This commit is contained in:
parent
68df239020
commit
0e29cb7e8a
|
@ -1,8 +1,8 @@
|
||||||
__author__ = "Nocturn9x aka Isgiambyy"
|
__author__ = "Nocturn9x aka Isgiambyy"
|
||||||
__version__ = (0, 0, 1)
|
__version__ = (0, 0, 1)
|
||||||
from .core import EventLoop
|
from .core import EventLoop
|
||||||
from .exceptions import GiambioError, AlreadyJoinedError, CancelledError
|
from .exceptions import GiambioError, AlreadyJoinedError, CancelledError, TaskCancelled
|
||||||
from .traps import sleep, join
|
from .traps import sleep, join
|
||||||
|
from .util import TaskManager
|
||||||
|
|
||||||
|
__all__ = ["EventLoop", "sleep", "join", "GiambioError", "AlreadyJoinedError", "CancelledError", "TaskManager", "TaskCancelled"]
|
||||||
__all__ = ["EventLoop", "sleep", "join", "GiambioError", "AlreadyJoinedError", "CancelledError"]
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import types
|
import types
|
||||||
from .traps import join, sleep, want_read, want_write, cancel
|
from .traps import join, sleep, want_read, want_write, cancel
|
||||||
|
from .exceptions import CancelledError
|
||||||
|
|
||||||
class Result:
|
class Result:
|
||||||
"""A wrapper for results of coroutines"""
|
"""A wrapper for results of coroutines"""
|
||||||
|
@ -23,6 +24,7 @@ class Task:
|
||||||
self.result = None # Updated when the coroutine execution ends
|
self.result = None # Updated when the coroutine execution ends
|
||||||
self.loop = loop # The EventLoop object that spawned the task
|
self.loop = loop # The EventLoop object that spawned the task
|
||||||
self.cancelled = False
|
self.cancelled = False
|
||||||
|
self.execution = "INIT"
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.status = True
|
self.status = True
|
||||||
|
|
|
@ -11,6 +11,7 @@ from .abstractions import Task, Result
|
||||||
from socket import SOL_SOCKET, SO_ERROR
|
from socket import SOL_SOCKET, SO_ERROR
|
||||||
from .traps import join, sleep, want_read, want_write, cancel
|
from .traps import join, sleep, want_read, want_write, cancel
|
||||||
|
|
||||||
|
|
||||||
class EventLoop:
|
class EventLoop:
|
||||||
|
|
||||||
"""Implementation of an event loop, alternates between execution of coroutines (asynchronous functions)
|
"""Implementation of an event loop, alternates between execution of coroutines (asynchronous functions)
|
||||||
|
@ -50,6 +51,7 @@ class EventLoop:
|
||||||
method, *args = self.running.run()
|
method, *args = self.running.run()
|
||||||
getattr(self, method)(*args) # Sneaky method call, thanks to David Beazley for this ;)
|
getattr(self, method)(*args) # Sneaky method call, thanks to David Beazley for this ;)
|
||||||
except StopIteration as e:
|
except StopIteration as e:
|
||||||
|
self.running.execution = "FINISH"
|
||||||
self.running.result = Result(e.args[0] if e.args else None, None) # Saves the return value
|
self.running.result = Result(e.args[0] if e.args else None, None) # Saves the return value
|
||||||
self.to_run.extend(self.joined.pop(self.running, ())) # Reschedules the parent task
|
self.to_run.extend(self.joined.pop(self.running, ())) # Reschedules the parent task
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
|
|
@ -14,4 +14,7 @@ class CancelledError(GiambioError):
|
||||||
return "giambio.exceptions.CancelledError"
|
return "giambio.exceptions.CancelledError"
|
||||||
|
|
||||||
class TaskCancelled(GiambioError):
|
class TaskCancelled(GiambioError):
|
||||||
"""This exception is raised when the user attempts to join a cancelled task"""
|
"""This exception is raised when the user attempts to join a cancelled task"""
|
||||||
|
|
||||||
|
class TaskFinished(TaskCancelled):
|
||||||
|
"""This exception is raised when the user attempts to join an already finished task"""
|
||||||
|
|
|
@ -39,6 +39,8 @@ def join(task):
|
||||||
|
|
||||||
if task.cancelled:
|
if task.cancelled:
|
||||||
raise TaskCancelled("Cannot join cancelled task!")
|
raise TaskCancelled("Cannot join cancelled task!")
|
||||||
|
if task.execution == "FINISH":
|
||||||
|
raise TaskFinished("Cannot join already terminated task!")
|
||||||
task.joined = True
|
task.joined = True
|
||||||
yield "want_join", task
|
yield "want_join", task
|
||||||
return task.get_result() # This raises an exception if the child task errored
|
return task.get_result() # This raises an exception if the child task errored
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
from .abstractions import Task
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
|
|
||||||
|
class TaskManager(Task):
|
||||||
|
"""Class to be used inside context managers to spawn multiple tasks and be sure that they will all joined before the code exits the with block"""
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, loop):
|
||||||
|
self.tasks = deque() # All tasks spawned
|
||||||
|
self.values = {} # Results OR exceptions of each task
|
||||||
|
self.loop = loop
|
||||||
|
|
||||||
|
async def __aenter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
async def __aexit__(self, *args):
|
||||||
|
for task in self.tasks:
|
||||||
|
self.values[task.coroutine.__name__] = await task.join()
|
||||||
|
|
||||||
|
async def spawn(self, coro):
|
||||||
|
task = self.loop.spawn(coro)
|
||||||
|
self.tasks.append(task)
|
||||||
|
return task
|
||||||
|
|
||||||
|
async def schedule(self, coro, delay):
|
||||||
|
task = self.loop.schedule(coro, delay)
|
||||||
|
self.tasks.append(task)
|
||||||
|
return task
|
Loading…
Reference in New Issue