orionis 0.532.0__py3-none-any.whl → 0.534.0__py3-none-any.whl
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.
- orionis/console/commands/make_listener.py +57 -0
- orionis/console/core/reactor.py +3 -1
- orionis/console/tasks/schedule.py +79 -93
- orionis/failure/base/handler.py +15 -11
- orionis/failure/catch.py +88 -18
- orionis/failure/contracts/handler.py +4 -4
- orionis/metadata/framework.py +1 -1
- orionis/services/asynchrony/coroutines.py +117 -12
- {orionis-0.532.0.dist-info → orionis-0.534.0.dist-info}/METADATA +1 -1
- {orionis-0.532.0.dist-info → orionis-0.534.0.dist-info}/RECORD +15 -14
- tests/services/asynchrony/test_services_asynchrony_coroutine.py +1 -1
- {orionis-0.532.0.dist-info → orionis-0.534.0.dist-info}/WHEEL +0 -0
- {orionis-0.532.0.dist-info → orionis-0.534.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.532.0.dist-info → orionis-0.534.0.dist-info}/top_level.txt +0 -0
- {orionis-0.532.0.dist-info → orionis-0.534.0.dist-info}/zip-safe +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from orionis.console.base.command import BaseCommand
|
|
2
|
+
from orionis.console.contracts.reactor import IReactor
|
|
3
|
+
from orionis.console.exceptions import CLIOrionisRuntimeError
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
from rich.panel import Panel
|
|
6
|
+
|
|
7
|
+
class MakeListenerCommand(BaseCommand):
|
|
8
|
+
"""
|
|
9
|
+
Este comando se encarga de crear los listener tando para CLI como para otro tipo de Eventos.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# Indicates whether timestamps will be shown in the command output
|
|
13
|
+
timestamps: bool = False
|
|
14
|
+
|
|
15
|
+
# Command signature and description
|
|
16
|
+
signature: str = "make:listener"
|
|
17
|
+
|
|
18
|
+
# Command description
|
|
19
|
+
description: str = "Displays usage information, examples, and a list of available commands in the Orionis CLI."
|
|
20
|
+
|
|
21
|
+
def handle(self) -> dict:
|
|
22
|
+
"""
|
|
23
|
+
Displays usage information and a list of available commands for the Orionis CLI.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
reactor : IReactor
|
|
28
|
+
The reactor instance providing command metadata via the `info()` method.
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
dict
|
|
33
|
+
A dictionary containing the list of available commands, each with its signature and description.
|
|
34
|
+
|
|
35
|
+
Raises
|
|
36
|
+
------
|
|
37
|
+
CLIOrionisRuntimeError
|
|
38
|
+
If an unexpected error occurs during help information generation or display.
|
|
39
|
+
"""
|
|
40
|
+
try:
|
|
41
|
+
|
|
42
|
+
# Solicitar el nombre del listener al usuario
|
|
43
|
+
ans = self.choice(
|
|
44
|
+
question="Tipo de Listener",
|
|
45
|
+
choices=[
|
|
46
|
+
"Listener para eventos CLI",
|
|
47
|
+
"Listener para eventos de Schedule",
|
|
48
|
+
],
|
|
49
|
+
default_index=0
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
print(ans)
|
|
53
|
+
|
|
54
|
+
except Exception as e:
|
|
55
|
+
|
|
56
|
+
# Raise a custom runtime error if any exception occurs
|
|
57
|
+
raise CLIOrionisRuntimeError(f"An unexpected error occurred: {e}") from e
|
orionis/console/core/reactor.py
CHANGED
|
@@ -114,6 +114,7 @@ class Reactor(IReactor):
|
|
|
114
114
|
from orionis.console.commands.cache import CacheClearCommand
|
|
115
115
|
from orionis.console.commands.scheduler_work import ScheduleWorkCommand
|
|
116
116
|
from orionis.console.commands.scheduler_list import ScheduleListCommand
|
|
117
|
+
from orionis.console.commands.make_listener import MakeListenerCommand
|
|
117
118
|
|
|
118
119
|
# List of core command classes to load (extend this list as more core commands are added)
|
|
119
120
|
core_commands = [
|
|
@@ -124,7 +125,8 @@ class Reactor(IReactor):
|
|
|
124
125
|
WorkFlowGithubCommand,
|
|
125
126
|
CacheClearCommand,
|
|
126
127
|
ScheduleWorkCommand,
|
|
127
|
-
ScheduleListCommand
|
|
128
|
+
ScheduleListCommand,
|
|
129
|
+
MakeListenerCommand
|
|
128
130
|
]
|
|
129
131
|
|
|
130
132
|
# Iterate through the core command classes and register them
|
|
@@ -37,6 +37,7 @@ from orionis.console.exceptions import CLIOrionisRuntimeError
|
|
|
37
37
|
from orionis.console.exceptions.cli_orionis_value_error import CLIOrionisValueError
|
|
38
38
|
from orionis.failure.contracts.catch import ICatch
|
|
39
39
|
from orionis.foundation.contracts.application import IApplication
|
|
40
|
+
from orionis.services.asynchrony.coroutines import Coroutine
|
|
40
41
|
from orionis.services.log.contracts.log_service import ILogger
|
|
41
42
|
|
|
42
43
|
class Schedule(ISchedule):
|
|
@@ -478,44 +479,13 @@ class Schedule(ISchedule):
|
|
|
478
479
|
# If is Callable
|
|
479
480
|
if callable(listener):
|
|
480
481
|
|
|
482
|
+
# Invoke the listener, handling both coroutine and regular functions
|
|
481
483
|
try:
|
|
482
484
|
|
|
483
|
-
#
|
|
484
|
-
|
|
485
|
+
# Use Coroutine to handle both sync and async listeners
|
|
486
|
+
Coroutine(listener).invoke(event_data, self)
|
|
485
487
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
# Try to get the current running event loop
|
|
489
|
-
loop = asyncio.get_running_loop()
|
|
490
|
-
|
|
491
|
-
# Schedule the coroutine as a task in the current loop
|
|
492
|
-
loop.create_task(listener(event_data, self))
|
|
493
|
-
|
|
494
|
-
except RuntimeError:
|
|
495
|
-
|
|
496
|
-
# No running event loop, create a new one
|
|
497
|
-
try:
|
|
498
|
-
|
|
499
|
-
# Create and run the coroutine in a new event loop
|
|
500
|
-
asyncio.run(listener(event_data, self))
|
|
501
|
-
|
|
502
|
-
except Exception as e:
|
|
503
|
-
|
|
504
|
-
# Handle exceptions during coroutine execution
|
|
505
|
-
error_msg = f"Failed to run async listener for '{scheduler_event}': {str(e)}"
|
|
506
|
-
self.__logger.error(error_msg)
|
|
507
|
-
raise CLIOrionisRuntimeError(error_msg) from e
|
|
508
|
-
|
|
509
|
-
else:
|
|
510
|
-
|
|
511
|
-
# Call the regular listener function directly
|
|
512
|
-
listener(event_data, self)
|
|
513
|
-
|
|
514
|
-
except Exception as e:
|
|
515
|
-
|
|
516
|
-
# Re-raise CLIOrionisRuntimeError exceptions
|
|
517
|
-
if isinstance(e, CLIOrionisRuntimeError):
|
|
518
|
-
raise e
|
|
488
|
+
except BaseException as e:
|
|
519
489
|
|
|
520
490
|
# Construct and log error message
|
|
521
491
|
error_msg = f"An error occurred while invoking the listener for event '{scheduler_event}': {str(e)}"
|
|
@@ -588,45 +558,14 @@ class Schedule(ISchedule):
|
|
|
588
558
|
# Retrieve the method from the listener
|
|
589
559
|
listener_method = getattr(listener, scheduler_event)
|
|
590
560
|
|
|
561
|
+
# Invoke the listener method, handling both coroutine and regular functions
|
|
591
562
|
try:
|
|
592
563
|
|
|
593
|
-
#
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
try:
|
|
597
|
-
|
|
598
|
-
# Try to get the current running event loop
|
|
599
|
-
loop = asyncio.get_running_loop()
|
|
600
|
-
|
|
601
|
-
# Schedule the coroutine as a task in the current loop
|
|
602
|
-
loop.create_task(listener_method(event_data, self))
|
|
603
|
-
|
|
604
|
-
except RuntimeError:
|
|
605
|
-
|
|
606
|
-
# No running event loop, create a new one
|
|
607
|
-
try:
|
|
608
|
-
|
|
609
|
-
# Create and run the coroutine in a new event loop
|
|
610
|
-
asyncio.run(listener_method(event_data, self))
|
|
611
|
-
|
|
612
|
-
except Exception as e:
|
|
613
|
-
|
|
614
|
-
# Handle exceptions during coroutine execution
|
|
615
|
-
error_msg = f"Failed to run async listener_method for '{scheduler_event}': {str(e)}"
|
|
616
|
-
self.__logger.error(error_msg)
|
|
617
|
-
raise CLIOrionisRuntimeError(error_msg) from e
|
|
618
|
-
|
|
619
|
-
else:
|
|
620
|
-
|
|
621
|
-
# Call the regular listener_method function directly
|
|
622
|
-
listener_method(event_data, self)
|
|
564
|
+
# Use Coroutine to handle both sync and async listener methods
|
|
565
|
+
Coroutine(listener_method).invoke(event_data, self)
|
|
623
566
|
|
|
624
567
|
except Exception as e:
|
|
625
568
|
|
|
626
|
-
# Re-raise CLIOrionisRuntimeError exceptions
|
|
627
|
-
if isinstance(e, CLIOrionisRuntimeError):
|
|
628
|
-
raise e
|
|
629
|
-
|
|
630
569
|
# Construct and log error message
|
|
631
570
|
error_msg = f"An error occurred while invoking the listener_method for event '{scheduler_event}': {str(e)}"
|
|
632
571
|
self.__logger.error(error_msg)
|
|
@@ -1081,52 +1020,99 @@ class Schedule(ISchedule):
|
|
|
1081
1020
|
func: Callable[..., Awaitable[Any]]
|
|
1082
1021
|
) -> Callable[..., Any]:
|
|
1083
1022
|
"""
|
|
1084
|
-
Wrap an asynchronous function to be
|
|
1023
|
+
Wrap an asynchronous function to be executed in a synchronous context.
|
|
1085
1024
|
|
|
1086
|
-
This method
|
|
1087
|
-
|
|
1088
|
-
|
|
1025
|
+
This method creates a synchronous wrapper around an asynchronous function (coroutine)
|
|
1026
|
+
that enables its execution within non-async contexts. The wrapper leverages the
|
|
1027
|
+
Coroutine utility class to handle the complexities of asyncio event loop management
|
|
1028
|
+
and provides proper error handling with detailed logging and custom exception
|
|
1029
|
+
propagation.
|
|
1030
|
+
|
|
1031
|
+
The wrapper is particularly useful when integrating asynchronous functions with
|
|
1032
|
+
synchronous APIs or frameworks that do not natively support async operations,
|
|
1033
|
+
such as the APScheduler job execution environment.
|
|
1089
1034
|
|
|
1090
1035
|
Parameters
|
|
1091
1036
|
----------
|
|
1092
1037
|
func : Callable[..., Awaitable[Any]]
|
|
1093
|
-
The asynchronous function (coroutine) to be wrapped. This function
|
|
1094
|
-
defined using the `async def` syntax and return an awaitable object.
|
|
1038
|
+
The asynchronous function (coroutine) to be wrapped. This function must be
|
|
1039
|
+
defined using the `async def` syntax and return an awaitable object. The
|
|
1040
|
+
function can accept any number of positional and keyword arguments.
|
|
1095
1041
|
|
|
1096
1042
|
Returns
|
|
1097
1043
|
-------
|
|
1098
1044
|
Callable[..., Any]
|
|
1099
|
-
A synchronous wrapper function that
|
|
1100
|
-
|
|
1101
|
-
|
|
1045
|
+
A synchronous wrapper function that executes the original asynchronous
|
|
1046
|
+
function and returns its result. The wrapper function accepts the same
|
|
1047
|
+
arguments as the original async function and forwards them appropriately.
|
|
1048
|
+
The return type depends on what the wrapped asynchronous function returns.
|
|
1102
1049
|
|
|
1103
1050
|
Raises
|
|
1104
1051
|
------
|
|
1105
1052
|
CLIOrionisRuntimeError
|
|
1106
|
-
If the
|
|
1053
|
+
If the asynchronous function execution fails or if the provided `func`
|
|
1054
|
+
parameter is not a valid asynchronous function. The original exception
|
|
1055
|
+
is wrapped to provide additional context for debugging.
|
|
1056
|
+
|
|
1057
|
+
Notes
|
|
1058
|
+
-----
|
|
1059
|
+
This method relies on the Coroutine utility class from the orionis.services.asynchrony
|
|
1060
|
+
module to handle the execution of the wrapped asynchronous function. The wrapper
|
|
1061
|
+
uses the instance logger for comprehensive error reporting and debugging information.
|
|
1107
1062
|
"""
|
|
1108
1063
|
|
|
1109
1064
|
def sync_wrapper(*args, **kwargs) -> Any:
|
|
1065
|
+
"""
|
|
1066
|
+
Synchronous wrapper function that executes asynchronous functions in a thread-safe manner.
|
|
1067
|
+
|
|
1068
|
+
This wrapper provides a uniform interface for executing asynchronous functions within
|
|
1069
|
+
synchronous contexts by leveraging the Coroutine utility class. It handles the complexity
|
|
1070
|
+
of managing async/await patterns and provides proper error handling with detailed logging
|
|
1071
|
+
and custom exception propagation.
|
|
1072
|
+
|
|
1073
|
+
The wrapper is particularly useful when integrating asynchronous functions with
|
|
1074
|
+
synchronous APIs or frameworks that do not natively support async operations.
|
|
1075
|
+
|
|
1076
|
+
Parameters
|
|
1077
|
+
----------
|
|
1078
|
+
*args : tuple
|
|
1079
|
+
Variable length argument list to pass to the wrapped asynchronous function.
|
|
1080
|
+
These arguments are forwarded directly to the original function.
|
|
1081
|
+
**kwargs : dict
|
|
1082
|
+
Arbitrary keyword arguments to pass to the wrapped asynchronous function.
|
|
1083
|
+
These keyword arguments are forwarded directly to the original function.
|
|
1084
|
+
|
|
1085
|
+
Returns
|
|
1086
|
+
-------
|
|
1087
|
+
Any
|
|
1088
|
+
The return value from the executed asynchronous function. The type depends
|
|
1089
|
+
on what the wrapped function returns and can be any Python object.
|
|
1090
|
+
|
|
1091
|
+
Raises
|
|
1092
|
+
------
|
|
1093
|
+
CLIOrionisRuntimeError
|
|
1094
|
+
When the asynchronous function execution fails, wrapping the original
|
|
1095
|
+
exception with additional context and error details for better debugging.
|
|
1096
|
+
|
|
1097
|
+
Notes
|
|
1098
|
+
-----
|
|
1099
|
+
This function relies on the Coroutine utility class to handle the execution
|
|
1100
|
+
of the wrapped asynchronous function and uses the instance logger for comprehensive
|
|
1101
|
+
error reporting and debugging information.
|
|
1102
|
+
"""
|
|
1110
1103
|
|
|
1111
1104
|
try:
|
|
1112
|
-
|
|
1113
|
-
#
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
# If we're already in an event loop, create a task
|
|
1117
|
-
loop = asyncio.get_running_loop()
|
|
1118
|
-
task = loop.create_task(func(*args, **kwargs))
|
|
1119
|
-
return task
|
|
1120
|
-
|
|
1121
|
-
except RuntimeError:
|
|
1122
|
-
|
|
1123
|
-
# No running loop, so we can run the coroutine directly
|
|
1124
|
-
return asyncio.run(func(*args, **kwargs))
|
|
1105
|
+
# Execute the asynchronous function using the Coroutine utility class
|
|
1106
|
+
# The Coroutine class handles the event loop management and async execution
|
|
1107
|
+
return Coroutine(func).invoke(*args, **kwargs)
|
|
1125
1108
|
|
|
1126
1109
|
except Exception as e:
|
|
1127
1110
|
|
|
1128
|
-
# Log the error
|
|
1111
|
+
# Log the error with detailed information for debugging purposes
|
|
1129
1112
|
self.__logger.error(f"Error executing async function: {str(e)}")
|
|
1113
|
+
|
|
1114
|
+
# Re-raise the exception wrapped in a custom exception type
|
|
1115
|
+
# This provides better error context and maintains the original stack trace
|
|
1130
1116
|
raise CLIOrionisRuntimeError(f"Failed to execute async function: {str(e)}") from e
|
|
1131
1117
|
|
|
1132
1118
|
# Return the synchronous wrapper function
|
orionis/failure/base/handler.py
CHANGED
|
@@ -8,12 +8,12 @@ from orionis.services.log.contracts.log_service import ILogger
|
|
|
8
8
|
class BaseExceptionHandler(IBaseExceptionHandler):
|
|
9
9
|
|
|
10
10
|
# Exceptions that should not be caught by the handler
|
|
11
|
-
|
|
11
|
+
dont_catch: List[type[BaseException]] = [
|
|
12
12
|
# Add specific exceptions that should not be caught
|
|
13
13
|
# Example: OrionisContainerException
|
|
14
14
|
]
|
|
15
15
|
|
|
16
|
-
def destructureException(self, e: BaseException) -> Throwable:
|
|
16
|
+
async def destructureException(self, e: BaseException) -> Throwable:
|
|
17
17
|
"""
|
|
18
18
|
Converts an exception into a structured `Throwable` object containing detailed information.
|
|
19
19
|
|
|
@@ -41,7 +41,7 @@ class BaseExceptionHandler(IBaseExceptionHandler):
|
|
|
41
41
|
traceback=getattr(e, '__traceback__', None) # The traceback object, if available
|
|
42
42
|
)
|
|
43
43
|
|
|
44
|
-
def shouldIgnoreException(self, e: BaseException) -> bool:
|
|
44
|
+
async def shouldIgnoreException(self, e: BaseException) -> bool:
|
|
45
45
|
"""
|
|
46
46
|
Determines if the exception should be ignored (not handled) by the handler.
|
|
47
47
|
|
|
@@ -61,12 +61,12 @@ class BaseExceptionHandler(IBaseExceptionHandler):
|
|
|
61
61
|
raise TypeError(f"Expected BaseException, got {type(e).__name__}")
|
|
62
62
|
|
|
63
63
|
# Convert the exception into a structured Throwable object
|
|
64
|
-
throwable = self.destructureException(e)
|
|
64
|
+
throwable = await self.destructureException(e)
|
|
65
65
|
|
|
66
66
|
# Check if the exception type is in the list of exceptions to ignore
|
|
67
|
-
return hasattr(self, '
|
|
67
|
+
return hasattr(self, 'dont_catch') and throwable.classtype in self.dont_catch
|
|
68
68
|
|
|
69
|
-
def report(self, exception: BaseException, log: ILogger) -> Any:
|
|
69
|
+
async def report(self, exception: BaseException, log: ILogger) -> Any:
|
|
70
70
|
"""
|
|
71
71
|
Report or log an exception.
|
|
72
72
|
|
|
@@ -84,7 +84,7 @@ class BaseExceptionHandler(IBaseExceptionHandler):
|
|
|
84
84
|
raise TypeError(f"Expected BaseException, got {type(exception).__name__}")
|
|
85
85
|
|
|
86
86
|
# Convert the exception into a structured Throwable object
|
|
87
|
-
throwable = self.destructureException(exception)
|
|
87
|
+
throwable = await self.destructureException(exception)
|
|
88
88
|
|
|
89
89
|
# Log the exception details
|
|
90
90
|
log.error(f"[{throwable.classtype.__name__}] {throwable.message}")
|
|
@@ -92,7 +92,7 @@ class BaseExceptionHandler(IBaseExceptionHandler):
|
|
|
92
92
|
# Return the structured exception
|
|
93
93
|
return throwable
|
|
94
94
|
|
|
95
|
-
def renderCLI(self, request: CLIRequest, exception: BaseException, log: ILogger, console: IConsole) -> Any:
|
|
95
|
+
async def renderCLI(self, request: CLIRequest, exception: BaseException, log: ILogger, console: IConsole) -> Any:
|
|
96
96
|
"""
|
|
97
97
|
Render the exception message for CLI output.
|
|
98
98
|
|
|
@@ -109,11 +109,15 @@ class BaseExceptionHandler(IBaseExceptionHandler):
|
|
|
109
109
|
if not isinstance(exception, BaseException):
|
|
110
110
|
raise TypeError(f"Expected BaseException, got {type(exception).__name__}")
|
|
111
111
|
|
|
112
|
+
# Ensure the request is a CLIRequest
|
|
113
|
+
if not isinstance(request, CLIRequest):
|
|
114
|
+
raise TypeError(f"Expected CLIRequest, got {type(request).__name__}")
|
|
115
|
+
|
|
112
116
|
# Convert the exception into a structured Throwable object
|
|
113
|
-
throwable = self.destructureException(exception)
|
|
117
|
+
throwable = await self.destructureException(exception)
|
|
114
118
|
|
|
115
|
-
|
|
116
|
-
string_args = ' '.join(args)
|
|
119
|
+
# Convert the request arguments to a string for logging
|
|
120
|
+
string_args = ' '.join(request.args)
|
|
117
121
|
|
|
118
122
|
# Log the CLI error message with arguments
|
|
119
123
|
log.error(f"CLI Error: {throwable.message} (Args: {string_args})")
|
orionis/failure/catch.py
CHANGED
|
@@ -5,7 +5,9 @@ from orionis.console.tasks.schedule import Schedule
|
|
|
5
5
|
from orionis.failure.contracts.catch import ICatch
|
|
6
6
|
from orionis.failure.contracts.handler import IBaseExceptionHandler
|
|
7
7
|
from orionis.foundation.contracts.application import IApplication
|
|
8
|
+
from orionis.services.asynchrony.coroutines import Coroutine
|
|
8
9
|
from orionis.services.log.contracts.log_service import ILogger
|
|
10
|
+
import asyncio
|
|
9
11
|
|
|
10
12
|
class Catch(ICatch):
|
|
11
13
|
|
|
@@ -74,21 +76,89 @@ class Catch(ICatch):
|
|
|
74
76
|
If a valid kernel is provided, the exception details are rendered to the CLI.
|
|
75
77
|
"""
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
79
|
+
async def handle():
|
|
80
|
+
"""
|
|
81
|
+
Handles exceptions asynchronously using the provided exception handler.
|
|
82
|
+
|
|
83
|
+
This method performs the following steps:
|
|
84
|
+
1. Determines if the exception should be ignored by invoking the `shouldIgnoreException` method
|
|
85
|
+
of the exception handler. This method supports both coroutine and regular functions.
|
|
86
|
+
2. Reports the exception using the `report` method of the exception handler. This method
|
|
87
|
+
also supports both coroutine and regular functions.
|
|
88
|
+
3. If the kernel is of type `KernelCLI` or `Any`, it attempts to render the exception
|
|
89
|
+
for the CLI using the `renderCLI` method of the exception handler. This method supports
|
|
90
|
+
both coroutine and regular functions.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
None
|
|
95
|
+
|
|
96
|
+
Returns
|
|
97
|
+
-------
|
|
98
|
+
Any or None
|
|
99
|
+
The result of the `renderCLI` method if applicable, otherwise `None`.
|
|
100
|
+
|
|
101
|
+
Notes
|
|
102
|
+
-----
|
|
103
|
+
- The `self.__exception_handler` is expected to have the methods `shouldIgnoreException`,
|
|
104
|
+
`report`, and `renderCLI`.
|
|
105
|
+
- The `self.__logger` is passed to the `report` and `renderCLI` methods for logging purposes.
|
|
106
|
+
- The `self.__console` is passed to the `renderCLI` method for CLI rendering.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
# Check if the `shouldIgnoreException` method is a coroutine function
|
|
110
|
+
if asyncio.iscoroutinefunction(self.__exception_handler.shouldIgnoreException):
|
|
111
|
+
|
|
112
|
+
# If it is, await its result to determine if the exception should be ignored
|
|
113
|
+
if await self.__exception_handler.shouldIgnoreException(e):
|
|
114
|
+
return
|
|
115
|
+
|
|
116
|
+
else:
|
|
117
|
+
|
|
118
|
+
# If it is not a coroutine, call it directly
|
|
119
|
+
if self.__exception_handler.shouldIgnoreException(e):
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
# Check if the `report` method is a coroutine function
|
|
123
|
+
if asyncio.iscoroutinefunction(self.__exception_handler.report):
|
|
124
|
+
|
|
125
|
+
# If it is, await its execution to report the exception
|
|
126
|
+
await self.__exception_handler.report(
|
|
127
|
+
exception=e,
|
|
128
|
+
log=self.__logger
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
else:
|
|
132
|
+
|
|
133
|
+
# If it is not a coroutine, call it directly
|
|
134
|
+
self.__exception_handler.report(
|
|
135
|
+
exception=e,
|
|
136
|
+
log=self.__logger
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# Check if the kernel is of type `KernelCLI` or `Any`
|
|
140
|
+
if isinstance(kernel, KernelCLI) or isinstance(kernel, Schedule):
|
|
141
|
+
|
|
142
|
+
# Check if the `renderCLI` method is a coroutine function
|
|
143
|
+
if asyncio.iscoroutinefunction(self.__exception_handler.renderCLI):
|
|
144
|
+
|
|
145
|
+
# If it is, await its execution to render the exception for the CLI
|
|
146
|
+
return await self.__exception_handler.renderCLI(
|
|
147
|
+
request=request,
|
|
148
|
+
exception=e,
|
|
149
|
+
log=self.__logger,
|
|
150
|
+
console=self.__console
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
else:
|
|
154
|
+
|
|
155
|
+
# If it is not a coroutine, call it directly
|
|
156
|
+
return self.__exception_handler.renderCLI(
|
|
157
|
+
request=request,
|
|
158
|
+
exception=e,
|
|
159
|
+
log=self.__logger,
|
|
160
|
+
console=self.__console
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Execute the exception handling logic using the Coroutine wrapper
|
|
164
|
+
Coroutine(handle()).run()
|
|
@@ -7,7 +7,7 @@ from orionis.services.log.contracts.log_service import ILogger
|
|
|
7
7
|
class IBaseExceptionHandler:
|
|
8
8
|
|
|
9
9
|
@abstractmethod
|
|
10
|
-
def destructureException(self, e: BaseException):
|
|
10
|
+
async def destructureException(self, e: BaseException):
|
|
11
11
|
"""
|
|
12
12
|
Converts an exception into a structured `Throwable` object containing detailed information.
|
|
13
13
|
|
|
@@ -29,7 +29,7 @@ class IBaseExceptionHandler:
|
|
|
29
29
|
pass
|
|
30
30
|
|
|
31
31
|
@abstractmethod
|
|
32
|
-
def shouldIgnoreException(self, e: BaseException) -> bool:
|
|
32
|
+
async def shouldIgnoreException(self, e: BaseException) -> bool:
|
|
33
33
|
"""
|
|
34
34
|
Determines if the exception should be ignored (not handled) by the handler.
|
|
35
35
|
|
|
@@ -46,7 +46,7 @@ class IBaseExceptionHandler:
|
|
|
46
46
|
pass
|
|
47
47
|
|
|
48
48
|
@abstractmethod
|
|
49
|
-
def report (self, exception: BaseException, log: ILogger) -> Any:
|
|
49
|
+
async def report (self, exception: BaseException, log: ILogger) -> Any:
|
|
50
50
|
"""
|
|
51
51
|
Report or log an exception.
|
|
52
52
|
|
|
@@ -62,7 +62,7 @@ class IBaseExceptionHandler:
|
|
|
62
62
|
pass
|
|
63
63
|
|
|
64
64
|
@abstractmethod
|
|
65
|
-
def renderCLI(self, request: CLIRequest, exception: BaseException, log: ILogger, console: IConsole) -> Any:
|
|
65
|
+
async def renderCLI(self, request: CLIRequest, exception: BaseException, log: ILogger, console: IConsole) -> Any:
|
|
66
66
|
"""
|
|
67
67
|
Render the exception message for CLI output.
|
|
68
68
|
|
orionis/metadata/framework.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from typing import Any, Coroutine as TypingCoroutine, TypeVar, Union
|
|
2
|
+
from typing import Any, Callable, Coroutine as TypingCoroutine, TypeVar, Union
|
|
3
3
|
from orionis.services.asynchrony.contracts.coroutines import ICoroutine
|
|
4
4
|
from orionis.services.asynchrony.exceptions import OrionisCoroutineException
|
|
5
5
|
from orionis.services.introspection.objects.types import Type
|
|
@@ -8,29 +8,128 @@ T = TypeVar("T")
|
|
|
8
8
|
|
|
9
9
|
class Coroutine(ICoroutine):
|
|
10
10
|
|
|
11
|
-
def __init__(self, func: TypingCoroutine[Any, Any, T]) -> None:
|
|
11
|
+
def __init__(self, func: Union[TypingCoroutine[Any, Any, T], Callable[..., TypingCoroutine[Any, Any, T]]]) -> None:
|
|
12
12
|
"""
|
|
13
|
-
|
|
13
|
+
Initialize a Coroutine wrapper for managing and executing coroutine objects.
|
|
14
|
+
|
|
15
|
+
This constructor accepts either a coroutine object directly or a callable that
|
|
16
|
+
returns a coroutine when invoked. The wrapped coroutine can later be executed
|
|
17
|
+
using the run() method with automatic context detection.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
func : Union[TypingCoroutine[Any, Any, T], Callable[..., TypingCoroutine[Any, Any, T]]]
|
|
22
|
+
The coroutine object to be wrapped and managed, or a callable that returns
|
|
23
|
+
a coroutine. This will be stored internally for later execution.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
None
|
|
28
|
+
This is a constructor method and does not return any value.
|
|
29
|
+
|
|
30
|
+
Notes
|
|
31
|
+
-----
|
|
32
|
+
- The coroutine type validation is performed during execution in the run() method,
|
|
33
|
+
not during initialization.
|
|
34
|
+
- Both coroutine objects and coroutine functions are accepted as valid input.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
# Store the coroutine object or callable for later execution
|
|
38
|
+
self.__func = func
|
|
39
|
+
|
|
40
|
+
def invoke(self, *args, **kwargs) -> Union[T, asyncio.Task, None]:
|
|
41
|
+
"""
|
|
42
|
+
Invoke the callable coroutine function with the provided arguments.
|
|
43
|
+
|
|
44
|
+
This method executes a callable coroutine function or regular function with the given
|
|
45
|
+
arguments and keyword arguments. It automatically detects the execution context and
|
|
46
|
+
handles both synchronous and asynchronous execution appropriately.
|
|
14
47
|
|
|
15
48
|
Parameters
|
|
16
49
|
----------
|
|
17
|
-
|
|
18
|
-
|
|
50
|
+
*args : tuple
|
|
51
|
+
Positional arguments to pass to the callable function.
|
|
52
|
+
**kwargs : dict
|
|
53
|
+
Keyword arguments to pass to the callable function.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
Union[T, asyncio.Task, None]
|
|
58
|
+
- T: The result of the coroutine if executed synchronously
|
|
59
|
+
- asyncio.Task: A task object if scheduled for asynchronous execution
|
|
60
|
+
- None: If the callable is not a coroutine function
|
|
19
61
|
|
|
20
62
|
Raises
|
|
21
63
|
------
|
|
22
64
|
OrionisCoroutineException
|
|
23
|
-
If
|
|
24
|
-
|
|
65
|
+
If an error occurs during coroutine execution.
|
|
66
|
+
RuntimeError
|
|
67
|
+
If an error occurs during callable execution that is not coroutine-related.
|
|
25
68
|
|
|
26
|
-
|
|
27
|
-
|
|
69
|
+
Notes
|
|
70
|
+
-----
|
|
71
|
+
- Only callable objects can be invoked with this method
|
|
72
|
+
- For coroutine functions, execution context is automatically detected
|
|
73
|
+
- Non-coroutine callables are executed directly and return None
|
|
74
|
+
- Exceptions are wrapped with appropriate context information
|
|
75
|
+
|
|
76
|
+
Examples
|
|
77
|
+
--------
|
|
78
|
+
>>> async def my_coro(x, y):
|
|
79
|
+
... return x + y
|
|
80
|
+
>>> coro = Coroutine(my_coro)
|
|
81
|
+
>>> result = coro.invoke(1, 2) # Returns Task or result depending on context
|
|
82
|
+
"""
|
|
83
|
+
if not callable(self.__func):
|
|
28
84
|
raise OrionisCoroutineException(
|
|
29
|
-
f"
|
|
85
|
+
f"Cannot invoke non-callable object of type {type(self.__func).__name__}"
|
|
30
86
|
)
|
|
31
87
|
|
|
32
|
-
|
|
33
|
-
|
|
88
|
+
try:
|
|
89
|
+
|
|
90
|
+
# Check if the callable is a coroutine function
|
|
91
|
+
if asyncio.iscoroutinefunction(self.__func):
|
|
92
|
+
|
|
93
|
+
# Create the coroutine object
|
|
94
|
+
coroutine_obj = self.__func(*args, **kwargs)
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
|
|
98
|
+
# Check if we're inside a running event loop
|
|
99
|
+
loop = asyncio.get_running_loop()
|
|
100
|
+
return loop.create_task(coroutine_obj)
|
|
101
|
+
|
|
102
|
+
except RuntimeError:
|
|
103
|
+
|
|
104
|
+
# No running event loop, execute synchronously
|
|
105
|
+
try:
|
|
106
|
+
|
|
107
|
+
# Use asyncio.run to execute the coroutine and return its result
|
|
108
|
+
return asyncio.run(coroutine_obj)
|
|
109
|
+
|
|
110
|
+
except Exception as e:
|
|
111
|
+
|
|
112
|
+
# Wrap and raise any exceptions that occur during execution
|
|
113
|
+
raise OrionisCoroutineException(
|
|
114
|
+
f"Failed to execute coroutine synchronously: {str(e)}"
|
|
115
|
+
) from e
|
|
116
|
+
|
|
117
|
+
else:
|
|
118
|
+
|
|
119
|
+
# Execute regular callable directly
|
|
120
|
+
return self.__func(*args, **kwargs)
|
|
121
|
+
|
|
122
|
+
except OrionisCoroutineException:
|
|
123
|
+
|
|
124
|
+
# Re-raise our custom exceptions as-is
|
|
125
|
+
raise
|
|
126
|
+
|
|
127
|
+
except Exception as e:
|
|
128
|
+
|
|
129
|
+
# Wrap and raise any other exceptions that occur during invocation
|
|
130
|
+
raise RuntimeError(
|
|
131
|
+
f"Unexpected error during callable invocation: {str(e)}"
|
|
132
|
+
) from e
|
|
34
133
|
|
|
35
134
|
def run(self) -> Union[T, asyncio.Future]:
|
|
36
135
|
"""
|
|
@@ -53,6 +152,12 @@ class Coroutine(ICoroutine):
|
|
|
53
152
|
- The method automatically detects the execution context and chooses the appropriate execution strategy.
|
|
54
153
|
"""
|
|
55
154
|
|
|
155
|
+
# Validate that the provided object is a coroutine
|
|
156
|
+
if not Type(self.__func).isCoroutine():
|
|
157
|
+
raise OrionisCoroutineException(
|
|
158
|
+
f"Expected a coroutine object, but got {type(self.__func).__name__}."
|
|
159
|
+
)
|
|
160
|
+
|
|
56
161
|
# Attempt to get the currently running event loop
|
|
57
162
|
try:
|
|
58
163
|
loop = asyncio.get_running_loop()
|
|
@@ -13,6 +13,7 @@ orionis/console/base/scheduler_event_listener.py,sha256=tmdAMPzTmT8z0BcpyoIZwyTR
|
|
|
13
13
|
orionis/console/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
orionis/console/commands/cache.py,sha256=8DsYoRzSBLn0P9qkGVItRbo0R6snWBDBg0_Xa7tmVhs,2322
|
|
15
15
|
orionis/console/commands/help.py,sha256=zfSw0pYaOnFN-_Ozdn4veBQDYMgSSDY10nPDCi-7tTY,3199
|
|
16
|
+
orionis/console/commands/make_listener.py,sha256=iPOMCc41njwUKurxSwatZUTjpp-bBLdO9nN-w2FJ4mI,1921
|
|
16
17
|
orionis/console/commands/publisher.py,sha256=FUg-EUzK7LLXsla10ZUZro8V0Z5S-KjmsaSdRHSSGbA,21381
|
|
17
18
|
orionis/console/commands/scheduler_list.py,sha256=A2N_mEXEJDHO8DX2TDrL1ROeeRhFSkWD3rCw64Hrf0o,4763
|
|
18
19
|
orionis/console/commands/scheduler_work.py,sha256=mzSFes8Wl1gCf253tNYClij0abT5HlpW1QZVFrU5EXo,6445
|
|
@@ -28,7 +29,7 @@ orionis/console/contracts/schedule.py,sha256=17cfPYtLo-jqF8FxYOhh4epJZnxw5mMPuLG
|
|
|
28
29
|
orionis/console/contracts/schedule_event_listener.py,sha256=7fQdPh6X_npfGpQW_2x81D7-5Pe40jIog9uDeEU0kro,4390
|
|
29
30
|
orionis/console/contracts/scheduler.py,sha256=OW-a_YDDNPrenYT9z8Tv71VjyZ1aSzqzqhTBhTCZhGM,7698
|
|
30
31
|
orionis/console/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
-
orionis/console/core/reactor.py,sha256=
|
|
32
|
+
orionis/console/core/reactor.py,sha256=cUYZwOyWjKai885peSaRRu3vM0IpWxskCNyl9IangHs,30626
|
|
32
33
|
orionis/console/dumper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
34
|
orionis/console/dumper/dump.py,sha256=CATERiQ6XuIrKQsDaWcVxzTtlAJI9qLJX44fQxEX8ws,22443
|
|
34
35
|
orionis/console/dumper/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -83,7 +84,7 @@ orionis/console/request/cli_request.py,sha256=7-sgYmNUCipuHLVAwWLJiHv0cJCDmsM1Lu
|
|
|
83
84
|
orionis/console/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
84
85
|
orionis/console/tasks/event.py,sha256=l4J-HEPaj1mxB_PYQMgG9dRHUe01wUag8fKLLnR2N2M,164395
|
|
85
86
|
orionis/console/tasks/listener.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
86
|
-
orionis/console/tasks/schedule.py,sha256=
|
|
87
|
+
orionis/console/tasks/schedule.py,sha256=lou90LaOWw4_tw2ONrplVOEUI9A5esKspFL900EIUBI,82842
|
|
87
88
|
orionis/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
88
89
|
orionis/container/container.py,sha256=aF_b6lTUpG4YCo9yFJEzsntTdIzgMMXFW5LyWqAJVBQ,87987
|
|
89
90
|
orionis/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -116,12 +117,12 @@ orionis/container/validators/is_subclass.py,sha256=4sBaGLoRs8nUhuWjlP0VJqyTwVHYq
|
|
|
116
117
|
orionis/container/validators/is_valid_alias.py,sha256=4uAYcq8xov7jZbXnpKpjNkxcZtlTNnL5RRctVPMwJes,1424
|
|
117
118
|
orionis/container/validators/lifetime.py,sha256=IQ43fDNrxYHMlZH2zlYDJnlkLO_eS4U7Fs3UJgQBidI,1844
|
|
118
119
|
orionis/failure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
119
|
-
orionis/failure/catch.py,sha256=
|
|
120
|
+
orionis/failure/catch.py,sha256=kmw2mbkGrFNw9s8jrr2NdJeGlbJVvXQQSlnjltwC4oM,6819
|
|
120
121
|
orionis/failure/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
121
|
-
orionis/failure/base/handler.py,sha256=
|
|
122
|
+
orionis/failure/base/handler.py,sha256=a7fQJMWVjALwFiITRsMYg3s7WSO6zcbmq171iQRWy48,4867
|
|
122
123
|
orionis/failure/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
123
124
|
orionis/failure/contracts/catch.py,sha256=e2wM1p6VxbvAjgWm-MwoM9p2ystSsyBu8Qnt6Ehr6Vc,1179
|
|
124
|
-
orionis/failure/contracts/handler.py,sha256=
|
|
125
|
+
orionis/failure/contracts/handler.py,sha256=drNE8iu8RUHi3TgKn-lUEIfVsZeGsMTUecTZOfay19E,2240
|
|
125
126
|
orionis/failure/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
126
127
|
orionis/failure/entities/throwable.py,sha256=ogys062uhim5QMYU62ezlnumRAnYQlUf_vZvQY47S3U,1227
|
|
127
128
|
orionis/foundation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -241,11 +242,11 @@ orionis/foundation/providers/scheduler_provider.py,sha256=1do4B09bU_6xbFHHVYYTGM
|
|
|
241
242
|
orionis/foundation/providers/testing_provider.py,sha256=SrJRpdvcblx9WvX7x9Y3zc7OQfiTf7la0HAJrm2ESlE,3725
|
|
242
243
|
orionis/foundation/providers/workers_provider.py,sha256=oa_2NIDH6UxZrtuGkkoo_zEoNIMGgJ46vg5CCgAm7wI,3926
|
|
243
244
|
orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
244
|
-
orionis/metadata/framework.py,sha256=
|
|
245
|
+
orionis/metadata/framework.py,sha256=nuA2nefeGQ2B3VGS-om5qZigBmEBbAZwhTnm54CFJn0,4109
|
|
245
246
|
orionis/metadata/package.py,sha256=k7Yriyp5aUcR-iR8SK2ec_lf0_Cyc-C7JczgXa-I67w,16039
|
|
246
247
|
orionis/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
247
248
|
orionis/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
248
|
-
orionis/services/asynchrony/coroutines.py,sha256=
|
|
249
|
+
orionis/services/asynchrony/coroutines.py,sha256=M1o4Al5dk8BR85CWHHUgymVQaD_6PgirenQMeITUoZQ,6863
|
|
249
250
|
orionis/services/asynchrony/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
250
251
|
orionis/services/asynchrony/contracts/coroutines.py,sha256=rVy1HO58RFKliGeaf6GUC7mGtPZXimIhzkFHR1EWRoc,1082
|
|
251
252
|
orionis/services/asynchrony/exceptions/__init__.py,sha256=COm6RhSiuwWqy3YcJ_0gVu6XHjn5P3zVaiUp5Pw_h48,99
|
|
@@ -419,7 +420,7 @@ orionis/test/validators/web_report.py,sha256=n9BfzOZz6aEiNTypXcwuWbFRG0OdHNSmCNu
|
|
|
419
420
|
orionis/test/validators/workers.py,sha256=rWcdRexINNEmGaO7mnc1MKUxkHKxrTsVuHgbnIfJYgc,1206
|
|
420
421
|
orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
421
422
|
orionis/test/view/render.py,sha256=f-zNhtKSg9R5Njqujbg2l2amAs2-mRVESneLIkWOZjU,4082
|
|
422
|
-
orionis-0.
|
|
423
|
+
orionis-0.534.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
|
|
423
424
|
tests/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
424
425
|
tests/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
425
426
|
tests/container/context/test_manager.py,sha256=wOwXpl9rHNfTTexa9GBKYMwK0_-KSQPbI-AEyGNkmAE,1356
|
|
@@ -512,7 +513,7 @@ tests/metadata/test_metadata_framework.py,sha256=vOsp5owDMMoL5dtgiN9EC5Sdj8pemXV
|
|
|
512
513
|
tests/metadata/test_metadata_package.py,sha256=AcD5rlkD5MeX2tJvQkIHeGeAl88k0tsF2wOU5v4JVN0,4894
|
|
513
514
|
tests/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
514
515
|
tests/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
515
|
-
tests/services/asynchrony/test_services_asynchrony_coroutine.py,sha256=
|
|
516
|
+
tests/services/asynchrony/test_services_asynchrony_coroutine.py,sha256=xWdH5CKrXQ8zGSFadEDN_7LoNEAcDWWIBdm2TVQPuLo,3445
|
|
516
517
|
tests/services/environment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
517
518
|
tests/services/environment/test_services_environment.py,sha256=8gbF2vK238lracBipHCHgiYxThRnfLtN9pj--rFald0,9570
|
|
518
519
|
tests/services/introspection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -565,8 +566,8 @@ tests/testing/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
565
566
|
tests/testing/validators/test_testing_validators.py,sha256=WPo5GxTP6xE-Dw3X1vZoqOMpb6HhokjNSbgDsDRDvy4,16588
|
|
566
567
|
tests/testing/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
567
568
|
tests/testing/view/test_render.py,sha256=tnnMBwS0iKUIbogLvu-7Rii50G6Koddp3XT4wgdFEYM,1050
|
|
568
|
-
orionis-0.
|
|
569
|
-
orionis-0.
|
|
570
|
-
orionis-0.
|
|
571
|
-
orionis-0.
|
|
572
|
-
orionis-0.
|
|
569
|
+
orionis-0.534.0.dist-info/METADATA,sha256=R7FBw3jg3tfT8gujp8PmJLFqoTJK6oXImdwynE9zV9c,4801
|
|
570
|
+
orionis-0.534.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
571
|
+
orionis-0.534.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
|
|
572
|
+
orionis-0.534.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
573
|
+
orionis-0.534.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|