99 lines
2.7 KiB
Python
99 lines
2.7 KiB
Python
import inspect
|
|
import functools
|
|
from threading import local
|
|
from structio.abc import (
|
|
BaseKernel,
|
|
BaseDebugger,
|
|
BaseClock,
|
|
SignalManager,
|
|
BaseIOManager,
|
|
)
|
|
from structio.exceptions import StructIOException
|
|
from structio.core.task import Task
|
|
from typing import Callable, Any, Coroutine
|
|
|
|
_RUN = local()
|
|
|
|
|
|
def current_loop() -> BaseKernel:
|
|
"""
|
|
Returns the current event loop in the calling
|
|
thread. Raises a StructIOException if no async
|
|
context exists
|
|
"""
|
|
try:
|
|
return _RUN.kernel
|
|
except AttributeError:
|
|
raise StructIOException("must be called from async context") from None
|
|
|
|
|
|
def current_task() -> Task:
|
|
"""
|
|
Shorthand for current_loop().current_task
|
|
"""
|
|
|
|
return current_loop().current_task
|
|
|
|
|
|
def new_event_loop(kernel: BaseKernel):
|
|
"""
|
|
Initializes a new event loop using the
|
|
given kernel implementation. Cannot be
|
|
called from an asynchronous context
|
|
"""
|
|
|
|
try:
|
|
current_loop()
|
|
except StructIOException:
|
|
_RUN.kernel = kernel
|
|
else:
|
|
if not _RUN.kernel.done():
|
|
raise StructIOException(
|
|
"cannot be called from running async context"
|
|
) from None
|
|
|
|
|
|
def run(
|
|
func: Callable[[Any, Any], Coroutine[Any, Any, Any]],
|
|
kernel: type,
|
|
io_manager: BaseIOManager,
|
|
signal_managers: list[SignalManager],
|
|
clock: BaseClock,
|
|
tools: list[BaseDebugger] | None = None,
|
|
restrict_ki_to_checkpoints: bool = False,
|
|
*args,
|
|
):
|
|
"""
|
|
Starts the event loop from a synchronous entry point. All
|
|
positional arguments are passed to the given coroutine
|
|
function. If you want to pass keyword arguments, consider
|
|
using functools.partial()
|
|
"""
|
|
|
|
if not issubclass(kernel, BaseKernel):
|
|
raise TypeError(
|
|
f"kernel must be a subclass of {BaseKernel.__module__}.{BaseKernel.__qualname__}!"
|
|
)
|
|
check = func
|
|
if isinstance(func, functools.partial):
|
|
check = func.func
|
|
if inspect.iscoroutine(check):
|
|
raise StructIOException(
|
|
"Looks like you tried to call structio.run(your_func(arg1, arg2, ...)), that is wrong!"
|
|
"\nWhat you wanna do, instead, is this: structio.run(your_func, arg1, arg2, ...)"
|
|
)
|
|
elif not inspect.iscoroutinefunction(check):
|
|
raise StructIOException(
|
|
"structio.run() requires an async function as its first argument!"
|
|
)
|
|
new_event_loop(
|
|
kernel(
|
|
clock=clock,
|
|
restrict_ki_to_checkpoints=restrict_ki_to_checkpoints,
|
|
io_manager=io_manager,
|
|
signal_managers=signal_managers,
|
|
tools=tools,
|
|
)
|
|
)
|
|
return current_loop().start(func, *args)
|