orionis 0.536.0__py3-none-any.whl → 0.538.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/contracts/event.py +20 -12
- orionis/console/contracts/schedule.py +106 -3
- orionis/console/enums/event.py +7 -1
- orionis/console/tasks/event.py +51 -1
- orionis/console/tasks/schedule.py +87 -76
- orionis/container/container.py +144 -5
- orionis/container/contracts/container.py +52 -0
- orionis/failure/base/handler.py +9 -9
- orionis/failure/catch.py +14 -96
- orionis/failure/entities/throwable.py +1 -1
- orionis/foundation/application.py +2 -2
- orionis/metadata/framework.py +1 -1
- orionis/services/introspection/dependencies/entities/resolve_argument.py +10 -0
- orionis/services/introspection/dependencies/reflection.py +7 -1
- {orionis-0.536.0.dist-info → orionis-0.538.0.dist-info}/METADATA +1 -1
- {orionis-0.536.0.dist-info → orionis-0.538.0.dist-info}/RECORD +20 -20
- {orionis-0.536.0.dist-info → orionis-0.538.0.dist-info}/WHEEL +0 -0
- {orionis-0.536.0.dist-info → orionis-0.538.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.536.0.dist-info → orionis-0.538.0.dist-info}/top_level.txt +0 -0
- {orionis-0.536.0.dist-info → orionis-0.538.0.dist-info}/zip-safe +0 -0
|
@@ -5,24 +5,32 @@ from orionis.console.enums.event import Event as EventEntity
|
|
|
5
5
|
|
|
6
6
|
class IEvent(ABC):
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
) ->
|
|
8
|
+
def misfireGraceTime(
|
|
9
|
+
self,
|
|
10
|
+
seconds: int = 60
|
|
11
|
+
) -> 'IEvent':
|
|
12
12
|
"""
|
|
13
|
-
|
|
13
|
+
Set the misfire grace time for the event.
|
|
14
14
|
|
|
15
|
-
This method
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
This method allows you to specify a grace period (in seconds) during which
|
|
16
|
+
a missed execution of the event can still be executed. If the event is not
|
|
17
|
+
executed within this time frame after its scheduled time, it will be skipped.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
seconds : int
|
|
22
|
+
The number of seconds to allow for a misfire grace period. Must be a positive integer.
|
|
18
23
|
|
|
19
24
|
Returns
|
|
20
25
|
-------
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
Event
|
|
27
|
+
Returns the current instance of the Event to allow method chaining.
|
|
28
|
+
|
|
29
|
+
Raises
|
|
30
|
+
------
|
|
31
|
+
CLIOrionisValueError
|
|
32
|
+
If the provided seconds is not a positive integer.
|
|
24
33
|
"""
|
|
25
|
-
pass
|
|
26
34
|
|
|
27
35
|
@abstractmethod
|
|
28
36
|
def purpose(
|
|
@@ -218,7 +218,7 @@ class ISchedule(ABC):
|
|
|
218
218
|
pass
|
|
219
219
|
|
|
220
220
|
@abstractmethod
|
|
221
|
-
def
|
|
221
|
+
def pauseTask(self, signature: str) -> bool:
|
|
222
222
|
"""
|
|
223
223
|
Pause a scheduled job in the AsyncIO scheduler.
|
|
224
224
|
|
|
@@ -246,7 +246,7 @@ class ISchedule(ABC):
|
|
|
246
246
|
pass
|
|
247
247
|
|
|
248
248
|
@abstractmethod
|
|
249
|
-
def
|
|
249
|
+
def resumeTask(self, signature: str) -> bool:
|
|
250
250
|
"""
|
|
251
251
|
Resume a paused job in the AsyncIO scheduler.
|
|
252
252
|
|
|
@@ -274,7 +274,7 @@ class ISchedule(ABC):
|
|
|
274
274
|
pass
|
|
275
275
|
|
|
276
276
|
@abstractmethod
|
|
277
|
-
def
|
|
277
|
+
def removeTask(self, signature: str) -> bool:
|
|
278
278
|
"""
|
|
279
279
|
Remove a scheduled job from the AsyncIO scheduler.
|
|
280
280
|
|
|
@@ -324,4 +324,107 @@ class ISchedule(ABC):
|
|
|
324
324
|
- 'end_date': str or None, the formatted end date and time of the job, or None if not set.
|
|
325
325
|
- 'details': any, additional details about the job.
|
|
326
326
|
"""
|
|
327
|
+
pass
|
|
328
|
+
|
|
329
|
+
@abstractmethod
|
|
330
|
+
def cancelScheduledPause(self) -> bool:
|
|
331
|
+
"""
|
|
332
|
+
Cancel a previously scheduled pause operation.
|
|
333
|
+
|
|
334
|
+
This method attempts to remove a job from the scheduler that was set to pause
|
|
335
|
+
the scheduler at a specific time. If the job exists, it is removed, and a log entry
|
|
336
|
+
is created to indicate the cancellation. If no such job exists, the method returns False.
|
|
337
|
+
|
|
338
|
+
Returns
|
|
339
|
+
-------
|
|
340
|
+
bool
|
|
341
|
+
True if the scheduled pause job was successfully cancelled.
|
|
342
|
+
False if no pause job was found or an error occurred during the cancellation process.
|
|
343
|
+
"""
|
|
344
|
+
pass
|
|
345
|
+
|
|
346
|
+
@abstractmethod
|
|
347
|
+
def cancelScheduledResume(self) -> bool:
|
|
348
|
+
"""
|
|
349
|
+
Cancel a previously scheduled resume operation.
|
|
350
|
+
|
|
351
|
+
This method attempts to remove a job from the scheduler that was set to resume
|
|
352
|
+
the scheduler at a specific time. If the job exists, it is removed, and a log entry
|
|
353
|
+
is created to indicate the cancellation. If no such job exists, the method returns False.
|
|
354
|
+
|
|
355
|
+
Returns
|
|
356
|
+
-------
|
|
357
|
+
bool
|
|
358
|
+
True if the scheduled resume job was successfully cancelled.
|
|
359
|
+
False if no resume job was found or an error occurred during the cancellation process.
|
|
360
|
+
"""
|
|
361
|
+
pass
|
|
362
|
+
|
|
363
|
+
@abstractmethod
|
|
364
|
+
def cancelScheduledShutdown(self) -> bool:
|
|
365
|
+
"""
|
|
366
|
+
Cancel a previously scheduled shutdown operation.
|
|
367
|
+
|
|
368
|
+
This method attempts to remove a job from the scheduler that was set to shut down
|
|
369
|
+
the scheduler at a specific time. If the job exists, it is removed, and a log entry
|
|
370
|
+
is created to indicate the cancellation. If no such job exists, the method returns False.
|
|
371
|
+
|
|
372
|
+
Returns
|
|
373
|
+
-------
|
|
374
|
+
bool
|
|
375
|
+
True if the scheduled shutdown job was successfully cancelled.
|
|
376
|
+
False if no shutdown job was found or an error occurred during the cancellation process.
|
|
377
|
+
"""
|
|
378
|
+
pass
|
|
379
|
+
|
|
380
|
+
@abstractmethod
|
|
381
|
+
def isRunning(self) -> bool:
|
|
382
|
+
"""
|
|
383
|
+
Determine if the scheduler is currently active and running.
|
|
384
|
+
|
|
385
|
+
This method checks the internal state of the AsyncIOScheduler instance to determine
|
|
386
|
+
whether it is currently running. The scheduler is considered running if it has been
|
|
387
|
+
started and has not been paused or shut down.
|
|
388
|
+
|
|
389
|
+
Returns
|
|
390
|
+
-------
|
|
391
|
+
bool
|
|
392
|
+
True if the scheduler is running, False otherwise.
|
|
393
|
+
"""
|
|
394
|
+
pass
|
|
395
|
+
|
|
396
|
+
@abstractmethod
|
|
397
|
+
def forceStop(self) -> None:
|
|
398
|
+
"""
|
|
399
|
+
Forcefully stop the scheduler immediately without waiting for jobs to complete.
|
|
400
|
+
|
|
401
|
+
This method shuts down the AsyncIOScheduler instance without waiting for currently
|
|
402
|
+
running jobs to finish. It is intended for emergency situations where an immediate
|
|
403
|
+
stop is required. The method also signals the internal stop event to ensure that
|
|
404
|
+
the scheduler's main loop is interrupted and the application can proceed with
|
|
405
|
+
shutdown procedures.
|
|
406
|
+
|
|
407
|
+
Returns
|
|
408
|
+
-------
|
|
409
|
+
None
|
|
410
|
+
This method does not return any value. It forcefully stops the scheduler and
|
|
411
|
+
signals the stop event.
|
|
412
|
+
"""
|
|
413
|
+
pass
|
|
414
|
+
|
|
415
|
+
@abstractmethod
|
|
416
|
+
def stop(self) -> None:
|
|
417
|
+
"""
|
|
418
|
+
Stop the scheduler synchronously by setting the stop event.
|
|
419
|
+
|
|
420
|
+
This method signals the scheduler to stop by setting the internal stop event.
|
|
421
|
+
It can be called from non-async contexts to initiate a shutdown. If the asyncio
|
|
422
|
+
event loop is running, the stop event is set in a thread-safe manner. Otherwise,
|
|
423
|
+
the stop event is set directly.
|
|
424
|
+
|
|
425
|
+
Returns
|
|
426
|
+
-------
|
|
427
|
+
None
|
|
428
|
+
This method does not return any value. It signals the scheduler to stop.
|
|
429
|
+
"""
|
|
327
430
|
pass
|
orionis/console/enums/event.py
CHANGED
|
@@ -60,4 +60,10 @@ class Event:
|
|
|
60
60
|
details: Optional[str] = None
|
|
61
61
|
|
|
62
62
|
# Optional listener that implements IScheduleEventListener
|
|
63
|
-
listener: Optional[IScheduleEventListener] = None
|
|
63
|
+
listener: Optional[IScheduleEventListener] = None
|
|
64
|
+
|
|
65
|
+
# Maximum number of concurrent instances allowed for the event
|
|
66
|
+
max_instances: int = 1
|
|
67
|
+
|
|
68
|
+
# Grace time in seconds for misfired events
|
|
69
|
+
misfire_grace_time : Optional[int] = None
|
orionis/console/tasks/event.py
CHANGED
|
@@ -77,6 +77,9 @@ class Event(IEvent):
|
|
|
77
77
|
# Initialize the maximum instances attribute as None
|
|
78
78
|
self.__max_instances: Optional[int] = None
|
|
79
79
|
|
|
80
|
+
# Initialize the misfire grace time attribute as None
|
|
81
|
+
self.__misfire_grace_time: Optional[int] = None
|
|
82
|
+
|
|
80
83
|
def toEntity(
|
|
81
84
|
self
|
|
82
85
|
) -> EventEntity:
|
|
@@ -128,6 +131,14 @@ class Event(IEvent):
|
|
|
128
131
|
if self.__listener is not None and not issubclass(self.__listener, IScheduleEventListener):
|
|
129
132
|
raise CLIOrionisValueError("Listener must implement IScheduleEventListener interface or be None.")
|
|
130
133
|
|
|
134
|
+
# Validate that max_instances is a positive integer if it is set
|
|
135
|
+
if self.__max_instances is not None and (not isinstance(self.__max_instances, int) or self.__max_instances <= 0):
|
|
136
|
+
raise CLIOrionisValueError("Max instances must be a positive integer or None.")
|
|
137
|
+
|
|
138
|
+
# Validate that misfire_grace_time is a positive integer if it is set
|
|
139
|
+
if self.__misfire_grace_time is not None and (not isinstance(self.__misfire_grace_time, int) or self.__misfire_grace_time <= 0):
|
|
140
|
+
raise CLIOrionisValueError("Misfire grace time must be a positive integer or None.")
|
|
141
|
+
|
|
131
142
|
# Construct and return an EventEntity with the current event's attributes
|
|
132
143
|
return EventEntity(
|
|
133
144
|
signature=self.__signature,
|
|
@@ -138,9 +149,48 @@ class Event(IEvent):
|
|
|
138
149
|
end_date=self.__end_date,
|
|
139
150
|
trigger=self.__trigger,
|
|
140
151
|
details=self.__details,
|
|
141
|
-
listener=self.__listener
|
|
152
|
+
listener=self.__listener,
|
|
153
|
+
max_instances=self.__max_instances,
|
|
154
|
+
misfire_grace_time=self.__misfire_grace_time
|
|
142
155
|
)
|
|
143
156
|
|
|
157
|
+
def misfireGraceTime(
|
|
158
|
+
self,
|
|
159
|
+
seconds: int = 60
|
|
160
|
+
) -> 'Event':
|
|
161
|
+
"""
|
|
162
|
+
Set the misfire grace time for the event.
|
|
163
|
+
|
|
164
|
+
This method allows you to specify a grace period (in seconds) during which
|
|
165
|
+
a missed execution of the event can still be executed. If the event is not
|
|
166
|
+
executed within this time frame after its scheduled time, it will be skipped.
|
|
167
|
+
|
|
168
|
+
Parameters
|
|
169
|
+
----------
|
|
170
|
+
seconds : int
|
|
171
|
+
The number of seconds to allow for a misfire grace period. Must be a positive integer.
|
|
172
|
+
|
|
173
|
+
Returns
|
|
174
|
+
-------
|
|
175
|
+
Event
|
|
176
|
+
Returns the current instance of the Event to allow method chaining.
|
|
177
|
+
|
|
178
|
+
Raises
|
|
179
|
+
------
|
|
180
|
+
CLIOrionisValueError
|
|
181
|
+
If the provided seconds is not a positive integer.
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
# Validate that the seconds parameter is a positive integer
|
|
185
|
+
if not isinstance(seconds, int) or seconds <= 0:
|
|
186
|
+
raise CLIOrionisValueError("Misfire grace time must be a positive integer.")
|
|
187
|
+
|
|
188
|
+
# Set the internal misfire grace time attribute
|
|
189
|
+
self.__misfire_grace_time = seconds
|
|
190
|
+
|
|
191
|
+
# Return self to support method chaining
|
|
192
|
+
return self
|
|
193
|
+
|
|
144
194
|
def purpose(
|
|
145
195
|
self,
|
|
146
196
|
purpose: str
|
|
@@ -37,7 +37,6 @@ 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
|
|
41
40
|
from orionis.services.log.contracts.log_service import ILogger
|
|
42
41
|
|
|
43
42
|
class Schedule(ISchedule):
|
|
@@ -167,7 +166,7 @@ class Schedule(ISchedule):
|
|
|
167
166
|
# Store each job's signature and description in the commands dictionary
|
|
168
167
|
commands[job['signature']] = {
|
|
169
168
|
'signature': job['signature'],
|
|
170
|
-
'description': job.get('description', '')
|
|
169
|
+
'description': job.get('description', 'No description available.')
|
|
171
170
|
}
|
|
172
171
|
|
|
173
172
|
# Return the commands dictionary
|
|
@@ -268,7 +267,7 @@ class Schedule(ISchedule):
|
|
|
268
267
|
|
|
269
268
|
# Prevent adding new commands while the scheduler is running
|
|
270
269
|
if self.isRunning():
|
|
271
|
-
|
|
270
|
+
self.__raiseException(CLIOrionisValueError("Cannot add new commands while the scheduler is running."))
|
|
272
271
|
|
|
273
272
|
# Validate that the command signature is a non-empty string
|
|
274
273
|
if not isinstance(signature, str) or not signature.strip():
|
|
@@ -465,7 +464,7 @@ class Schedule(ISchedule):
|
|
|
465
464
|
|
|
466
465
|
# Validate that the provided event is an instance of ListeningEvent
|
|
467
466
|
if not isinstance(listening_vent, ListeningEvent):
|
|
468
|
-
|
|
467
|
+
self.__raiseException(CLIOrionisValueError("The event must be an instance of ListeningEvent."))
|
|
469
468
|
|
|
470
469
|
# Retrieve the global identifier for the event from the ListeningEvent enum
|
|
471
470
|
scheduler_event = listening_vent.value
|
|
@@ -481,16 +480,9 @@ class Schedule(ISchedule):
|
|
|
481
480
|
|
|
482
481
|
# Invoke the listener, handling both coroutine and regular functions
|
|
483
482
|
try:
|
|
484
|
-
|
|
485
|
-
# Use Coroutine to handle both sync and async listeners
|
|
486
|
-
Coroutine(listener).invoke(event_data, self)
|
|
487
|
-
|
|
483
|
+
self.__app.invoke(listener, event_data, self)
|
|
488
484
|
except BaseException as e:
|
|
489
|
-
|
|
490
|
-
# Construct and log error message
|
|
491
|
-
error_msg = f"An error occurred while invoking the listener for event '{scheduler_event}': {str(e)}"
|
|
492
|
-
self.__logger.error(error_msg)
|
|
493
|
-
raise CLIOrionisRuntimeError(error_msg) from e
|
|
485
|
+
self.__raiseException(e)
|
|
494
486
|
|
|
495
487
|
def __taskCallableListener(
|
|
496
488
|
self,
|
|
@@ -528,9 +520,7 @@ class Schedule(ISchedule):
|
|
|
528
520
|
|
|
529
521
|
# Validate that the provided event is an instance of ListeningEvent
|
|
530
522
|
if not isinstance(listening_vent, ListeningEvent):
|
|
531
|
-
|
|
532
|
-
self.__logger.error(error_msg)
|
|
533
|
-
raise CLIOrionisValueError(error_msg)
|
|
523
|
+
self.__raiseException(CLIOrionisValueError("The event must be an instance of ListeningEvent."))
|
|
534
524
|
|
|
535
525
|
# Validate that event_data is not None and has a id attribute
|
|
536
526
|
if not isinstance(event_data, EventJob) or not hasattr(event_data, 'id') or not event_data.id:
|
|
@@ -548,38 +538,25 @@ class Schedule(ISchedule):
|
|
|
548
538
|
# Check if the listener is an instance of IScheduleEventListener
|
|
549
539
|
if issubclass(listener, IScheduleEventListener):
|
|
550
540
|
|
|
551
|
-
|
|
552
|
-
if isinstance(listener, type):
|
|
553
|
-
listener = listener()
|
|
554
|
-
|
|
555
|
-
# Check if the listener has a method corresponding to the event type
|
|
556
|
-
if hasattr(listener, scheduler_event) and callable(getattr(listener, scheduler_event)):
|
|
557
|
-
|
|
558
|
-
# Retrieve the method from the listener
|
|
559
|
-
listener_method = getattr(listener, scheduler_event)
|
|
560
|
-
|
|
561
|
-
# Invoke the listener method, handling both coroutine and regular functions
|
|
562
|
-
try:
|
|
563
|
-
|
|
564
|
-
# Use Coroutine to handle both sync and async listener methods
|
|
565
|
-
Coroutine(listener_method).invoke(event_data, self)
|
|
541
|
+
try:
|
|
566
542
|
|
|
567
|
-
|
|
543
|
+
# Initialize the listener if it's a class
|
|
544
|
+
if isinstance(listener, type):
|
|
545
|
+
listener = self.__app.make(listener)
|
|
568
546
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
self.
|
|
572
|
-
raise CLIOrionisRuntimeError(error_msg) from e
|
|
547
|
+
# Check if the listener has a method corresponding to the event type
|
|
548
|
+
if hasattr(listener, scheduler_event) and callable(getattr(listener, scheduler_event)):
|
|
549
|
+
self.__app.call(listener, scheduler_event, event_data, self)
|
|
573
550
|
|
|
574
|
-
|
|
551
|
+
except BaseException as e:
|
|
575
552
|
|
|
576
|
-
#
|
|
577
|
-
self.
|
|
553
|
+
# If an error occurs while invoking the listener, raise an exception
|
|
554
|
+
self.__raiseException(e)
|
|
578
555
|
|
|
579
556
|
else:
|
|
580
557
|
|
|
581
|
-
#
|
|
582
|
-
self.
|
|
558
|
+
# If the listener is not a subclass of IScheduleEventListener, raise an exception
|
|
559
|
+
self.__raiseException(CLIOrionisValueError(f"The listener for job ID '{event_data.id}' must be a subclass of IScheduleEventListener."))
|
|
583
560
|
|
|
584
561
|
def __startedListener(
|
|
585
562
|
self,
|
|
@@ -727,10 +704,7 @@ class Schedule(ISchedule):
|
|
|
727
704
|
self.__globalCallableListener(event_data, ListeningEvent.SCHEDULER_ERROR)
|
|
728
705
|
|
|
729
706
|
# Catch any exceptions that occur during command handling
|
|
730
|
-
self.
|
|
731
|
-
command=job_event_data.id,
|
|
732
|
-
args=list(job_event_data.args) or []
|
|
733
|
-
), event.exception)
|
|
707
|
+
self.__raiseException(event.exception)
|
|
734
708
|
|
|
735
709
|
def __submittedListener(
|
|
736
710
|
self,
|
|
@@ -929,7 +903,7 @@ class Schedule(ISchedule):
|
|
|
929
903
|
|
|
930
904
|
try:
|
|
931
905
|
# Convert the event to its entity representation
|
|
932
|
-
entity = event.toEntity()
|
|
906
|
+
entity: EventEntity = event.toEntity()
|
|
933
907
|
|
|
934
908
|
# Add the job to the internal jobs list
|
|
935
909
|
self.__jobs.append(entity)
|
|
@@ -944,7 +918,9 @@ class Schedule(ISchedule):
|
|
|
944
918
|
trigger=entity.trigger,
|
|
945
919
|
id=signature,
|
|
946
920
|
name=signature,
|
|
947
|
-
replace_existing=True
|
|
921
|
+
replace_existing=True,
|
|
922
|
+
max_instances=entity.max_instances,
|
|
923
|
+
misfire_grace_time=entity.misfire_grace_time
|
|
948
924
|
)
|
|
949
925
|
|
|
950
926
|
# If a listener is associated with the event, register it
|
|
@@ -965,6 +941,48 @@ class Schedule(ISchedule):
|
|
|
965
941
|
# Raise a runtime error if loading the scheduled event fails
|
|
966
942
|
raise CLIOrionisRuntimeError(error_msg)
|
|
967
943
|
|
|
944
|
+
def __raiseException(
|
|
945
|
+
self,
|
|
946
|
+
exception: BaseException
|
|
947
|
+
) -> None:
|
|
948
|
+
"""
|
|
949
|
+
Handle and propagate exceptions through the application's error handling system.
|
|
950
|
+
|
|
951
|
+
This private method serves as a centralized exception handler for the scheduler,
|
|
952
|
+
delegating exception processing to the application's error catching mechanism.
|
|
953
|
+
It ensures that all exceptions occurring within the scheduler context are
|
|
954
|
+
properly handled according to the application's error handling policies.
|
|
955
|
+
|
|
956
|
+
The method acts as a bridge between the scheduler's internal operations and
|
|
957
|
+
the application's global exception handling system, providing consistent
|
|
958
|
+
error handling behavior across the entire application.
|
|
959
|
+
|
|
960
|
+
Parameters
|
|
961
|
+
----------
|
|
962
|
+
exception : BaseException
|
|
963
|
+
The exception instance that was raised during command execution. This can be
|
|
964
|
+
any type of exception that inherits from BaseException, including system
|
|
965
|
+
exceptions, custom application exceptions, and runtime errors.
|
|
966
|
+
|
|
967
|
+
Returns
|
|
968
|
+
-------
|
|
969
|
+
None
|
|
970
|
+
This method does not return any value. It delegates exception handling
|
|
971
|
+
to the application's error catching mechanism and may re-raise the
|
|
972
|
+
exception depending on the configured error handling behavior.
|
|
973
|
+
|
|
974
|
+
Notes
|
|
975
|
+
-----
|
|
976
|
+
This method is intended for internal use within the scheduler and should not
|
|
977
|
+
be called directly by external code. The error catching mechanism may perform
|
|
978
|
+
various actions such as logging, reporting, or re-raising the exception based
|
|
979
|
+
on the application's configuration.
|
|
980
|
+
"""
|
|
981
|
+
|
|
982
|
+
# Delegate exception handling to the application's error catching mechanism
|
|
983
|
+
# This ensures consistent error handling across the entire application
|
|
984
|
+
self.__catch.exception(self, CLIRequest(command="schedule:work", args=[]), exception)
|
|
985
|
+
|
|
968
986
|
def setListener(
|
|
969
987
|
self,
|
|
970
988
|
event: Union[str, ListeningEvent],
|
|
@@ -995,7 +1013,7 @@ class Schedule(ISchedule):
|
|
|
995
1013
|
|
|
996
1014
|
Raises
|
|
997
1015
|
------
|
|
998
|
-
|
|
1016
|
+
CLIOrionisValueError
|
|
999
1017
|
If the event name is not a non-empty string or if the listener is not callable
|
|
1000
1018
|
or an instance of IScheduleEventListener.
|
|
1001
1019
|
"""
|
|
@@ -1006,11 +1024,11 @@ class Schedule(ISchedule):
|
|
|
1006
1024
|
|
|
1007
1025
|
# Validate that the event name is a non-empty string
|
|
1008
1026
|
if not isinstance(event, str) or not event.strip():
|
|
1009
|
-
raise
|
|
1027
|
+
raise CLIOrionisValueError("Event name must be a non-empty string.")
|
|
1010
1028
|
|
|
1011
1029
|
# Validate that the listener is either callable or an instance of IScheduleEventListener
|
|
1012
1030
|
if not callable(listener) and not isinstance(listener, IScheduleEventListener):
|
|
1013
|
-
raise
|
|
1031
|
+
raise CLIOrionisValueError("Listener must be a callable function or an instance of IScheduleEventListener.")
|
|
1014
1032
|
|
|
1015
1033
|
# Register the listener for the specified event in the internal listeners dictionary
|
|
1016
1034
|
self.__listeners[event] = listener
|
|
@@ -1101,19 +1119,13 @@ class Schedule(ISchedule):
|
|
|
1101
1119
|
error reporting and debugging information.
|
|
1102
1120
|
"""
|
|
1103
1121
|
|
|
1122
|
+
# Execute the asynchronous function using the container's invoke method
|
|
1104
1123
|
try:
|
|
1105
|
-
|
|
1106
|
-
# The Coroutine class handles the event loop management and async execution
|
|
1107
|
-
return Coroutine(func).invoke(*args, **kwargs)
|
|
1124
|
+
self.__app.invoke(func, *args, **kwargs)
|
|
1108
1125
|
|
|
1126
|
+
# If an error occurs during execution, raise a custom exception
|
|
1109
1127
|
except Exception as e:
|
|
1110
|
-
|
|
1111
|
-
# Log the error with detailed information for debugging purposes
|
|
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
|
|
1116
|
-
raise CLIOrionisRuntimeError(f"Failed to execute async function: {str(e)}") from e
|
|
1128
|
+
self.__raiseException(e)
|
|
1117
1129
|
|
|
1118
1130
|
# Return the synchronous wrapper function
|
|
1119
1131
|
return sync_wrapper
|
|
@@ -1151,7 +1163,7 @@ class Schedule(ISchedule):
|
|
|
1151
1163
|
|
|
1152
1164
|
# Validate that the 'at' parameter is a datetime object
|
|
1153
1165
|
if not isinstance(at, datetime):
|
|
1154
|
-
|
|
1166
|
+
CLIOrionisValueError("The 'at' parameter must be a datetime object.")
|
|
1155
1167
|
|
|
1156
1168
|
# Define an async function to pause the scheduler
|
|
1157
1169
|
async def schedule_pause():
|
|
@@ -1198,8 +1210,8 @@ class Schedule(ISchedule):
|
|
|
1198
1210
|
|
|
1199
1211
|
except Exception as e:
|
|
1200
1212
|
|
|
1201
|
-
#
|
|
1202
|
-
self.
|
|
1213
|
+
# If an error occurs while pausing the job, raise an exception
|
|
1214
|
+
self.__raiseException(e)
|
|
1203
1215
|
|
|
1204
1216
|
# Execute the global callable listener after all jobs are paused
|
|
1205
1217
|
self.__globalCallableListener(SchedulerPaused(
|
|
@@ -1270,7 +1282,7 @@ class Schedule(ISchedule):
|
|
|
1270
1282
|
|
|
1271
1283
|
# Validate that the 'at' parameter is a datetime object
|
|
1272
1284
|
if not isinstance(at, datetime):
|
|
1273
|
-
raise
|
|
1285
|
+
raise CLIOrionisValueError("The 'at' parameter must be a datetime object.")
|
|
1274
1286
|
|
|
1275
1287
|
# Define an async function to resume the scheduler
|
|
1276
1288
|
async def schedule_resume():
|
|
@@ -1300,8 +1312,8 @@ class Schedule(ISchedule):
|
|
|
1300
1312
|
|
|
1301
1313
|
except Exception as e:
|
|
1302
1314
|
|
|
1303
|
-
#
|
|
1304
|
-
self.
|
|
1315
|
+
# If an error occurs while resuming the job, raise an exception
|
|
1316
|
+
self.__raiseException(e)
|
|
1305
1317
|
|
|
1306
1318
|
# Clear the set after resuming all jobs
|
|
1307
1319
|
self.__pausedByPauseEverything.clear()
|
|
@@ -1407,8 +1419,7 @@ class Schedule(ISchedule):
|
|
|
1407
1419
|
except Exception as e:
|
|
1408
1420
|
|
|
1409
1421
|
# Log any errors that occur during shutdown
|
|
1410
|
-
|
|
1411
|
-
self.__logger.error(error_msg)
|
|
1422
|
+
self.__logger.error(f"Error during scheduled shutdown: {str(e)}")
|
|
1412
1423
|
|
|
1413
1424
|
# Force stop if graceful shutdown fails
|
|
1414
1425
|
self.forceStop()
|
|
@@ -1542,7 +1553,7 @@ class Schedule(ISchedule):
|
|
|
1542
1553
|
|
|
1543
1554
|
# Validate the wait parameter
|
|
1544
1555
|
if not isinstance(wait, bool):
|
|
1545
|
-
|
|
1556
|
+
self.__raiseException(CLIOrionisValueError("The 'wait' parameter must be a boolean value."))
|
|
1546
1557
|
|
|
1547
1558
|
# If the scheduler is not running, there's nothing to shut down
|
|
1548
1559
|
if not self.isRunning():
|
|
@@ -1570,9 +1581,9 @@ class Schedule(ISchedule):
|
|
|
1570
1581
|
except Exception as e:
|
|
1571
1582
|
|
|
1572
1583
|
# Handle exceptions that may occur during shutdown
|
|
1573
|
-
|
|
1584
|
+
self.__raiseException(CLIOrionisRuntimeError(f"Failed to shut down the scheduler: {str(e)}"))
|
|
1574
1585
|
|
|
1575
|
-
def
|
|
1586
|
+
def pauseTask(self, signature: str) -> bool:
|
|
1576
1587
|
"""
|
|
1577
1588
|
Pause a scheduled job in the AsyncIO scheduler.
|
|
1578
1589
|
|
|
@@ -1600,7 +1611,7 @@ class Schedule(ISchedule):
|
|
|
1600
1611
|
|
|
1601
1612
|
# Validate that the signature is a non-empty string
|
|
1602
1613
|
if not isinstance(signature, str) or not signature.strip():
|
|
1603
|
-
|
|
1614
|
+
self.__raiseException(CLIOrionisValueError("Signature must be a non-empty string."))
|
|
1604
1615
|
|
|
1605
1616
|
try:
|
|
1606
1617
|
|
|
@@ -1618,7 +1629,7 @@ class Schedule(ISchedule):
|
|
|
1618
1629
|
# Return False if the job could not be paused (e.g., it does not exist)
|
|
1619
1630
|
return False
|
|
1620
1631
|
|
|
1621
|
-
def
|
|
1632
|
+
def resumeTask(self, signature: str) -> bool:
|
|
1622
1633
|
"""
|
|
1623
1634
|
Resume a paused job in the AsyncIO scheduler.
|
|
1624
1635
|
|
|
@@ -1646,7 +1657,7 @@ class Schedule(ISchedule):
|
|
|
1646
1657
|
|
|
1647
1658
|
# Validate that the signature is a non-empty string
|
|
1648
1659
|
if not isinstance(signature, str) or not signature.strip():
|
|
1649
|
-
|
|
1660
|
+
self.__raiseException(CLIOrionisValueError("Signature must be a non-empty string."))
|
|
1650
1661
|
|
|
1651
1662
|
try:
|
|
1652
1663
|
# Attempt to resume the job with the given signature
|
|
@@ -1663,7 +1674,7 @@ class Schedule(ISchedule):
|
|
|
1663
1674
|
# Return False if the job could not be resumed (e.g., it does not exist)
|
|
1664
1675
|
return False
|
|
1665
1676
|
|
|
1666
|
-
def
|
|
1677
|
+
def removeTask(self, signature: str) -> bool:
|
|
1667
1678
|
"""
|
|
1668
1679
|
Remove a scheduled job from the AsyncIO scheduler.
|
|
1669
1680
|
|
|
@@ -1692,7 +1703,7 @@ class Schedule(ISchedule):
|
|
|
1692
1703
|
|
|
1693
1704
|
# Validate that the signature is a non-empty string
|
|
1694
1705
|
if not isinstance(signature, str) or not signature.strip():
|
|
1695
|
-
|
|
1706
|
+
self.__raiseException(CLIOrionisValueError("Signature must be a non-empty string."))
|
|
1696
1707
|
|
|
1697
1708
|
try:
|
|
1698
1709
|
|
orionis/container/container.py
CHANGED
|
@@ -17,6 +17,8 @@ from orionis.services.introspection.callables.reflection import ReflectionCallab
|
|
|
17
17
|
from orionis.services.introspection.concretes.reflection import ReflectionConcrete
|
|
18
18
|
from orionis.services.introspection.dependencies.entities.argument import Argument
|
|
19
19
|
from orionis.services.introspection.dependencies.entities.resolve_argument import ResolveArguments
|
|
20
|
+
from orionis.services.introspection.dependencies.reflection import ReflectDependencies
|
|
21
|
+
from orionis.services.introspection.instances.reflection import ReflectionInstance
|
|
20
22
|
|
|
21
23
|
class Container(IContainer):
|
|
22
24
|
|
|
@@ -206,9 +208,72 @@ class Container(IContainer):
|
|
|
206
208
|
|
|
207
209
|
try:
|
|
208
210
|
|
|
209
|
-
#
|
|
210
|
-
|
|
211
|
-
|
|
211
|
+
# Count the total number of provided arguments
|
|
212
|
+
total_provided_args = len(args) + len(kwargs)
|
|
213
|
+
|
|
214
|
+
# Inspect the callable to determine its signature and parameters
|
|
215
|
+
dependencies = ReflectDependencies(fn).getCallableDependencies()
|
|
216
|
+
total_dependencies = len(dependencies.resolved) + len(dependencies.unresolved)
|
|
217
|
+
|
|
218
|
+
# If the callable does not require any dependencies, invoke directly
|
|
219
|
+
if total_dependencies == 0:
|
|
220
|
+
result = fn(*args, **kwargs)
|
|
221
|
+
return self.__handleSyncAsyncResult(result)
|
|
222
|
+
|
|
223
|
+
# If enough arguments are provided, invoke directly
|
|
224
|
+
if total_provided_args >= total_dependencies:
|
|
225
|
+
result = fn(*args, **kwargs)
|
|
226
|
+
return self.__handleSyncAsyncResult(result)
|
|
227
|
+
|
|
228
|
+
# If not enough arguments are provided, attempt to resolve missing dependencies
|
|
229
|
+
if total_provided_args < total_dependencies:
|
|
230
|
+
|
|
231
|
+
# New lists to hold the final arguments to pass to the callable
|
|
232
|
+
n_args = []
|
|
233
|
+
n_kwargs = {}
|
|
234
|
+
|
|
235
|
+
# Iterate through the function's required arguments in order
|
|
236
|
+
args_index = 0
|
|
237
|
+
|
|
238
|
+
# Iterate over all dependencies in the order they were defined
|
|
239
|
+
for name, dep in dependencies.ordered.items():
|
|
240
|
+
|
|
241
|
+
# Check if the argument was provided positionally and hasn't been used yet
|
|
242
|
+
if args_index < len(args) and name not in kwargs:
|
|
243
|
+
|
|
244
|
+
# Add the positional argument to the new list
|
|
245
|
+
n_args.append(args[args_index])
|
|
246
|
+
|
|
247
|
+
# Move to the next positional argument
|
|
248
|
+
args_index += 1
|
|
249
|
+
|
|
250
|
+
# Check if the argument was provided as a keyword argument
|
|
251
|
+
elif name in kwargs:
|
|
252
|
+
|
|
253
|
+
# Add the keyword argument to the new dictionary
|
|
254
|
+
n_kwargs[name] = kwargs[name]
|
|
255
|
+
|
|
256
|
+
# Remove the argument from the original kwargs to avoid duplication
|
|
257
|
+
del kwargs[name]
|
|
258
|
+
|
|
259
|
+
# If not provided, attempt to resolve it from the container
|
|
260
|
+
else:
|
|
261
|
+
|
|
262
|
+
n_kwargs[name] = self.__resolveSingleDependency(
|
|
263
|
+
getattr(fn, '__name__', str(fn)),
|
|
264
|
+
name,
|
|
265
|
+
dep
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# Add any remaining positional arguments that weren't mapped to specific parameters
|
|
269
|
+
n_args.extend(args[args_index:])
|
|
270
|
+
|
|
271
|
+
# Add any remaining keyword arguments that weren't processed
|
|
272
|
+
n_kwargs.update(kwargs)
|
|
273
|
+
|
|
274
|
+
# Invoke the function with the resolved arguments
|
|
275
|
+
result = fn(*n_args, **n_kwargs)
|
|
276
|
+
return self.__handleSyncAsyncResult(result)
|
|
212
277
|
|
|
213
278
|
except TypeError as e:
|
|
214
279
|
|
|
@@ -219,8 +284,9 @@ class Container(IContainer):
|
|
|
219
284
|
|
|
220
285
|
# Raise a more informative exception with the function name and signature
|
|
221
286
|
raise OrionisContainerException(
|
|
222
|
-
f"Failed to invoke function [{function_name}] with the provided arguments: {e}
|
|
223
|
-
f"
|
|
287
|
+
f"Failed to invoke function [{function_name}] with the provided arguments: {e}. "
|
|
288
|
+
f"Note that this may include a reference to the same 'self' object.\n"
|
|
289
|
+
f"Expected function signature: {function_name}{signature}"
|
|
224
290
|
) from e
|
|
225
291
|
|
|
226
292
|
def transient(
|
|
@@ -2360,6 +2426,79 @@ class Container(IContainer):
|
|
|
2360
2426
|
f"Method '{method_name}' not found or not callable on instance '{type(instance).__name__}'."
|
|
2361
2427
|
)
|
|
2362
2428
|
|
|
2429
|
+
def invoke(
|
|
2430
|
+
self,
|
|
2431
|
+
fn: Callable,
|
|
2432
|
+
*args,
|
|
2433
|
+
**kwargs
|
|
2434
|
+
) -> Any:
|
|
2435
|
+
"""
|
|
2436
|
+
Invokes a callable with automatic dependency injection and sync/async handling.
|
|
2437
|
+
|
|
2438
|
+
Parameters
|
|
2439
|
+
----------
|
|
2440
|
+
fn : Callable
|
|
2441
|
+
The callable to invoke.
|
|
2442
|
+
*args : tuple
|
|
2443
|
+
Positional arguments to pass to the callable.
|
|
2444
|
+
**kwargs : dict
|
|
2445
|
+
Keyword arguments to pass to the callable.
|
|
2446
|
+
|
|
2447
|
+
Returns
|
|
2448
|
+
-------
|
|
2449
|
+
Any
|
|
2450
|
+
The result of the callable invocation.
|
|
2451
|
+
"""
|
|
2452
|
+
|
|
2453
|
+
# Validate that fn is indeed callable
|
|
2454
|
+
if not callable(fn):
|
|
2455
|
+
raise OrionisContainerException(
|
|
2456
|
+
f"Provided fn '{getattr(fn, '__name__', str(fn))}' is not callable."
|
|
2457
|
+
)
|
|
2458
|
+
|
|
2459
|
+
# Execute the callable with appropriate handling
|
|
2460
|
+
return self.__executeMethod(fn, *args, **kwargs)
|
|
2461
|
+
|
|
2462
|
+
async def invokeAsync(
|
|
2463
|
+
self,
|
|
2464
|
+
fn: Callable,
|
|
2465
|
+
*args,
|
|
2466
|
+
**kwargs
|
|
2467
|
+
) -> Any:
|
|
2468
|
+
"""
|
|
2469
|
+
Async version of invoke for when you're in an async context and need to await the result.
|
|
2470
|
+
|
|
2471
|
+
Parameters
|
|
2472
|
+
----------
|
|
2473
|
+
fn : Callable
|
|
2474
|
+
The callable to invoke.
|
|
2475
|
+
*args : tuple
|
|
2476
|
+
Positional arguments to pass to the callable.
|
|
2477
|
+
**kwargs : dict
|
|
2478
|
+
Keyword arguments to pass to the callable.
|
|
2479
|
+
|
|
2480
|
+
Returns
|
|
2481
|
+
-------
|
|
2482
|
+
Any
|
|
2483
|
+
The result of the callable invocation, properly awaited if async.
|
|
2484
|
+
"""
|
|
2485
|
+
|
|
2486
|
+
# Validate that fn is indeed callable
|
|
2487
|
+
if not callable(fn):
|
|
2488
|
+
raise OrionisContainerException(
|
|
2489
|
+
f"Provided fn '{getattr(fn, '__name__', str(fn))}' is not callable."
|
|
2490
|
+
)
|
|
2491
|
+
|
|
2492
|
+
# Execute the callable with appropriate handling
|
|
2493
|
+
result = self.__executeMethod(fn, *args, **kwargs)
|
|
2494
|
+
|
|
2495
|
+
# If the result is a coroutine, await it
|
|
2496
|
+
if asyncio.iscoroutine(result):
|
|
2497
|
+
return await result
|
|
2498
|
+
|
|
2499
|
+
# Otherwise, return the result directly
|
|
2500
|
+
return result
|
|
2501
|
+
|
|
2363
2502
|
def __executeMethod(
|
|
2364
2503
|
self,
|
|
2365
2504
|
method: Callable,
|
|
@@ -449,3 +449,55 @@ class IContainer(ABC):
|
|
|
449
449
|
The result of the method call, properly awaited if async.
|
|
450
450
|
"""
|
|
451
451
|
pass
|
|
452
|
+
|
|
453
|
+
@abstractmethod
|
|
454
|
+
def invoke(
|
|
455
|
+
self,
|
|
456
|
+
fn: Callable,
|
|
457
|
+
*args,
|
|
458
|
+
**kwargs
|
|
459
|
+
) -> Any:
|
|
460
|
+
"""
|
|
461
|
+
Invokes a callable with automatic dependency injection and sync/async handling.
|
|
462
|
+
|
|
463
|
+
Parameters
|
|
464
|
+
----------
|
|
465
|
+
fn : Callable
|
|
466
|
+
The callable to invoke.
|
|
467
|
+
*args : tuple
|
|
468
|
+
Positional arguments to pass to the callable.
|
|
469
|
+
**kwargs : dict
|
|
470
|
+
Keyword arguments to pass to the callable.
|
|
471
|
+
|
|
472
|
+
Returns
|
|
473
|
+
-------
|
|
474
|
+
Any
|
|
475
|
+
The result of the callable invocation.
|
|
476
|
+
"""
|
|
477
|
+
pass
|
|
478
|
+
|
|
479
|
+
@abstractmethod
|
|
480
|
+
async def invokeAsync(
|
|
481
|
+
self,
|
|
482
|
+
fn: Callable,
|
|
483
|
+
*args,
|
|
484
|
+
**kwargs
|
|
485
|
+
) -> Any:
|
|
486
|
+
"""
|
|
487
|
+
Async version of invoke for when you're in an async context and need to await the result.
|
|
488
|
+
|
|
489
|
+
Parameters
|
|
490
|
+
----------
|
|
491
|
+
fn : Callable
|
|
492
|
+
The callable to invoke.
|
|
493
|
+
*args : tuple
|
|
494
|
+
Positional arguments to pass to the callable.
|
|
495
|
+
**kwargs : dict
|
|
496
|
+
Keyword arguments to pass to the callable.
|
|
497
|
+
|
|
498
|
+
Returns
|
|
499
|
+
-------
|
|
500
|
+
Any
|
|
501
|
+
The result of the callable invocation, properly awaited if async.
|
|
502
|
+
"""
|
|
503
|
+
pass
|
orionis/failure/base/handler.py
CHANGED
|
@@ -13,7 +13,7 @@ class BaseExceptionHandler(IBaseExceptionHandler):
|
|
|
13
13
|
# Example: OrionisContainerException
|
|
14
14
|
]
|
|
15
15
|
|
|
16
|
-
async def destructureException(self,
|
|
16
|
+
async def destructureException(self, exception: BaseException) -> Throwable:
|
|
17
17
|
"""
|
|
18
18
|
Converts an exception into a structured `Throwable` object containing detailed information.
|
|
19
19
|
|
|
@@ -35,13 +35,13 @@ class BaseExceptionHandler(IBaseExceptionHandler):
|
|
|
35
35
|
|
|
36
36
|
# Create and return a Throwable object with detailed exception information
|
|
37
37
|
return Throwable(
|
|
38
|
-
classtype=type(
|
|
39
|
-
message=str(
|
|
40
|
-
args=
|
|
41
|
-
traceback=getattr(
|
|
38
|
+
classtype=type(exception), # The class/type of the exception
|
|
39
|
+
message=str(exception), # The exception message as a string
|
|
40
|
+
args=exception.args, # The arguments passed to the exception
|
|
41
|
+
traceback=getattr(exception, '__traceback__', None) # The traceback object, if available
|
|
42
42
|
)
|
|
43
43
|
|
|
44
|
-
async def shouldIgnoreException(self,
|
|
44
|
+
async def shouldIgnoreException(self, exception: BaseException) -> bool:
|
|
45
45
|
"""
|
|
46
46
|
Determines if the exception should be ignored (not handled) by the handler.
|
|
47
47
|
|
|
@@ -57,11 +57,11 @@ class BaseExceptionHandler(IBaseExceptionHandler):
|
|
|
57
57
|
"""
|
|
58
58
|
|
|
59
59
|
# Ensure the provided object is an exception
|
|
60
|
-
if not isinstance(
|
|
61
|
-
raise TypeError(f"Expected BaseException, got {type(
|
|
60
|
+
if not isinstance(exception, BaseException):
|
|
61
|
+
raise TypeError(f"Expected BaseException, got {type(exception).__name__}")
|
|
62
62
|
|
|
63
63
|
# Convert the exception into a structured Throwable object
|
|
64
|
-
throwable = await self.destructureException(
|
|
64
|
+
throwable = await self.destructureException(exception)
|
|
65
65
|
|
|
66
66
|
# Check if the exception type is in the list of exceptions to ignore
|
|
67
67
|
return hasattr(self, 'dont_catch') and throwable.classtype in self.dont_catch
|
orionis/failure/catch.py
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
from orionis.console.kernel import KernelCLI
|
|
3
|
-
from orionis.console.output.contracts.console import IConsole
|
|
4
3
|
from orionis.console.tasks.schedule import Schedule
|
|
5
4
|
from orionis.failure.contracts.catch import ICatch
|
|
6
5
|
from orionis.failure.contracts.handler import IBaseExceptionHandler
|
|
7
6
|
from orionis.foundation.contracts.application import IApplication
|
|
8
|
-
from orionis.services.asynchrony.coroutines import Coroutine
|
|
9
|
-
from orionis.services.log.contracts.log_service import ILogger
|
|
10
|
-
import asyncio
|
|
11
7
|
|
|
12
8
|
class Catch(ICatch):
|
|
13
9
|
|
|
14
|
-
|
|
15
10
|
def __init__(self, app: IApplication) -> None:
|
|
16
11
|
"""
|
|
17
12
|
Initializes the Catch handler with application services for console output and logging.
|
|
@@ -40,11 +35,8 @@ class Catch(ICatch):
|
|
|
40
35
|
error reporting and output.
|
|
41
36
|
"""
|
|
42
37
|
|
|
43
|
-
#
|
|
44
|
-
self.
|
|
45
|
-
|
|
46
|
-
# Retrieve the logger service from the application container
|
|
47
|
-
self.__logger: ILogger = app.make('x-orionis.services.log.log_service')
|
|
38
|
+
# Store the application instance
|
|
39
|
+
self.__app: IApplication = app
|
|
48
40
|
|
|
49
41
|
# Retrieve the console output service from the application container
|
|
50
42
|
self.__exception_handler: IBaseExceptionHandler = app.getExceptionHandler()
|
|
@@ -76,89 +68,15 @@ class Catch(ICatch):
|
|
|
76
68
|
If a valid kernel is provided, the exception details are rendered to the CLI.
|
|
77
69
|
"""
|
|
78
70
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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()
|
|
71
|
+
# If there is no exception handler, return early
|
|
72
|
+
if self.__app.call(self.__exception_handler, 'shouldIgnoreException', exception=e):
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
# Report the exception using the exception handler and logger
|
|
76
|
+
self.__app.call(self.__exception_handler, 'report', exception=e)
|
|
77
|
+
|
|
78
|
+
# Check if the kernel is of type `KernelCLI` or `Any`
|
|
79
|
+
if isinstance(kernel, KernelCLI) or isinstance(kernel, Schedule):
|
|
80
|
+
|
|
81
|
+
# Render the exception details to the CLI using the exception handler
|
|
82
|
+
self.__app.call(self.__exception_handler, 'renderCLI', request=request, exception=e)
|
|
@@ -469,10 +469,10 @@ class Application(Container, IApplication):
|
|
|
469
469
|
if self.__exception_handler is None:
|
|
470
470
|
|
|
471
471
|
# Return the default exception handler instance
|
|
472
|
-
return BaseExceptionHandler
|
|
472
|
+
return self.make(BaseExceptionHandler)
|
|
473
473
|
|
|
474
474
|
# Instantiate and return the registered exception handler
|
|
475
|
-
return self.__exception_handler
|
|
475
|
+
return self.make(self.__exception_handler)
|
|
476
476
|
|
|
477
477
|
def setScheduler(
|
|
478
478
|
self,
|
orionis/metadata/framework.py
CHANGED
|
@@ -43,6 +43,9 @@ class ResolveArguments(BaseEntity):
|
|
|
43
43
|
# Unresolved dependencies as a dictionary of names to Argument instances
|
|
44
44
|
unresolved: Dict[str, Argument]
|
|
45
45
|
|
|
46
|
+
# All dependencies in the order they were defined
|
|
47
|
+
ordered: Dict[str, Argument]
|
|
48
|
+
|
|
46
49
|
def __post_init__(self):
|
|
47
50
|
"""
|
|
48
51
|
Validates the types and contents of the resolved and unresolved attributes.
|
|
@@ -79,4 +82,11 @@ class ResolveArguments(BaseEntity):
|
|
|
79
82
|
if not isinstance(self.unresolved, dict):
|
|
80
83
|
raise ReflectionTypeError(
|
|
81
84
|
f"'unresolved' must be a dict, got {type(self.unresolved).__name__}"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Validate that the 'ordered' attribute is a dictionary type
|
|
88
|
+
# This ensures that all dependencies maintain the same structure as resolved ones
|
|
89
|
+
if not isinstance(self.ordered, dict):
|
|
90
|
+
raise ReflectionTypeError(
|
|
91
|
+
f"'ordered' must be a dict, got {type(self.ordered).__name__}"
|
|
82
92
|
)
|
|
@@ -121,6 +121,7 @@ class ReflectDependencies(IReflectDependencies):
|
|
|
121
121
|
# Initialize dictionaries to store categorized dependencies
|
|
122
122
|
resolved_dependencies: Dict[str, Argument] = {}
|
|
123
123
|
unresolved_dependencies: Dict[str, Argument] = {}
|
|
124
|
+
ordered_dependencies: Dict[str, Argument] = {}
|
|
124
125
|
|
|
125
126
|
# Iterate through all parameters in the signature
|
|
126
127
|
for param_name, param in signature.parameters.items():
|
|
@@ -140,6 +141,7 @@ class ReflectDependencies(IReflectDependencies):
|
|
|
140
141
|
type=Any,
|
|
141
142
|
full_class_path=None,
|
|
142
143
|
)
|
|
144
|
+
ordered_dependencies[param_name] = unresolved_dependencies[param_name]
|
|
143
145
|
continue
|
|
144
146
|
|
|
145
147
|
# Case 2: Parameters with default values
|
|
@@ -153,6 +155,7 @@ class ReflectDependencies(IReflectDependencies):
|
|
|
153
155
|
full_class_path=f"{type(param.default).__module__}.{type(param.default).__name__}",
|
|
154
156
|
default=param.default
|
|
155
157
|
)
|
|
158
|
+
ordered_dependencies[param_name] = resolved_dependencies[param_name]
|
|
156
159
|
continue
|
|
157
160
|
|
|
158
161
|
# Case 3: Parameters with type annotations
|
|
@@ -168,6 +171,7 @@ class ReflectDependencies(IReflectDependencies):
|
|
|
168
171
|
type=param.annotation,
|
|
169
172
|
full_class_path=f"{param.annotation.__module__}.{param.annotation.__name__}"
|
|
170
173
|
)
|
|
174
|
+
ordered_dependencies[param_name] = unresolved_dependencies[param_name]
|
|
171
175
|
else:
|
|
172
176
|
# Non-builtin types with annotations are considered resolved
|
|
173
177
|
# as they can be instantiated by the dependency injection system
|
|
@@ -178,12 +182,14 @@ class ReflectDependencies(IReflectDependencies):
|
|
|
178
182
|
type=param.annotation,
|
|
179
183
|
full_class_path=f"{param.annotation.__module__}.{param.annotation.__name__}"
|
|
180
184
|
)
|
|
185
|
+
ordered_dependencies[param_name] = resolved_dependencies[param_name]
|
|
181
186
|
continue
|
|
182
187
|
|
|
183
188
|
# Return the categorized dependencies
|
|
184
189
|
return ResolveArguments(
|
|
185
190
|
resolved=resolved_dependencies,
|
|
186
|
-
unresolved=unresolved_dependencies
|
|
191
|
+
unresolved=unresolved_dependencies,
|
|
192
|
+
ordered=ordered_dependencies
|
|
187
193
|
)
|
|
188
194
|
|
|
189
195
|
def getConstructorDependencies(self) -> ResolveArguments:
|
|
@@ -22,10 +22,10 @@ orionis/console/commands/version.py,sha256=SUuNDJ40f2uq69OQUmPQXJKaa9Bm_iVRDPmBd
|
|
|
22
22
|
orionis/console/commands/workflow.py,sha256=NYOmjTSvm2o6AE4h9LSTZMFSYPQreNmEJtronyOxaYk,2451
|
|
23
23
|
orionis/console/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
orionis/console/contracts/command.py,sha256=vmAJD0yMQ5-AD_s9_xCFEAl64sKk65z7U2E196dALQM,5760
|
|
25
|
-
orionis/console/contracts/event.py,sha256=
|
|
25
|
+
orionis/console/contracts/event.py,sha256=GEgpmsyVGKJYi0LwvEklTm7aAHqsqUprtC2p6qq0eZU,120005
|
|
26
26
|
orionis/console/contracts/kernel.py,sha256=mh4LlhEYHh3FuGZZQ0GBhD6ZLa5YQvaNj2r01IIHI5Y,826
|
|
27
27
|
orionis/console/contracts/reactor.py,sha256=Xeq7Zrw6WE5MV_XOQfiQEchAFbb6-0TjLpjWOxYW--g,4554
|
|
28
|
-
orionis/console/contracts/schedule.py,sha256=
|
|
28
|
+
orionis/console/contracts/schedule.py,sha256=N-AYUa1CJY7a4CV9L1EX_EUDtGlDJMg4y0aV9EDby1Q,16090
|
|
29
29
|
orionis/console/contracts/schedule_event_listener.py,sha256=7fQdPh6X_npfGpQW_2x81D7-5Pe40jIog9uDeEU0kro,4390
|
|
30
30
|
orionis/console/contracts/scheduler.py,sha256=OW-a_YDDNPrenYT9z8Tv71VjyZ1aSzqzqhTBhTCZhGM,7698
|
|
31
31
|
orionis/console/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -65,7 +65,7 @@ orionis/console/entities/scheduler_shutdown.py,sha256=vRFXUt3hxKueaT6M4335HFL3NO
|
|
|
65
65
|
orionis/console/entities/scheduler_started.py,sha256=U0pduaFhWrEUJQws81jTjDmTp4Kxfy6ontq8rQN4Y6I,910
|
|
66
66
|
orionis/console/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
67
|
orionis/console/enums/command.py,sha256=lCfVp2vnDojJN2gjdVxE_XU3mRjZZgOIxPfBVQYo9w4,1278
|
|
68
|
-
orionis/console/enums/event.py,sha256=
|
|
68
|
+
orionis/console/enums/event.py,sha256=xyJfJQmXnZ_c-zPZx3_pzKm54R-kKyJkQzIercv556w,3004
|
|
69
69
|
orionis/console/enums/listener.py,sha256=bDHDOkKQFEfEmZyiisZj37ozr8Hs7_lKvm_3uYjvEpw,2988
|
|
70
70
|
orionis/console/exceptions/__init__.py,sha256=0qlHNuHMVZO87M-rP8lThUUyljRM1jSFNikaxSCjSbw,366
|
|
71
71
|
orionis/console/exceptions/cli_exception.py,sha256=HsZ_vSeNiJWQ0gznVFNcIdhM0Bj_vkSRVBJs0wMjEKY,1141
|
|
@@ -82,16 +82,16 @@ orionis/console/output/enums/__init__.py,sha256=LAaAxg-DpArCjf_jqZ0_9s3p8899gntD
|
|
|
82
82
|
orionis/console/output/enums/styles.py,sha256=6a4oQCOBOKMh2ARdeq5GlIskJ3wjiylYmh66tUKKmpQ,4053
|
|
83
83
|
orionis/console/request/cli_request.py,sha256=7-sgYmNUCipuHLVAwWLJiHv0cJCDmsM1Lu9s2D8RIII,1498
|
|
84
84
|
orionis/console/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
85
|
-
orionis/console/tasks/event.py,sha256=
|
|
85
|
+
orionis/console/tasks/event.py,sha256=yE64gWAWaaz-mlWk5LIKDh4HYO14iwRfdYfwFh7Wktk,166479
|
|
86
86
|
orionis/console/tasks/listener.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
87
|
-
orionis/console/tasks/schedule.py,sha256=
|
|
87
|
+
orionis/console/tasks/schedule.py,sha256=EQs1wmowaYxN8KBy-csj27ZXnza5xHctSbk3qr0-88I,83378
|
|
88
88
|
orionis/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
89
|
-
orionis/container/container.py,sha256=
|
|
89
|
+
orionis/container/container.py,sha256=262gahG9L_72QovlHP7cF5QhFX4HTolwcYrVo86HcVg,93196
|
|
90
90
|
orionis/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
91
91
|
orionis/container/context/manager.py,sha256=I08K_jKXSKmrq18Pv33qYyMKIlAovVOwIgmfiVm-J7c,2971
|
|
92
92
|
orionis/container/context/scope.py,sha256=p_oCzR7dDz-5ZAd16ab4vfLc3gBf34CaN0f4iR9D0bQ,1155
|
|
93
93
|
orionis/container/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
94
|
-
orionis/container/contracts/container.py,sha256=
|
|
94
|
+
orionis/container/contracts/container.py,sha256=r-HpuMUbkI19lNTisgxB2lbvvt0YFA4xsEDVLCPDrys,15507
|
|
95
95
|
orionis/container/contracts/service_provider.py,sha256=TJtwFoPYvw3hvBSfIEO3-httq8iszaRQh1IjCKfDyVM,1016
|
|
96
96
|
orionis/container/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
97
97
|
orionis/container/entities/binding.py,sha256=sY0ioHbRcjp9TSQjfrFHxkO3vRn_VOrbHK62_QEGe1U,3717
|
|
@@ -117,16 +117,16 @@ orionis/container/validators/is_subclass.py,sha256=4sBaGLoRs8nUhuWjlP0VJqyTwVHYq
|
|
|
117
117
|
orionis/container/validators/is_valid_alias.py,sha256=4uAYcq8xov7jZbXnpKpjNkxcZtlTNnL5RRctVPMwJes,1424
|
|
118
118
|
orionis/container/validators/lifetime.py,sha256=IQ43fDNrxYHMlZH2zlYDJnlkLO_eS4U7Fs3UJgQBidI,1844
|
|
119
119
|
orionis/failure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
120
|
-
orionis/failure/catch.py,sha256=
|
|
120
|
+
orionis/failure/catch.py,sha256=XpPISy-83grGYP1PSScrF7jyogpvOjDjbz-11iop2FQ,3286
|
|
121
121
|
orionis/failure/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
122
|
-
orionis/failure/base/handler.py,sha256=
|
|
122
|
+
orionis/failure/base/handler.py,sha256=6QU2XHpJgH2hhGBANvioJBz16Aoi9Xy6QEF1PJBGLDQ,4939
|
|
123
123
|
orionis/failure/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
124
124
|
orionis/failure/contracts/catch.py,sha256=e2wM1p6VxbvAjgWm-MwoM9p2ystSsyBu8Qnt6Ehr6Vc,1179
|
|
125
125
|
orionis/failure/contracts/handler.py,sha256=drNE8iu8RUHi3TgKn-lUEIfVsZeGsMTUecTZOfay19E,2240
|
|
126
126
|
orionis/failure/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
127
|
-
orionis/failure/entities/throwable.py,sha256=
|
|
127
|
+
orionis/failure/entities/throwable.py,sha256=1zD-awcuAyEtlR-L7V7ZIfPSF4GpXkf-neL5sXul7dc,1240
|
|
128
128
|
orionis/foundation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
129
|
-
orionis/foundation/application.py,sha256=
|
|
129
|
+
orionis/foundation/application.py,sha256=_I8EAPcsRmGdmG9ajdSHovwny_tsELXWwvej6WZQj0A,86506
|
|
130
130
|
orionis/foundation/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
131
131
|
orionis/foundation/config/startup.py,sha256=vbzduprRCNyYeR2nnMaqc1uKXw6PTzAY2jVfXNQKN8I,9691
|
|
132
132
|
orionis/foundation/config/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -242,7 +242,7 @@ orionis/foundation/providers/scheduler_provider.py,sha256=1do4B09bU_6xbFHHVYYTGM
|
|
|
242
242
|
orionis/foundation/providers/testing_provider.py,sha256=SrJRpdvcblx9WvX7x9Y3zc7OQfiTf7la0HAJrm2ESlE,3725
|
|
243
243
|
orionis/foundation/providers/workers_provider.py,sha256=oa_2NIDH6UxZrtuGkkoo_zEoNIMGgJ46vg5CCgAm7wI,3926
|
|
244
244
|
orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
245
|
-
orionis/metadata/framework.py,sha256=
|
|
245
|
+
orionis/metadata/framework.py,sha256=iH8hUXm6LKEb4khPzo0501jhpYsPSCLa_DlR-u7Ct6k,4109
|
|
246
246
|
orionis/metadata/package.py,sha256=k7Yriyp5aUcR-iR8SK2ec_lf0_Cyc-C7JczgXa-I67w,16039
|
|
247
247
|
orionis/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
248
248
|
orionis/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -298,12 +298,12 @@ orionis/services/introspection/concretes/contracts/reflection.py,sha256=LwEAgdN_
|
|
|
298
298
|
orionis/services/introspection/dataclass/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
299
299
|
orionis/services/introspection/dataclass/attributes.py,sha256=VGBUxH40PxUE8J4TBBYdSqwTO0xwYYmIS6BITgff-cE,1695
|
|
300
300
|
orionis/services/introspection/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
301
|
-
orionis/services/introspection/dependencies/reflection.py,sha256=
|
|
301
|
+
orionis/services/introspection/dependencies/reflection.py,sha256=3aQl541JkohRcoZFxQGiGPz3CnBMK8gmcRwO9XiLSY0,13906
|
|
302
302
|
orionis/services/introspection/dependencies/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
303
303
|
orionis/services/introspection/dependencies/contracts/reflection.py,sha256=DhkAmsl8fxNr3L1kCSpVmTZx9YBejq2kYcfUrCWG8o0,5364
|
|
304
304
|
orionis/services/introspection/dependencies/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
305
305
|
orionis/services/introspection/dependencies/entities/argument.py,sha256=o30iMSghV8CFBWmnM__8_IOnOGrCLZfRUIQGD2GVl_g,4188
|
|
306
|
-
orionis/services/introspection/dependencies/entities/resolve_argument.py,sha256=
|
|
306
|
+
orionis/services/introspection/dependencies/entities/resolve_argument.py,sha256=einKDEIp9NjBUfc9_ulmkwzAv7sRuxS3lM_FE3zFN-s,3810
|
|
307
307
|
orionis/services/introspection/exceptions/__init__.py,sha256=oe7uzaGwjeMgz62ZTeNn6ersCApOVv3PXFlUw0vYLQM,234
|
|
308
308
|
orionis/services/introspection/exceptions/attribute.py,sha256=_JerTjfhikYwC2FKJV8XbVZqiZdLcBt7WGtw8r6vkqo,473
|
|
309
309
|
orionis/services/introspection/exceptions/type.py,sha256=73DB8JoTbxd7LNMnZKXf4jJ8OzLyC0HPXgDo5pffkYY,466
|
|
@@ -420,7 +420,7 @@ orionis/test/validators/web_report.py,sha256=n9BfzOZz6aEiNTypXcwuWbFRG0OdHNSmCNu
|
|
|
420
420
|
orionis/test/validators/workers.py,sha256=rWcdRexINNEmGaO7mnc1MKUxkHKxrTsVuHgbnIfJYgc,1206
|
|
421
421
|
orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
422
422
|
orionis/test/view/render.py,sha256=f-zNhtKSg9R5Njqujbg2l2amAs2-mRVESneLIkWOZjU,4082
|
|
423
|
-
orionis-0.
|
|
423
|
+
orionis-0.538.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
|
|
424
424
|
tests/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
425
425
|
tests/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
426
426
|
tests/container/context/test_manager.py,sha256=wOwXpl9rHNfTTexa9GBKYMwK0_-KSQPbI-AEyGNkmAE,1356
|
|
@@ -566,8 +566,8 @@ tests/testing/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
566
566
|
tests/testing/validators/test_testing_validators.py,sha256=WPo5GxTP6xE-Dw3X1vZoqOMpb6HhokjNSbgDsDRDvy4,16588
|
|
567
567
|
tests/testing/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
568
568
|
tests/testing/view/test_render.py,sha256=tnnMBwS0iKUIbogLvu-7Rii50G6Koddp3XT4wgdFEYM,1050
|
|
569
|
-
orionis-0.
|
|
570
|
-
orionis-0.
|
|
571
|
-
orionis-0.
|
|
572
|
-
orionis-0.
|
|
573
|
-
orionis-0.
|
|
569
|
+
orionis-0.538.0.dist-info/METADATA,sha256=4fH1vZ-4R_AT8VmMWs3HzV8vZFOmPCB7f-gr2fDH54Y,4801
|
|
570
|
+
orionis-0.538.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
571
|
+
orionis-0.538.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
|
|
572
|
+
orionis-0.538.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
573
|
+
orionis-0.538.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|