orionis 0.522.0__py3-none-any.whl → 0.524.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- orionis/console/base/scheduler.py +0 -165
- orionis/console/commands/scheduler_work.py +6 -4
- orionis/console/tasks/schedule.py +273 -172
- orionis/foundation/application.py +66 -12
- orionis/foundation/config/session/entities/session.py +2 -0
- orionis/metadata/framework.py +1 -1
- orionis/services/introspection/dataclass/__init__.py +0 -0
- orionis/services/introspection/dataclass/attributes.py +30 -0
- {orionis-0.522.0.dist-info → orionis-0.524.0.dist-info}/METADATA +1 -1
- {orionis-0.522.0.dist-info → orionis-0.524.0.dist-info}/RECORD +14 -12
- {orionis-0.522.0.dist-info → orionis-0.524.0.dist-info}/WHEEL +0 -0
- {orionis-0.522.0.dist-info → orionis-0.524.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.522.0.dist-info → orionis-0.524.0.dist-info}/top_level.txt +0 -0
- {orionis-0.522.0.dist-info → orionis-0.524.0.dist-info}/zip-safe +0 -0
|
@@ -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.
|
|
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.
|
|
123
|
+
schedule_service.resumeEverythingAt(scheduler.RESUME_AT)
|
|
122
124
|
|
|
123
|
-
#
|
|
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.
|
|
129
|
+
schedule_service.pauseEverythingAt(scheduler.PAUSE_AT)
|
|
128
130
|
|
|
129
131
|
# Start the scheduler worker asynchronously
|
|
130
132
|
await schedule_service.start()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
import logging
|
|
4
|
-
from typing import Dict, List, Optional, Union
|
|
4
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional, Union
|
|
5
5
|
import pytz
|
|
6
6
|
from apscheduler.triggers.date import DateTrigger
|
|
7
7
|
from apscheduler.events import (
|
|
@@ -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
|
-
|
|
382
|
-
|
|
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 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
|
-
|
|
476
|
-
|
|
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,79 +597,8 @@ 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
|
|
|
556
|
-
|
|
557
|
-
self
|
|
558
|
-
event: SchedulerPaused
|
|
559
|
-
) -> None:
|
|
560
|
-
"""
|
|
561
|
-
Handle the scheduler paused event for logging and invoking registered listeners.
|
|
562
|
-
|
|
563
|
-
This method is triggered when the scheduler is paused. It logs an informational
|
|
564
|
-
message indicating that the scheduler has been paused successfully and displays
|
|
565
|
-
a formatted message on the rich console. If a listener is registered for the
|
|
566
|
-
scheduler paused event, it invokes the listener with the event details.
|
|
567
|
-
|
|
568
|
-
Parameters
|
|
569
|
-
----------
|
|
570
|
-
event : SchedulerPaused
|
|
571
|
-
An event object containing details about the scheduler paused event.
|
|
572
|
-
|
|
573
|
-
Returns
|
|
574
|
-
-------
|
|
575
|
-
None
|
|
576
|
-
This method does not return any value. It performs logging, displays
|
|
577
|
-
a message on the console, and invokes any registered listener for the
|
|
578
|
-
scheduler paused event.
|
|
579
|
-
"""
|
|
580
|
-
|
|
581
|
-
# Get the current time in the configured timezone
|
|
582
|
-
now = self.__getCurrentTime()
|
|
583
|
-
|
|
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
|
-
# Check if a listener is registered for the scheduler paused event
|
|
591
|
-
self.__globalCallableListener(event, ListeningEvent.SCHEDULER_PAUSED)
|
|
592
|
-
|
|
593
|
-
def __resumedListener(
|
|
594
|
-
self,
|
|
595
|
-
event: SchedulerResumed
|
|
596
|
-
) -> None:
|
|
597
|
-
"""
|
|
598
|
-
Handle the scheduler resumed event for logging and invoking registered listeners.
|
|
599
|
-
|
|
600
|
-
This method is triggered when the scheduler resumes from a paused state. It logs an informational
|
|
601
|
-
message indicating that the scheduler has resumed successfully and displays a formatted message
|
|
602
|
-
on the rich console. If a listener is registered for the scheduler resumed event, it invokes
|
|
603
|
-
the listener with the event details.
|
|
604
|
-
|
|
605
|
-
Parameters
|
|
606
|
-
----------
|
|
607
|
-
event : SchedulerResumed
|
|
608
|
-
An event object containing details about the scheduler resumed event.
|
|
609
|
-
|
|
610
|
-
Returns
|
|
611
|
-
-------
|
|
612
|
-
None
|
|
613
|
-
This method does not return any value. It performs logging, displays
|
|
614
|
-
a message on the console, and invokes any registered listener for the
|
|
615
|
-
scheduler resumed event.
|
|
616
|
-
"""
|
|
617
|
-
|
|
618
|
-
# Get the current time in the configured timezone
|
|
619
|
-
now = self.__getCurrentTime()
|
|
620
|
-
|
|
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
|
-
# Check if a listener is registered for the scheduler resumed event
|
|
628
|
-
self.__globalCallableListener(event, ListeningEvent.SCHEDULER_RESUMED)
|
|
600
|
+
# Log an informational message indicating that the scheduler has started
|
|
601
|
+
self.__logger.info(f"Orionis Scheduler started successfully at {now}.")
|
|
629
602
|
|
|
630
603
|
def __shutdownListener(
|
|
631
604
|
self,
|
|
@@ -655,15 +628,12 @@ class Scheduler(ISchedule):
|
|
|
655
628
|
# Get the current time in the configured timezone
|
|
656
629
|
now = self.__getCurrentTime()
|
|
657
630
|
|
|
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
631
|
# Check if a listener is registered for the scheduler shutdown event
|
|
665
632
|
self.__globalCallableListener(event, ListeningEvent.SCHEDULER_SHUTDOWN)
|
|
666
633
|
|
|
634
|
+
# Log an informational message indicating that the scheduler has shut down
|
|
635
|
+
self.__logger.info(f"Orionis Scheduler shut down successfully at {now}.")
|
|
636
|
+
|
|
667
637
|
def __errorListener(
|
|
668
638
|
self,
|
|
669
639
|
event: JobError
|
|
@@ -689,11 +659,8 @@ class Scheduler(ISchedule):
|
|
|
689
659
|
and listener invocation for the job error event.
|
|
690
660
|
"""
|
|
691
661
|
|
|
692
|
-
# Create an error message
|
|
693
|
-
message = f"Task {event.job_id} raised an exception: {event.exception}"
|
|
694
|
-
|
|
695
662
|
# Log an error message indicating that the job raised an exception
|
|
696
|
-
self.__logger.error(
|
|
663
|
+
self.__logger.error(f"Task {event.job_id} raised an exception: {event.exception}")
|
|
697
664
|
|
|
698
665
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
699
666
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_FAILURE)
|
|
@@ -726,11 +693,8 @@ class Scheduler(ISchedule):
|
|
|
726
693
|
and listener invocation for the job submission event.
|
|
727
694
|
"""
|
|
728
695
|
|
|
729
|
-
# Create a submission message
|
|
730
|
-
message = f"Task {event.job_id} submitted to executor."
|
|
731
|
-
|
|
732
696
|
# Log an informational message indicating that the job has been submitted
|
|
733
|
-
self.__logger.info(
|
|
697
|
+
self.__logger.info(f"Task {event.job_id} submitted to executor.")
|
|
734
698
|
|
|
735
699
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
736
700
|
self.__taskCallableListener(event, ListeningEvent.JOB_BEFORE)
|
|
@@ -761,11 +725,8 @@ class Scheduler(ISchedule):
|
|
|
761
725
|
and listener invocation for the job execution event.
|
|
762
726
|
"""
|
|
763
727
|
|
|
764
|
-
# Create an execution message
|
|
765
|
-
message = f"Task {event.job_id} executed."
|
|
766
|
-
|
|
767
728
|
# Log an informational message indicating that the job has been executed
|
|
768
|
-
self.__logger.info(
|
|
729
|
+
self.__logger.info(f"Task {event.job_id} executed.")
|
|
769
730
|
|
|
770
731
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
771
732
|
self.__taskCallableListener(event, ListeningEvent.JOB_AFTER)
|
|
@@ -796,11 +757,8 @@ class Scheduler(ISchedule):
|
|
|
796
757
|
and listener invocation for the missed job event.
|
|
797
758
|
"""
|
|
798
759
|
|
|
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
760
|
# Log a warning indicating that the job was missed
|
|
803
|
-
self.__logger.warning(
|
|
761
|
+
self.__logger.warning(f"Task {event.job_id} was missed. It was scheduled to run at {event.scheduled_run_time}.")
|
|
804
762
|
|
|
805
763
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
806
764
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_MISSED)
|
|
@@ -831,11 +789,8 @@ class Scheduler(ISchedule):
|
|
|
831
789
|
and listener invocation for the job max instances event.
|
|
832
790
|
"""
|
|
833
791
|
|
|
834
|
-
# Create a max instances error message
|
|
835
|
-
message = f"Task {event.job_id} exceeded maximum instances"
|
|
836
|
-
|
|
837
792
|
# Log an error message indicating that the job exceeded maximum instances
|
|
838
|
-
self.__logger.error(
|
|
793
|
+
self.__logger.error(f"Task {event.job_id} exceeded maximum instances")
|
|
839
794
|
|
|
840
795
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
841
796
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_MAXINSTANCES)
|
|
@@ -866,16 +821,12 @@ class Scheduler(ISchedule):
|
|
|
866
821
|
and listener invocation for the job modified event.
|
|
867
822
|
"""
|
|
868
823
|
|
|
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
824
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
876
825
|
if event.next_run_time is None:
|
|
826
|
+
self.__logger.info(f"Task {event.job_id} has been paused.")
|
|
877
827
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_PAUSED)
|
|
878
828
|
else:
|
|
829
|
+
self.__logger.info(f"Task {event.job_id} has been resumed.")
|
|
879
830
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_RESUMED)
|
|
880
831
|
|
|
881
832
|
def __removedListener(
|
|
@@ -903,11 +854,8 @@ class Scheduler(ISchedule):
|
|
|
903
854
|
listener for the job removal event.
|
|
904
855
|
"""
|
|
905
856
|
|
|
906
|
-
# Create a message indicating that the job has been removed
|
|
907
|
-
message = f"Task {event.job_id} has been removed."
|
|
908
|
-
|
|
909
857
|
# Log the removal of the job
|
|
910
|
-
self.__logger.info(
|
|
858
|
+
self.__logger.info(f"Task {event.job_id} has been removed.")
|
|
911
859
|
|
|
912
860
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
913
861
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_REMOVED)
|
|
@@ -958,12 +906,19 @@ class Scheduler(ISchedule):
|
|
|
958
906
|
if entity.listener:
|
|
959
907
|
self.setListener(signature, entity.listener)
|
|
960
908
|
|
|
909
|
+
# Log the successful loading of the scheduled event
|
|
910
|
+
self.__logger.debug(f"Scheduled event '{signature}' loaded successfully.")
|
|
911
|
+
|
|
961
912
|
except Exception as e:
|
|
962
913
|
|
|
914
|
+
# Construct the error message
|
|
915
|
+
error_msg = f"Failed to load scheduled event '{signature}': {str(e)}"
|
|
916
|
+
|
|
917
|
+
# Log the error message
|
|
918
|
+
self.__logger.error(error_msg)
|
|
919
|
+
|
|
963
920
|
# 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
|
|
921
|
+
raise CLIOrionisRuntimeError(error_msg)
|
|
967
922
|
|
|
968
923
|
def setListener(
|
|
969
924
|
self,
|
|
@@ -1015,6 +970,53 @@ class Scheduler(ISchedule):
|
|
|
1015
970
|
# Register the listener for the specified event in the internal listeners dictionary
|
|
1016
971
|
self.__listeners[event] = listener
|
|
1017
972
|
|
|
973
|
+
def wrapAsyncFunction(
|
|
974
|
+
self,
|
|
975
|
+
func: Callable[..., Awaitable[Any]]
|
|
976
|
+
) -> Callable[..., Any]:
|
|
977
|
+
"""
|
|
978
|
+
Wrap an asynchronous function to be called in a synchronous context.
|
|
979
|
+
|
|
980
|
+
This method takes an asynchronous function (a coroutine) and returns a synchronous
|
|
981
|
+
wrapper function that can be called in a non-async context. The wrapper function
|
|
982
|
+
ensures that the asynchronous function is executed within the appropriate event loop.
|
|
983
|
+
|
|
984
|
+
Parameters
|
|
985
|
+
----------
|
|
986
|
+
func : Callable[..., Awaitable[Any]]
|
|
987
|
+
The asynchronous function (coroutine) to be wrapped. This function should be
|
|
988
|
+
defined using the `async def` syntax and return an awaitable object.
|
|
989
|
+
|
|
990
|
+
Returns
|
|
991
|
+
-------
|
|
992
|
+
Callable[..., Any]
|
|
993
|
+
A synchronous wrapper function that can be called in a non-async context.
|
|
994
|
+
When invoked, this wrapper will execute the original asynchronous function
|
|
995
|
+
within the appropriate event loop.
|
|
996
|
+
|
|
997
|
+
Raises
|
|
998
|
+
------
|
|
999
|
+
ValueError
|
|
1000
|
+
If the provided `func` is not an asynchronous function (coroutine).
|
|
1001
|
+
"""
|
|
1002
|
+
|
|
1003
|
+
# Define a synchronous wrapper function
|
|
1004
|
+
def sync_wrapper(*args, **kwargs) -> Any:
|
|
1005
|
+
try:
|
|
1006
|
+
# Try to get the current event loop
|
|
1007
|
+
loop = asyncio.get_event_loop()
|
|
1008
|
+
if loop.is_running():
|
|
1009
|
+
# If the loop is already running, create a task for the coroutine
|
|
1010
|
+
return asyncio.create_task(func(*args, **kwargs))
|
|
1011
|
+
else:
|
|
1012
|
+
# If the loop is not running, run the coroutine until complete
|
|
1013
|
+
return loop.run_until_complete(func(*args, **kwargs))
|
|
1014
|
+
except RuntimeError:
|
|
1015
|
+
# If no event loop exists, create a new one and run the coroutine
|
|
1016
|
+
return asyncio.run(func(*args, **kwargs))
|
|
1017
|
+
|
|
1018
|
+
return sync_wrapper
|
|
1019
|
+
|
|
1018
1020
|
def pauseEverythingAt(
|
|
1019
1021
|
self,
|
|
1020
1022
|
at: datetime
|
|
@@ -1050,21 +1052,68 @@ class Scheduler(ISchedule):
|
|
|
1050
1052
|
if not isinstance(at, datetime):
|
|
1051
1053
|
raise ValueError("The 'at' parameter must be a datetime object.")
|
|
1052
1054
|
|
|
1053
|
-
# Define
|
|
1054
|
-
def schedule_pause():
|
|
1055
|
+
# Define an async function to pause the scheduler
|
|
1056
|
+
async def schedule_pause():
|
|
1057
|
+
|
|
1058
|
+
# Only pause jobs if the scheduler is currently running
|
|
1055
1059
|
if self.isRunning():
|
|
1056
|
-
|
|
1060
|
+
|
|
1061
|
+
# Clear the set of previously paused jobs
|
|
1062
|
+
self.__paused_by_pause_everything.clear()
|
|
1063
|
+
|
|
1064
|
+
# Get all jobs from the scheduler
|
|
1065
|
+
all_jobs = self.__scheduler.get_jobs()
|
|
1066
|
+
|
|
1067
|
+
# Filter out system jobs (pause, resume, shutdown tasks)
|
|
1068
|
+
system_job_ids = {
|
|
1069
|
+
"scheduler_pause_at",
|
|
1070
|
+
"scheduler_resume_at",
|
|
1071
|
+
"scheduler_shutdown_at"
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
# Pause only user jobs, not system jobs
|
|
1075
|
+
for job in all_jobs:
|
|
1076
|
+
|
|
1077
|
+
# Pause the job only if it is not a system job
|
|
1078
|
+
if job.id not in system_job_ids:
|
|
1079
|
+
|
|
1080
|
+
# Pause the job and add its ID to the set of paused jobs
|
|
1081
|
+
try:
|
|
1082
|
+
|
|
1083
|
+
# Pause the job in the scheduler
|
|
1084
|
+
self.__scheduler.pause_job(job.id)
|
|
1085
|
+
self.__paused_by_pause_everything.add(job.id)
|
|
1086
|
+
|
|
1087
|
+
# Execute the task callable listener
|
|
1088
|
+
self.__globalCallableListener(SchedulerPaused(EVENT_SCHEDULER_PAUSED), ListeningEvent.SCHEDULER_PAUSED)
|
|
1089
|
+
|
|
1090
|
+
# Get the current time in the configured timezone
|
|
1091
|
+
now = self.__getCurrentTime()
|
|
1092
|
+
|
|
1093
|
+
# Log an informational message indicating that the scheduler has resumed
|
|
1094
|
+
self.__logger.info(f"Orionis Scheduler resumed successfully at {now}.")
|
|
1095
|
+
|
|
1096
|
+
except Exception as e:
|
|
1097
|
+
|
|
1098
|
+
# Log a warning if pausing a job fails, but continue with others
|
|
1099
|
+
self.__logger.warning(f"Failed to pause job '{job.id}': {str(e)}")
|
|
1100
|
+
|
|
1101
|
+
# Log that all user jobs have been paused
|
|
1102
|
+
self.__logger.info("All user jobs have been paused. System jobs remain active.")
|
|
1057
1103
|
|
|
1058
1104
|
try:
|
|
1105
|
+
|
|
1059
1106
|
# Remove any existing pause job to avoid conflicts
|
|
1060
1107
|
try:
|
|
1061
1108
|
self.__scheduler.remove_job("scheduler_pause_at")
|
|
1109
|
+
|
|
1110
|
+
# If the job doesn't exist, it's fine to proceed
|
|
1062
1111
|
except:
|
|
1063
|
-
pass
|
|
1112
|
+
pass
|
|
1064
1113
|
|
|
1065
1114
|
# Add a job to the scheduler to pause it at the specified datetime
|
|
1066
1115
|
self.__scheduler.add_job(
|
|
1067
|
-
func=schedule_pause,
|
|
1116
|
+
func=self.wrapAsyncFunction(schedule_pause), # Function to pause the scheduler
|
|
1068
1117
|
trigger=DateTrigger(run_date=at), # Trigger type is 'date' for one-time execution
|
|
1069
1118
|
id="scheduler_pause_at", # Unique job ID for pausing the scheduler
|
|
1070
1119
|
name="Pause Scheduler", # Descriptive name for the job
|
|
@@ -1114,22 +1163,57 @@ class Scheduler(ISchedule):
|
|
|
1114
1163
|
if not isinstance(at, datetime):
|
|
1115
1164
|
raise ValueError("The 'at' parameter must be a datetime object.")
|
|
1116
1165
|
|
|
1117
|
-
# Define
|
|
1118
|
-
def schedule_resume():
|
|
1166
|
+
# Define an async function to resume the scheduler
|
|
1167
|
+
async def schedule_resume():
|
|
1168
|
+
|
|
1169
|
+
# Only resume jobs if the scheduler is currently running
|
|
1119
1170
|
if self.isRunning():
|
|
1120
|
-
|
|
1171
|
+
|
|
1172
|
+
# Resume only jobs that were paused by pauseEverythingAt
|
|
1173
|
+
if self.__paused_by_pause_everything:
|
|
1174
|
+
|
|
1175
|
+
# Iterate through the set of paused job IDs and resume each one
|
|
1176
|
+
for job_id in list(self.__paused_by_pause_everything):
|
|
1177
|
+
|
|
1178
|
+
try:
|
|
1179
|
+
|
|
1180
|
+
# Resume the job and log the action
|
|
1181
|
+
self.__scheduler.resume_job(job_id)
|
|
1182
|
+
self.__logger.info(f"User job '{job_id}' has been resumed.")
|
|
1183
|
+
|
|
1184
|
+
# Execute the task callable listener
|
|
1185
|
+
self.__globalCallableListener(SchedulerResumed(EVENT_SCHEDULER_RESUMED), ListeningEvent.SCHEDULER_RESUMED)
|
|
1186
|
+
|
|
1187
|
+
# Get the current time in the configured timezone
|
|
1188
|
+
now = self.__getCurrentTime()
|
|
1189
|
+
|
|
1190
|
+
# Log an informational message indicating that the scheduler has been paused
|
|
1191
|
+
self.__logger.info(f"Orionis Scheduler paused successfully at {now}.")
|
|
1192
|
+
|
|
1193
|
+
except Exception as e:
|
|
1194
|
+
|
|
1195
|
+
# Log a warning if resuming a job fails, but continue with others
|
|
1196
|
+
self.__logger.warning(f"Failed to resume job '{job_id}': {str(e)}")
|
|
1197
|
+
|
|
1198
|
+
# Clear the set after resuming all jobs
|
|
1199
|
+
self.__paused_by_pause_everything.clear()
|
|
1200
|
+
|
|
1201
|
+
# Log that all previously paused jobs have been resumed
|
|
1202
|
+
self.__logger.info("All previously paused user jobs have been resumed.")
|
|
1121
1203
|
|
|
1122
1204
|
try:
|
|
1123
1205
|
|
|
1124
1206
|
# Remove any existing resume job to avoid conflicts
|
|
1125
1207
|
try:
|
|
1126
1208
|
self.__scheduler.remove_job("scheduler_resume_at")
|
|
1209
|
+
|
|
1210
|
+
# If the job doesn't exist, it's fine to proceed
|
|
1127
1211
|
except:
|
|
1128
|
-
pass
|
|
1212
|
+
pass
|
|
1129
1213
|
|
|
1130
1214
|
# Add a job to the scheduler to resume it at the specified datetime
|
|
1131
1215
|
self.__scheduler.add_job(
|
|
1132
|
-
func=schedule_resume,
|
|
1216
|
+
func=self.wrapAsyncFunction(schedule_resume), # Function to resume the scheduler
|
|
1133
1217
|
trigger=DateTrigger(run_date=at), # Trigger type is 'date' for one-time execution
|
|
1134
1218
|
id="scheduler_resume_at", # Unique job ID for resuming the scheduler
|
|
1135
1219
|
name="Resume Scheduler", # Descriptive name for the job
|
|
@@ -1190,8 +1274,13 @@ class Scheduler(ISchedule):
|
|
|
1190
1274
|
|
|
1191
1275
|
# Define a function to shut down the scheduler
|
|
1192
1276
|
def schedule_shutdown():
|
|
1277
|
+
|
|
1278
|
+
# Only shut down the scheduler if it is currently running
|
|
1193
1279
|
if self.isRunning():
|
|
1280
|
+
|
|
1281
|
+
# Execute the shutdown process
|
|
1194
1282
|
self.__scheduler.shutdown(wait=wait)
|
|
1283
|
+
|
|
1195
1284
|
# Signal the stop event to break the wait in start()
|
|
1196
1285
|
if self._stop_event and not self._stop_event.is_set():
|
|
1197
1286
|
self._stop_event.set()
|
|
@@ -1201,12 +1290,14 @@ class Scheduler(ISchedule):
|
|
|
1201
1290
|
# Remove any existing shutdown job to avoid conflicts
|
|
1202
1291
|
try:
|
|
1203
1292
|
self.__scheduler.remove_job("scheduler_shutdown_at")
|
|
1293
|
+
|
|
1294
|
+
# If the job doesn't exist, it's fine to proceed
|
|
1204
1295
|
except:
|
|
1205
|
-
pass
|
|
1296
|
+
pass
|
|
1206
1297
|
|
|
1207
1298
|
# Add a job to the scheduler to shut it down at the specified datetime
|
|
1208
1299
|
self.__scheduler.add_job(
|
|
1209
|
-
func=schedule_shutdown,
|
|
1300
|
+
func=schedule_shutdown, # Function to shut down the scheduler
|
|
1210
1301
|
trigger=DateTrigger(run_date=at), # Trigger type is 'date' for one-time execution
|
|
1211
1302
|
id="scheduler_shutdown_at", # Unique job ID for shutting down the scheduler
|
|
1212
1303
|
name="Shutdown Scheduler", # Descriptive name for the job
|
|
@@ -1260,7 +1351,7 @@ class Scheduler(ISchedule):
|
|
|
1260
1351
|
self.__scheduler.start()
|
|
1261
1352
|
|
|
1262
1353
|
# Log that the scheduler is now active and waiting for events
|
|
1263
|
-
self.__logger.info("Scheduler is now active and waiting for events...")
|
|
1354
|
+
self.__logger.info("Orionis Scheduler is now active and waiting for events...")
|
|
1264
1355
|
|
|
1265
1356
|
try:
|
|
1266
1357
|
# Wait for the stop event to be set, which signals a shutdown
|
|
@@ -1565,8 +1656,18 @@ class Scheduler(ISchedule):
|
|
|
1565
1656
|
False if no pause job was found or an error occurred during the cancellation process.
|
|
1566
1657
|
"""
|
|
1567
1658
|
try:
|
|
1659
|
+
|
|
1660
|
+
# Remove any listener associated with the pause event
|
|
1661
|
+
listener = ListeningEvent.SCHEDULER_PAUSED.value
|
|
1662
|
+
if listener in self.__listeners:
|
|
1663
|
+
del self.__listeners[listener]
|
|
1664
|
+
|
|
1568
1665
|
# Attempt to remove the pause job with the specific ID
|
|
1569
|
-
|
|
1666
|
+
# if it exists
|
|
1667
|
+
try:
|
|
1668
|
+
self.__scheduler.remove_job("scheduler_pause_at")
|
|
1669
|
+
finally:
|
|
1670
|
+
pass
|
|
1570
1671
|
|
|
1571
1672
|
# Log the successful cancellation of the pause operation
|
|
1572
1673
|
self.__logger.info("Scheduled pause operation cancelled.")
|
|
@@ -1593,8 +1694,18 @@ class Scheduler(ISchedule):
|
|
|
1593
1694
|
False if no resume job was found or an error occurred during the cancellation process.
|
|
1594
1695
|
"""
|
|
1595
1696
|
try:
|
|
1697
|
+
|
|
1698
|
+
# Remove any listener associated with the resume event
|
|
1699
|
+
listener = ListeningEvent.SCHEDULER_RESUMED.value
|
|
1700
|
+
if listener in self.__listeners:
|
|
1701
|
+
del self.__listeners[listener]
|
|
1702
|
+
|
|
1596
1703
|
# Attempt to remove the resume job with the specific ID
|
|
1597
|
-
|
|
1704
|
+
# if it exists
|
|
1705
|
+
try:
|
|
1706
|
+
self.__scheduler.remove_job("scheduler_resume_at")
|
|
1707
|
+
finally:
|
|
1708
|
+
pass
|
|
1598
1709
|
|
|
1599
1710
|
# Log the successful cancellation of the resume operation
|
|
1600
1711
|
self.__logger.info("Scheduled resume operation cancelled.")
|
|
@@ -1622,8 +1733,18 @@ class Scheduler(ISchedule):
|
|
|
1622
1733
|
False if no shutdown job was found or an error occurred during the cancellation process.
|
|
1623
1734
|
"""
|
|
1624
1735
|
try:
|
|
1736
|
+
|
|
1737
|
+
# Remove any listener associated with the shutdown event
|
|
1738
|
+
listener = ListeningEvent.SCHEDULER_SHUTDOWN.value
|
|
1739
|
+
if listener in self.__listeners:
|
|
1740
|
+
del self.__listeners[listener]
|
|
1741
|
+
|
|
1625
1742
|
# Attempt to remove the shutdown job with the specific ID
|
|
1626
|
-
|
|
1743
|
+
# if it exists
|
|
1744
|
+
try:
|
|
1745
|
+
self.__scheduler.remove_job("scheduler_shutdown_at")
|
|
1746
|
+
finally:
|
|
1747
|
+
pass
|
|
1627
1748
|
|
|
1628
1749
|
# Log the successful cancellation of the shutdown operation
|
|
1629
1750
|
self.__logger.info("Scheduled shutdown operation cancelled.")
|
|
@@ -1653,27 +1774,6 @@ class Scheduler(ISchedule):
|
|
|
1653
1774
|
# Return the running state of the scheduler
|
|
1654
1775
|
return self.__scheduler.running
|
|
1655
1776
|
|
|
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
1777
|
def forceStop(self) -> None:
|
|
1678
1778
|
"""
|
|
1679
1779
|
Forcefully stop the scheduler immediately without waiting for jobs to complete.
|
|
@@ -1718,6 +1818,7 @@ class Scheduler(ISchedule):
|
|
|
1718
1818
|
|
|
1719
1819
|
# Check if the stop event exists and has not already been set
|
|
1720
1820
|
if self._stop_event and not self._stop_event.is_set():
|
|
1821
|
+
|
|
1721
1822
|
# Get the current asyncio event loop
|
|
1722
1823
|
loop = asyncio.get_event_loop()
|
|
1723
1824
|
|
|
@@ -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
|
|
orionis/metadata/framework.py
CHANGED
|
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()
|
|
@@ -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=
|
|
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=
|
|
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=
|
|
84
|
+
orionis/console/tasks/schedule.py,sha256=gaH9YSoYDQOTTktEaFyk5OIFUQz-jtkpzQJfKHs6hf4,77213
|
|
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=
|
|
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=
|
|
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=
|
|
242
|
+
orionis/metadata/framework.py,sha256=TVYmpZeUzyz9k7416c1ZPMT-vPrPgTbht4x1iJwTmu4,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.
|
|
420
|
+
orionis-0.524.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.
|
|
565
|
-
orionis-0.
|
|
566
|
-
orionis-0.
|
|
567
|
-
orionis-0.
|
|
568
|
-
orionis-0.
|
|
566
|
+
orionis-0.524.0.dist-info/METADATA,sha256=YIVkp5NLpvcgxHQzPTGxREf3MOnCRs65C-f4QkJPAuI,4801
|
|
567
|
+
orionis-0.524.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
568
|
+
orionis-0.524.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
|
|
569
|
+
orionis-0.524.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
570
|
+
orionis-0.524.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|