orionis 0.1.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.
Files changed (133) hide show
  1. orionis/__init__.py +0 -0
  2. orionis/cli_manager.py +48 -0
  3. orionis/framework.py +45 -0
  4. orionis/luminate/__init__.py +0 -0
  5. orionis/luminate/app.py +0 -0
  6. orionis/luminate/bootstrap/__init__.py +0 -0
  7. orionis/luminate/bootstrap/parser.py +49 -0
  8. orionis/luminate/bootstrap/register.py +95 -0
  9. orionis/luminate/cache/__init__.py +0 -0
  10. orionis/luminate/cache/app/__init__.py +0 -0
  11. orionis/luminate/cache/app/config.py +96 -0
  12. orionis/luminate/cache/console/__init__.py +0 -0
  13. orionis/luminate/cache/console/commands.py +98 -0
  14. orionis/luminate/config/__init__.py +0 -0
  15. orionis/luminate/config/dataclass/__init__.py +0 -0
  16. orionis/luminate/config/dataclass/app.py +50 -0
  17. orionis/luminate/config/dataclass/auth.py +17 -0
  18. orionis/luminate/config/dataclass/cache.py +51 -0
  19. orionis/luminate/config/dataclass/cors.py +58 -0
  20. orionis/luminate/config/dataclass/database.py +203 -0
  21. orionis/luminate/config/dataclass/filesystems.py +102 -0
  22. orionis/luminate/config/dataclass/logging.py +107 -0
  23. orionis/luminate/config/dataclass/mail.py +81 -0
  24. orionis/luminate/config/dataclass/queue.py +63 -0
  25. orionis/luminate/config/dataclass/session.py +59 -0
  26. orionis/luminate/config/environment.py +110 -0
  27. orionis/luminate/config/sections.py +37 -0
  28. orionis/luminate/console/__init__.py +0 -0
  29. orionis/luminate/console/base/__init__.py +0 -0
  30. orionis/luminate/console/base/command.py +427 -0
  31. orionis/luminate/console/cache.py +132 -0
  32. orionis/luminate/console/command.py +40 -0
  33. orionis/luminate/console/command_filter.py +40 -0
  34. orionis/luminate/console/commands/__init__.py +0 -0
  35. orionis/luminate/console/commands/cache_clear.py +56 -0
  36. orionis/luminate/console/commands/help.py +59 -0
  37. orionis/luminate/console/commands/schedule_work.py +50 -0
  38. orionis/luminate/console/commands/tests.py +40 -0
  39. orionis/luminate/console/commands/version.py +39 -0
  40. orionis/luminate/console/exceptions/__init__.py +0 -0
  41. orionis/luminate/console/exceptions/cli_exception.py +125 -0
  42. orionis/luminate/console/kernel.py +32 -0
  43. orionis/luminate/console/output/__init__.py +0 -0
  44. orionis/luminate/console/output/console.py +426 -0
  45. orionis/luminate/console/output/executor.py +90 -0
  46. orionis/luminate/console/output/progress_bar.py +100 -0
  47. orionis/luminate/console/output/styles.py +95 -0
  48. orionis/luminate/console/parser.py +159 -0
  49. orionis/luminate/console/register.py +98 -0
  50. orionis/luminate/console/runner.py +126 -0
  51. orionis/luminate/console/scripts/__init__.py +0 -0
  52. orionis/luminate/console/scripts/management.py +94 -0
  53. orionis/luminate/console/tasks/__init__.py +0 -0
  54. orionis/luminate/console/tasks/scheduler.py +616 -0
  55. orionis/luminate/contracts/__init__.py +0 -0
  56. orionis/luminate/contracts/bootstrap/parser_interface.py +46 -0
  57. orionis/luminate/contracts/cache/__init__.py +0 -0
  58. orionis/luminate/contracts/cache/cache_commands_interface.py +69 -0
  59. orionis/luminate/contracts/config/__init__.py +0 -0
  60. orionis/luminate/contracts/config/config_interface.py +27 -0
  61. orionis/luminate/contracts/config/environment_interface.py +64 -0
  62. orionis/luminate/contracts/console/__init__.py +0 -0
  63. orionis/luminate/contracts/console/base_command_interface.py +448 -0
  64. orionis/luminate/contracts/console/cli_cache_interface.py +34 -0
  65. orionis/luminate/contracts/console/command_filter_interface.py +32 -0
  66. orionis/luminate/contracts/console/command_interface.py +36 -0
  67. orionis/luminate/contracts/console/console_interface.py +305 -0
  68. orionis/luminate/contracts/console/executor_interface.py +51 -0
  69. orionis/luminate/contracts/console/kernel_interface.py +32 -0
  70. orionis/luminate/contracts/console/management_interface.py +63 -0
  71. orionis/luminate/contracts/console/parser_interface.py +76 -0
  72. orionis/luminate/contracts/console/progress_bar_interface.py +66 -0
  73. orionis/luminate/contracts/console/register_interface.py +32 -0
  74. orionis/luminate/contracts/console/runner_interface.py +50 -0
  75. orionis/luminate/contracts/console/schedule_interface.py +317 -0
  76. orionis/luminate/contracts/console/task_manager_interface.py +37 -0
  77. orionis/luminate/contracts/facades/__init__.py +0 -0
  78. orionis/luminate/contracts/facades/env_interface.py +64 -0
  79. orionis/luminate/contracts/facades/log_interface.py +48 -0
  80. orionis/luminate/contracts/facades/paths_interface.py +141 -0
  81. orionis/luminate/contracts/facades/tests_interface.py +33 -0
  82. orionis/luminate/contracts/files/__init__.py +0 -0
  83. orionis/luminate/contracts/files/paths_interface.py +29 -0
  84. orionis/luminate/contracts/installer/__init__.py +0 -0
  85. orionis/luminate/contracts/installer/output_interface.py +125 -0
  86. orionis/luminate/contracts/installer/setup_interface.py +29 -0
  87. orionis/luminate/contracts/installer/upgrade_interface.py +24 -0
  88. orionis/luminate/contracts/log/__init__.py +0 -0
  89. orionis/luminate/contracts/log/logger_interface.py +33 -0
  90. orionis/luminate/contracts/pipelines/cli_pipeline_interface.py +84 -0
  91. orionis/luminate/contracts/publisher/__init__.py +0 -0
  92. orionis/luminate/contracts/publisher/pypi_publisher_interface.py +36 -0
  93. orionis/luminate/contracts/test/__init__.py +0 -0
  94. orionis/luminate/contracts/test/unit_test_interface.py +51 -0
  95. orionis/luminate/contracts/tools/__init__.py +0 -0
  96. orionis/luminate/contracts/tools/reflection_interface.py +343 -0
  97. orionis/luminate/contracts/tools/std_interface.py +56 -0
  98. orionis/luminate/facades/__init__.py +0 -0
  99. orionis/luminate/facades/environment.py +81 -0
  100. orionis/luminate/facades/log.py +56 -0
  101. orionis/luminate/facades/paths.py +268 -0
  102. orionis/luminate/facades/tests.py +48 -0
  103. orionis/luminate/files/__init__.py +0 -0
  104. orionis/luminate/files/paths.py +56 -0
  105. orionis/luminate/installer/__init__.py +0 -0
  106. orionis/luminate/installer/icon.ascii +11 -0
  107. orionis/luminate/installer/info.ascii +13 -0
  108. orionis/luminate/installer/output.py +188 -0
  109. orionis/luminate/installer/setup.py +191 -0
  110. orionis/luminate/installer/upgrade.py +42 -0
  111. orionis/luminate/log/__init__.py +0 -0
  112. orionis/luminate/log/logger.py +116 -0
  113. orionis/luminate/pipelines/__init__.py +0 -0
  114. orionis/luminate/pipelines/cli_pipeline.py +116 -0
  115. orionis/luminate/publisher/__init__.py +0 -0
  116. orionis/luminate/publisher/pypi.py +206 -0
  117. orionis/luminate/static/logos/flaskavel.png +0 -0
  118. orionis/luminate/test/__init__.py +0 -0
  119. orionis/luminate/test/exception.py +48 -0
  120. orionis/luminate/test/unit_test.py +108 -0
  121. orionis/luminate/tools/__init__.py +0 -0
  122. orionis/luminate/tools/reflection.py +390 -0
  123. orionis/luminate/tools/std.py +53 -0
  124. orionis-0.1.0.dist-info/LICENCE +21 -0
  125. orionis-0.1.0.dist-info/METADATA +27 -0
  126. orionis-0.1.0.dist-info/RECORD +133 -0
  127. orionis-0.1.0.dist-info/WHEEL +5 -0
  128. orionis-0.1.0.dist-info/entry_points.txt +2 -0
  129. orionis-0.1.0.dist-info/top_level.txt +2 -0
  130. tests/__init__.py +0 -0
  131. tests/tools/__init__.py +0 -0
  132. tests/tools/class_example.py +50 -0
  133. tests/tools/test_reflection.py +128 -0
@@ -0,0 +1,616 @@
1
+ import re
2
+ import sys
3
+ import time
4
+ import logging
5
+ from typing import Any
6
+ from datetime import datetime
7
+ from apscheduler.triggers.cron import CronTrigger
8
+ from orionis.luminate.console.command import Command
9
+ from apscheduler.triggers.interval import IntervalTrigger
10
+ from apscheduler.schedulers.background import BackgroundScheduler
11
+ from orionis.luminate.contracts.console.schedule_interface import ISchedule
12
+ from orionis.luminate.console.exceptions.cli_exception import CLIOrionisScheduleException
13
+
14
+ class Schedule(ISchedule):
15
+ """
16
+ A class that manages the scheduling of tasks using the APScheduler.
17
+
18
+ Attributes
19
+ ----------
20
+ scheduler : BackgroundScheduler
21
+ The background scheduler instance used to schedule tasks.
22
+ callback : function | None
23
+ A callback function that will be called when the scheduled task is triggered.
24
+
25
+ Methods
26
+ -------
27
+ command(signature: str, vars: dict[str, Any] = {}, *args: Any, **kwargs: Any) -> 'Schedule':
28
+ Defines a command to execute.
29
+ """
30
+
31
+ def __init__(self, logger_level=logging.CRITICAL):
32
+ """
33
+ Initializes the Schedule object.
34
+
35
+ This method sets up the background scheduler, starts it, and configures the logging level for APScheduler.
36
+
37
+ Parameters
38
+ ----------
39
+ logger_level : int, optional
40
+ The logging level for the APScheduler logger. Default is `logging.CRITICAL` to suppress most logs.
41
+ """
42
+ logging.getLogger("apscheduler").setLevel(logger_level)
43
+ self.scheduler = BackgroundScheduler()
44
+ self.scheduler.start()
45
+ self.callback = None
46
+ self.wait = True
47
+
48
+ def command(self, signature: str, vars: dict[str, Any] = {}, *args: Any, **kwargs: Any) -> 'Schedule':
49
+ """
50
+ Defines a Orionis command to be executed.
51
+
52
+ Parameters
53
+ ----------
54
+ signature : str
55
+ The signature of the command to execute.
56
+ vars : dict, optional
57
+ A dictionary of variables to pass to the command, by default an empty dictionary.
58
+ *args : Any
59
+ Additional positional arguments to pass to the command.
60
+ **kwargs : Any
61
+ Additional keyword arguments to pass to the command.
62
+
63
+ Returns
64
+ -------
65
+ Schedule
66
+ Returns the Schedule instance itself, allowing method chaining.
67
+ """
68
+ # Store the command logic as a lambda function
69
+ def func():
70
+ try:
71
+ Command.call(signature, vars, *args, **kwargs)
72
+ finally:
73
+ if not self.scheduler.get_jobs():
74
+ self.wait = False
75
+
76
+ self.callback = func
77
+ return self
78
+
79
+ def _checkCommand(self):
80
+ """
81
+ Raises an exception to test the exception handling in the CLI.
82
+ """
83
+ if not self.callback:
84
+ raise CLIOrionisScheduleException("No command has been defined to execute.")
85
+
86
+ def _resetCallback(self):
87
+ """
88
+ Resets the callback function to None.
89
+ """
90
+ self.callback = None
91
+
92
+ def _hourFormat(self, at: str):
93
+ """
94
+ Validates the time format in 'HH:MM' 24-hour format.
95
+ """
96
+ if not isinstance(at, str):
97
+ raise CLIOrionisScheduleException("Time must be a string in 'HH:MM' format. Example: '23:59'.")
98
+
99
+ # Regular expression for the "HH:MM" 24-hour format
100
+ pattern = r"^(?:[01]\d|2[0-3]):[0-5]\d$"
101
+
102
+ if not re.match(pattern, at):
103
+ raise CLIOrionisScheduleException("Invalid time format. Expected 'HH:MM' (24-hour format). Example: '23:59'.")
104
+
105
+ return at.split(':')
106
+
107
+ def _checkDateTime(self, start_date: datetime = None, end_date: datetime = None):
108
+ """
109
+ Validates the `start_date` and `end_date` parameters.
110
+
111
+ Ensures that both parameters are either `None` or valid `datetime` instances.
112
+ Additionally, it verifies that `start_date` is earlier than `end_date` if both are provided.
113
+
114
+ Parameters
115
+ ----------
116
+ start_date : datetime, optional
117
+ The start time of the scheduled job. Must be a valid `datetime` object if provided.
118
+ end_date : datetime, optional
119
+ The end time of the scheduled job. Must be a valid `datetime` object if provided.
120
+
121
+ Raises
122
+ ------
123
+ CLIOrionisScheduleException
124
+ If `start_date` or `end_date` are not valid `datetime` objects.
125
+ If `start_date` is later than or equal to `end_date`.
126
+ """
127
+
128
+ # Ensure `start_date` is either None or a valid datetime object
129
+ if start_date is not None and not isinstance(start_date, datetime):
130
+ raise CLIOrionisScheduleException("start_date must be a valid datetime object.")
131
+
132
+ # Ensure `end_date` is either None or a valid datetime object
133
+ if end_date is not None and not isinstance(end_date, datetime):
134
+ raise CLIOrionisScheduleException("end_date must be a valid datetime object.")
135
+
136
+ # Ensure `start_date` is earlier than `end_date` if both are provided
137
+ if start_date and end_date and start_date >= end_date:
138
+ raise CLIOrionisScheduleException("start_date must be earlier than end_date.")
139
+
140
+ def _checkGreterThanZero(self, value: int, identifier: str = 'interval'):
141
+ """
142
+ Validates that the value is greater than 0.
143
+ """
144
+ if value < 1:
145
+ raise CLIOrionisScheduleException(f"The {identifier} must be greater than 0.")
146
+
147
+ def onceAt(self, date: datetime):
148
+ """
149
+ Schedule the defined command to execute every X seconds.
150
+ """
151
+ self._checkCommand()
152
+
153
+ if not isinstance(date, datetime):
154
+ raise CLIOrionisScheduleException("The date must be a valid datetime object.")
155
+
156
+ self.scheduler.add_job(
157
+ self.callback,
158
+ 'date',
159
+ run_date=date
160
+ )
161
+
162
+ self._resetCallback()
163
+
164
+ def everySeconds(self, seconds: int, start_date: datetime = None, end_date: datetime = None):
165
+ """
166
+ Schedule the defined command to execute every X seconds.
167
+ """
168
+ self._checkCommand()
169
+ self._checkGreterThanZero(seconds)
170
+ self._checkDateTime(start_date, end_date)
171
+
172
+ self.scheduler.add_job(
173
+ self.callback,
174
+ IntervalTrigger(seconds=seconds, start_date=start_date, end_date=end_date),
175
+ replace_existing=True
176
+ )
177
+
178
+ self._resetCallback()
179
+
180
+ def everySecond(self, start_date: datetime = None, end_date: datetime = None):
181
+ """
182
+ Schedules the defined command to execute every second.
183
+ """
184
+ self.everySeconds(seconds=1, start_date=start_date, end_date=end_date)
185
+
186
+ def everyTwoSeconds(self, start_date: datetime = None, end_date: datetime = None):
187
+ """
188
+ Schedules the defined command to execute every two seconds.
189
+ """
190
+ self.everySeconds(seconds=2, start_date=start_date, end_date=end_date)
191
+
192
+ def everyFiveSeconds(self, start_date: datetime = None, end_date: datetime = None):
193
+ """
194
+ Schedules the defined command to execute every five seconds.
195
+ """
196
+ self.everySeconds(seconds=5, start_date=start_date, end_date=end_date)
197
+
198
+ def everyTenSeconds(self, start_date: datetime = None, end_date: datetime = None):
199
+ """
200
+ Schedules the defined command to execute every ten seconds.
201
+ """
202
+ self.everySeconds(seconds=10, start_date=start_date, end_date=end_date)
203
+
204
+ def everyFifteenSeconds(self, start_date: datetime = None, end_date: datetime = None):
205
+ """
206
+ Schedules the defined command to execute every fifteen seconds.
207
+ """
208
+ self.everySeconds(seconds=15, start_date=start_date, end_date=end_date)
209
+
210
+ def everyTwentySeconds(self, start_date: datetime = None, end_date: datetime = None):
211
+ """
212
+ Schedules the defined command to execute every twenty seconds.
213
+ """
214
+ self.everySeconds(seconds=20, start_date=start_date, end_date=end_date)
215
+
216
+ def everyThirtySeconds(self, start_date: datetime = None, end_date: datetime = None):
217
+ """
218
+ Schedules the defined command to execute every thirty seconds.
219
+ """
220
+ self.everySeconds(seconds=30, start_date=start_date, end_date=end_date)
221
+
222
+ def everyMinutes(self, minutes: int, start_date: datetime = None, end_date: datetime = None):
223
+ """
224
+ Schedules the defined command to execute every X minutes.
225
+ """
226
+ self._checkCommand()
227
+ self._checkGreterThanZero(minutes)
228
+ self._checkDateTime(start_date, end_date)
229
+
230
+ self.scheduler.add_job(
231
+ self.callback,
232
+ IntervalTrigger(minutes=minutes, start_date=start_date, end_date=end_date),
233
+ replace_existing=True
234
+ )
235
+
236
+ self._resetCallback()
237
+
238
+ def everyMinute(self, start_date: datetime = None, end_date: datetime = None):
239
+ """
240
+ Schedules the defined command to execute every minute.
241
+ """
242
+ self.everyMinutes(minutes=1, start_date=start_date, end_date=end_date)
243
+
244
+ def everyTwoMinutes(self, start_date: datetime = None, end_date: datetime = None):
245
+ """
246
+ Schedules the defined command to execute every two minutes.
247
+ """
248
+ self.everyMinutes(minutes=2, start_date=start_date, end_date=end_date)
249
+
250
+ def everyThreeMinutes(self, start_date: datetime = None, end_date: datetime = None):
251
+ """
252
+ Schedules the defined command to execute every three minutes.
253
+ """
254
+ self.everyMinutes(minutes=3, start_date=start_date, end_date=end_date)
255
+
256
+ def everyFourMinutes(self, start_date: datetime = None, end_date: datetime = None):
257
+ """
258
+ Schedules the defined command to execute every four minutes.
259
+ """
260
+ self.everyMinutes(minutes=4, start_date=start_date, end_date=end_date)
261
+
262
+ def everyFiveMinutes(self, start_date: datetime = None, end_date: datetime = None):
263
+ """
264
+ Schedules the defined command to execute every five minutes.
265
+ """
266
+ self.everyMinutes(minutes=5, start_date=start_date, end_date=end_date)
267
+
268
+ def everyTenMinutes(self, start_date: datetime = None, end_date: datetime = None):
269
+ """
270
+ Schedules the defined command to execute every ten minutes.
271
+ """
272
+ self.everyMinutes(minutes=10, start_date=start_date, end_date=end_date)
273
+
274
+ def everyFifteenMinutes(self, start_date: datetime = None, end_date: datetime = None):
275
+ """
276
+ Schedules the defined command to execute every fifteen minutes.
277
+ """
278
+ self.everyMinutes(minutes=15, start_date=start_date, end_date=end_date)
279
+
280
+ def everyThirtyMinutes(self, start_date: datetime = None, end_date: datetime = None):
281
+ """
282
+ Schedules the defined command to execute every thirty minutes.
283
+ """
284
+ self.everyMinutes(minutes=30, start_date=start_date, end_date=end_date)
285
+
286
+ def hours(self, hours: int, start_date: datetime = None, end_date: datetime = None):
287
+ """
288
+ Schedules the defined command to execute every X hours.
289
+ """
290
+ self._checkCommand()
291
+ self._checkGreterThanZero(hours)
292
+ self._checkDateTime(start_date, end_date)
293
+
294
+ self.scheduler.add_job(
295
+ self.callback,
296
+ IntervalTrigger(hours=hours, start_date=start_date, end_date=end_date),
297
+ replace_existing=True
298
+ )
299
+
300
+ self._resetCallback()
301
+
302
+ def hourly(self, start_date: datetime = None, end_date: datetime = None):
303
+ """
304
+ Schedules the defined command to execute every hour.
305
+ """
306
+ self.hours(hours=1, start_date=start_date, end_date=end_date)
307
+
308
+ def hourlyAt(self, minute: int, start_date: datetime = None, end_date: datetime = None):
309
+ """
310
+ Schedules the defined command to execute every hour at a specific minute.
311
+ """
312
+ self._checkCommand()
313
+ self._checkGreterThanZero(minute)
314
+ self._checkDateTime(start_date, end_date)
315
+
316
+ self.scheduler.add_job(
317
+ self.callback,
318
+ CronTrigger(hour='*', minute=minute, start_date=start_date, end_date=end_date),
319
+ replace_existing=True
320
+ )
321
+
322
+ self._resetCallback()
323
+
324
+ def everyOddHour(self, minute: int, start_date: datetime = None, end_date: datetime = None):
325
+ """
326
+ Schedules the defined command to execute every odd hour.
327
+ """
328
+ self._checkCommand()
329
+ self._checkGreterThanZero(minute)
330
+ self._checkDateTime(start_date, end_date)
331
+
332
+ self.scheduler.add_job(
333
+ self.callback,
334
+ CronTrigger(hour='1,3,5,7,9,11,13,15,17,19,21,23', minute=minute, start_date=start_date, end_date=end_date),
335
+ replace_existing=True
336
+ )
337
+
338
+ self._resetCallback()
339
+
340
+ def everyTwoHours(self, minute: int, start_date: datetime = None, end_date: datetime = None):
341
+ """
342
+ Schedules the defined command to execute every two hours.
343
+ """
344
+ self._checkCommand()
345
+ self._checkGreterThanZero(minute)
346
+ self._checkDateTime(start_date, end_date)
347
+
348
+ self.scheduler.add_job(
349
+ self.callback,
350
+ CronTrigger(hour='*/2', minute=minute, start_date=start_date, end_date=end_date),
351
+ replace_existing=True
352
+ )
353
+
354
+ self._resetCallback()
355
+
356
+ def everyThreeHours(self, minute: int, start_date: datetime = None, end_date: datetime = None):
357
+ """
358
+ Schedules the defined command to execute every three hours.
359
+ """
360
+ self._checkCommand()
361
+ self._checkGreterThanZero(minute)
362
+ self._checkDateTime(start_date, end_date)
363
+
364
+ self.scheduler.add_job(
365
+ self.callback,
366
+ CronTrigger(hour='*/3', minute=minute, start_date=start_date, end_date=end_date),
367
+ replace_existing=True
368
+ )
369
+
370
+ self._resetCallback()
371
+
372
+ def everyFourHours(self, minute: int, start_date: datetime = None, end_date: datetime = None):
373
+ """
374
+ Schedules the defined command to execute every four hours.
375
+ """
376
+ self._checkCommand()
377
+ self._checkGreterThanZero(minute)
378
+ self._checkDateTime(start_date, end_date)
379
+
380
+ self.scheduler.add_job(
381
+ self.callback,
382
+ CronTrigger(hour='*/4', minute=minute, start_date=start_date, end_date=end_date),
383
+ replace_existing=True
384
+ )
385
+
386
+ self._resetCallback()
387
+
388
+ def everySixHours(self, minute: int, start_date: datetime = None, end_date: datetime = None):
389
+ """
390
+ Schedules the defined command to execute every six hours.
391
+ """
392
+ self._checkCommand()
393
+ self._checkGreterThanZero(minute)
394
+ self._checkDateTime(start_date, end_date)
395
+
396
+ self.scheduler.add_job(
397
+ self.callback,
398
+ CronTrigger(hour='*/6', minute=minute, start_date=start_date, end_date=end_date),
399
+ replace_existing=True
400
+ )
401
+
402
+ self._resetCallback()
403
+
404
+ def days(self, days: int, start_date: datetime = None, end_date: datetime = None):
405
+ """
406
+ Schedules the defined command to execute every X days.
407
+ """
408
+ self._checkCommand()
409
+ self._checkGreterThanZero(days)
410
+ self._checkDateTime(start_date, end_date)
411
+
412
+ self.scheduler.add_job(
413
+ self.callback,
414
+ IntervalTrigger(days=days, start_date=start_date, end_date=end_date),
415
+ replace_existing=True
416
+ )
417
+
418
+ self._resetCallback()
419
+
420
+ def daily(self, start_date: datetime = None, end_date: datetime = None):
421
+ """
422
+ Schedules the defined command to execute daily at midnight.
423
+ """
424
+ self._checkCommand()
425
+ self._checkDateTime(start_date, end_date)
426
+
427
+ self.scheduler.add_job(
428
+ self.callback,
429
+ CronTrigger(hour=0, minute=0, second=1, start_date=start_date, end_date=end_date),
430
+ replace_existing=True
431
+ )
432
+
433
+ self._resetCallback()
434
+
435
+ def dailyAt(self, at: str, start_date: datetime = None, end_date: datetime = None):
436
+ """
437
+ Schedules the defined command to execute daily at a specific time.
438
+ """
439
+ self._checkCommand()
440
+ self._checkDateTime(start_date, end_date)
441
+ hour, minute = self._hourFormat(at)
442
+
443
+ self.scheduler.add_job(
444
+ self.callback,
445
+ CronTrigger(hour=hour, minute=minute, start_date=start_date, end_date=end_date),
446
+ replace_existing=True
447
+ )
448
+
449
+ self._resetCallback()
450
+
451
+ def twiceDaily(self, first_hour: int, second_hour: int, start_date: datetime = None, end_date: datetime = None):
452
+ """
453
+ Schedules the defined command to execute twice a day at specific hours.
454
+ """
455
+ self._checkCommand()
456
+ self._checkGreterThanZero(first_hour)
457
+ self._checkGreterThanZero(second_hour)
458
+ self._checkDateTime(start_date, end_date)
459
+
460
+ self.scheduler.add_job(
461
+ self.callback,
462
+ CronTrigger(hour=f'{first_hour},{second_hour}', minute=0, start_date=start_date, end_date=end_date),
463
+ replace_existing=True
464
+ )
465
+
466
+ self._resetCallback()
467
+
468
+ def monday(self, at: str, start_date: datetime = None, end_date: datetime = None):
469
+ """
470
+ Schedules the defined command to execute every Monday at a specific time.
471
+ """
472
+
473
+ self._checkCommand()
474
+ self._checkDateTime(start_date, end_date)
475
+ hour, minute = self._hourFormat(at)
476
+
477
+ self.scheduler.add_job(
478
+ self.callback,
479
+ CronTrigger(day_of_week='mon', hour=hour, minute=minute, start_date=start_date, end_date=end_date),
480
+ replace_existing=True
481
+ )
482
+
483
+ self._resetCallback()
484
+
485
+ def tuesday(self, at: str, start_date: datetime = None, end_date: datetime = None):
486
+ """
487
+ Schedules the defined command to execute every tuesday at a specific time.
488
+ """
489
+
490
+ self._checkCommand()
491
+ self._checkDateTime(start_date, end_date)
492
+ hour, minute = self._hourFormat(at)
493
+
494
+ self.scheduler.add_job(
495
+ self.callback,
496
+ CronTrigger(day_of_week='tue', hour=hour, minute=minute, start_date=start_date, end_date=end_date),
497
+ replace_existing=True
498
+ )
499
+
500
+ self._resetCallback()
501
+
502
+ def wednesday(self, at: str, start_date: datetime = None, end_date: datetime = None):
503
+ """
504
+ Schedules the defined command to execute every wednesday at a specific time.
505
+ """
506
+
507
+ self._checkCommand()
508
+ self._checkDateTime(start_date, end_date)
509
+ hour, minute = self._hourFormat(at)
510
+
511
+ self.scheduler.add_job(
512
+ self.callback,
513
+ CronTrigger(day_of_week='wed', hour=hour, minute=minute, start_date=start_date, end_date=end_date),
514
+ replace_existing=True
515
+ )
516
+
517
+ self._resetCallback()
518
+
519
+ def thursday(self, at: str, start_date: datetime = None, end_date: datetime = None):
520
+ """
521
+ Schedules the defined command to execute every thursday at a specific time.
522
+ """
523
+
524
+ self._checkCommand()
525
+ self._checkDateTime(start_date, end_date)
526
+ hour, minute = self._hourFormat(at)
527
+
528
+ self.scheduler.add_job(
529
+ self.callback,
530
+ CronTrigger(day_of_week='thu', hour=hour, minute=minute, start_date=start_date, end_date=end_date),
531
+ replace_existing=True
532
+ )
533
+
534
+ self._resetCallback()
535
+
536
+ def friday(self, at: str, start_date: datetime = None, end_date: datetime = None):
537
+ """
538
+ Schedules the defined command to execute every friday at a specific time.
539
+ """
540
+
541
+ self._checkCommand()
542
+ self._checkDateTime(start_date, end_date)
543
+ hour, minute = self._hourFormat(at)
544
+
545
+ self.scheduler.add_job(
546
+ self.callback,
547
+ CronTrigger(day_of_week='fri', hour=hour, minute=minute, start_date=start_date, end_date=end_date),
548
+ replace_existing=True
549
+ )
550
+
551
+ self._resetCallback()
552
+
553
+ def saturday(self, at: str, start_date: datetime = None, end_date: datetime = None):
554
+ """
555
+ Schedules the defined command to execute every saturday at a specific time.
556
+ """
557
+
558
+ self._checkCommand()
559
+ self._checkDateTime(start_date, end_date)
560
+ hour, minute = self._hourFormat(at)
561
+
562
+ self.scheduler.add_job(
563
+ self.callback,
564
+ CronTrigger(day_of_week='sat', hour=hour, minute=minute, start_date=start_date, end_date=end_date),
565
+ replace_existing=True
566
+ )
567
+
568
+ self._resetCallback()
569
+
570
+ def sunday(self, at: str, start_date: datetime = None, end_date: datetime = None):
571
+ """
572
+ Schedules the defined command to execute every sunday at a specific time.
573
+ """
574
+
575
+ self._checkCommand()
576
+ self._checkDateTime(start_date, end_date)
577
+ hour, minute = self._hourFormat(at)
578
+
579
+ self.scheduler.add_job(
580
+ self.callback,
581
+ CronTrigger(day_of_week='sun', hour=hour, minute=minute, start_date=start_date, end_date=end_date),
582
+ replace_existing=True
583
+ )
584
+
585
+ self._resetCallback()
586
+
587
+ def weekly(self, start_date: datetime = None, end_date: datetime = None):
588
+ """
589
+ Schedules the defined command to execute weekly on Sunday at midnight.
590
+ """
591
+
592
+ self._checkCommand()
593
+ self._checkDateTime(start_date, end_date)
594
+
595
+ self.scheduler.add_job(
596
+ self.callback,
597
+ CronTrigger(day_of_week='sun', hour=0, minute=0, second=1, start_date=start_date, end_date=end_date),
598
+ replace_existing=True
599
+ )
600
+
601
+ self._resetCallback()
602
+
603
+ def start(self):
604
+ """
605
+ Starts the scheduler and stops automatically when there are no more jobs.
606
+ """
607
+ try:
608
+ # Start the scheduler
609
+ while self.wait:
610
+ time.sleep(1)
611
+ except (KeyboardInterrupt, SystemExit):
612
+ # Stop the scheduler if it is running
613
+ if self.scheduler.running:
614
+ self.scheduler.shutdown()
615
+ # Exit with status code 1 to indicate an error
616
+ sys.exit(1)
File without changes
@@ -0,0 +1,46 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any
3
+
4
+ class IParser(ABC):
5
+ """
6
+ A class responsible for parsing an instance's configuration and outputting it as a dictionary.
7
+
8
+ This class uses Python's `dataclasses.asdict()` method to convert an instance's `config` attribute to a dictionary.
9
+
10
+ Methods
11
+ -------
12
+ parse(instance: Any) -> dict
13
+ Takes an instance with a `config` attribute and returns its dictionary representation.
14
+
15
+ Notes
16
+ -----
17
+ - This method expects the instance to have a `config` attribute that is a dataclass or any object that supports `asdict()`.
18
+ - The `asdict()` function will recursively convert dataclass fields into a dictionary format.
19
+ - If `instance.config` is not a dataclass, this could raise an exception depending on the type.
20
+ """
21
+
22
+ @abstractmethod
23
+ def toDict(self, instance: Any) -> dict:
24
+ """
25
+ Converts the `config` attribute of the provided instance to a dictionary and returns it.
26
+
27
+ Parameters
28
+ ----------
29
+ instance : Any
30
+ The instance to parse. It is expected that the instance has a `config` attribute
31
+ that is a dataclass or any object that supports `asdict()`.
32
+
33
+ Returns
34
+ -------
35
+ dict
36
+ The dictionary representation of the `config` attribute.
37
+
38
+ Raises
39
+ ------
40
+ AttributeError
41
+ If the `instance` does not have a `config` attribute.
42
+ TypeError
43
+ If the `instance.config` is not a valid dataclass or object that supports `asdict()`.
44
+ """
45
+ pass
46
+
File without changes