orionis 0.521.0__py3-none-any.whl → 0.522.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 +165 -0
- orionis/console/commands/scheduler_work.py +11 -11
- orionis/console/tasks/schedule.py +320 -63
- orionis/metadata/framework.py +1 -1
- {orionis-0.521.0.dist-info → orionis-0.522.0.dist-info}/METADATA +1 -1
- {orionis-0.521.0.dist-info → orionis-0.522.0.dist-info}/RECORD +10 -10
- {orionis-0.521.0.dist-info → orionis-0.522.0.dist-info}/WHEEL +0 -0
- {orionis-0.521.0.dist-info → orionis-0.522.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.521.0.dist-info → orionis-0.522.0.dist-info}/top_level.txt +0 -0
- {orionis-0.521.0.dist-info → orionis-0.522.0.dist-info}/zip-safe +0 -0
|
@@ -18,6 +18,171 @@ 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
|
+
|
|
21
186
|
async def tasks(self, schedule: ISchedule):
|
|
22
187
|
"""
|
|
23
188
|
Defines and registers scheduled tasks for the application.
|
|
@@ -110,21 +110,21 @@ 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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
schedule_service.pauseEverythingAt(scheduler.PAUSE_AT)
|
|
113
|
+
if hasattr(scheduler, "FINALIZE_AT") and scheduler.FINALIZE_AT is not None:
|
|
114
|
+
if not isinstance(scheduler.FINALIZE_AT, datetime):
|
|
115
|
+
raise CLIOrionisRuntimeError("FINALIZE_AT must be a datetime instance.")
|
|
116
|
+
schedule_service.shutdownEverythingAt(scheduler.finalizeAt())
|
|
118
117
|
|
|
119
118
|
if hasattr(scheduler, "RESUME_AT") and scheduler.RESUME_AT is not None:
|
|
120
119
|
if not isinstance(scheduler.RESUME_AT, datetime):
|
|
121
120
|
raise CLIOrionisRuntimeError("RESUME_AT must be a datetime instance.")
|
|
122
|
-
schedule_service.resumeEverythingAt(scheduler.
|
|
121
|
+
schedule_service.resumeEverythingAt(scheduler.resumeAt())
|
|
123
122
|
|
|
124
|
-
if
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
123
|
+
# Check if the scheduler has specific pause, resume, and finalize times
|
|
124
|
+
if hasattr(scheduler, "PAUSE_AT") and scheduler.PAUSE_AT is not None:
|
|
125
|
+
if not isinstance(scheduler.PAUSE_AT, datetime):
|
|
126
|
+
raise CLIOrionisRuntimeError("PAUSE_AT must be a datetime instance.")
|
|
127
|
+
schedule_service.pauseEverythingAt(scheduler.pauseAt())
|
|
128
128
|
|
|
129
129
|
# Start the scheduler worker asynchronously
|
|
130
130
|
await schedule_service.start()
|
|
@@ -137,4 +137,4 @@ class ScheduleWorkCommand(BaseCommand):
|
|
|
137
137
|
# Raise any unexpected exceptions as CLIOrionisRuntimeError
|
|
138
138
|
raise CLIOrionisRuntimeError(
|
|
139
139
|
f"An unexpected error occurred while starting the scheduler worker: {e}"
|
|
140
|
-
)
|
|
140
|
+
)
|
|
@@ -50,7 +50,6 @@ class Scheduler(ISchedule):
|
|
|
50
50
|
self,
|
|
51
51
|
reactor: IReactor,
|
|
52
52
|
app: IApplication,
|
|
53
|
-
console: IConsole,
|
|
54
53
|
rich_console: Console
|
|
55
54
|
) -> None:
|
|
56
55
|
"""
|
|
@@ -74,10 +73,7 @@ class Scheduler(ISchedule):
|
|
|
74
73
|
"""
|
|
75
74
|
|
|
76
75
|
# Store the application instance for configuration access.
|
|
77
|
-
self.__app = app
|
|
78
|
-
|
|
79
|
-
# Store the console instance for output operations.
|
|
80
|
-
self.__console = console
|
|
76
|
+
self.__app: IApplication = app
|
|
81
77
|
|
|
82
78
|
# Store the rich console instance for advanced output formatting.
|
|
83
79
|
self.__rich_console = rich_console
|
|
@@ -99,7 +95,7 @@ class Scheduler(ISchedule):
|
|
|
99
95
|
self.__logger: ILogger = self.__app.make('x-orionis.services.log.log_service')
|
|
100
96
|
|
|
101
97
|
# Store the reactor instance for command management.
|
|
102
|
-
self.__reactor = reactor
|
|
98
|
+
self.__reactor: IReactor = reactor
|
|
103
99
|
|
|
104
100
|
# Retrieve and store all available commands from the reactor.
|
|
105
101
|
self.__available_commands = self.__getCommands()
|
|
@@ -116,7 +112,6 @@ class Scheduler(ISchedule):
|
|
|
116
112
|
# Add this line to the existing __init__ method
|
|
117
113
|
self._stop_event: Optional[asyncio.Event] = None
|
|
118
114
|
|
|
119
|
-
|
|
120
115
|
def __getCurrentTime(
|
|
121
116
|
self
|
|
122
117
|
) -> str:
|
|
@@ -267,7 +262,7 @@ class Scheduler(ISchedule):
|
|
|
267
262
|
"""
|
|
268
263
|
|
|
269
264
|
# Prevent adding new commands while the scheduler is running
|
|
270
|
-
if self.
|
|
265
|
+
if self.isRunning():
|
|
271
266
|
raise CLIOrionisRuntimeError("Cannot add new commands while the scheduler is running.")
|
|
272
267
|
|
|
273
268
|
# Validate that the command signature is a non-empty string
|
|
@@ -282,8 +277,10 @@ class Scheduler(ISchedule):
|
|
|
282
277
|
if not self.__isAvailable(signature):
|
|
283
278
|
raise CLIOrionisValueError(f"The command '{signature}' is not available or does not exist.")
|
|
284
279
|
|
|
285
|
-
#
|
|
280
|
+
# Import Event here to avoid circular dependency issues
|
|
286
281
|
from orionis.console.tasks.event import Event
|
|
282
|
+
|
|
283
|
+
# Store the command and its arguments for scheduling
|
|
287
284
|
self.__events[signature] = Event(
|
|
288
285
|
signature=signature,
|
|
289
286
|
args=args or [],
|
|
@@ -367,6 +364,8 @@ class Scheduler(ISchedule):
|
|
|
367
364
|
|
|
368
365
|
# Check if a listener is registered for the specified event
|
|
369
366
|
if scheduler_event in self.__listeners:
|
|
367
|
+
|
|
368
|
+
# Retrieve the listener for the specified event
|
|
370
369
|
listener = self.__listeners[scheduler_event]
|
|
371
370
|
|
|
372
371
|
# Ensure the listener is callable before invoking it
|
|
@@ -376,21 +375,29 @@ class Scheduler(ISchedule):
|
|
|
376
375
|
|
|
377
376
|
# If the listener is a coroutine, schedule it as an asyncio task
|
|
378
377
|
if asyncio.iscoroutinefunction(listener):
|
|
378
|
+
|
|
379
|
+
# Try to get the running event loop
|
|
379
380
|
try:
|
|
380
|
-
# Try to get the running event loop
|
|
381
381
|
loop = asyncio.get_running_loop()
|
|
382
382
|
loop.create_task(listener(event_data, self))
|
|
383
|
+
|
|
384
|
+
# If no event loop is running, log a warning instead of creating one
|
|
383
385
|
except RuntimeError:
|
|
384
|
-
|
|
385
|
-
|
|
386
|
+
|
|
387
|
+
# 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
|
+
)
|
|
391
|
+
|
|
386
392
|
# Otherwise, invoke the listener directly as a regular function
|
|
387
393
|
else:
|
|
388
394
|
listener(event_data, self)
|
|
389
395
|
|
|
390
396
|
except Exception as e:
|
|
391
397
|
|
|
392
|
-
#
|
|
393
|
-
|
|
398
|
+
# Re-raise CLIOrionisRuntimeError exceptions
|
|
399
|
+
if isinstance(e, CLIOrionisRuntimeError):
|
|
400
|
+
raise e
|
|
394
401
|
|
|
395
402
|
# Raise a runtime error if listener invocation fails
|
|
396
403
|
raise CLIOrionisRuntimeError(
|
|
@@ -453,19 +460,43 @@ class Scheduler(ISchedule):
|
|
|
453
460
|
|
|
454
461
|
# Check if the listener has a method corresponding to the event type
|
|
455
462
|
if hasattr(listener, scheduler_event) and callable(getattr(listener, scheduler_event)):
|
|
463
|
+
|
|
464
|
+
# Retrieve the method from the listener
|
|
456
465
|
listener_method = getattr(listener, scheduler_event)
|
|
457
466
|
|
|
467
|
+
# Try to invoke the listener method
|
|
458
468
|
try:
|
|
469
|
+
|
|
459
470
|
# Invoke the listener method, handling both coroutine and regular functions
|
|
460
471
|
if asyncio.iscoroutinefunction(listener_method):
|
|
461
|
-
|
|
462
|
-
|
|
472
|
+
|
|
473
|
+
# Try to get the running event loop
|
|
474
|
+
try:
|
|
475
|
+
loop = asyncio.get_running_loop()
|
|
476
|
+
loop.create_task(listener_method(event_data, self))
|
|
477
|
+
|
|
478
|
+
# If no event loop is running, log a warning
|
|
479
|
+
except RuntimeError:
|
|
480
|
+
|
|
481
|
+
# 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
|
+
)
|
|
485
|
+
|
|
486
|
+
# Call the regular listener method directly
|
|
463
487
|
else:
|
|
464
|
-
# Call the regular listener method directly
|
|
465
488
|
listener_method(event_data, self)
|
|
489
|
+
|
|
466
490
|
except Exception as e:
|
|
467
|
-
|
|
468
|
-
|
|
491
|
+
|
|
492
|
+
# Re-raise CLIOrionisRuntimeError exceptions
|
|
493
|
+
if isinstance(e, CLIOrionisRuntimeError):
|
|
494
|
+
raise e
|
|
495
|
+
|
|
496
|
+
# 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
|
+
)
|
|
469
500
|
|
|
470
501
|
def __startedListener(
|
|
471
502
|
self,
|
|
@@ -903,27 +934,36 @@ class Scheduler(ISchedule):
|
|
|
903
934
|
# Iterate through all scheduled jobs in the AsyncIOScheduler
|
|
904
935
|
for signature, event in self.__events.items():
|
|
905
936
|
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
937
|
+
try:
|
|
938
|
+
# Convert the event to its entity representation
|
|
939
|
+
entity = event.toEntity()
|
|
940
|
+
|
|
941
|
+
# Add the job to the internal jobs list
|
|
942
|
+
self.__jobs.append(entity)
|
|
943
|
+
|
|
944
|
+
# Create a unique key for the job based on its signature
|
|
945
|
+
def create_job_func(cmd, args_list):
|
|
946
|
+
return lambda: self.__reactor.call(cmd, args_list)
|
|
947
|
+
|
|
948
|
+
# Add the job to the scheduler with the specified trigger and parameters
|
|
949
|
+
self.__scheduler.add_job(
|
|
950
|
+
func=create_job_func(signature, list(entity.args)),
|
|
951
|
+
trigger=entity.trigger,
|
|
952
|
+
id=signature,
|
|
953
|
+
name=signature,
|
|
954
|
+
replace_existing=True
|
|
955
|
+
)
|
|
911
956
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
957
|
+
# If a listener is associated with the event, register it
|
|
958
|
+
if entity.listener:
|
|
959
|
+
self.setListener(signature, entity.listener)
|
|
915
960
|
|
|
916
|
-
|
|
917
|
-
func=create_job_func(signature, list(entity.args)),
|
|
918
|
-
trigger=entity.trigger,
|
|
919
|
-
id=signature,
|
|
920
|
-
name=signature,
|
|
921
|
-
replace_existing=True
|
|
922
|
-
)
|
|
961
|
+
except Exception as e:
|
|
923
962
|
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
963
|
+
# 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
|
|
927
967
|
|
|
928
968
|
def setListener(
|
|
929
969
|
self,
|
|
@@ -1001,7 +1041,7 @@ class Scheduler(ISchedule):
|
|
|
1001
1041
|
Raises
|
|
1002
1042
|
------
|
|
1003
1043
|
ValueError
|
|
1004
|
-
If the 'at' parameter is not a valid datetime object.
|
|
1044
|
+
If the 'at' parameter is not a valid datetime object or is not in the future.
|
|
1005
1045
|
CLIOrionisRuntimeError
|
|
1006
1046
|
If the scheduler is not running or if an error occurs during job scheduling.
|
|
1007
1047
|
"""
|
|
@@ -1010,27 +1050,32 @@ class Scheduler(ISchedule):
|
|
|
1010
1050
|
if not isinstance(at, datetime):
|
|
1011
1051
|
raise ValueError("The 'at' parameter must be a datetime object.")
|
|
1012
1052
|
|
|
1013
|
-
#
|
|
1014
|
-
|
|
1015
|
-
|
|
1053
|
+
# Define a function to pause the scheduler
|
|
1054
|
+
def schedule_pause():
|
|
1055
|
+
if self.isRunning():
|
|
1056
|
+
self.__scheduler.pause()
|
|
1016
1057
|
|
|
1017
1058
|
try:
|
|
1018
1059
|
# Remove any existing pause job to avoid conflicts
|
|
1019
1060
|
try:
|
|
1020
|
-
self.__scheduler.remove_job(
|
|
1061
|
+
self.__scheduler.remove_job("scheduler_pause_at")
|
|
1021
1062
|
except:
|
|
1022
1063
|
pass # If the job doesn't exist, it's fine to proceed
|
|
1023
1064
|
|
|
1024
1065
|
# Add a job to the scheduler to pause it at the specified datetime
|
|
1025
1066
|
self.__scheduler.add_job(
|
|
1026
|
-
func=
|
|
1067
|
+
func=schedule_pause, # Function to pause the scheduler
|
|
1027
1068
|
trigger=DateTrigger(run_date=at), # Trigger type is 'date' for one-time execution
|
|
1028
|
-
id=
|
|
1069
|
+
id="scheduler_pause_at", # Unique job ID for pausing the scheduler
|
|
1029
1070
|
name="Pause Scheduler", # Descriptive name for the job
|
|
1030
1071
|
replace_existing=True # Replace any existing job with the same ID
|
|
1031
1072
|
)
|
|
1032
1073
|
|
|
1074
|
+
# Log the scheduled pause
|
|
1075
|
+
self.__logger.info(f"Scheduler pause scheduled for {at.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
1076
|
+
|
|
1033
1077
|
except Exception as e:
|
|
1078
|
+
|
|
1034
1079
|
# Handle exceptions that may occur during job scheduling
|
|
1035
1080
|
raise CLIOrionisRuntimeError(f"Failed to schedule scheduler pause: {str(e)}") from e
|
|
1036
1081
|
|
|
@@ -1060,7 +1105,7 @@ class Scheduler(ISchedule):
|
|
|
1060
1105
|
Raises
|
|
1061
1106
|
------
|
|
1062
1107
|
ValueError
|
|
1063
|
-
If the 'at' parameter is not a valid datetime object.
|
|
1108
|
+
If the 'at' parameter is not a valid datetime object or is not in the future.
|
|
1064
1109
|
CLIOrionisRuntimeError
|
|
1065
1110
|
If the scheduler is not running or if an error occurs during job scheduling.
|
|
1066
1111
|
"""
|
|
@@ -1069,33 +1114,40 @@ class Scheduler(ISchedule):
|
|
|
1069
1114
|
if not isinstance(at, datetime):
|
|
1070
1115
|
raise ValueError("The 'at' parameter must be a datetime object.")
|
|
1071
1116
|
|
|
1072
|
-
#
|
|
1073
|
-
|
|
1074
|
-
|
|
1117
|
+
# Define a function to resume the scheduler
|
|
1118
|
+
def schedule_resume():
|
|
1119
|
+
if self.isRunning():
|
|
1120
|
+
self.__scheduler.resume()
|
|
1075
1121
|
|
|
1076
1122
|
try:
|
|
1123
|
+
|
|
1077
1124
|
# Remove any existing resume job to avoid conflicts
|
|
1078
1125
|
try:
|
|
1079
|
-
self.__scheduler.remove_job(
|
|
1126
|
+
self.__scheduler.remove_job("scheduler_resume_at")
|
|
1080
1127
|
except:
|
|
1081
1128
|
pass # If the job doesn't exist, it's fine to proceed
|
|
1082
1129
|
|
|
1083
1130
|
# Add a job to the scheduler to resume it at the specified datetime
|
|
1084
1131
|
self.__scheduler.add_job(
|
|
1085
|
-
func=
|
|
1132
|
+
func=schedule_resume, # Function to resume the scheduler
|
|
1086
1133
|
trigger=DateTrigger(run_date=at), # Trigger type is 'date' for one-time execution
|
|
1087
|
-
id=
|
|
1134
|
+
id="scheduler_resume_at", # Unique job ID for resuming the scheduler
|
|
1088
1135
|
name="Resume Scheduler", # Descriptive name for the job
|
|
1089
1136
|
replace_existing=True # Replace any existing job with the same ID
|
|
1090
1137
|
)
|
|
1091
1138
|
|
|
1139
|
+
# Log the scheduled resume
|
|
1140
|
+
self.__logger.info(f"Scheduler resume scheduled for {at.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
1141
|
+
|
|
1092
1142
|
except Exception as e:
|
|
1143
|
+
|
|
1093
1144
|
# Handle exceptions that may occur during job scheduling
|
|
1094
1145
|
raise CLIOrionisRuntimeError(f"Failed to schedule scheduler resume: {str(e)}") from e
|
|
1095
1146
|
|
|
1096
1147
|
def shutdownEverythingAt(
|
|
1097
1148
|
self,
|
|
1098
|
-
at: datetime
|
|
1149
|
+
at: datetime,
|
|
1150
|
+
wait: bool = True
|
|
1099
1151
|
) -> None:
|
|
1100
1152
|
"""
|
|
1101
1153
|
Schedule the scheduler to shut down all operations at a specific datetime.
|
|
@@ -1109,6 +1161,9 @@ class Scheduler(ISchedule):
|
|
|
1109
1161
|
at : datetime
|
|
1110
1162
|
The datetime at which the scheduler should be shut down. Must be a valid
|
|
1111
1163
|
datetime object.
|
|
1164
|
+
wait : bool, optional
|
|
1165
|
+
Whether to wait for currently running jobs to complete before shutdown.
|
|
1166
|
+
Default is True.
|
|
1112
1167
|
|
|
1113
1168
|
Returns
|
|
1114
1169
|
-------
|
|
@@ -1119,7 +1174,8 @@ class Scheduler(ISchedule):
|
|
|
1119
1174
|
Raises
|
|
1120
1175
|
------
|
|
1121
1176
|
ValueError
|
|
1122
|
-
If the 'at' parameter is not a valid datetime object
|
|
1177
|
+
If the 'at' parameter is not a valid datetime object or 'wait' is not boolean,
|
|
1178
|
+
or if the scheduled time is not in the future.
|
|
1123
1179
|
CLIOrionisRuntimeError
|
|
1124
1180
|
If the scheduler is not running or if an error occurs during job scheduling.
|
|
1125
1181
|
"""
|
|
@@ -1128,27 +1184,40 @@ class Scheduler(ISchedule):
|
|
|
1128
1184
|
if not isinstance(at, datetime):
|
|
1129
1185
|
raise ValueError("The 'at' parameter must be a datetime object.")
|
|
1130
1186
|
|
|
1131
|
-
#
|
|
1132
|
-
if not
|
|
1133
|
-
raise
|
|
1187
|
+
# Validate that the 'wait' parameter is a boolean
|
|
1188
|
+
if not isinstance(wait, bool):
|
|
1189
|
+
raise ValueError("The 'wait' parameter must be a boolean value.")
|
|
1190
|
+
|
|
1191
|
+
# Define a function to shut down the scheduler
|
|
1192
|
+
def schedule_shutdown():
|
|
1193
|
+
if self.isRunning():
|
|
1194
|
+
self.__scheduler.shutdown(wait=wait)
|
|
1195
|
+
# Signal the stop event to break the wait in start()
|
|
1196
|
+
if self._stop_event and not self._stop_event.is_set():
|
|
1197
|
+
self._stop_event.set()
|
|
1134
1198
|
|
|
1135
1199
|
try:
|
|
1200
|
+
|
|
1136
1201
|
# Remove any existing shutdown job to avoid conflicts
|
|
1137
1202
|
try:
|
|
1138
|
-
self.__scheduler.remove_job(
|
|
1203
|
+
self.__scheduler.remove_job("scheduler_shutdown_at")
|
|
1139
1204
|
except:
|
|
1140
1205
|
pass # If the job doesn't exist, it's fine to proceed
|
|
1141
1206
|
|
|
1142
1207
|
# Add a job to the scheduler to shut it down at the specified datetime
|
|
1143
1208
|
self.__scheduler.add_job(
|
|
1144
|
-
func=
|
|
1209
|
+
func=schedule_shutdown, # Function to shut down the scheduler
|
|
1145
1210
|
trigger=DateTrigger(run_date=at), # Trigger type is 'date' for one-time execution
|
|
1146
|
-
id=
|
|
1211
|
+
id="scheduler_shutdown_at", # Unique job ID for shutting down the scheduler
|
|
1147
1212
|
name="Shutdown Scheduler", # Descriptive name for the job
|
|
1148
1213
|
replace_existing=True # Replace any existing job with the same ID
|
|
1149
1214
|
)
|
|
1150
1215
|
|
|
1216
|
+
# Log the scheduled shutdown
|
|
1217
|
+
self.__logger.info(f"Scheduler shutdown scheduled for {at.strftime('%Y-%m-%d %H:%M:%S')} (wait={wait})")
|
|
1218
|
+
|
|
1151
1219
|
except Exception as e:
|
|
1220
|
+
|
|
1152
1221
|
# Handle exceptions that may occur during job scheduling
|
|
1153
1222
|
raise CLIOrionisRuntimeError(f"Failed to schedule scheduler shutdown: {str(e)}") from e
|
|
1154
1223
|
|
|
@@ -1173,6 +1242,7 @@ class Scheduler(ISchedule):
|
|
|
1173
1242
|
If the scheduler fails to start due to missing an asyncio event loop or other runtime issues.
|
|
1174
1243
|
"""
|
|
1175
1244
|
try:
|
|
1245
|
+
|
|
1176
1246
|
# Ensure the method is called within an asyncio event loop
|
|
1177
1247
|
loop = asyncio.get_running_loop()
|
|
1178
1248
|
|
|
@@ -1186,7 +1256,7 @@ class Scheduler(ISchedule):
|
|
|
1186
1256
|
self.__subscribeListeners()
|
|
1187
1257
|
|
|
1188
1258
|
# Start the scheduler if it is not already running
|
|
1189
|
-
if not self.
|
|
1259
|
+
if not self.isRunning():
|
|
1190
1260
|
self.__scheduler.start()
|
|
1191
1261
|
|
|
1192
1262
|
# Log that the scheduler is now active and waiting for events
|
|
@@ -1198,27 +1268,32 @@ class Scheduler(ISchedule):
|
|
|
1198
1268
|
await self._stop_event.wait()
|
|
1199
1269
|
|
|
1200
1270
|
except (KeyboardInterrupt, asyncio.CancelledError):
|
|
1271
|
+
|
|
1201
1272
|
# Handle graceful shutdown when an interruption signal is received
|
|
1202
1273
|
self.__logger.info("Received shutdown signal, stopping scheduler...")
|
|
1203
1274
|
await self.shutdown(wait=True)
|
|
1204
1275
|
|
|
1205
1276
|
except Exception as e:
|
|
1277
|
+
|
|
1206
1278
|
# Log and raise any unexpected exceptions during scheduler operation
|
|
1207
1279
|
self.__logger.error(f"Error during scheduler operation: {str(e)}")
|
|
1208
1280
|
raise CLIOrionisRuntimeError(f"Scheduler operation failed: {str(e)}") from e
|
|
1209
1281
|
|
|
1210
1282
|
finally:
|
|
1283
|
+
|
|
1211
1284
|
# Ensure the scheduler is shut down properly, even if an error occurs
|
|
1212
1285
|
if self.__scheduler.running:
|
|
1213
1286
|
await self.shutdown(wait=False)
|
|
1214
1287
|
|
|
1215
1288
|
except RuntimeError as e:
|
|
1289
|
+
|
|
1216
1290
|
# Handle the case where no asyncio event loop is running
|
|
1217
1291
|
if "no running event loop" in str(e):
|
|
1218
1292
|
raise CLIOrionisRuntimeError("Scheduler must be started within an asyncio event loop") from e
|
|
1219
1293
|
raise CLIOrionisRuntimeError(f"Failed to start the scheduler: {str(e)}") from e
|
|
1220
1294
|
|
|
1221
1295
|
except Exception as e:
|
|
1296
|
+
|
|
1222
1297
|
# Raise a runtime error for any other issues during startup
|
|
1223
1298
|
raise CLIOrionisRuntimeError(f"Failed to start the scheduler: {str(e)}") from e
|
|
1224
1299
|
|
|
@@ -1251,10 +1326,11 @@ class Scheduler(ISchedule):
|
|
|
1251
1326
|
raise ValueError("The 'wait' parameter must be a boolean value.")
|
|
1252
1327
|
|
|
1253
1328
|
# If the scheduler is not running, there's nothing to shut down
|
|
1254
|
-
if not self.
|
|
1329
|
+
if not self.isRunning():
|
|
1255
1330
|
return
|
|
1256
1331
|
|
|
1257
1332
|
try:
|
|
1333
|
+
|
|
1258
1334
|
# Log the shutdown process
|
|
1259
1335
|
self.__logger.info(f"Shutting down scheduler (wait={wait})...")
|
|
1260
1336
|
|
|
@@ -1269,9 +1345,12 @@ class Scheduler(ISchedule):
|
|
|
1269
1345
|
if wait:
|
|
1270
1346
|
await asyncio.sleep(0.1)
|
|
1271
1347
|
|
|
1348
|
+
# Log the successful shutdown
|
|
1272
1349
|
self.__logger.info("Scheduler shutdown completed successfully.")
|
|
1273
1350
|
|
|
1274
1351
|
except Exception as e:
|
|
1352
|
+
|
|
1353
|
+
# Handle exceptions that may occur during shutdown
|
|
1275
1354
|
raise CLIOrionisRuntimeError(f"Failed to shut down the scheduler: {str(e)}") from e
|
|
1276
1355
|
|
|
1277
1356
|
def pause(self, signature: str) -> bool:
|
|
@@ -1403,7 +1482,7 @@ class Scheduler(ISchedule):
|
|
|
1403
1482
|
|
|
1404
1483
|
# Iterate through the internal jobs list to find and remove the job
|
|
1405
1484
|
for job in self.__jobs:
|
|
1406
|
-
if job
|
|
1485
|
+
if job.signature == signature:
|
|
1407
1486
|
self.__jobs.remove(job) # Remove the job from the internal list
|
|
1408
1487
|
break
|
|
1409
1488
|
|
|
@@ -1469,4 +1548,182 @@ class Scheduler(ISchedule):
|
|
|
1469
1548
|
})
|
|
1470
1549
|
|
|
1471
1550
|
# Return the list of scheduled job details
|
|
1472
|
-
return events
|
|
1551
|
+
return events
|
|
1552
|
+
|
|
1553
|
+
def cancelScheduledPause(self) -> bool:
|
|
1554
|
+
"""
|
|
1555
|
+
Cancel a previously scheduled pause operation.
|
|
1556
|
+
|
|
1557
|
+
This method attempts to remove a job from the scheduler that was set to pause
|
|
1558
|
+
the scheduler at a specific time. If the job exists, it is removed, and a log entry
|
|
1559
|
+
is created to indicate the cancellation. If no such job exists, the method returns False.
|
|
1560
|
+
|
|
1561
|
+
Returns
|
|
1562
|
+
-------
|
|
1563
|
+
bool
|
|
1564
|
+
True if the scheduled pause job was successfully cancelled.
|
|
1565
|
+
False if no pause job was found or an error occurred during the cancellation process.
|
|
1566
|
+
"""
|
|
1567
|
+
try:
|
|
1568
|
+
# Attempt to remove the pause job with the specific ID
|
|
1569
|
+
self.__scheduler.remove_job("scheduler_pause_at")
|
|
1570
|
+
|
|
1571
|
+
# Log the successful cancellation of the pause operation
|
|
1572
|
+
self.__logger.info("Scheduled pause operation cancelled.")
|
|
1573
|
+
|
|
1574
|
+
# Return True to indicate the pause job was successfully cancelled
|
|
1575
|
+
return True
|
|
1576
|
+
|
|
1577
|
+
except:
|
|
1578
|
+
# Return False if the pause job does not exist or an error occurred
|
|
1579
|
+
return False
|
|
1580
|
+
|
|
1581
|
+
def cancelScheduledResume(self) -> bool:
|
|
1582
|
+
"""
|
|
1583
|
+
Cancel a previously scheduled resume operation.
|
|
1584
|
+
|
|
1585
|
+
This method attempts to remove a job from the scheduler that was set to resume
|
|
1586
|
+
the scheduler at a specific time. If the job exists, it is removed, and a log entry
|
|
1587
|
+
is created to indicate the cancellation. If no such job exists, the method returns False.
|
|
1588
|
+
|
|
1589
|
+
Returns
|
|
1590
|
+
-------
|
|
1591
|
+
bool
|
|
1592
|
+
True if the scheduled resume job was successfully cancelled.
|
|
1593
|
+
False if no resume job was found or an error occurred during the cancellation process.
|
|
1594
|
+
"""
|
|
1595
|
+
try:
|
|
1596
|
+
# Attempt to remove the resume job with the specific ID
|
|
1597
|
+
self.__scheduler.remove_job("scheduler_resume_at")
|
|
1598
|
+
|
|
1599
|
+
# Log the successful cancellation of the resume operation
|
|
1600
|
+
self.__logger.info("Scheduled resume operation cancelled.")
|
|
1601
|
+
|
|
1602
|
+
# Return True to indicate the resume job was successfully cancelled
|
|
1603
|
+
return True
|
|
1604
|
+
|
|
1605
|
+
except:
|
|
1606
|
+
|
|
1607
|
+
# Return False if the resume job does not exist or an error occurred
|
|
1608
|
+
return False
|
|
1609
|
+
|
|
1610
|
+
def cancelScheduledShutdown(self) -> bool:
|
|
1611
|
+
"""
|
|
1612
|
+
Cancel a previously scheduled shutdown operation.
|
|
1613
|
+
|
|
1614
|
+
This method attempts to remove a job from the scheduler that was set to shut down
|
|
1615
|
+
the scheduler at a specific time. If the job exists, it is removed, and a log entry
|
|
1616
|
+
is created to indicate the cancellation. If no such job exists, the method returns False.
|
|
1617
|
+
|
|
1618
|
+
Returns
|
|
1619
|
+
-------
|
|
1620
|
+
bool
|
|
1621
|
+
True if the scheduled shutdown job was successfully cancelled.
|
|
1622
|
+
False if no shutdown job was found or an error occurred during the cancellation process.
|
|
1623
|
+
"""
|
|
1624
|
+
try:
|
|
1625
|
+
# Attempt to remove the shutdown job with the specific ID
|
|
1626
|
+
self.__scheduler.remove_job("scheduler_shutdown_at")
|
|
1627
|
+
|
|
1628
|
+
# Log the successful cancellation of the shutdown operation
|
|
1629
|
+
self.__logger.info("Scheduled shutdown operation cancelled.")
|
|
1630
|
+
|
|
1631
|
+
# Return True to indicate the shutdown job was successfully cancelled
|
|
1632
|
+
return True
|
|
1633
|
+
|
|
1634
|
+
except:
|
|
1635
|
+
|
|
1636
|
+
# Return False if the shutdown job does not exist or an error occurred
|
|
1637
|
+
return False
|
|
1638
|
+
|
|
1639
|
+
def isRunning(self) -> bool:
|
|
1640
|
+
"""
|
|
1641
|
+
Determine if the scheduler is currently active and running.
|
|
1642
|
+
|
|
1643
|
+
This method checks the internal state of the AsyncIOScheduler instance to determine
|
|
1644
|
+
whether it is currently running. The scheduler is considered running if it has been
|
|
1645
|
+
started and has not been paused or shut down.
|
|
1646
|
+
|
|
1647
|
+
Returns
|
|
1648
|
+
-------
|
|
1649
|
+
bool
|
|
1650
|
+
True if the scheduler is running, False otherwise.
|
|
1651
|
+
"""
|
|
1652
|
+
|
|
1653
|
+
# Return the running state of the scheduler
|
|
1654
|
+
return self.__scheduler.running
|
|
1655
|
+
|
|
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
|
+
def forceStop(self) -> None:
|
|
1678
|
+
"""
|
|
1679
|
+
Forcefully stop the scheduler immediately without waiting for jobs to complete.
|
|
1680
|
+
|
|
1681
|
+
This method shuts down the AsyncIOScheduler instance without waiting for currently
|
|
1682
|
+
running jobs to finish. It is intended for emergency situations where an immediate
|
|
1683
|
+
stop is required. The method also signals the internal stop event to ensure that
|
|
1684
|
+
the scheduler's main loop is interrupted and the application can proceed with
|
|
1685
|
+
shutdown procedures.
|
|
1686
|
+
|
|
1687
|
+
Returns
|
|
1688
|
+
-------
|
|
1689
|
+
None
|
|
1690
|
+
This method does not return any value. It forcefully stops the scheduler and
|
|
1691
|
+
signals the stop event.
|
|
1692
|
+
"""
|
|
1693
|
+
|
|
1694
|
+
# Check if the scheduler is currently running
|
|
1695
|
+
if self.__scheduler.running:
|
|
1696
|
+
# Shut down the scheduler immediately without waiting for jobs to complete
|
|
1697
|
+
self.__scheduler.shutdown(wait=False)
|
|
1698
|
+
|
|
1699
|
+
# Check if the stop event exists and has not already been set
|
|
1700
|
+
if self._stop_event and not self._stop_event.is_set():
|
|
1701
|
+
# Signal the stop event to interrupt the scheduler's main loop
|
|
1702
|
+
self._stop_event.set()
|
|
1703
|
+
|
|
1704
|
+
def stop(self) -> None:
|
|
1705
|
+
"""
|
|
1706
|
+
Stop the scheduler synchronously by setting the stop event.
|
|
1707
|
+
|
|
1708
|
+
This method signals the scheduler to stop by setting the internal stop event.
|
|
1709
|
+
It can be called from non-async contexts to initiate a shutdown. If the asyncio
|
|
1710
|
+
event loop is running, the stop event is set in a thread-safe manner. Otherwise,
|
|
1711
|
+
the stop event is set directly.
|
|
1712
|
+
|
|
1713
|
+
Returns
|
|
1714
|
+
-------
|
|
1715
|
+
None
|
|
1716
|
+
This method does not return any value. It signals the scheduler to stop.
|
|
1717
|
+
"""
|
|
1718
|
+
|
|
1719
|
+
# Check if the stop event exists and has not already been set
|
|
1720
|
+
if self._stop_event and not self._stop_event.is_set():
|
|
1721
|
+
# Get the current asyncio event loop
|
|
1722
|
+
loop = asyncio.get_event_loop()
|
|
1723
|
+
|
|
1724
|
+
# If the event loop is running, set the stop event in a thread-safe manner
|
|
1725
|
+
if loop.is_running():
|
|
1726
|
+
loop.call_soon_threadsafe(self._stop_event.set)
|
|
1727
|
+
else:
|
|
1728
|
+
# Otherwise, set the stop event directly
|
|
1729
|
+
self._stop_event.set()
|
orionis/metadata/framework.py
CHANGED
|
@@ -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=LFzWUFk07LrcpKFL7sS7exHzTkxFRd1DPDSqDSpRcOk,15157
|
|
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=FHBQ8Ajs1zacuQFXaG-KLVRy07m9FqwyJRNVmp7cDg0,6337
|
|
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=Lpm_P0Brw8XHiqA-Me9SMevNlo0CzUf-rrt2PKTFW_I,72389
|
|
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
|
|
@@ -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=LNUd5w9wDJVTDwfg_BIGNlRYyyCu3UpQnvpmOQsMlIQ,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
|
|
@@ -415,7 +415,7 @@ orionis/test/validators/web_report.py,sha256=n9BfzOZz6aEiNTypXcwuWbFRG0OdHNSmCNu
|
|
|
415
415
|
orionis/test/validators/workers.py,sha256=rWcdRexINNEmGaO7mnc1MKUxkHKxrTsVuHgbnIfJYgc,1206
|
|
416
416
|
orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
417
417
|
orionis/test/view/render.py,sha256=f-zNhtKSg9R5Njqujbg2l2amAs2-mRVESneLIkWOZjU,4082
|
|
418
|
-
orionis-0.
|
|
418
|
+
orionis-0.522.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
|
|
419
419
|
tests/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
420
420
|
tests/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
421
421
|
tests/container/context/test_manager.py,sha256=wOwXpl9rHNfTTexa9GBKYMwK0_-KSQPbI-AEyGNkmAE,1356
|
|
@@ -561,8 +561,8 @@ tests/testing/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
561
561
|
tests/testing/validators/test_testing_validators.py,sha256=WPo5GxTP6xE-Dw3X1vZoqOMpb6HhokjNSbgDsDRDvy4,16588
|
|
562
562
|
tests/testing/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
563
563
|
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.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|