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.
@@ -5,24 +5,32 @@ from orionis.console.enums.event import Event as EventEntity
5
5
 
6
6
  class IEvent(ABC):
7
7
 
8
- @abstractmethod
9
- def toEntity(
10
- self
11
- ) -> EventEntity:
8
+ def misfireGraceTime(
9
+ self,
10
+ seconds: int = 60
11
+ ) -> 'IEvent':
12
12
  """
13
- Retrieve the event details as an EventEntity instance.
13
+ Set the misfire grace time for the event.
14
14
 
15
- This method gathers all relevant attributes of the current Event object,
16
- such as its signature, arguments, purpose, random delay, start and end dates,
17
- and trigger, and returns them encapsulated in an EventEntity object.
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
- EventEntity
22
- An EventEntity instance containing the event's signature, arguments,
23
- purpose, random delay, start date, end date, and trigger.
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 pause(self, signature: str) -> bool:
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 resume(self, signature: str) -> bool:
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 remove(self, signature: str) -> bool:
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
@@ -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
@@ -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
- raise CLIOrionisRuntimeError("Cannot add new commands while the scheduler is running.")
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
- raise CLIOrionisValueError("The event must be an instance of ListeningEvent.")
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
- error_msg = "The event must be an instance of ListeningEvent."
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
- # Initialize the listener if it's a class
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
- except Exception as e:
543
+ # Initialize the listener if it's a class
544
+ if isinstance(listener, type):
545
+ listener = self.__app.make(listener)
568
546
 
569
- # Construct and log error message
570
- error_msg = f"An error occurred while invoking the listener_method for event '{scheduler_event}': {str(e)}"
571
- self.__logger.error(error_msg)
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
- else:
551
+ except BaseException as e:
575
552
 
576
- # Log a warning if the listener does not have the required method
577
- self.__logger.warning(f"The listener for job ID '{event_data.id}' does not have a method for event '{scheduler_event}'.")
553
+ # If an error occurs while invoking the listener, raise an exception
554
+ self.__raiseException(e)
578
555
 
579
556
  else:
580
557
 
581
- # Log a warning if the listener is not an instance of IScheduleEventListener
582
- self.__logger.warning(f"The listener for job ID '{event_data.id}' is not an instance of IScheduleEventListener.")
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.__catch.exception(self, CLIRequest(
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
- ValueError
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 ValueError("Event name must be a non-empty string.")
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 ValueError("Listener must be a callable function or an instance of IScheduleEventListener.")
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
- # 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)
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
- raise ValueError("The 'at' parameter must be a datetime object.")
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
- # Log a warning if pausing a job fails, but continue with others
1202
- self.__logger.warning(f"Failed to pause job '{job.id}': {str(e)}")
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 ValueError("The 'at' parameter must be a datetime object.")
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
- # Log a warning if resuming a job fails, but continue with others
1304
- self.__logger.warning(f"Failed to resume job '{job_id}': {str(e)}")
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
- error_msg = f"Error during scheduled shutdown: {str(e)}"
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
- raise ValueError("The 'wait' parameter must be a boolean value.")
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
- raise CLIOrionisRuntimeError(f"Failed to shut down the scheduler: {str(e)}") from e
1584
+ self.__raiseException(CLIOrionisRuntimeError(f"Failed to shut down the scheduler: {str(e)}"))
1574
1585
 
1575
- def pause(self, signature: str) -> bool:
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
- raise CLIOrionisValueError("Signature must be a non-empty string.")
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 resume(self, signature: str) -> bool:
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
- raise CLIOrionisValueError("Signature must be a non-empty string.")
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 remove(self, signature: str) -> bool:
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
- raise CLIOrionisValueError("Signature must be a non-empty string.")
1706
+ self.__raiseException(CLIOrionisValueError("Signature must be a non-empty string."))
1696
1707
 
1697
1708
  try:
1698
1709
 
@@ -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
- # Check if the callable is a coroutine function
210
- result = fn(*args, **kwargs)
211
- return self.__handleSyncAsyncResult(result)
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}\n"
223
- f"Expected function signature: [{signature}]"
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
@@ -13,7 +13,7 @@ class BaseExceptionHandler(IBaseExceptionHandler):
13
13
  # Example: OrionisContainerException
14
14
  ]
15
15
 
16
- async def destructureException(self, e: BaseException) -> Throwable:
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(e), # The class/type of the exception
39
- message=str(e), # The exception message as a string
40
- args=e.args, # The arguments passed to the exception
41
- traceback=getattr(e, '__traceback__', None) # The traceback object, if available
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, e: BaseException) -> bool:
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(e, BaseException):
61
- raise TypeError(f"Expected BaseException, got {type(e).__name__}")
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(e)
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
- # Retrieve the console output service from the application container
44
- self.__console: IConsole = app.make('x-orionis.console.output.console')
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
- 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()
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)
@@ -1,6 +1,6 @@
1
1
  from dataclasses import dataclass
2
2
 
3
- @dataclass(kw_only=True)
3
+ @dataclass(kw_only=True, frozen=True)
4
4
  class Throwable:
5
5
  """
6
6
  Represents a throwable entity (such as an exception or error) within the framework.
@@ -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,
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.536.0"
8
+ VERSION = "0.538.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
@@ -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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orionis
3
- Version: 0.536.0
3
+ Version: 0.538.0
4
4
  Summary: Orionis Framework – Elegant, Fast, and Powerful.
5
5
  Home-page: https://github.com/orionis-framework/framework
6
6
  Author: Raul Mauricio Uñate Castro
@@ -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=zaOkbRNKpU6U_cIEFic84C3WIcD8kCIyX9hc50jN8N0,119797
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=17cfPYtLo-jqF8FxYOhh4epJZnxw5mMPuLGaWoUwxL4,12171
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=G_6QEagrjtQ81dgkVhTTc2M2YuhnnKRkRSjd2i8m3OQ,2808
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=l4J-HEPaj1mxB_PYQMgG9dRHUe01wUag8fKLLnR2N2M,164395
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=0DxGovmetj5bmeMzvL5fCFePy6p8Gl_5uwsLgi-E1xY,82854
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=aF_b6lTUpG4YCo9yFJEzsntTdIzgMMXFW5LyWqAJVBQ,87987
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=l-wVi6KMLL4I55JSHnNqykiaZSZO9ea6BDSzCKsysak,14217
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=kmw2mbkGrFNw9s8jrr2NdJeGlbJVvXQQSlnjltwC4oM,6819
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=a7fQJMWVjALwFiITRsMYg3s7WSO6zcbmq171iQRWy48,4867
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=ogys062uhim5QMYU62ezlnumRAnYQlUf_vZvQY47S3U,1227
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=RwMRjRp9kkKRbDsz_lAN4NYadCuaDbmDnccWKl8aKng,86488
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=WTvqT0Hj7mUOGLnlkmB7AYj6OZPyvYlfAwd0Cy0U1eI,4109
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=VEe3cY6LTpOW3dm0IFECTHh7F_9_X-siTAeQc2XRQeM,13451
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=GxlW-JwoJwYO1TWH4aqJ982Y4mTiU69GEU3GlevDWtM,3373
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.536.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
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.536.0.dist-info/METADATA,sha256=Ea7HN9aJxUuIxswX2rZ6rdLcFdaExCsUaaHC8VCX8Wo,4801
570
- orionis-0.536.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
571
- orionis-0.536.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
572
- orionis-0.536.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
573
- orionis-0.536.0.dist-info/RECORD,,
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,,