orionis 0.522.0__py3-none-any.whl → 0.523.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.
@@ -18,171 +18,6 @@ class BaseScheduler(IBaseScheduler):
18
18
  # Finalize Global Scheduler at a specific time
19
19
  FINALIZE_AT: datetime = None
20
20
 
21
- def pauseAt(self, timezone: str = None) -> datetime:
22
- """
23
- Retrieves the datetime at which the global scheduler should be paused.
24
-
25
- This method returns the `PAUSE_AT` attribute as a timezone-aware datetime object.
26
- If `PAUSE_AT` is not set (i.e., `None`), the method will return `None`.
27
- If a timezone is provided, it converts the naive datetime to a timezone-aware
28
- datetime using the specified timezone. If no timezone is provided, the naive
29
- datetime is returned as is.
30
-
31
- Parameters
32
- ----------
33
- timezone : str, optional
34
- The name of the timezone to use for converting the naive datetime
35
- to a timezone-aware datetime. For example, "UTC" or "America/New_York".
36
- If not provided, the method returns the naive datetime.
37
-
38
- Returns
39
- -------
40
- datetime or None
41
- - A timezone-aware datetime object representing the pause time of the scheduler
42
- if `PAUSE_AT` is set and a valid timezone is provided.
43
- - A naive datetime object representing the pause time if `PAUSE_AT` is set
44
- but no timezone is provided.
45
- - `None` if `PAUSE_AT` is not set.
46
-
47
- Notes
48
- -----
49
- - The `PAUSE_AT` attribute is expected to be a naive datetime object.
50
- - The method uses the `pytz` library to localize the naive datetime to the specified timezone.
51
- - If the `PAUSE_AT` attribute is `None`, the method will return `None` without performing any conversion.
52
- """
53
-
54
- # Retrieve the naive datetime value for the pause time
55
- dt_naive = self.PAUSE_AT
56
-
57
- # If no pause time is set, return None
58
- if dt_naive is None:
59
- return None
60
-
61
- # If no timezone is provided, return the naive datetime as is
62
- if timezone is None:
63
- return dt_naive
64
-
65
- # Import the pytz library for timezone handling
66
- import pytz
67
-
68
- # Get the specified timezone using pytz
69
- # This will raise an exception if the timezone string is invalid
70
- tz = pytz.timezone(timezone)
71
-
72
- # Convert the naive datetime to a timezone-aware datetime
73
- # This ensures the datetime is localized to the specified timezone
74
- return tz.localize(dt_naive)
75
-
76
- def resumeAt(self, timezone: str = None) -> datetime:
77
- """
78
- Retrieves the datetime at which the global scheduler should be resumed.
79
-
80
- This method returns the `RESUME_AT` attribute as a timezone-aware datetime object.
81
- If `RESUME_AT` is not set (i.e., `None`), the method will return `None`.
82
- If a timezone is provided, it converts the naive datetime to a timezone-aware
83
- datetime using the specified timezone. If no timezone is provided, the naive
84
- datetime is returned as is.
85
-
86
- Parameters
87
- ----------
88
- timezone : str, optional
89
- The name of the timezone to use for converting the naive datetime
90
- to a timezone-aware datetime. For example, "UTC" or "America/New_York".
91
- If not provided, the method returns the naive datetime.
92
-
93
- Returns
94
- -------
95
- datetime or None
96
- - A timezone-aware datetime object representing the resume time of the scheduler
97
- if `RESUME_AT` is set and a valid timezone is provided.
98
- - A naive datetime object representing the resume time if `RESUME_AT` is set
99
- but no timezone is provided.
100
- - `None` if `RESUME_AT` is not set.
101
-
102
- Notes
103
- -----
104
- - The `RESUME_AT` attribute is expected to be a naive datetime object.
105
- - The method uses the `pytz` library to localize the naive datetime to the specified timezone.
106
- - If the `RESUME_AT` attribute is `None`, the method will return `None` without performing any conversion.
107
- """
108
-
109
- # Retrieve the naive datetime value for the resume time
110
- dt_naive = self.RESUME_AT
111
-
112
- # If no resume time is set, return None
113
- if dt_naive is None:
114
- return None
115
-
116
- # If no timezone is provided, return the naive datetime as is
117
- if timezone is None:
118
- return dt_naive
119
-
120
- # Import the pytz library for timezone handling
121
- import pytz
122
-
123
- # Get the specified timezone using pytz
124
- # This will raise an exception if the timezone string is invalid
125
- tz = pytz.timezone(timezone)
126
-
127
- # Convert the naive datetime to a timezone-aware datetime
128
- # This ensures the datetime is localized to the specified timezone
129
- return tz.localize(dt_naive)
130
-
131
- def finalizeAt(self, timezone: str = None) -> datetime:
132
- """
133
- Retrieves the datetime at which the global scheduler should be finalized.
134
-
135
- This method returns the `FINALIZE_AT` attribute as a timezone-aware datetime object.
136
- If `FINALIZE_AT` is not set (i.e., `None`), the method will return `None`.
137
- If a timezone is provided, it converts the naive datetime to a timezone-aware
138
- datetime using the specified timezone. If no timezone is provided, the naive
139
- datetime is returned as is.
140
-
141
- Parameters
142
- ----------
143
- timezone : str, optional
144
- The name of the timezone to use for converting the naive datetime
145
- to a timezone-aware datetime. For example, "UTC" or "America/New_York".
146
- If not provided, the method returns the naive datetime.
147
-
148
- Returns
149
- -------
150
- datetime or None
151
- - A timezone-aware datetime object representing the finalize time of the scheduler
152
- if `FINALIZE_AT` is set and a valid timezone is provided.
153
- - A naive datetime object representing the finalize time if `FINALIZE_AT` is set
154
- but no timezone is provided.
155
- - `None` if `FINALIZE_AT` is not set.
156
-
157
- Notes
158
- -----
159
- - The `FINALIZE_AT` attribute is expected to be a naive datetime object.
160
- - The method uses the `pytz` library to localize the naive datetime to the specified timezone.
161
- - If the `FINALIZE_AT` attribute is `None`, the method will return `None` without performing any conversion.
162
- """
163
-
164
- # Retrieve the naive datetime value for the finalize time
165
- dt_naive = self.FINALIZE_AT
166
-
167
- # If no finalize time is set, return None
168
- if dt_naive is None:
169
- return None
170
-
171
- # If no timezone is provided, return the naive datetime as is
172
- if timezone is None:
173
- return dt_naive
174
-
175
- # Import the pytz library for timezone handling
176
- import pytz
177
-
178
- # Get the specified timezone using pytz
179
- # This will raise an exception if the timezone string is invalid
180
- tz = pytz.timezone(timezone)
181
-
182
- # Convert the naive datetime to a timezone-aware datetime
183
- # This ensures the datetime is localized to the specified timezone
184
- return tz.localize(dt_naive)
185
-
186
21
  async def tasks(self, schedule: ISchedule):
187
22
  """
188
23
  Defines and registers scheduled tasks for the application.
@@ -110,21 +110,23 @@ class ScheduleWorkCommand(BaseCommand):
110
110
  if hasattr(scheduler, "onError") and callable(scheduler.onError):
111
111
  schedule_service.setListener(ListeningEvent.SCHEDULER_ERROR, scheduler.onError)
112
112
 
113
+ # If the scheduler has FINALIZE_AT and it is not None
113
114
  if hasattr(scheduler, "FINALIZE_AT") and scheduler.FINALIZE_AT is not None:
114
115
  if not isinstance(scheduler.FINALIZE_AT, datetime):
115
116
  raise CLIOrionisRuntimeError("FINALIZE_AT must be a datetime instance.")
116
- schedule_service.shutdownEverythingAt(scheduler.finalizeAt())
117
+ schedule_service.shutdownEverythingAt(scheduler.FINALIZE_AT)
117
118
 
119
+ # If the scheduler has RESUME_AT and it is not None
118
120
  if hasattr(scheduler, "RESUME_AT") and scheduler.RESUME_AT is not None:
119
121
  if not isinstance(scheduler.RESUME_AT, datetime):
120
122
  raise CLIOrionisRuntimeError("RESUME_AT must be a datetime instance.")
121
- schedule_service.resumeEverythingAt(scheduler.resumeAt())
123
+ schedule_service.resumeEverythingAt(scheduler.RESUME_AT)
122
124
 
123
- # Check if the scheduler has specific pause, resume, and finalize times
125
+ # If the scheduler has PAUSE_AT and it is not None
124
126
  if hasattr(scheduler, "PAUSE_AT") and scheduler.PAUSE_AT is not None:
125
127
  if not isinstance(scheduler.PAUSE_AT, datetime):
126
128
  raise CLIOrionisRuntimeError("PAUSE_AT must be a datetime instance.")
127
- schedule_service.pauseEverythingAt(scheduler.pauseAt())
129
+ schedule_service.pauseEverythingAt(scheduler.PAUSE_AT)
128
130
 
129
131
  # Start the scheduler worker asynchronously
130
132
  await schedule_service.start()
@@ -30,7 +30,9 @@ from orionis.console.entities.job_executed import JobExecuted
30
30
  from orionis.console.entities.job_max_instances import JobMaxInstances
31
31
  from orionis.console.entities.job_missed import JobMissed
32
32
  from orionis.console.entities.job_modified import JobModified
33
+ from orionis.console.entities.job_pause import JobPause
33
34
  from orionis.console.entities.job_removed import JobRemoved
35
+ from orionis.console.entities.job_resume import JobResume
34
36
  from orionis.console.entities.job_submitted import JobSubmitted
35
37
  from orionis.console.entities.scheduler_paused import SchedulerPaused
36
38
  from orionis.console.entities.scheduler_resumed import SchedulerResumed
@@ -40,7 +42,6 @@ from orionis.console.enums.listener import ListeningEvent
40
42
  from orionis.console.enums.event import Event as EventEntity
41
43
  from orionis.console.exceptions import CLIOrionisRuntimeError
42
44
  from orionis.console.exceptions.cli_orionis_value_error import CLIOrionisValueError
43
- from orionis.console.output.contracts.console import IConsole
44
45
  from orionis.foundation.contracts.application import IApplication
45
46
  from orionis.services.log.contracts.log_service import ILogger
46
47
 
@@ -109,6 +110,9 @@ class Scheduler(ISchedule):
109
110
  # Initialize the listeners dictionary to manage event listeners.
110
111
  self.__listeners: Dict[str, callable] = {}
111
112
 
113
+ # Initialize set to track jobs paused by pauseEverythingAt
114
+ self.__paused_by_pause_everything: set = set()
115
+
112
116
  # Add this line to the existing __init__ method
113
117
  self._stop_event: Optional[asyncio.Event] = None
114
118
 
@@ -132,6 +136,9 @@ class Scheduler(ISchedule):
132
136
  tz = pytz.timezone(self.__app.config("app.timezone", "UTC"))
133
137
  now = datetime.now(tz)
134
138
 
139
+ # Log the timezone assignment for debugging purposes
140
+ self.__logger.info(f"Timezone assigned to the scheduler: {self.__app.config("app.timezone", "UTC")}")
141
+
135
142
  # Format the current time as a string
136
143
  return now.strftime("%Y-%m-%d %H:%M:%S")
137
144
 
@@ -312,8 +319,6 @@ class Scheduler(ISchedule):
312
319
  """
313
320
 
314
321
  self.__scheduler.add_listener(self.__startedListener, EVENT_SCHEDULER_STARTED)
315
- self.__scheduler.add_listener(self.__pausedListener, EVENT_SCHEDULER_PAUSED)
316
- self.__scheduler.add_listener(self.__resumedListener, EVENT_SCHEDULER_RESUMED)
317
322
  self.__scheduler.add_listener(self.__shutdownListener, EVENT_SCHEDULER_SHUTDOWN)
318
323
  self.__scheduler.add_listener(self.__errorListener, EVENT_JOB_ERROR)
319
324
  self.__scheduler.add_listener(self.__submittedListener, EVENT_JOB_SUBMITTED)
@@ -378,19 +383,36 @@ class Scheduler(ISchedule):
378
383
 
379
384
  # Try to get the running event loop
380
385
  try:
381
- loop = asyncio.get_running_loop()
382
- loop.create_task(listener(event_data, self))
386
+
387
+ try:
388
+
389
+ # Try to get the current running event loop
390
+ loop = asyncio.get_running_loop()
391
+ loop.create_task(listener(event_data, self))
392
+
393
+ except RuntimeError:
394
+
395
+ # If no event loop is running, create a new one
396
+ loop = asyncio.new_event_loop()
397
+ asyncio.set_event_loop(loop)
398
+ loop.create_task(listener(event_data, self))
383
399
 
384
400
  # If no event loop is running, log a warning instead of creating one
385
401
  except RuntimeError:
386
402
 
403
+ # Message indicating that the listener could not be invoked
404
+ error_msg = f"Cannot run async listener for '{scheduler_event}': no event loop running"
405
+
406
+ # Log the error message
407
+ self.__logger.error(error_msg)
408
+
387
409
  # Raise an error to inform the caller that the listener could not be invoked
388
- raise CLIOrionisRuntimeError(
389
- f"Cannot run async listener for '{scheduler_event}': no event loop running"
390
- )
410
+ raise CLIOrionisRuntimeError(error_msg)
391
411
 
392
412
  # Otherwise, invoke the listener directly as a regular function
393
413
  else:
414
+
415
+ # Call the regular listener function directly
394
416
  listener(event_data, self)
395
417
 
396
418
  except Exception as e:
@@ -399,10 +421,14 @@ class Scheduler(ISchedule):
399
421
  if isinstance(e, CLIOrionisRuntimeError):
400
422
  raise e
401
423
 
424
+ # Construct the error message
425
+ error_msg = f"An error occurred while invoking the listener for event '{scheduler_event}': {str(e)}"
426
+
427
+ # Log the error message
428
+ self.__logger.error(error_msg)
429
+
402
430
  # Raise a runtime error if listener invocation fails
403
- raise CLIOrionisRuntimeError(
404
- f"An error occurred while invoking the listener for event '{scheduler_event}': {str(e)}"
405
- )
431
+ raise CLIOrionisRuntimeError(error_msg)
406
432
 
407
433
  def __taskCallableListener(
408
434
  self,
@@ -472,19 +498,36 @@ class Scheduler(ISchedule):
472
498
 
473
499
  # Try to get the running event loop
474
500
  try:
475
- loop = asyncio.get_running_loop()
476
- loop.create_task(listener_method(event_data, self))
501
+
502
+ try:
503
+
504
+ # Try to get the current running event loop
505
+ loop = asyncio.get_running_loop()
506
+ loop.create_task(listener_method(event_data, self))
507
+
508
+ except RuntimeError:
509
+
510
+ # If no event loop is running, create a new one
511
+ loop = asyncio.new_event_loop()
512
+ asyncio.set_event_loop(loop)
513
+ loop.create_task(listener_method(event_data, self))
477
514
 
478
515
  # If no event loop is running, log a warning
479
516
  except RuntimeError:
480
517
 
518
+ # Construct the error message
519
+ error_msg = f"Cannot run async listener for '{scheduler_event}' on job '{event_data.job_id}': no event loop running"
520
+
521
+ # Log the error message
522
+ self.__logger.error(error_msg)
523
+
481
524
  # Raise an error to inform the caller that the listener could not be invoked
482
- raise CLIOrionisRuntimeError(
483
- f"Cannot run async listener for '{scheduler_event}' on job '{event_data.job_id}': no event loop running"
484
- )
525
+ raise CLIOrionisRuntimeError(error_msg)
485
526
 
486
527
  # Call the regular listener method directly
487
528
  else:
529
+
530
+ # Invoke the listener method directly
488
531
  listener_method(event_data, self)
489
532
 
490
533
  except Exception as e:
@@ -493,10 +536,14 @@ class Scheduler(ISchedule):
493
536
  if isinstance(e, CLIOrionisRuntimeError):
494
537
  raise e
495
538
 
539
+ # Construct the error message
540
+ error_msg = (f"An error occurred while invoking the listener for event '{scheduler_event}' on job '{event_data.job_id}': {str(e)}")
541
+
542
+ # Log the error message
543
+ self.__logger.error(error_msg)
544
+
496
545
  # Raise a runtime error if listener invocation fails
497
- raise CLIOrionisRuntimeError(
498
- f"An error occurred while invoking the listener for event '{scheduler_event}' on job '{event_data.job_id}': {str(e)}"
499
- )
546
+ raise CLIOrionisRuntimeError(error_msg)
500
547
 
501
548
  def __startedListener(
502
549
  self,
@@ -526,9 +573,6 @@ class Scheduler(ISchedule):
526
573
  # Get the current time in the configured timezone
527
574
  now = self.__getCurrentTime()
528
575
 
529
- # Log an informational message indicating that the scheduler has started
530
- self.__logger.info(f"Orionis Scheduler started successfully at {now}.")
531
-
532
576
  # Display a start message for the scheduler worker on the rich console
533
577
  # Add a blank line for better formatting
534
578
  self.__rich_console.line()
@@ -553,6 +597,9 @@ class Scheduler(ISchedule):
553
597
  # Check if a listener is registered for the scheduler started event
554
598
  self.__globalCallableListener(event, ListeningEvent.SCHEDULER_STARTED)
555
599
 
600
+ # Log an informational message indicating that the scheduler has started
601
+ self.__logger.info(f"Orionis Scheduler started successfully at {now}.")
602
+
556
603
  def __pausedListener(
557
604
  self,
558
605
  event: SchedulerPaused
@@ -581,15 +628,12 @@ class Scheduler(ISchedule):
581
628
  # Get the current time in the configured timezone
582
629
  now = self.__getCurrentTime()
583
630
 
584
- # Create a paused message
585
- message = f"Orionis Scheduler paused successfully at {now}."
586
-
587
- # Log an informational message indicating that the scheduler has been paused
588
- self.__logger.info(message)
589
-
590
631
  # Check if a listener is registered for the scheduler paused event
591
632
  self.__globalCallableListener(event, ListeningEvent.SCHEDULER_PAUSED)
592
633
 
634
+ # Log an informational message indicating that the scheduler has been paused
635
+ self.__logger.info(f"Orionis Scheduler paused successfully at {now}.")
636
+
593
637
  def __resumedListener(
594
638
  self,
595
639
  event: SchedulerResumed
@@ -618,15 +662,12 @@ class Scheduler(ISchedule):
618
662
  # Get the current time in the configured timezone
619
663
  now = self.__getCurrentTime()
620
664
 
621
- # Create a resumed message
622
- message = f"Orionis Scheduler resumed successfully at {now}."
623
-
624
- # Log an informational message indicating that the scheduler has resumed
625
- self.__logger.info(message)
626
-
627
665
  # Check if a listener is registered for the scheduler resumed event
628
666
  self.__globalCallableListener(event, ListeningEvent.SCHEDULER_RESUMED)
629
667
 
668
+ # Log an informational message indicating that the scheduler has resumed
669
+ self.__logger.info(f"Orionis Scheduler resumed successfully at {now}.")
670
+
630
671
  def __shutdownListener(
631
672
  self,
632
673
  event: SchedulerShutdown
@@ -655,15 +696,12 @@ class Scheduler(ISchedule):
655
696
  # Get the current time in the configured timezone
656
697
  now = self.__getCurrentTime()
657
698
 
658
- # Create a shutdown message
659
- message = f"Orionis Scheduler shut down successfully at {now}."
660
-
661
- # Log an informational message indicating that the scheduler has shut down
662
- self.__logger.info(message)
663
-
664
699
  # Check if a listener is registered for the scheduler shutdown event
665
700
  self.__globalCallableListener(event, ListeningEvent.SCHEDULER_SHUTDOWN)
666
701
 
702
+ # Log an informational message indicating that the scheduler has shut down
703
+ self.__logger.info(f"Orionis Scheduler shut down successfully at {now}.")
704
+
667
705
  def __errorListener(
668
706
  self,
669
707
  event: JobError
@@ -689,11 +727,8 @@ class Scheduler(ISchedule):
689
727
  and listener invocation for the job error event.
690
728
  """
691
729
 
692
- # Create an error message
693
- message = f"Task {event.job_id} raised an exception: {event.exception}"
694
-
695
730
  # Log an error message indicating that the job raised an exception
696
- self.__logger.error(message)
731
+ self.__logger.error(f"Task {event.job_id} raised an exception: {event.exception}")
697
732
 
698
733
  # If a listener is registered for this job ID, invoke the listener with the event details
699
734
  self.__taskCallableListener(event, ListeningEvent.JOB_ON_FAILURE)
@@ -726,11 +761,8 @@ class Scheduler(ISchedule):
726
761
  and listener invocation for the job submission event.
727
762
  """
728
763
 
729
- # Create a submission message
730
- message = f"Task {event.job_id} submitted to executor."
731
-
732
764
  # Log an informational message indicating that the job has been submitted
733
- self.__logger.info(message)
765
+ self.__logger.info(f"Task {event.job_id} submitted to executor.")
734
766
 
735
767
  # If a listener is registered for this job ID, invoke the listener with the event details
736
768
  self.__taskCallableListener(event, ListeningEvent.JOB_BEFORE)
@@ -761,11 +793,8 @@ class Scheduler(ISchedule):
761
793
  and listener invocation for the job execution event.
762
794
  """
763
795
 
764
- # Create an execution message
765
- message = f"Task {event.job_id} executed."
766
-
767
796
  # Log an informational message indicating that the job has been executed
768
- self.__logger.info(message)
797
+ self.__logger.info(f"Task {event.job_id} executed.")
769
798
 
770
799
  # If a listener is registered for this job ID, invoke the listener with the event details
771
800
  self.__taskCallableListener(event, ListeningEvent.JOB_AFTER)
@@ -796,11 +825,8 @@ class Scheduler(ISchedule):
796
825
  and listener invocation for the missed job event.
797
826
  """
798
827
 
799
- # Create a missed job message
800
- message = f"Task {event.job_id} was missed. It was scheduled to run at {event.scheduled_run_time}."
801
-
802
828
  # Log a warning indicating that the job was missed
803
- self.__logger.warning(message)
829
+ self.__logger.warning(f"Task {event.job_id} was missed. It was scheduled to run at {event.scheduled_run_time}.")
804
830
 
805
831
  # If a listener is registered for this job ID, invoke the listener with the event details
806
832
  self.__taskCallableListener(event, ListeningEvent.JOB_ON_MISSED)
@@ -831,11 +857,8 @@ class Scheduler(ISchedule):
831
857
  and listener invocation for the job max instances event.
832
858
  """
833
859
 
834
- # Create a max instances error message
835
- message = f"Task {event.job_id} exceeded maximum instances"
836
-
837
860
  # Log an error message indicating that the job exceeded maximum instances
838
- self.__logger.error(message)
861
+ self.__logger.error(f"Task {event.job_id} exceeded maximum instances")
839
862
 
840
863
  # If a listener is registered for this job ID, invoke the listener with the event details
841
864
  self.__taskCallableListener(event, ListeningEvent.JOB_ON_MAXINSTANCES)
@@ -866,16 +889,12 @@ class Scheduler(ISchedule):
866
889
  and listener invocation for the job modified event.
867
890
  """
868
891
 
869
- # Create a modified message
870
- message = f"Task {event.job_id} has been modified."
871
-
872
- # Log an informational message indicating that the job has been modified
873
- self.__logger.info(message)
874
-
875
892
  # If a listener is registered for this job ID, invoke the listener with the event details
876
893
  if event.next_run_time is None:
894
+ self.__logger.info(f"Task {event.job_id} has been paused.")
877
895
  self.__taskCallableListener(event, ListeningEvent.JOB_ON_PAUSED)
878
896
  else:
897
+ self.__logger.info(f"Task {event.job_id} has been resumed.")
879
898
  self.__taskCallableListener(event, ListeningEvent.JOB_ON_RESUMED)
880
899
 
881
900
  def __removedListener(
@@ -903,11 +922,8 @@ class Scheduler(ISchedule):
903
922
  listener for the job removal event.
904
923
  """
905
924
 
906
- # Create a message indicating that the job has been removed
907
- message = f"Task {event.job_id} has been removed."
908
-
909
925
  # Log the removal of the job
910
- self.__logger.info(message)
926
+ self.__logger.info(f"Task {event.job_id} has been removed.")
911
927
 
912
928
  # If a listener is registered for this job ID, invoke the listener with the event details
913
929
  self.__taskCallableListener(event, ListeningEvent.JOB_ON_REMOVED)
@@ -958,12 +974,19 @@ class Scheduler(ISchedule):
958
974
  if entity.listener:
959
975
  self.setListener(signature, entity.listener)
960
976
 
977
+ # Log the successful loading of the scheduled event
978
+ self.__logger.debug(f"Scheduled event '{signature}' loaded successfully.")
979
+
961
980
  except Exception as e:
962
981
 
982
+ # Construct the error message
983
+ error_msg = f"Failed to load scheduled event '{signature}': {str(e)}"
984
+
985
+ # Log the error message
986
+ self.__logger.error(error_msg)
987
+
963
988
  # Raise a runtime error if loading the scheduled event fails
964
- raise CLIOrionisRuntimeError(
965
- f"Failed to load scheduled event '{signature}': {str(e)}"
966
- ) from e
989
+ raise CLIOrionisRuntimeError(error_msg)
967
990
 
968
991
  def setListener(
969
992
  self,
@@ -1052,15 +1075,61 @@ class Scheduler(ISchedule):
1052
1075
 
1053
1076
  # Define a function to pause the scheduler
1054
1077
  def schedule_pause():
1078
+
1079
+ # Only pause jobs if the scheduler is currently running
1055
1080
  if self.isRunning():
1056
- self.__scheduler.pause()
1081
+
1082
+ # Clear the set of previously paused jobs
1083
+ self.__paused_by_pause_everything.clear()
1084
+
1085
+ # Get all jobs from the scheduler
1086
+ all_jobs = self.__scheduler.get_jobs()
1087
+
1088
+ # Filter out system jobs (pause, resume, shutdown tasks)
1089
+ system_job_ids = {
1090
+ "scheduler_pause_at",
1091
+ "scheduler_resume_at",
1092
+ "scheduler_shutdown_at"
1093
+ }
1094
+
1095
+ # Pause only user jobs, not system jobs
1096
+ for job in all_jobs:
1097
+
1098
+ # Pause the job only if it is not a system job
1099
+ if job.id not in system_job_ids:
1100
+
1101
+ # Pause the job and add its ID to the set of paused jobs
1102
+ try:
1103
+
1104
+ # Pause the job in the scheduler
1105
+ self.__scheduler.pause_job(job.id)
1106
+ self.__paused_by_pause_everything.add(job.id)
1107
+
1108
+ # Excute the paused listener
1109
+ self.__pausedListener(JobPause(
1110
+ code=EVENT_SCHEDULER_PAUSED,
1111
+ job_id=job.id if hasattr(job, 'id') else None,
1112
+ alias=job.name if hasattr(job, 'name') else None,
1113
+ jobstore=job.jobstore if hasattr(job, 'jobstore') else None,
1114
+ ))
1115
+
1116
+ except Exception as e:
1117
+
1118
+ # Log a warning if pausing a job fails, but continue with others
1119
+ self.__logger.warning(f"Failed to pause job '{job.id}': {str(e)}")
1120
+
1121
+ # Log that all user jobs have been paused
1122
+ self.__logger.info("All user jobs have been paused. System jobs remain active.")
1057
1123
 
1058
1124
  try:
1125
+
1059
1126
  # Remove any existing pause job to avoid conflicts
1060
1127
  try:
1061
1128
  self.__scheduler.remove_job("scheduler_pause_at")
1129
+
1130
+ # If the job doesn't exist, it's fine to proceed
1062
1131
  except:
1063
- pass # If the job doesn't exist, it's fine to proceed
1132
+ pass
1064
1133
 
1065
1134
  # Add a job to the scheduler to pause it at the specified datetime
1066
1135
  self.__scheduler.add_job(
@@ -1116,16 +1185,48 @@ class Scheduler(ISchedule):
1116
1185
 
1117
1186
  # Define a function to resume the scheduler
1118
1187
  def schedule_resume():
1188
+
1189
+ # Only resume jobs if the scheduler is currently running
1119
1190
  if self.isRunning():
1120
- self.__scheduler.resume()
1191
+
1192
+ # Resume only jobs that were paused by pauseEverythingAt
1193
+ if self.__paused_by_pause_everything:
1194
+
1195
+ # Iterate through the set of paused job IDs and resume each one
1196
+ for job_id in list(self.__paused_by_pause_everything):
1197
+
1198
+ try:
1199
+
1200
+ # Resume the job and log the action
1201
+ self.__scheduler.resume_job(job_id)
1202
+ self.__logger.info(f"User job '{job_id}' has been resumed.")
1203
+
1204
+ # Excute the resumed listener
1205
+ self.__resumedListener(JobResume(
1206
+ code=EVENT_SCHEDULER_RESUMED,
1207
+ job_id=job_id
1208
+ ))
1209
+
1210
+ except Exception as e:
1211
+
1212
+ # Log a warning if resuming a job fails, but continue with others
1213
+ self.__logger.warning(f"Failed to resume job '{job_id}': {str(e)}")
1214
+
1215
+ # Clear the set after resuming all jobs
1216
+ self.__paused_by_pause_everything.clear()
1217
+
1218
+ # Log that all previously paused jobs have been resumed
1219
+ self.__logger.info("All previously paused user jobs have been resumed.")
1121
1220
 
1122
1221
  try:
1123
1222
 
1124
1223
  # Remove any existing resume job to avoid conflicts
1125
1224
  try:
1126
1225
  self.__scheduler.remove_job("scheduler_resume_at")
1226
+
1227
+ # If the job doesn't exist, it's fine to proceed
1127
1228
  except:
1128
- pass # If the job doesn't exist, it's fine to proceed
1229
+ pass
1129
1230
 
1130
1231
  # Add a job to the scheduler to resume it at the specified datetime
1131
1232
  self.__scheduler.add_job(
@@ -1190,8 +1291,13 @@ class Scheduler(ISchedule):
1190
1291
 
1191
1292
  # Define a function to shut down the scheduler
1192
1293
  def schedule_shutdown():
1294
+
1295
+ # Only shut down the scheduler if it is currently running
1193
1296
  if self.isRunning():
1297
+
1298
+ # Execute the shutdown process
1194
1299
  self.__scheduler.shutdown(wait=wait)
1300
+
1195
1301
  # Signal the stop event to break the wait in start()
1196
1302
  if self._stop_event and not self._stop_event.is_set():
1197
1303
  self._stop_event.set()
@@ -1201,12 +1307,14 @@ class Scheduler(ISchedule):
1201
1307
  # Remove any existing shutdown job to avoid conflicts
1202
1308
  try:
1203
1309
  self.__scheduler.remove_job("scheduler_shutdown_at")
1310
+
1311
+ # If the job doesn't exist, it's fine to proceed
1204
1312
  except:
1205
- pass # If the job doesn't exist, it's fine to proceed
1313
+ pass
1206
1314
 
1207
1315
  # Add a job to the scheduler to shut it down at the specified datetime
1208
1316
  self.__scheduler.add_job(
1209
- func=schedule_shutdown, # Function to shut down the scheduler
1317
+ func=schedule_shutdown, # Function to shut down the scheduler
1210
1318
  trigger=DateTrigger(run_date=at), # Trigger type is 'date' for one-time execution
1211
1319
  id="scheduler_shutdown_at", # Unique job ID for shutting down the scheduler
1212
1320
  name="Shutdown Scheduler", # Descriptive name for the job
@@ -1260,7 +1368,7 @@ class Scheduler(ISchedule):
1260
1368
  self.__scheduler.start()
1261
1369
 
1262
1370
  # Log that the scheduler is now active and waiting for events
1263
- self.__logger.info("Scheduler is now active and waiting for events...")
1371
+ self.__logger.info("Orionis Scheduler is now active and waiting for events...")
1264
1372
 
1265
1373
  try:
1266
1374
  # Wait for the stop event to be set, which signals a shutdown
@@ -1565,8 +1673,18 @@ class Scheduler(ISchedule):
1565
1673
  False if no pause job was found or an error occurred during the cancellation process.
1566
1674
  """
1567
1675
  try:
1676
+
1677
+ # Remove any listener associated with the pause event
1678
+ listener = ListeningEvent.SCHEDULER_PAUSED.value
1679
+ if listener in self.__listeners:
1680
+ del self.__listeners[listener]
1681
+
1568
1682
  # Attempt to remove the pause job with the specific ID
1569
- self.__scheduler.remove_job("scheduler_pause_at")
1683
+ # if it exists
1684
+ try:
1685
+ self.__scheduler.remove_job("scheduler_pause_at")
1686
+ finally:
1687
+ pass
1570
1688
 
1571
1689
  # Log the successful cancellation of the pause operation
1572
1690
  self.__logger.info("Scheduled pause operation cancelled.")
@@ -1593,8 +1711,18 @@ class Scheduler(ISchedule):
1593
1711
  False if no resume job was found or an error occurred during the cancellation process.
1594
1712
  """
1595
1713
  try:
1714
+
1715
+ # Remove any listener associated with the resume event
1716
+ listener = ListeningEvent.SCHEDULER_RESUMED.value
1717
+ if listener in self.__listeners:
1718
+ del self.__listeners[listener]
1719
+
1596
1720
  # Attempt to remove the resume job with the specific ID
1597
- self.__scheduler.remove_job("scheduler_resume_at")
1721
+ # if it exists
1722
+ try:
1723
+ self.__scheduler.remove_job("scheduler_resume_at")
1724
+ finally:
1725
+ pass
1598
1726
 
1599
1727
  # Log the successful cancellation of the resume operation
1600
1728
  self.__logger.info("Scheduled resume operation cancelled.")
@@ -1622,8 +1750,18 @@ class Scheduler(ISchedule):
1622
1750
  False if no shutdown job was found or an error occurred during the cancellation process.
1623
1751
  """
1624
1752
  try:
1753
+
1754
+ # Remove any listener associated with the shutdown event
1755
+ listener = ListeningEvent.SCHEDULER_SHUTDOWN.value
1756
+ if listener in self.__listeners:
1757
+ del self.__listeners[listener]
1758
+
1625
1759
  # Attempt to remove the shutdown job with the specific ID
1626
- self.__scheduler.remove_job("scheduler_shutdown_at")
1760
+ # if it exists
1761
+ try:
1762
+ self.__scheduler.remove_job("scheduler_shutdown_at")
1763
+ finally:
1764
+ pass
1627
1765
 
1628
1766
  # Log the successful cancellation of the shutdown operation
1629
1767
  self.__logger.info("Scheduled shutdown operation cancelled.")
@@ -1653,27 +1791,6 @@ class Scheduler(ISchedule):
1653
1791
  # Return the running state of the scheduler
1654
1792
  return self.__scheduler.running
1655
1793
 
1656
- async def waitUntilStopped(self) -> None:
1657
- """
1658
- Wait for the scheduler to stop gracefully.
1659
-
1660
- This method blocks the execution until the scheduler is stopped. It waits for the
1661
- internal stop event to be set, which signals that the scheduler has been shut down.
1662
- This is useful for ensuring that the scheduler completes its operations before
1663
- proceeding with other tasks.
1664
-
1665
- Returns
1666
- -------
1667
- None
1668
- This method does not return any value. It waits until the scheduler is stopped.
1669
- """
1670
-
1671
- # Check if the stop event is initialized
1672
- if self._stop_event:
1673
-
1674
- # Wait for the stop event to be set, signaling the scheduler has stopped
1675
- await self._stop_event.wait()
1676
-
1677
1794
  def forceStop(self) -> None:
1678
1795
  """
1679
1796
  Forcefully stop the scheduler immediately without waiting for jobs to complete.
@@ -1718,6 +1835,7 @@ class Scheduler(ISchedule):
1718
1835
 
1719
1836
  # Check if the stop event exists and has not already been set
1720
1837
  if self._stop_event and not self._stop_event.is_set():
1838
+
1721
1839
  # Get the current asyncio event loop
1722
1840
  loop = asyncio.get_event_loop()
1723
1841
 
@@ -626,62 +626,89 @@ class Application(Container, IApplication):
626
626
  configuration system.
627
627
  """
628
628
 
629
+ # Convert dataclass instances to dictionaries
630
+ from orionis.services.introspection.dataclass.attributes import attributes
631
+
629
632
  # Load app configurator
633
+ if (isinstance(app, type) and issubclass(app, App)):
634
+ app = attributes(app)
630
635
  if not isinstance(app, (App, dict)):
631
636
  raise OrionisTypeError(f"Expected App instance or dict, got {type(app).__name__}")
632
637
  self.loadConfigApp(app)
633
638
 
634
639
  # Load auth configurator
640
+ if (isinstance(auth, type) and issubclass(auth, Auth)):
641
+ auth = attributes(auth)
635
642
  if not isinstance(auth, (Auth, dict)):
636
643
  raise OrionisTypeError(f"Expected Auth instance or dict, got {type(auth).__name__}")
637
644
  self.loadConfigAuth(auth)
638
645
 
639
646
  # Load cache configurator
647
+ if (isinstance(cache, type) and issubclass(cache, Cache)):
648
+ cache = attributes(cache)
640
649
  if not isinstance(cache, (Cache, dict)):
641
650
  raise OrionisTypeError(f"Expected Cache instance or dict, got {type(cache).__name__}")
642
651
  self.loadConfigCache(cache)
643
652
 
644
653
  # Load cors configurator
654
+ if (isinstance(cors, type) and issubclass(cors, Cors)):
655
+ cors = attributes(cors)
645
656
  if not isinstance(cors, (Cors, dict)):
646
657
  raise OrionisTypeError(f"Expected Cors instance or dict, got {type(cors).__name__}")
647
658
  self.loadConfigCors(cors)
648
659
 
649
660
  # Load database configurator
661
+ if (isinstance(database, type) and issubclass(database, Database)):
662
+ database = attributes(database)
650
663
  if not isinstance(database, (Database, dict)):
651
664
  raise OrionisTypeError(f"Expected Database instance or dict, got {type(database).__name__}")
652
665
  self.loadConfigDatabase(database)
653
666
 
654
667
  # Load filesystems configurator
668
+ if (isinstance(filesystems, type) and issubclass(filesystems, Filesystems)):
669
+ filesystems = attributes(filesystems)
655
670
  if not isinstance(filesystems, (Filesystems, dict)):
656
671
  raise OrionisTypeError(f"Expected Filesystems instance or dict, got {type(filesystems).__name__}")
657
672
  self.loadConfigFilesystems(filesystems)
658
673
 
659
674
  # Load logging configurator
675
+ if (isinstance(logging, type) and issubclass(logging, Logging)):
676
+ logging = attributes(logging)
660
677
  if not isinstance(logging, (Logging, dict)):
661
678
  raise OrionisTypeError(f"Expected Logging instance or dict, got {type(logging).__name__}")
662
679
  self.loadConfigLogging(logging)
663
680
 
664
681
  # Load mail configurator
682
+ if (isinstance(mail, type) and issubclass(mail, Mail)):
683
+ mail = attributes(mail)
665
684
  if not isinstance(mail, (Mail, dict)):
666
685
  raise OrionisTypeError(f"Expected Mail instance or dict, got {type(mail).__name__}")
667
686
  self.loadConfigMail(mail)
668
687
 
669
688
  # Load paths configurator
689
+ if (isinstance(path, type) and issubclass(path, Paths)):
690
+ path = attributes(path)
670
691
  if not isinstance(path, (Paths, dict)):
671
692
  raise OrionisTypeError(f"Expected Paths instance or dict, got {type(path).__name__}")
672
693
  self.loadPaths(path)
673
694
 
674
695
  # Load queue configurator
696
+ if (isinstance(queue, type) and issubclass(queue, Queue)):
697
+ queue = attributes(queue)
675
698
  if not isinstance(queue, (Queue, dict)):
676
699
  raise OrionisTypeError(f"Expected Queue instance or dict, got {type(queue).__name__}")
677
700
  self.loadConfigQueue(queue)
678
701
 
679
702
  # Load session configurator
703
+ if (isinstance(session, type) and issubclass(session, Session)):
704
+ session = attributes(session)
680
705
  if not isinstance(session, (Session, dict)):
681
706
  raise OrionisTypeError(f"Expected Session instance or dict, got {type(session).__name__}")
682
707
  self.loadConfigSession(session)
683
708
 
684
709
  # Load testing configurator
710
+ if (isinstance(testing, type) and issubclass(testing, Testing)):
711
+ testing = attributes(testing)
685
712
  if not isinstance(testing, (Testing, dict)):
686
713
  raise OrionisTypeError(f"Expected Testing instance or dict, got {type(testing).__name__}")
687
714
  self.loadConfigTesting(testing)
@@ -767,7 +794,9 @@ class Application(Container, IApplication):
767
794
 
768
795
  # If app is a dict, convert it to App instance
769
796
  if isinstance(app, dict):
770
- app = App(**app)
797
+ app = App(**app).toDict()
798
+ elif isinstance(app, App):
799
+ app = app.toDict()
771
800
 
772
801
  # Store the configuration
773
802
  self.__configurators['app'] = app
@@ -853,7 +882,9 @@ class Application(Container, IApplication):
853
882
 
854
883
  # If auth is a dict, convert it to Auth instance
855
884
  if isinstance(auth, dict):
856
- auth = Auth(**auth)
885
+ auth = Auth(**auth).toDict()
886
+ elif isinstance(auth, Auth):
887
+ auth = auth.toDict()
857
888
 
858
889
  # Store the configuration
859
890
  self.__configurators['auth'] = auth
@@ -939,7 +970,9 @@ class Application(Container, IApplication):
939
970
 
940
971
  # If cache is a dict, convert it to Cache instance
941
972
  if isinstance(cache, dict):
942
- cache = Cache(**cache)
973
+ cache = Cache(**cache).toDict()
974
+ elif isinstance(cache, Cache):
975
+ cache = cache.toDict()
943
976
 
944
977
  # Store the configuration
945
978
  self.__configurators['cache'] = cache
@@ -1025,7 +1058,9 @@ class Application(Container, IApplication):
1025
1058
 
1026
1059
  # If cors is a dict, convert it to Cors instance
1027
1060
  if isinstance(cors, dict):
1028
- cors = Cors(**cors)
1061
+ cors = Cors(**cors).toDict()
1062
+ elif isinstance(cors, Cors):
1063
+ cors = cors.toDict()
1029
1064
 
1030
1065
  # Store the configuration
1031
1066
  self.__configurators['cors'] = cors
@@ -1111,7 +1146,9 @@ class Application(Container, IApplication):
1111
1146
 
1112
1147
  # If database is a dict, convert it to Database instance
1113
1148
  if isinstance(database, dict):
1114
- database = Database(**database)
1149
+ database = Database(**database).toDict()
1150
+ elif isinstance(database, Database):
1151
+ database = database.toDict()
1115
1152
 
1116
1153
  # Store the configuration
1117
1154
  self.__configurators['database'] = database
@@ -1197,7 +1234,9 @@ class Application(Container, IApplication):
1197
1234
 
1198
1235
  # If filesystems is a dict, convert it to Filesystems instance
1199
1236
  if isinstance(filesystems, dict):
1200
- filesystems = Filesystems(**filesystems)
1237
+ filesystems = Filesystems(**filesystems).toDict()
1238
+ elif isinstance(filesystems, Filesystems):
1239
+ filesystems = filesystems.toDict()
1201
1240
 
1202
1241
  # Store the configuration
1203
1242
  self.__configurators['filesystems'] = filesystems
@@ -1283,7 +1322,9 @@ class Application(Container, IApplication):
1283
1322
 
1284
1323
  # If logging is a dict, convert it to Logging instance
1285
1324
  if isinstance(logging, dict):
1286
- logging = Logging(**logging)
1325
+ logging = Logging(**logging).toDict()
1326
+ elif isinstance(logging, Logging):
1327
+ logging = logging.toDict()
1287
1328
 
1288
1329
  # Store the configuration
1289
1330
  self.__configurators['logging'] = logging
@@ -1369,7 +1410,9 @@ class Application(Container, IApplication):
1369
1410
 
1370
1411
  # If mail is a dict, convert it to Mail instance
1371
1412
  if isinstance(mail, dict):
1372
- mail = Mail(**mail)
1413
+ mail = Mail(**mail).toDict()
1414
+ elif isinstance(mail, Mail):
1415
+ mail = mail.toDict()
1373
1416
 
1374
1417
  # Store the configuration
1375
1418
  self.__configurators['mail'] = mail
@@ -1558,7 +1601,12 @@ class Application(Container, IApplication):
1558
1601
  paths.update({
1559
1602
  'root': self.__bootstrap_base_path or str(Path.cwd().resolve())
1560
1603
  })
1561
- paths = Paths(**paths)
1604
+ paths = Paths(**paths).toDict()
1605
+ elif isinstance(paths, Paths):
1606
+ paths = paths.toDict()
1607
+ paths.update({
1608
+ 'root': self.__bootstrap_base_path or str(Path.cwd().resolve())
1609
+ })
1562
1610
 
1563
1611
  # Store the configuration
1564
1612
  self.__configurators['path'] = paths
@@ -1690,7 +1738,9 @@ class Application(Container, IApplication):
1690
1738
 
1691
1739
  # If queue is a dict, convert it to Queue instance
1692
1740
  if isinstance(queue, dict):
1693
- queue = Queue(**queue)
1741
+ queue = Queue(**queue).toDict()
1742
+ elif isinstance(queue, Queue):
1743
+ queue = queue.toDict()
1694
1744
 
1695
1745
  # Store the configuration
1696
1746
  self.__configurators['queue'] = queue
@@ -1776,7 +1826,9 @@ class Application(Container, IApplication):
1776
1826
 
1777
1827
  # If session is a dict, convert it to Session instance
1778
1828
  if isinstance(session, dict):
1779
- session = Session(**session)
1829
+ session = Session(**session).toDict()
1830
+ elif isinstance(session, Session):
1831
+ session = session.toDict()
1780
1832
 
1781
1833
  # Store the configuration
1782
1834
  self.__configurators['session'] = session
@@ -1862,7 +1914,9 @@ class Application(Container, IApplication):
1862
1914
 
1863
1915
  # If testing is a dict, convert it to Testing instance
1864
1916
  if isinstance(testing, dict):
1865
- testing = Testing(**testing)
1917
+ testing = Testing(**testing).toDict()
1918
+ elif isinstance(testing, Testing):
1919
+ testing = testing.toDict()
1866
1920
 
1867
1921
  # Store the configuration
1868
1922
  self.__configurators['testing'] = testing
@@ -92,6 +92,8 @@ class Session(BaseEntity):
92
92
  """
93
93
 
94
94
  # Validate secret_key
95
+ if self.secret_key is None:
96
+ self.secret_key = SecretKey.random()
95
97
  if not isinstance(self.secret_key, str) or not self.secret_key.strip():
96
98
  raise OrionisIntegrityException("Session secret_key must be a non-empty string")
97
99
 
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.522.0"
8
+ VERSION = "0.523.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
File without changes
@@ -0,0 +1,30 @@
1
+ class DataclassValues:
2
+
3
+ def __call__(self, dataclass_type: type) -> dict:
4
+ """
5
+ Extract attributes and their values from a given dataclass type.
6
+
7
+ This method retrieves all attributes defined in the provided dataclass type,
8
+ excluding special attributes (those whose names start with '__'). It returns
9
+ a dictionary where the keys are the attribute names and the values are the
10
+ corresponding attribute values.
11
+
12
+ Parameters
13
+ ----------
14
+ dataclass_type : type
15
+ The dataclass type from which to extract attributes.
16
+
17
+ Returns
18
+ -------
19
+ dict
20
+ A dictionary containing attribute names as keys and their corresponding
21
+ values as values. Special attributes (those starting with '__') are excluded.
22
+ """
23
+
24
+ # Retrieve all attributes from the dataclass type's __dict__ attribute
25
+ # Exclude special attributes (names starting with '__')
26
+ values = {k: v for k, v in dataclass_type.__dict__.items() if not k.startswith("__")}
27
+ return values
28
+
29
+ # Instantiate the DataclassValues callable
30
+ attributes = DataclassValues()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orionis
3
- Version: 0.522.0
3
+ Version: 0.523.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
@@ -8,14 +8,14 @@ orionis/console/args/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
8
8
  orionis/console/args/enums/actions.py,sha256=S3T-vWS6DJSGtANrq3od3-90iYAjPvJwaOZ2V02y34c,1222
9
9
  orionis/console/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  orionis/console/base/command.py,sha256=OM4xqVgpv_1RZVyVG8BzOHl1sP9FT5mPUwZjMil8IRg,6637
11
- orionis/console/base/scheduler.py,sha256=LFzWUFk07LrcpKFL7sS7exHzTkxFRd1DPDSqDSpRcOk,15157
11
+ orionis/console/base/scheduler.py,sha256=w86p-4KjfMqMcGlQBsmiBASpzv33M-PWLbgYza7Um9g,8030
12
12
  orionis/console/base/scheduler_event_listener.py,sha256=5qWPmf6jmiRwUz6U1ZvpQCG5eovOpeCl0KAb8kKDkfU,3905
13
13
  orionis/console/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  orionis/console/commands/cache.py,sha256=8DsYoRzSBLn0P9qkGVItRbo0R6snWBDBg0_Xa7tmVhs,2322
15
15
  orionis/console/commands/help.py,sha256=zfSw0pYaOnFN-_Ozdn4veBQDYMgSSDY10nPDCi-7tTY,3199
16
16
  orionis/console/commands/publisher.py,sha256=FUg-EUzK7LLXsla10ZUZro8V0Z5S-KjmsaSdRHSSGbA,21381
17
17
  orionis/console/commands/scheduler_list.py,sha256=A2N_mEXEJDHO8DX2TDrL1ROeeRhFSkWD3rCw64Hrf0o,4763
18
- orionis/console/commands/scheduler_work.py,sha256=FHBQ8Ajs1zacuQFXaG-KLVRy07m9FqwyJRNVmp7cDg0,6337
18
+ orionis/console/commands/scheduler_work.py,sha256=mzSFes8Wl1gCf253tNYClij0abT5HlpW1QZVFrU5EXo,6445
19
19
  orionis/console/commands/test.py,sha256=-EmQwFwMBuby3OI9HwqMIwuJzd2CGbWbOqmwrR25sOE,2402
20
20
  orionis/console/commands/version.py,sha256=SUuNDJ40f2uq69OQUmPQXJKaa9Bm_iVRDPmBd7zc1Yc,3658
21
21
  orionis/console/commands/workflow.py,sha256=NYOmjTSvm2o6AE4h9LSTZMFSYPQreNmEJtronyOxaYk,2451
@@ -81,7 +81,7 @@ orionis/console/request/cli_request.py,sha256=7-sgYmNUCipuHLVAwWLJiHv0cJCDmsM1Lu
81
81
  orionis/console/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
82
  orionis/console/tasks/event.py,sha256=l4J-HEPaj1mxB_PYQMgG9dRHUe01wUag8fKLLnR2N2M,164395
83
83
  orionis/console/tasks/listener.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
- orionis/console/tasks/schedule.py,sha256=Lpm_P0Brw8XHiqA-Me9SMevNlo0CzUf-rrt2PKTFW_I,72389
84
+ orionis/console/tasks/schedule.py,sha256=QQtETxI_SrApPN6JlyWgWB3ExkR3w2iFgeR-UCEV8fA,77612
85
85
  orionis/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
86
  orionis/container/container.py,sha256=aF_b6lTUpG4YCo9yFJEzsntTdIzgMMXFW5LyWqAJVBQ,87987
87
87
  orionis/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -123,7 +123,7 @@ orionis/failure/contracts/handler.py,sha256=4N9yMkMgdhtHbRGAyCtuTx3GmkPP74vhqdRL
123
123
  orionis/failure/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
124
  orionis/failure/entities/throwable.py,sha256=ogys062uhim5QMYU62ezlnumRAnYQlUf_vZvQY47S3U,1227
125
125
  orionis/foundation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
126
- orionis/foundation/application.py,sha256=GmfLnpWuhX_6d1gzUk1v7jy_R72XpLJdA-hEOrXQn_Q,83792
126
+ orionis/foundation/application.py,sha256=OOe10s0Dpo3uC4L3xrhjRitaZo7ukaFJaRSJcpdl0cA,86448
127
127
  orionis/foundation/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
128
128
  orionis/foundation/config/startup.py,sha256=vbzduprRCNyYeR2nnMaqc1uKXw6PTzAY2jVfXNQKN8I,9691
129
129
  orionis/foundation/config/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -204,7 +204,7 @@ orionis/foundation/config/roots/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
204
204
  orionis/foundation/config/roots/paths.py,sha256=qQpghBFyF6hdtrt88sLX-4uqrq0frvaQrcDl0fmsTGU,10565
205
205
  orionis/foundation/config/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
206
206
  orionis/foundation/config/session/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
207
- orionis/foundation/config/session/entities/session.py,sha256=sJoD-_CiwUR88tva-rO22bagG3RTcHXrQGWbq4B5joM,5998
207
+ orionis/foundation/config/session/entities/session.py,sha256=G3dRlzDCsL5_2A2ZKpge2Jwcu6N-YVsum09pWk9oHDc,6085
208
208
  orionis/foundation/config/session/enums/__init__.py,sha256=bvjCUkQbSfKB0J8V1BwOHSjOyZn6xhOmamH3urhoKCA,84
209
209
  orionis/foundation/config/session/enums/same_site_policy.py,sha256=Oo05CJ-5keJWzfflylodyBquofsXqThQPcnar2-ChCw,645
210
210
  orionis/foundation/config/session/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -239,7 +239,7 @@ orionis/foundation/providers/scheduler_provider.py,sha256=72SoixFog9IOE9Ve9Xcfw6
239
239
  orionis/foundation/providers/testing_provider.py,sha256=SrJRpdvcblx9WvX7x9Y3zc7OQfiTf7la0HAJrm2ESlE,3725
240
240
  orionis/foundation/providers/workers_provider.py,sha256=oa_2NIDH6UxZrtuGkkoo_zEoNIMGgJ46vg5CCgAm7wI,3926
241
241
  orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
242
- orionis/metadata/framework.py,sha256=LNUd5w9wDJVTDwfg_BIGNlRYyyCu3UpQnvpmOQsMlIQ,4109
242
+ orionis/metadata/framework.py,sha256=JjXMnmgYxlzZmmwSkOaQe2TZAI5nx3vfWRDzNbUMKVM,4109
243
243
  orionis/metadata/package.py,sha256=k7Yriyp5aUcR-iR8SK2ec_lf0_Cyc-C7JczgXa-I67w,16039
244
244
  orionis/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
245
245
  orionis/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -292,6 +292,8 @@ orionis/services/introspection/concretes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
292
292
  orionis/services/introspection/concretes/reflection.py,sha256=5DkNr6gUYdccSo7htzILoV38OAJCwLz-jLXViqZg6eY,55916
293
293
  orionis/services/introspection/concretes/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
294
294
  orionis/services/introspection/concretes/contracts/reflection.py,sha256=LwEAgdN_WLCfS9b8pnFRVfN0PTRK4Br9qngu5km5aIk,24955
295
+ orionis/services/introspection/dataclass/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
296
+ orionis/services/introspection/dataclass/attributes.py,sha256=Z847Gya_0hdiK7eNCI8-tE1o2KtkxSKVcGxXYj94r_A,1186
295
297
  orionis/services/introspection/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
296
298
  orionis/services/introspection/dependencies/reflection.py,sha256=VEe3cY6LTpOW3dm0IFECTHh7F_9_X-siTAeQc2XRQeM,13451
297
299
  orionis/services/introspection/dependencies/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -415,7 +417,7 @@ orionis/test/validators/web_report.py,sha256=n9BfzOZz6aEiNTypXcwuWbFRG0OdHNSmCNu
415
417
  orionis/test/validators/workers.py,sha256=rWcdRexINNEmGaO7mnc1MKUxkHKxrTsVuHgbnIfJYgc,1206
416
418
  orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
417
419
  orionis/test/view/render.py,sha256=f-zNhtKSg9R5Njqujbg2l2amAs2-mRVESneLIkWOZjU,4082
418
- orionis-0.522.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
420
+ orionis-0.523.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
419
421
  tests/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
420
422
  tests/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
421
423
  tests/container/context/test_manager.py,sha256=wOwXpl9rHNfTTexa9GBKYMwK0_-KSQPbI-AEyGNkmAE,1356
@@ -561,8 +563,8 @@ tests/testing/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
561
563
  tests/testing/validators/test_testing_validators.py,sha256=WPo5GxTP6xE-Dw3X1vZoqOMpb6HhokjNSbgDsDRDvy4,16588
562
564
  tests/testing/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
563
565
  tests/testing/view/test_render.py,sha256=tnnMBwS0iKUIbogLvu-7Rii50G6Koddp3XT4wgdFEYM,1050
564
- orionis-0.522.0.dist-info/METADATA,sha256=tcvGNIB23Yo-X3d9ClTaZfP9tChX79uyxXZPstmEyhs,4801
565
- orionis-0.522.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
566
- orionis-0.522.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
567
- orionis-0.522.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
568
- orionis-0.522.0.dist-info/RECORD,,
566
+ orionis-0.523.0.dist-info/METADATA,sha256=628aQJLd-wjZTMQT2KZF_n4t8gWzcu36dWBrrTQWEpw,4801
567
+ orionis-0.523.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
568
+ orionis-0.523.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
569
+ orionis-0.523.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
570
+ orionis-0.523.0.dist-info/RECORD,,