asyncz 0.8.2__tar.gz → 0.8.3__tar.gz
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.
- {asyncz-0.8.2 → asyncz-0.8.3}/PKG-INFO +1 -1
- asyncz-0.8.3/asyncz/__init__.py +1 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/executors/base.py +1 -3
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/schedulers/base.py +0 -2
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/stores/memory.py +1 -1
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/utils.py +5 -1
- asyncz-0.8.2/asyncz/__init__.py +0 -1
- asyncz-0.8.2/asyncz/contrib/esmerald/__init__.py +0 -0
- asyncz-0.8.2/asyncz/contrib/esmerald/decorator.py +0 -40
- asyncz-0.8.2/asyncz/contrib/esmerald/scheduler.py +0 -217
- asyncz-0.8.2/asyncz/stores/__init__.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/.gitignore +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/LICENSE +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/README.md +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/_mapping.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/datastructures.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/enums.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/events/__init__.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/events/base.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/events/constants.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/exceptions.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/executors/__init__.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/executors/asyncio.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/executors/debug.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/executors/pool.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/executors/types.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/py.typed +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/schedulers/__init__.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/schedulers/asyncio.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/schedulers/datastructures.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/schedulers/types.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/schedulers/utils.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/state.py +0 -0
- {asyncz-0.8.2/asyncz/contrib → asyncz-0.8.3/asyncz/stores}/__init__.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/stores/base.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/stores/mongo.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/stores/redis.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/stores/types.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/tasks/__init__.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/tasks/base.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/tasks/types.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/__init__.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/base.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/combination.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/cron/__init__.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/cron/constants.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/cron/expressions.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/cron/fields.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/cron/trigger.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/cron/types.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/date.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/interval.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/triggers/types.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/asyncz/typing.py +0 -0
- {asyncz-0.8.2 → asyncz-0.8.3}/pyproject.toml +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.8.3"
|
|
@@ -97,9 +97,7 @@ class BaseExecutor(BaseStateExtra, ABC):
|
|
|
97
97
|
if self.instances[task_id] == 0:
|
|
98
98
|
del self.instances[task_id]
|
|
99
99
|
|
|
100
|
-
self.logger.opt(exception=True).error(
|
|
101
|
-
f"Error running task {task_id}", exc_info=True
|
|
102
|
-
)
|
|
100
|
+
self.logger.opt(exception=True).error(f"Error running task {task_id}", exc_info=True)
|
|
103
101
|
|
|
104
102
|
|
|
105
103
|
def run_task(
|
|
@@ -155,7 +155,6 @@ class BaseScheduler(BaseStateExtra, ABC):
|
|
|
155
155
|
raise SchedulerAlreadyRunningError()
|
|
156
156
|
|
|
157
157
|
self.check_uwsgi()
|
|
158
|
-
|
|
159
158
|
with self.executor_lock:
|
|
160
159
|
if "default" not in self.executors:
|
|
161
160
|
self.add_executor(self.create_default_executor(), "default")
|
|
@@ -824,7 +823,6 @@ class BaseScheduler(BaseStateExtra, ABC):
|
|
|
824
823
|
|
|
825
824
|
# Apply replacements
|
|
826
825
|
task._update(**replacements)
|
|
827
|
-
|
|
828
826
|
# Add the task to the given store
|
|
829
827
|
store = self.lookup_store(store_alias)
|
|
830
828
|
try:
|
|
@@ -234,10 +234,14 @@ def ref_to_obj(ref: str) -> Any:
|
|
|
234
234
|
raise AsynczLookupError(
|
|
235
235
|
"Error resolving reference %s: could not import module" % ref
|
|
236
236
|
) from None
|
|
237
|
-
|
|
238
237
|
try:
|
|
239
238
|
for name in rest.split("."):
|
|
240
239
|
obj = getattr(obj, name)
|
|
240
|
+
|
|
241
|
+
# It might come from a class containing the fn attribute
|
|
242
|
+
# implementation of the __call__ method
|
|
243
|
+
if hasattr(obj, "fn"):
|
|
244
|
+
obj = obj.fn
|
|
241
245
|
return obj
|
|
242
246
|
except Exception:
|
|
243
247
|
raise AsynczLookupError(
|
asyncz-0.8.2/asyncz/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.8.2"
|
|
File without changes
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
|
-
from typing import Any, Dict, Optional
|
|
3
|
-
|
|
4
|
-
from asyncz.contrib.esmerald.scheduler import Task
|
|
5
|
-
from asyncz.triggers.types import TriggerType
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class scheduler(Task):
|
|
9
|
-
def __init__(
|
|
10
|
-
self,
|
|
11
|
-
*,
|
|
12
|
-
name: Optional[str] = None,
|
|
13
|
-
trigger: Optional[TriggerType] = None,
|
|
14
|
-
id: Optional[str] = None,
|
|
15
|
-
mistrigger_grace_time: Optional[int] = None,
|
|
16
|
-
coalesce: Optional[bool] = None,
|
|
17
|
-
max_instances: Optional[int] = None,
|
|
18
|
-
next_run_time: Optional[datetime] = None,
|
|
19
|
-
store: Optional[str] = "default",
|
|
20
|
-
executor: Optional[str] = "default",
|
|
21
|
-
replace_existing: bool = True,
|
|
22
|
-
extra_args: Optional[Any] = None,
|
|
23
|
-
extra_kwargs: Optional[Dict[str, Any]] = None,
|
|
24
|
-
is_enabled: bool = True,
|
|
25
|
-
) -> None:
|
|
26
|
-
super().__init__(
|
|
27
|
-
name=name,
|
|
28
|
-
trigger=trigger,
|
|
29
|
-
id=id,
|
|
30
|
-
mistrigger_grace_time=mistrigger_grace_time,
|
|
31
|
-
coalesce=coalesce,
|
|
32
|
-
max_instances=max_instances,
|
|
33
|
-
next_run_time=next_run_time,
|
|
34
|
-
store=store,
|
|
35
|
-
executor=executor,
|
|
36
|
-
replace_existing=replace_existing,
|
|
37
|
-
args=extra_args,
|
|
38
|
-
kwargs=extra_kwargs,
|
|
39
|
-
is_enabled=is_enabled,
|
|
40
|
-
)
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import warnings
|
|
2
|
-
from datetime import datetime
|
|
3
|
-
from datetime import timezone as dtimezone
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
|
|
5
|
-
|
|
6
|
-
from asyncz.schedulers.types import SchedulerType
|
|
7
|
-
from asyncz.triggers.types import TriggerType
|
|
8
|
-
from asyncz.typing import undefined
|
|
9
|
-
|
|
10
|
-
try:
|
|
11
|
-
from esmerald.conf import settings
|
|
12
|
-
from esmerald.exceptions import ImproperlyConfigured
|
|
13
|
-
from esmerald.utils.module_loading import import_string
|
|
14
|
-
except ImportError:
|
|
15
|
-
raise ImportError(
|
|
16
|
-
"Esmerald cannot be found. Please install it by running `pip install esmerald`."
|
|
17
|
-
) from None
|
|
18
|
-
|
|
19
|
-
if TYPE_CHECKING:
|
|
20
|
-
from esmerald.applications import Esmerald
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class EsmeraldScheduler:
|
|
24
|
-
"""
|
|
25
|
-
Scheduler instance to be used by the Esmerald application instance.
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
app: Esmerald application
|
|
29
|
-
scheduler_class: An instance of a SchedulerType
|
|
30
|
-
tasks: A dictinary str, str mapping the tasks to be executed.
|
|
31
|
-
timezone: The timezone instance.
|
|
32
|
-
configurations: A dictionary with extra configurations to be passed to the scheduler.
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
def __init__(
|
|
36
|
-
self,
|
|
37
|
-
app: Optional["Esmerald"] = None,
|
|
38
|
-
scheduler_class: Optional["SchedulerType"] = None,
|
|
39
|
-
tasks: Optional[Dict[str, str]] = None,
|
|
40
|
-
timezone: Optional[Union[dtimezone, str]] = None,
|
|
41
|
-
configurations: Optional[Dict[str, Dict[str, str]]] = None,
|
|
42
|
-
) -> None:
|
|
43
|
-
self.app = app
|
|
44
|
-
self.tasks = tasks
|
|
45
|
-
self.timezone = timezone
|
|
46
|
-
self.scheduler_class = scheduler_class
|
|
47
|
-
self.configurations = configurations
|
|
48
|
-
|
|
49
|
-
if not self.scheduler_class and self.app.enable_scheduler:
|
|
50
|
-
raise ImproperlyConfigured(
|
|
51
|
-
"It cannot start the scheduler if there is no scheduler_class declared."
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
for task, module in self.tasks.items():
|
|
55
|
-
if not isinstance(task, str) or not isinstance(module, str):
|
|
56
|
-
raise ImproperlyConfigured("The dict of tasks must be Dict[str, str].")
|
|
57
|
-
|
|
58
|
-
if not self.tasks:
|
|
59
|
-
warnings.warn(
|
|
60
|
-
"Esmerald is starting the scheduler, yet there are no tasks declared.",
|
|
61
|
-
UserWarning,
|
|
62
|
-
stacklevel=2,
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
# Load the scheduler object
|
|
66
|
-
self.handler = self.get_scheduler(
|
|
67
|
-
scheduler=self.scheduler_class,
|
|
68
|
-
timezone=self.timezone,
|
|
69
|
-
configurations=self.configurations,
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
self.register_events(app=self.app)
|
|
73
|
-
self.register_tasks(tasks=self.tasks)
|
|
74
|
-
|
|
75
|
-
def register_tasks(self, tasks: Dict[str, str]) -> None:
|
|
76
|
-
"""
|
|
77
|
-
Registers the tasks in the Scheduler
|
|
78
|
-
"""
|
|
79
|
-
for task, _module in tasks.items():
|
|
80
|
-
imported_task = f"{_module}.{task}"
|
|
81
|
-
scheduled_task: "Task" = import_string(imported_task)
|
|
82
|
-
|
|
83
|
-
if not scheduled_task.is_enabled:
|
|
84
|
-
continue
|
|
85
|
-
|
|
86
|
-
try:
|
|
87
|
-
scheduled_task.add_task(self.handler)
|
|
88
|
-
except Exception as e:
|
|
89
|
-
raise ImproperlyConfigured(str(e)) from e
|
|
90
|
-
|
|
91
|
-
def register_events(self, app: "Esmerald") -> None:
|
|
92
|
-
"""
|
|
93
|
-
Registers the scheduler events in the Esmerald application.
|
|
94
|
-
"""
|
|
95
|
-
if app.on_startup is not None:
|
|
96
|
-
app.on_startup.append(self.handler.start)
|
|
97
|
-
else:
|
|
98
|
-
app.on_startup = [self.handler.start]
|
|
99
|
-
|
|
100
|
-
if app.on_shutdown is not None:
|
|
101
|
-
app.on_shutdown.append(self.handler.shutdown)
|
|
102
|
-
else:
|
|
103
|
-
app.on_shutdown = [self.handler.shutdown]
|
|
104
|
-
|
|
105
|
-
def get_scheduler(
|
|
106
|
-
self,
|
|
107
|
-
scheduler: "SchedulerType",
|
|
108
|
-
timezone: Optional[dtimezone] = None,
|
|
109
|
-
configurations: Optional[Dict[str, str]] = None,
|
|
110
|
-
) -> SchedulerType:
|
|
111
|
-
"""
|
|
112
|
-
Initiates the scheduler from the given time.
|
|
113
|
-
If no value is provided, it will default to AsyncIOScheduler.
|
|
114
|
-
|
|
115
|
-
The value of `scheduler_class` can be overwritten by any esmerald custom settings.
|
|
116
|
-
|
|
117
|
-
Args:
|
|
118
|
-
scheduler: AsyncIOScheduler.
|
|
119
|
-
timezone: The timezone instance.
|
|
120
|
-
configurations: A dictionary with extra configurations to be passed to the scheduler.
|
|
121
|
-
|
|
122
|
-
Return:
|
|
123
|
-
SchedulerType: An instance of a Scheduler.
|
|
124
|
-
"""
|
|
125
|
-
if not timezone:
|
|
126
|
-
timezone = settings.timezone
|
|
127
|
-
|
|
128
|
-
if not configurations:
|
|
129
|
-
return scheduler(timezone=timezone)
|
|
130
|
-
|
|
131
|
-
return scheduler(global_config=configurations, timezone=timezone)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
class Task:
|
|
135
|
-
"""
|
|
136
|
-
Base for the scheduler decorator that will auto discover the
|
|
137
|
-
tasks in the application and add them to the internal scheduler.
|
|
138
|
-
"""
|
|
139
|
-
|
|
140
|
-
def __init__(
|
|
141
|
-
self,
|
|
142
|
-
*,
|
|
143
|
-
name: Optional[str] = None,
|
|
144
|
-
trigger: Optional[TriggerType] = None,
|
|
145
|
-
id: Optional[str] = None,
|
|
146
|
-
mistrigger_grace_time: Optional[int] = None,
|
|
147
|
-
coalesce: Optional[bool] = None,
|
|
148
|
-
max_instances: Optional[int] = None,
|
|
149
|
-
next_run_time: Optional[datetime] = None,
|
|
150
|
-
store: Optional[str] = "default",
|
|
151
|
-
executor: Optional[str] = "default",
|
|
152
|
-
replace_existing: bool = False,
|
|
153
|
-
args: Optional[Any] = None,
|
|
154
|
-
kwargs: Optional[Dict[str, Any]] = None,
|
|
155
|
-
is_enabled: bool = True,
|
|
156
|
-
) -> None:
|
|
157
|
-
"""_summary_
|
|
158
|
-
|
|
159
|
-
Args:
|
|
160
|
-
name: Textual description of the task.
|
|
161
|
-
trigger: An instance of a trigger class.
|
|
162
|
-
identifier: Explicit identifier for the task.
|
|
163
|
-
mistrigger_grace_time: Seconds after the designated runtime that the task is still allowed to be run (or None to allow the task to run no
|
|
164
|
-
matter how late it is).
|
|
165
|
-
coalesce: Run once instead of many times if the scheduler determines that the task should be run more than once in succession.
|
|
166
|
-
max_instances: Maximum number of concurrently running instances allowed for this task.
|
|
167
|
-
next_run_time: When to first run the task, regardless of the trigger (pass None to add the task as paused).
|
|
168
|
-
store: Alias of the task store to store the task in.
|
|
169
|
-
executor: Alias of the executor to run the task with.
|
|
170
|
-
replace_existing: True to replace an existing task with the same id
|
|
171
|
-
(but retain the number of runs from the existing one).
|
|
172
|
-
args: List of positional arguments to call func with.
|
|
173
|
-
kwargs: Dict of keyword arguments to call func with.
|
|
174
|
-
is_enabled: True if the the task to be added to the scheduler.
|
|
175
|
-
"""
|
|
176
|
-
self.name = name
|
|
177
|
-
self.trigger = trigger
|
|
178
|
-
self.id = id
|
|
179
|
-
self.mistrigger_grace_time = mistrigger_grace_time or undefined
|
|
180
|
-
self.coalesce = coalesce or undefined
|
|
181
|
-
self.max_instances = max_instances or undefined
|
|
182
|
-
self.next_run_time = next_run_time or undefined
|
|
183
|
-
self.store = store
|
|
184
|
-
self.executor = executor
|
|
185
|
-
self.replace_existing = replace_existing
|
|
186
|
-
self.args = args
|
|
187
|
-
self.kwargs = kwargs
|
|
188
|
-
self.is_enabled = is_enabled
|
|
189
|
-
self.fn = None
|
|
190
|
-
|
|
191
|
-
def add_task(self, scheduler: "SchedulerType"):
|
|
192
|
-
try:
|
|
193
|
-
scheduler.add_task(
|
|
194
|
-
fn=self.fn,
|
|
195
|
-
trigger=self.trigger,
|
|
196
|
-
args=self.args,
|
|
197
|
-
kwargs=self.kwargs,
|
|
198
|
-
id=self.id,
|
|
199
|
-
name=self.name,
|
|
200
|
-
mistrigger_grace_time=self.mistrigger_grace_time,
|
|
201
|
-
coalesce=self.coalesce,
|
|
202
|
-
max_instances=self.max_instances,
|
|
203
|
-
next_run_time=self.next_run_time,
|
|
204
|
-
store=self.store,
|
|
205
|
-
executor=self.executor,
|
|
206
|
-
replace_existing=self.replace_existing,
|
|
207
|
-
)
|
|
208
|
-
except Exception as e:
|
|
209
|
-
raise ImproperlyConfigured(str(e)) from e
|
|
210
|
-
|
|
211
|
-
def __call__(self, fn: Any) -> None:
|
|
212
|
-
"""
|
|
213
|
-
Tricking the object into think it's being instantiated by in reality
|
|
214
|
-
is just returning itself.
|
|
215
|
-
"""
|
|
216
|
-
self.fn = fn
|
|
217
|
-
return self
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|