orionis 0.522.0__py3-none-any.whl → 0.523.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- orionis/console/base/scheduler.py +0 -165
- orionis/console/commands/scheduler_work.py +6 -4
- orionis/console/tasks/schedule.py +222 -104
- 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.523.0.dist-info}/METADATA +1 -1
- {orionis-0.522.0.dist-info → orionis-0.523.0.dist-info}/RECORD +14 -12
- {orionis-0.522.0.dist-info → orionis-0.523.0.dist-info}/WHEEL +0 -0
- {orionis-0.522.0.dist-info → orionis-0.523.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.522.0.dist-info → orionis-0.523.0.dist-info}/top_level.txt +0 -0
- {orionis-0.522.0.dist-info → orionis-0.523.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()
|
|
@@ -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 async listener for '{scheduler_event}': no event loop running"
|
|
405
|
+
|
|
406
|
+
# Log the error message
|
|
407
|
+
self.__logger.error(error_msg)
|
|
408
|
+
|
|
387
409
|
# Raise an error to inform the caller that the listener could not be invoked
|
|
388
|
-
raise CLIOrionisRuntimeError(
|
|
389
|
-
f"Cannot run async listener for '{scheduler_event}': no event loop running"
|
|
390
|
-
)
|
|
410
|
+
raise CLIOrionisRuntimeError(error_msg)
|
|
391
411
|
|
|
392
412
|
# Otherwise, invoke the listener directly as a regular function
|
|
393
413
|
else:
|
|
414
|
+
|
|
415
|
+
# Call the regular listener function directly
|
|
394
416
|
listener(event_data, self)
|
|
395
417
|
|
|
396
418
|
except Exception as e:
|
|
@@ -399,10 +421,14 @@ class Scheduler(ISchedule):
|
|
|
399
421
|
if isinstance(e, CLIOrionisRuntimeError):
|
|
400
422
|
raise e
|
|
401
423
|
|
|
424
|
+
# Construct the error message
|
|
425
|
+
error_msg = f"An error occurred while invoking the listener for event '{scheduler_event}': {str(e)}"
|
|
426
|
+
|
|
427
|
+
# Log the error message
|
|
428
|
+
self.__logger.error(error_msg)
|
|
429
|
+
|
|
402
430
|
# Raise a runtime error if listener invocation fails
|
|
403
|
-
raise CLIOrionisRuntimeError(
|
|
404
|
-
f"An error occurred while invoking the listener for event '{scheduler_event}': {str(e)}"
|
|
405
|
-
)
|
|
431
|
+
raise CLIOrionisRuntimeError(error_msg)
|
|
406
432
|
|
|
407
433
|
def __taskCallableListener(
|
|
408
434
|
self,
|
|
@@ -472,19 +498,36 @@ class Scheduler(ISchedule):
|
|
|
472
498
|
|
|
473
499
|
# Try to get the running event loop
|
|
474
500
|
try:
|
|
475
|
-
|
|
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,6 +597,9 @@ class Scheduler(ISchedule):
|
|
|
553
597
|
# Check if a listener is registered for the scheduler started event
|
|
554
598
|
self.__globalCallableListener(event, ListeningEvent.SCHEDULER_STARTED)
|
|
555
599
|
|
|
600
|
+
# Log an informational message indicating that the scheduler has started
|
|
601
|
+
self.__logger.info(f"Orionis Scheduler started successfully at {now}.")
|
|
602
|
+
|
|
556
603
|
def __pausedListener(
|
|
557
604
|
self,
|
|
558
605
|
event: SchedulerPaused
|
|
@@ -581,15 +628,12 @@ class Scheduler(ISchedule):
|
|
|
581
628
|
# Get the current time in the configured timezone
|
|
582
629
|
now = self.__getCurrentTime()
|
|
583
630
|
|
|
584
|
-
# Create a paused message
|
|
585
|
-
message = f"Orionis Scheduler paused successfully at {now}."
|
|
586
|
-
|
|
587
|
-
# Log an informational message indicating that the scheduler has been paused
|
|
588
|
-
self.__logger.info(message)
|
|
589
|
-
|
|
590
631
|
# Check if a listener is registered for the scheduler paused event
|
|
591
632
|
self.__globalCallableListener(event, ListeningEvent.SCHEDULER_PAUSED)
|
|
592
633
|
|
|
634
|
+
# Log an informational message indicating that the scheduler has been paused
|
|
635
|
+
self.__logger.info(f"Orionis Scheduler paused successfully at {now}.")
|
|
636
|
+
|
|
593
637
|
def __resumedListener(
|
|
594
638
|
self,
|
|
595
639
|
event: SchedulerResumed
|
|
@@ -618,15 +662,12 @@ class Scheduler(ISchedule):
|
|
|
618
662
|
# Get the current time in the configured timezone
|
|
619
663
|
now = self.__getCurrentTime()
|
|
620
664
|
|
|
621
|
-
# Create a resumed message
|
|
622
|
-
message = f"Orionis Scheduler resumed successfully at {now}."
|
|
623
|
-
|
|
624
|
-
# Log an informational message indicating that the scheduler has resumed
|
|
625
|
-
self.__logger.info(message)
|
|
626
|
-
|
|
627
665
|
# Check if a listener is registered for the scheduler resumed event
|
|
628
666
|
self.__globalCallableListener(event, ListeningEvent.SCHEDULER_RESUMED)
|
|
629
667
|
|
|
668
|
+
# Log an informational message indicating that the scheduler has resumed
|
|
669
|
+
self.__logger.info(f"Orionis Scheduler resumed successfully at {now}.")
|
|
670
|
+
|
|
630
671
|
def __shutdownListener(
|
|
631
672
|
self,
|
|
632
673
|
event: SchedulerShutdown
|
|
@@ -655,15 +696,12 @@ class Scheduler(ISchedule):
|
|
|
655
696
|
# Get the current time in the configured timezone
|
|
656
697
|
now = self.__getCurrentTime()
|
|
657
698
|
|
|
658
|
-
# Create a shutdown message
|
|
659
|
-
message = f"Orionis Scheduler shut down successfully at {now}."
|
|
660
|
-
|
|
661
|
-
# Log an informational message indicating that the scheduler has shut down
|
|
662
|
-
self.__logger.info(message)
|
|
663
|
-
|
|
664
699
|
# Check if a listener is registered for the scheduler shutdown event
|
|
665
700
|
self.__globalCallableListener(event, ListeningEvent.SCHEDULER_SHUTDOWN)
|
|
666
701
|
|
|
702
|
+
# Log an informational message indicating that the scheduler has shut down
|
|
703
|
+
self.__logger.info(f"Orionis Scheduler shut down successfully at {now}.")
|
|
704
|
+
|
|
667
705
|
def __errorListener(
|
|
668
706
|
self,
|
|
669
707
|
event: JobError
|
|
@@ -689,11 +727,8 @@ class Scheduler(ISchedule):
|
|
|
689
727
|
and listener invocation for the job error event.
|
|
690
728
|
"""
|
|
691
729
|
|
|
692
|
-
# Create an error message
|
|
693
|
-
message = f"Task {event.job_id} raised an exception: {event.exception}"
|
|
694
|
-
|
|
695
730
|
# Log an error message indicating that the job raised an exception
|
|
696
|
-
self.__logger.error(
|
|
731
|
+
self.__logger.error(f"Task {event.job_id} raised an exception: {event.exception}")
|
|
697
732
|
|
|
698
733
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
699
734
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_FAILURE)
|
|
@@ -726,11 +761,8 @@ class Scheduler(ISchedule):
|
|
|
726
761
|
and listener invocation for the job submission event.
|
|
727
762
|
"""
|
|
728
763
|
|
|
729
|
-
# Create a submission message
|
|
730
|
-
message = f"Task {event.job_id} submitted to executor."
|
|
731
|
-
|
|
732
764
|
# Log an informational message indicating that the job has been submitted
|
|
733
|
-
self.__logger.info(
|
|
765
|
+
self.__logger.info(f"Task {event.job_id} submitted to executor.")
|
|
734
766
|
|
|
735
767
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
736
768
|
self.__taskCallableListener(event, ListeningEvent.JOB_BEFORE)
|
|
@@ -761,11 +793,8 @@ class Scheduler(ISchedule):
|
|
|
761
793
|
and listener invocation for the job execution event.
|
|
762
794
|
"""
|
|
763
795
|
|
|
764
|
-
# Create an execution message
|
|
765
|
-
message = f"Task {event.job_id} executed."
|
|
766
|
-
|
|
767
796
|
# Log an informational message indicating that the job has been executed
|
|
768
|
-
self.__logger.info(
|
|
797
|
+
self.__logger.info(f"Task {event.job_id} executed.")
|
|
769
798
|
|
|
770
799
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
771
800
|
self.__taskCallableListener(event, ListeningEvent.JOB_AFTER)
|
|
@@ -796,11 +825,8 @@ class Scheduler(ISchedule):
|
|
|
796
825
|
and listener invocation for the missed job event.
|
|
797
826
|
"""
|
|
798
827
|
|
|
799
|
-
# Create a missed job message
|
|
800
|
-
message = f"Task {event.job_id} was missed. It was scheduled to run at {event.scheduled_run_time}."
|
|
801
|
-
|
|
802
828
|
# Log a warning indicating that the job was missed
|
|
803
|
-
self.__logger.warning(
|
|
829
|
+
self.__logger.warning(f"Task {event.job_id} was missed. It was scheduled to run at {event.scheduled_run_time}.")
|
|
804
830
|
|
|
805
831
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
806
832
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_MISSED)
|
|
@@ -831,11 +857,8 @@ class Scheduler(ISchedule):
|
|
|
831
857
|
and listener invocation for the job max instances event.
|
|
832
858
|
"""
|
|
833
859
|
|
|
834
|
-
# Create a max instances error message
|
|
835
|
-
message = f"Task {event.job_id} exceeded maximum instances"
|
|
836
|
-
|
|
837
860
|
# Log an error message indicating that the job exceeded maximum instances
|
|
838
|
-
self.__logger.error(
|
|
861
|
+
self.__logger.error(f"Task {event.job_id} exceeded maximum instances")
|
|
839
862
|
|
|
840
863
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
841
864
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_MAXINSTANCES)
|
|
@@ -866,16 +889,12 @@ class Scheduler(ISchedule):
|
|
|
866
889
|
and listener invocation for the job modified event.
|
|
867
890
|
"""
|
|
868
891
|
|
|
869
|
-
# Create a modified message
|
|
870
|
-
message = f"Task {event.job_id} has been modified."
|
|
871
|
-
|
|
872
|
-
# Log an informational message indicating that the job has been modified
|
|
873
|
-
self.__logger.info(message)
|
|
874
|
-
|
|
875
892
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
876
893
|
if event.next_run_time is None:
|
|
894
|
+
self.__logger.info(f"Task {event.job_id} has been paused.")
|
|
877
895
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_PAUSED)
|
|
878
896
|
else:
|
|
897
|
+
self.__logger.info(f"Task {event.job_id} has been resumed.")
|
|
879
898
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_RESUMED)
|
|
880
899
|
|
|
881
900
|
def __removedListener(
|
|
@@ -903,11 +922,8 @@ class Scheduler(ISchedule):
|
|
|
903
922
|
listener for the job removal event.
|
|
904
923
|
"""
|
|
905
924
|
|
|
906
|
-
# Create a message indicating that the job has been removed
|
|
907
|
-
message = f"Task {event.job_id} has been removed."
|
|
908
|
-
|
|
909
925
|
# Log the removal of the job
|
|
910
|
-
self.__logger.info(
|
|
926
|
+
self.__logger.info(f"Task {event.job_id} has been removed.")
|
|
911
927
|
|
|
912
928
|
# If a listener is registered for this job ID, invoke the listener with the event details
|
|
913
929
|
self.__taskCallableListener(event, ListeningEvent.JOB_ON_REMOVED)
|
|
@@ -958,12 +974,19 @@ class Scheduler(ISchedule):
|
|
|
958
974
|
if entity.listener:
|
|
959
975
|
self.setListener(signature, entity.listener)
|
|
960
976
|
|
|
977
|
+
# Log the successful loading of the scheduled event
|
|
978
|
+
self.__logger.debug(f"Scheduled event '{signature}' loaded successfully.")
|
|
979
|
+
|
|
961
980
|
except Exception as e:
|
|
962
981
|
|
|
982
|
+
# Construct the error message
|
|
983
|
+
error_msg = f"Failed to load scheduled event '{signature}': {str(e)}"
|
|
984
|
+
|
|
985
|
+
# Log the error message
|
|
986
|
+
self.__logger.error(error_msg)
|
|
987
|
+
|
|
963
988
|
# Raise a runtime error if loading the scheduled event fails
|
|
964
|
-
raise CLIOrionisRuntimeError(
|
|
965
|
-
f"Failed to load scheduled event '{signature}': {str(e)}"
|
|
966
|
-
) from e
|
|
989
|
+
raise CLIOrionisRuntimeError(error_msg)
|
|
967
990
|
|
|
968
991
|
def setListener(
|
|
969
992
|
self,
|
|
@@ -1052,15 +1075,61 @@ class Scheduler(ISchedule):
|
|
|
1052
1075
|
|
|
1053
1076
|
# Define a function to pause the scheduler
|
|
1054
1077
|
def schedule_pause():
|
|
1078
|
+
|
|
1079
|
+
# Only pause jobs if the scheduler is currently running
|
|
1055
1080
|
if self.isRunning():
|
|
1056
|
-
|
|
1081
|
+
|
|
1082
|
+
# Clear the set of previously paused jobs
|
|
1083
|
+
self.__paused_by_pause_everything.clear()
|
|
1084
|
+
|
|
1085
|
+
# Get all jobs from the scheduler
|
|
1086
|
+
all_jobs = self.__scheduler.get_jobs()
|
|
1087
|
+
|
|
1088
|
+
# Filter out system jobs (pause, resume, shutdown tasks)
|
|
1089
|
+
system_job_ids = {
|
|
1090
|
+
"scheduler_pause_at",
|
|
1091
|
+
"scheduler_resume_at",
|
|
1092
|
+
"scheduler_shutdown_at"
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
# Pause only user jobs, not system jobs
|
|
1096
|
+
for job in all_jobs:
|
|
1097
|
+
|
|
1098
|
+
# Pause the job only if it is not a system job
|
|
1099
|
+
if job.id not in system_job_ids:
|
|
1100
|
+
|
|
1101
|
+
# Pause the job and add its ID to the set of paused jobs
|
|
1102
|
+
try:
|
|
1103
|
+
|
|
1104
|
+
# Pause the job in the scheduler
|
|
1105
|
+
self.__scheduler.pause_job(job.id)
|
|
1106
|
+
self.__paused_by_pause_everything.add(job.id)
|
|
1107
|
+
|
|
1108
|
+
# Excute the paused listener
|
|
1109
|
+
self.__pausedListener(JobPause(
|
|
1110
|
+
code=EVENT_SCHEDULER_PAUSED,
|
|
1111
|
+
job_id=job.id if hasattr(job, 'id') else None,
|
|
1112
|
+
alias=job.name if hasattr(job, 'name') else None,
|
|
1113
|
+
jobstore=job.jobstore if hasattr(job, 'jobstore') else None,
|
|
1114
|
+
))
|
|
1115
|
+
|
|
1116
|
+
except Exception as e:
|
|
1117
|
+
|
|
1118
|
+
# Log a warning if pausing a job fails, but continue with others
|
|
1119
|
+
self.__logger.warning(f"Failed to pause job '{job.id}': {str(e)}")
|
|
1120
|
+
|
|
1121
|
+
# Log that all user jobs have been paused
|
|
1122
|
+
self.__logger.info("All user jobs have been paused. System jobs remain active.")
|
|
1057
1123
|
|
|
1058
1124
|
try:
|
|
1125
|
+
|
|
1059
1126
|
# Remove any existing pause job to avoid conflicts
|
|
1060
1127
|
try:
|
|
1061
1128
|
self.__scheduler.remove_job("scheduler_pause_at")
|
|
1129
|
+
|
|
1130
|
+
# If the job doesn't exist, it's fine to proceed
|
|
1062
1131
|
except:
|
|
1063
|
-
pass
|
|
1132
|
+
pass
|
|
1064
1133
|
|
|
1065
1134
|
# Add a job to the scheduler to pause it at the specified datetime
|
|
1066
1135
|
self.__scheduler.add_job(
|
|
@@ -1116,16 +1185,48 @@ class Scheduler(ISchedule):
|
|
|
1116
1185
|
|
|
1117
1186
|
# Define a function to resume the scheduler
|
|
1118
1187
|
def schedule_resume():
|
|
1188
|
+
|
|
1189
|
+
# Only resume jobs if the scheduler is currently running
|
|
1119
1190
|
if self.isRunning():
|
|
1120
|
-
|
|
1191
|
+
|
|
1192
|
+
# Resume only jobs that were paused by pauseEverythingAt
|
|
1193
|
+
if self.__paused_by_pause_everything:
|
|
1194
|
+
|
|
1195
|
+
# Iterate through the set of paused job IDs and resume each one
|
|
1196
|
+
for job_id in list(self.__paused_by_pause_everything):
|
|
1197
|
+
|
|
1198
|
+
try:
|
|
1199
|
+
|
|
1200
|
+
# Resume the job and log the action
|
|
1201
|
+
self.__scheduler.resume_job(job_id)
|
|
1202
|
+
self.__logger.info(f"User job '{job_id}' has been resumed.")
|
|
1203
|
+
|
|
1204
|
+
# Excute the resumed listener
|
|
1205
|
+
self.__resumedListener(JobResume(
|
|
1206
|
+
code=EVENT_SCHEDULER_RESUMED,
|
|
1207
|
+
job_id=job_id
|
|
1208
|
+
))
|
|
1209
|
+
|
|
1210
|
+
except Exception as e:
|
|
1211
|
+
|
|
1212
|
+
# Log a warning if resuming a job fails, but continue with others
|
|
1213
|
+
self.__logger.warning(f"Failed to resume job '{job_id}': {str(e)}")
|
|
1214
|
+
|
|
1215
|
+
# Clear the set after resuming all jobs
|
|
1216
|
+
self.__paused_by_pause_everything.clear()
|
|
1217
|
+
|
|
1218
|
+
# Log that all previously paused jobs have been resumed
|
|
1219
|
+
self.__logger.info("All previously paused user jobs have been resumed.")
|
|
1121
1220
|
|
|
1122
1221
|
try:
|
|
1123
1222
|
|
|
1124
1223
|
# Remove any existing resume job to avoid conflicts
|
|
1125
1224
|
try:
|
|
1126
1225
|
self.__scheduler.remove_job("scheduler_resume_at")
|
|
1226
|
+
|
|
1227
|
+
# If the job doesn't exist, it's fine to proceed
|
|
1127
1228
|
except:
|
|
1128
|
-
pass
|
|
1229
|
+
pass
|
|
1129
1230
|
|
|
1130
1231
|
# Add a job to the scheduler to resume it at the specified datetime
|
|
1131
1232
|
self.__scheduler.add_job(
|
|
@@ -1190,8 +1291,13 @@ class Scheduler(ISchedule):
|
|
|
1190
1291
|
|
|
1191
1292
|
# Define a function to shut down the scheduler
|
|
1192
1293
|
def schedule_shutdown():
|
|
1294
|
+
|
|
1295
|
+
# Only shut down the scheduler if it is currently running
|
|
1193
1296
|
if self.isRunning():
|
|
1297
|
+
|
|
1298
|
+
# Execute the shutdown process
|
|
1194
1299
|
self.__scheduler.shutdown(wait=wait)
|
|
1300
|
+
|
|
1195
1301
|
# Signal the stop event to break the wait in start()
|
|
1196
1302
|
if self._stop_event and not self._stop_event.is_set():
|
|
1197
1303
|
self._stop_event.set()
|
|
@@ -1201,12 +1307,14 @@ class Scheduler(ISchedule):
|
|
|
1201
1307
|
# Remove any existing shutdown job to avoid conflicts
|
|
1202
1308
|
try:
|
|
1203
1309
|
self.__scheduler.remove_job("scheduler_shutdown_at")
|
|
1310
|
+
|
|
1311
|
+
# If the job doesn't exist, it's fine to proceed
|
|
1204
1312
|
except:
|
|
1205
|
-
pass
|
|
1313
|
+
pass
|
|
1206
1314
|
|
|
1207
1315
|
# Add a job to the scheduler to shut it down at the specified datetime
|
|
1208
1316
|
self.__scheduler.add_job(
|
|
1209
|
-
func=schedule_shutdown,
|
|
1317
|
+
func=schedule_shutdown, # Function to shut down the scheduler
|
|
1210
1318
|
trigger=DateTrigger(run_date=at), # Trigger type is 'date' for one-time execution
|
|
1211
1319
|
id="scheduler_shutdown_at", # Unique job ID for shutting down the scheduler
|
|
1212
1320
|
name="Shutdown Scheduler", # Descriptive name for the job
|
|
@@ -1260,7 +1368,7 @@ class Scheduler(ISchedule):
|
|
|
1260
1368
|
self.__scheduler.start()
|
|
1261
1369
|
|
|
1262
1370
|
# Log that the scheduler is now active and waiting for events
|
|
1263
|
-
self.__logger.info("Scheduler is now active and waiting for events...")
|
|
1371
|
+
self.__logger.info("Orionis Scheduler is now active and waiting for events...")
|
|
1264
1372
|
|
|
1265
1373
|
try:
|
|
1266
1374
|
# Wait for the stop event to be set, which signals a shutdown
|
|
@@ -1565,8 +1673,18 @@ class Scheduler(ISchedule):
|
|
|
1565
1673
|
False if no pause job was found or an error occurred during the cancellation process.
|
|
1566
1674
|
"""
|
|
1567
1675
|
try:
|
|
1676
|
+
|
|
1677
|
+
# Remove any listener associated with the pause event
|
|
1678
|
+
listener = ListeningEvent.SCHEDULER_PAUSED.value
|
|
1679
|
+
if listener in self.__listeners:
|
|
1680
|
+
del self.__listeners[listener]
|
|
1681
|
+
|
|
1568
1682
|
# Attempt to remove the pause job with the specific ID
|
|
1569
|
-
|
|
1683
|
+
# if it exists
|
|
1684
|
+
try:
|
|
1685
|
+
self.__scheduler.remove_job("scheduler_pause_at")
|
|
1686
|
+
finally:
|
|
1687
|
+
pass
|
|
1570
1688
|
|
|
1571
1689
|
# Log the successful cancellation of the pause operation
|
|
1572
1690
|
self.__logger.info("Scheduled pause operation cancelled.")
|
|
@@ -1593,8 +1711,18 @@ class Scheduler(ISchedule):
|
|
|
1593
1711
|
False if no resume job was found or an error occurred during the cancellation process.
|
|
1594
1712
|
"""
|
|
1595
1713
|
try:
|
|
1714
|
+
|
|
1715
|
+
# Remove any listener associated with the resume event
|
|
1716
|
+
listener = ListeningEvent.SCHEDULER_RESUMED.value
|
|
1717
|
+
if listener in self.__listeners:
|
|
1718
|
+
del self.__listeners[listener]
|
|
1719
|
+
|
|
1596
1720
|
# Attempt to remove the resume job with the specific ID
|
|
1597
|
-
|
|
1721
|
+
# if it exists
|
|
1722
|
+
try:
|
|
1723
|
+
self.__scheduler.remove_job("scheduler_resume_at")
|
|
1724
|
+
finally:
|
|
1725
|
+
pass
|
|
1598
1726
|
|
|
1599
1727
|
# Log the successful cancellation of the resume operation
|
|
1600
1728
|
self.__logger.info("Scheduled resume operation cancelled.")
|
|
@@ -1622,8 +1750,18 @@ class Scheduler(ISchedule):
|
|
|
1622
1750
|
False if no shutdown job was found or an error occurred during the cancellation process.
|
|
1623
1751
|
"""
|
|
1624
1752
|
try:
|
|
1753
|
+
|
|
1754
|
+
# Remove any listener associated with the shutdown event
|
|
1755
|
+
listener = ListeningEvent.SCHEDULER_SHUTDOWN.value
|
|
1756
|
+
if listener in self.__listeners:
|
|
1757
|
+
del self.__listeners[listener]
|
|
1758
|
+
|
|
1625
1759
|
# Attempt to remove the shutdown job with the specific ID
|
|
1626
|
-
|
|
1760
|
+
# if it exists
|
|
1761
|
+
try:
|
|
1762
|
+
self.__scheduler.remove_job("scheduler_shutdown_at")
|
|
1763
|
+
finally:
|
|
1764
|
+
pass
|
|
1627
1765
|
|
|
1628
1766
|
# Log the successful cancellation of the shutdown operation
|
|
1629
1767
|
self.__logger.info("Scheduled shutdown operation cancelled.")
|
|
@@ -1653,27 +1791,6 @@ class Scheduler(ISchedule):
|
|
|
1653
1791
|
# Return the running state of the scheduler
|
|
1654
1792
|
return self.__scheduler.running
|
|
1655
1793
|
|
|
1656
|
-
async def waitUntilStopped(self) -> None:
|
|
1657
|
-
"""
|
|
1658
|
-
Wait for the scheduler to stop gracefully.
|
|
1659
|
-
|
|
1660
|
-
This method blocks the execution until the scheduler is stopped. It waits for the
|
|
1661
|
-
internal stop event to be set, which signals that the scheduler has been shut down.
|
|
1662
|
-
This is useful for ensuring that the scheduler completes its operations before
|
|
1663
|
-
proceeding with other tasks.
|
|
1664
|
-
|
|
1665
|
-
Returns
|
|
1666
|
-
-------
|
|
1667
|
-
None
|
|
1668
|
-
This method does not return any value. It waits until the scheduler is stopped.
|
|
1669
|
-
"""
|
|
1670
|
-
|
|
1671
|
-
# Check if the stop event is initialized
|
|
1672
|
-
if self._stop_event:
|
|
1673
|
-
|
|
1674
|
-
# Wait for the stop event to be set, signaling the scheduler has stopped
|
|
1675
|
-
await self._stop_event.wait()
|
|
1676
|
-
|
|
1677
1794
|
def forceStop(self) -> None:
|
|
1678
1795
|
"""
|
|
1679
1796
|
Forcefully stop the scheduler immediately without waiting for jobs to complete.
|
|
@@ -1718,6 +1835,7 @@ class Scheduler(ISchedule):
|
|
|
1718
1835
|
|
|
1719
1836
|
# Check if the stop event exists and has not already been set
|
|
1720
1837
|
if self._stop_event and not self._stop_event.is_set():
|
|
1838
|
+
|
|
1721
1839
|
# Get the current asyncio event loop
|
|
1722
1840
|
loop = asyncio.get_event_loop()
|
|
1723
1841
|
|
|
@@ -626,62 +626,89 @@ class Application(Container, IApplication):
|
|
|
626
626
|
configuration system.
|
|
627
627
|
"""
|
|
628
628
|
|
|
629
|
+
# Convert dataclass instances to dictionaries
|
|
630
|
+
from orionis.services.introspection.dataclass.attributes import attributes
|
|
631
|
+
|
|
629
632
|
# Load app configurator
|
|
633
|
+
if (isinstance(app, type) and issubclass(app, App)):
|
|
634
|
+
app = attributes(app)
|
|
630
635
|
if not isinstance(app, (App, dict)):
|
|
631
636
|
raise OrionisTypeError(f"Expected App instance or dict, got {type(app).__name__}")
|
|
632
637
|
self.loadConfigApp(app)
|
|
633
638
|
|
|
634
639
|
# Load auth configurator
|
|
640
|
+
if (isinstance(auth, type) and issubclass(auth, Auth)):
|
|
641
|
+
auth = attributes(auth)
|
|
635
642
|
if not isinstance(auth, (Auth, dict)):
|
|
636
643
|
raise OrionisTypeError(f"Expected Auth instance or dict, got {type(auth).__name__}")
|
|
637
644
|
self.loadConfigAuth(auth)
|
|
638
645
|
|
|
639
646
|
# Load cache configurator
|
|
647
|
+
if (isinstance(cache, type) and issubclass(cache, Cache)):
|
|
648
|
+
cache = attributes(cache)
|
|
640
649
|
if not isinstance(cache, (Cache, dict)):
|
|
641
650
|
raise OrionisTypeError(f"Expected Cache instance or dict, got {type(cache).__name__}")
|
|
642
651
|
self.loadConfigCache(cache)
|
|
643
652
|
|
|
644
653
|
# Load cors configurator
|
|
654
|
+
if (isinstance(cors, type) and issubclass(cors, Cors)):
|
|
655
|
+
cors = attributes(cors)
|
|
645
656
|
if not isinstance(cors, (Cors, dict)):
|
|
646
657
|
raise OrionisTypeError(f"Expected Cors instance or dict, got {type(cors).__name__}")
|
|
647
658
|
self.loadConfigCors(cors)
|
|
648
659
|
|
|
649
660
|
# Load database configurator
|
|
661
|
+
if (isinstance(database, type) and issubclass(database, Database)):
|
|
662
|
+
database = attributes(database)
|
|
650
663
|
if not isinstance(database, (Database, dict)):
|
|
651
664
|
raise OrionisTypeError(f"Expected Database instance or dict, got {type(database).__name__}")
|
|
652
665
|
self.loadConfigDatabase(database)
|
|
653
666
|
|
|
654
667
|
# Load filesystems configurator
|
|
668
|
+
if (isinstance(filesystems, type) and issubclass(filesystems, Filesystems)):
|
|
669
|
+
filesystems = attributes(filesystems)
|
|
655
670
|
if not isinstance(filesystems, (Filesystems, dict)):
|
|
656
671
|
raise OrionisTypeError(f"Expected Filesystems instance or dict, got {type(filesystems).__name__}")
|
|
657
672
|
self.loadConfigFilesystems(filesystems)
|
|
658
673
|
|
|
659
674
|
# Load logging configurator
|
|
675
|
+
if (isinstance(logging, type) and issubclass(logging, Logging)):
|
|
676
|
+
logging = attributes(logging)
|
|
660
677
|
if not isinstance(logging, (Logging, dict)):
|
|
661
678
|
raise OrionisTypeError(f"Expected Logging instance or dict, got {type(logging).__name__}")
|
|
662
679
|
self.loadConfigLogging(logging)
|
|
663
680
|
|
|
664
681
|
# Load mail configurator
|
|
682
|
+
if (isinstance(mail, type) and issubclass(mail, Mail)):
|
|
683
|
+
mail = attributes(mail)
|
|
665
684
|
if not isinstance(mail, (Mail, dict)):
|
|
666
685
|
raise OrionisTypeError(f"Expected Mail instance or dict, got {type(mail).__name__}")
|
|
667
686
|
self.loadConfigMail(mail)
|
|
668
687
|
|
|
669
688
|
# Load paths configurator
|
|
689
|
+
if (isinstance(path, type) and issubclass(path, Paths)):
|
|
690
|
+
path = attributes(path)
|
|
670
691
|
if not isinstance(path, (Paths, dict)):
|
|
671
692
|
raise OrionisTypeError(f"Expected Paths instance or dict, got {type(path).__name__}")
|
|
672
693
|
self.loadPaths(path)
|
|
673
694
|
|
|
674
695
|
# Load queue configurator
|
|
696
|
+
if (isinstance(queue, type) and issubclass(queue, Queue)):
|
|
697
|
+
queue = attributes(queue)
|
|
675
698
|
if not isinstance(queue, (Queue, dict)):
|
|
676
699
|
raise OrionisTypeError(f"Expected Queue instance or dict, got {type(queue).__name__}")
|
|
677
700
|
self.loadConfigQueue(queue)
|
|
678
701
|
|
|
679
702
|
# Load session configurator
|
|
703
|
+
if (isinstance(session, type) and issubclass(session, Session)):
|
|
704
|
+
session = attributes(session)
|
|
680
705
|
if not isinstance(session, (Session, dict)):
|
|
681
706
|
raise OrionisTypeError(f"Expected Session instance or dict, got {type(session).__name__}")
|
|
682
707
|
self.loadConfigSession(session)
|
|
683
708
|
|
|
684
709
|
# Load testing configurator
|
|
710
|
+
if (isinstance(testing, type) and issubclass(testing, Testing)):
|
|
711
|
+
testing = attributes(testing)
|
|
685
712
|
if not isinstance(testing, (Testing, dict)):
|
|
686
713
|
raise OrionisTypeError(f"Expected Testing instance or dict, got {type(testing).__name__}")
|
|
687
714
|
self.loadConfigTesting(testing)
|
|
@@ -767,7 +794,9 @@ class Application(Container, IApplication):
|
|
|
767
794
|
|
|
768
795
|
# If app is a dict, convert it to App instance
|
|
769
796
|
if isinstance(app, dict):
|
|
770
|
-
app = App(**app)
|
|
797
|
+
app = App(**app).toDict()
|
|
798
|
+
elif isinstance(app, App):
|
|
799
|
+
app = app.toDict()
|
|
771
800
|
|
|
772
801
|
# Store the configuration
|
|
773
802
|
self.__configurators['app'] = app
|
|
@@ -853,7 +882,9 @@ class Application(Container, IApplication):
|
|
|
853
882
|
|
|
854
883
|
# If auth is a dict, convert it to Auth instance
|
|
855
884
|
if isinstance(auth, dict):
|
|
856
|
-
auth = Auth(**auth)
|
|
885
|
+
auth = Auth(**auth).toDict()
|
|
886
|
+
elif isinstance(auth, Auth):
|
|
887
|
+
auth = auth.toDict()
|
|
857
888
|
|
|
858
889
|
# Store the configuration
|
|
859
890
|
self.__configurators['auth'] = auth
|
|
@@ -939,7 +970,9 @@ class Application(Container, IApplication):
|
|
|
939
970
|
|
|
940
971
|
# If cache is a dict, convert it to Cache instance
|
|
941
972
|
if isinstance(cache, dict):
|
|
942
|
-
cache = Cache(**cache)
|
|
973
|
+
cache = Cache(**cache).toDict()
|
|
974
|
+
elif isinstance(cache, Cache):
|
|
975
|
+
cache = cache.toDict()
|
|
943
976
|
|
|
944
977
|
# Store the configuration
|
|
945
978
|
self.__configurators['cache'] = cache
|
|
@@ -1025,7 +1058,9 @@ class Application(Container, IApplication):
|
|
|
1025
1058
|
|
|
1026
1059
|
# If cors is a dict, convert it to Cors instance
|
|
1027
1060
|
if isinstance(cors, dict):
|
|
1028
|
-
cors = Cors(**cors)
|
|
1061
|
+
cors = Cors(**cors).toDict()
|
|
1062
|
+
elif isinstance(cors, Cors):
|
|
1063
|
+
cors = cors.toDict()
|
|
1029
1064
|
|
|
1030
1065
|
# Store the configuration
|
|
1031
1066
|
self.__configurators['cors'] = cors
|
|
@@ -1111,7 +1146,9 @@ class Application(Container, IApplication):
|
|
|
1111
1146
|
|
|
1112
1147
|
# If database is a dict, convert it to Database instance
|
|
1113
1148
|
if isinstance(database, dict):
|
|
1114
|
-
database = Database(**database)
|
|
1149
|
+
database = Database(**database).toDict()
|
|
1150
|
+
elif isinstance(database, Database):
|
|
1151
|
+
database = database.toDict()
|
|
1115
1152
|
|
|
1116
1153
|
# Store the configuration
|
|
1117
1154
|
self.__configurators['database'] = database
|
|
@@ -1197,7 +1234,9 @@ class Application(Container, IApplication):
|
|
|
1197
1234
|
|
|
1198
1235
|
# If filesystems is a dict, convert it to Filesystems instance
|
|
1199
1236
|
if isinstance(filesystems, dict):
|
|
1200
|
-
filesystems = Filesystems(**filesystems)
|
|
1237
|
+
filesystems = Filesystems(**filesystems).toDict()
|
|
1238
|
+
elif isinstance(filesystems, Filesystems):
|
|
1239
|
+
filesystems = filesystems.toDict()
|
|
1201
1240
|
|
|
1202
1241
|
# Store the configuration
|
|
1203
1242
|
self.__configurators['filesystems'] = filesystems
|
|
@@ -1283,7 +1322,9 @@ class Application(Container, IApplication):
|
|
|
1283
1322
|
|
|
1284
1323
|
# If logging is a dict, convert it to Logging instance
|
|
1285
1324
|
if isinstance(logging, dict):
|
|
1286
|
-
logging = Logging(**logging)
|
|
1325
|
+
logging = Logging(**logging).toDict()
|
|
1326
|
+
elif isinstance(logging, Logging):
|
|
1327
|
+
logging = logging.toDict()
|
|
1287
1328
|
|
|
1288
1329
|
# Store the configuration
|
|
1289
1330
|
self.__configurators['logging'] = logging
|
|
@@ -1369,7 +1410,9 @@ class Application(Container, IApplication):
|
|
|
1369
1410
|
|
|
1370
1411
|
# If mail is a dict, convert it to Mail instance
|
|
1371
1412
|
if isinstance(mail, dict):
|
|
1372
|
-
mail = Mail(**mail)
|
|
1413
|
+
mail = Mail(**mail).toDict()
|
|
1414
|
+
elif isinstance(mail, Mail):
|
|
1415
|
+
mail = mail.toDict()
|
|
1373
1416
|
|
|
1374
1417
|
# Store the configuration
|
|
1375
1418
|
self.__configurators['mail'] = mail
|
|
@@ -1558,7 +1601,12 @@ class Application(Container, IApplication):
|
|
|
1558
1601
|
paths.update({
|
|
1559
1602
|
'root': self.__bootstrap_base_path or str(Path.cwd().resolve())
|
|
1560
1603
|
})
|
|
1561
|
-
paths = Paths(**paths)
|
|
1604
|
+
paths = Paths(**paths).toDict()
|
|
1605
|
+
elif isinstance(paths, Paths):
|
|
1606
|
+
paths = paths.toDict()
|
|
1607
|
+
paths.update({
|
|
1608
|
+
'root': self.__bootstrap_base_path or str(Path.cwd().resolve())
|
|
1609
|
+
})
|
|
1562
1610
|
|
|
1563
1611
|
# Store the configuration
|
|
1564
1612
|
self.__configurators['path'] = paths
|
|
@@ -1690,7 +1738,9 @@ class Application(Container, IApplication):
|
|
|
1690
1738
|
|
|
1691
1739
|
# If queue is a dict, convert it to Queue instance
|
|
1692
1740
|
if isinstance(queue, dict):
|
|
1693
|
-
queue = Queue(**queue)
|
|
1741
|
+
queue = Queue(**queue).toDict()
|
|
1742
|
+
elif isinstance(queue, Queue):
|
|
1743
|
+
queue = queue.toDict()
|
|
1694
1744
|
|
|
1695
1745
|
# Store the configuration
|
|
1696
1746
|
self.__configurators['queue'] = queue
|
|
@@ -1776,7 +1826,9 @@ class Application(Container, IApplication):
|
|
|
1776
1826
|
|
|
1777
1827
|
# If session is a dict, convert it to Session instance
|
|
1778
1828
|
if isinstance(session, dict):
|
|
1779
|
-
session = Session(**session)
|
|
1829
|
+
session = Session(**session).toDict()
|
|
1830
|
+
elif isinstance(session, Session):
|
|
1831
|
+
session = session.toDict()
|
|
1780
1832
|
|
|
1781
1833
|
# Store the configuration
|
|
1782
1834
|
self.__configurators['session'] = session
|
|
@@ -1862,7 +1914,9 @@ class Application(Container, IApplication):
|
|
|
1862
1914
|
|
|
1863
1915
|
# If testing is a dict, convert it to Testing instance
|
|
1864
1916
|
if isinstance(testing, dict):
|
|
1865
|
-
testing = Testing(**testing)
|
|
1917
|
+
testing = Testing(**testing).toDict()
|
|
1918
|
+
elif isinstance(testing, Testing):
|
|
1919
|
+
testing = testing.toDict()
|
|
1866
1920
|
|
|
1867
1921
|
# Store the configuration
|
|
1868
1922
|
self.__configurators['testing'] = testing
|
|
@@ -92,6 +92,8 @@ class Session(BaseEntity):
|
|
|
92
92
|
"""
|
|
93
93
|
|
|
94
94
|
# Validate secret_key
|
|
95
|
+
if self.secret_key is None:
|
|
96
|
+
self.secret_key = SecretKey.random()
|
|
95
97
|
if not isinstance(self.secret_key, str) or not self.secret_key.strip():
|
|
96
98
|
raise OrionisIntegrityException("Session secret_key must be a non-empty string")
|
|
97
99
|
|
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=QQtETxI_SrApPN6JlyWgWB3ExkR3w2iFgeR-UCEV8fA,77612
|
|
85
85
|
orionis/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
86
86
|
orionis/container/container.py,sha256=aF_b6lTUpG4YCo9yFJEzsntTdIzgMMXFW5LyWqAJVBQ,87987
|
|
87
87
|
orionis/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -123,7 +123,7 @@ orionis/failure/contracts/handler.py,sha256=4N9yMkMgdhtHbRGAyCtuTx3GmkPP74vhqdRL
|
|
|
123
123
|
orionis/failure/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
124
124
|
orionis/failure/entities/throwable.py,sha256=ogys062uhim5QMYU62ezlnumRAnYQlUf_vZvQY47S3U,1227
|
|
125
125
|
orionis/foundation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
126
|
-
orionis/foundation/application.py,sha256=
|
|
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=JjXMnmgYxlzZmmwSkOaQe2TZAI5nx3vfWRDzNbUMKVM,4109
|
|
243
243
|
orionis/metadata/package.py,sha256=k7Yriyp5aUcR-iR8SK2ec_lf0_Cyc-C7JczgXa-I67w,16039
|
|
244
244
|
orionis/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
245
245
|
orionis/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -292,6 +292,8 @@ orionis/services/introspection/concretes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
|
|
|
292
292
|
orionis/services/introspection/concretes/reflection.py,sha256=5DkNr6gUYdccSo7htzILoV38OAJCwLz-jLXViqZg6eY,55916
|
|
293
293
|
orionis/services/introspection/concretes/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
294
294
|
orionis/services/introspection/concretes/contracts/reflection.py,sha256=LwEAgdN_WLCfS9b8pnFRVfN0PTRK4Br9qngu5km5aIk,24955
|
|
295
|
+
orionis/services/introspection/dataclass/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
296
|
+
orionis/services/introspection/dataclass/attributes.py,sha256=Z847Gya_0hdiK7eNCI8-tE1o2KtkxSKVcGxXYj94r_A,1186
|
|
295
297
|
orionis/services/introspection/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
296
298
|
orionis/services/introspection/dependencies/reflection.py,sha256=VEe3cY6LTpOW3dm0IFECTHh7F_9_X-siTAeQc2XRQeM,13451
|
|
297
299
|
orionis/services/introspection/dependencies/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -415,7 +417,7 @@ orionis/test/validators/web_report.py,sha256=n9BfzOZz6aEiNTypXcwuWbFRG0OdHNSmCNu
|
|
|
415
417
|
orionis/test/validators/workers.py,sha256=rWcdRexINNEmGaO7mnc1MKUxkHKxrTsVuHgbnIfJYgc,1206
|
|
416
418
|
orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
417
419
|
orionis/test/view/render.py,sha256=f-zNhtKSg9R5Njqujbg2l2amAs2-mRVESneLIkWOZjU,4082
|
|
418
|
-
orionis-0.
|
|
420
|
+
orionis-0.523.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
|
|
419
421
|
tests/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
420
422
|
tests/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
421
423
|
tests/container/context/test_manager.py,sha256=wOwXpl9rHNfTTexa9GBKYMwK0_-KSQPbI-AEyGNkmAE,1356
|
|
@@ -561,8 +563,8 @@ tests/testing/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
561
563
|
tests/testing/validators/test_testing_validators.py,sha256=WPo5GxTP6xE-Dw3X1vZoqOMpb6HhokjNSbgDsDRDvy4,16588
|
|
562
564
|
tests/testing/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
563
565
|
tests/testing/view/test_render.py,sha256=tnnMBwS0iKUIbogLvu-7Rii50G6Koddp3XT4wgdFEYM,1050
|
|
564
|
-
orionis-0.
|
|
565
|
-
orionis-0.
|
|
566
|
-
orionis-0.
|
|
567
|
-
orionis-0.
|
|
568
|
-
orionis-0.
|
|
566
|
+
orionis-0.523.0.dist-info/METADATA,sha256=628aQJLd-wjZTMQT2KZF_n4t8gWzcu36dWBrrTQWEpw,4801
|
|
567
|
+
orionis-0.523.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
568
|
+
orionis-0.523.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
|
|
569
|
+
orionis-0.523.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
570
|
+
orionis-0.523.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|