asyncz 0.6.0__tar.gz → 0.8.0__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.6.0 → asyncz-0.8.0}/PKG-INFO +42 -65
- {asyncz-0.6.0 → asyncz-0.8.0}/README.md +25 -25
- asyncz-0.8.0/asyncz/__init__.py +1 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/_mapping.py +1 -1
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/contrib/esmerald/scheduler.py +9 -9
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/executors/base.py +6 -4
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/schedulers/asyncio.py +7 -2
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/schedulers/base.py +5 -11
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/stores/redis.py +15 -8
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/interval.py +14 -3
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/utils.py +11 -17
- {asyncz-0.6.0 → asyncz-0.8.0}/pyproject.toml +38 -30
- asyncz-0.6.0/asyncz/__init__.py +0 -1
- {asyncz-0.6.0 → asyncz-0.8.0}/.gitignore +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/LICENSE +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/contrib/__init__.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/contrib/esmerald/__init__.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/contrib/esmerald/decorator.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/datastructures.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/enums.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/events/__init__.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/events/base.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/events/constants.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/exceptions.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/executors/__init__.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/executors/asyncio.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/executors/debug.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/executors/pool.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/executors/types.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/py.typed +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/schedulers/__init__.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/schedulers/datastructures.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/schedulers/types.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/schedulers/utils.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/state.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/stores/__init__.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/stores/base.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/stores/memory.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/stores/mongo.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/stores/types.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/tasks/__init__.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/tasks/base.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/tasks/types.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/__init__.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/base.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/combination.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/cron/__init__.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/cron/constants.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/cron/expressions.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/cron/fields.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/cron/trigger.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/cron/types.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/date.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/triggers/types.py +0 -0
- {asyncz-0.6.0 → asyncz-0.8.0}/asyncz/typing.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: asyncz
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: The scheduler that nobody wants but every application needs.
|
|
5
|
-
Project-URL: Homepage, https://github.com/
|
|
6
|
-
Project-URL: Documentation, https://asyncz.
|
|
7
|
-
Project-URL: Changelog, https://asyncz.
|
|
5
|
+
Project-URL: Homepage, https://github.com/dymmond/asyncz
|
|
6
|
+
Project-URL: Documentation, https://asyncz.dymmond.com/
|
|
7
|
+
Project-URL: Changelog, https://asyncz.dymmond.com/release-notes/
|
|
8
8
|
Project-URL: Funding, https://github.com/sponsors/tarsil
|
|
9
|
-
Project-URL: Source, https://github.com/
|
|
9
|
+
Project-URL: Source, https://github.com/dymmond/asyncz
|
|
10
10
|
Author-email: Tiago Silva <tiago.arasilva@gmail.com>
|
|
11
11
|
License-Expression: MIT
|
|
12
12
|
License-File: LICENSE
|
|
@@ -37,43 +37,20 @@ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
|
37
37
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
38
38
|
Classifier: Typing :: Typed
|
|
39
39
|
Requires-Python: >=3.8
|
|
40
|
-
Requires-Dist:
|
|
40
|
+
Requires-Dist: backports-zoneinfo; python_version < '3.9'
|
|
41
41
|
Requires-Dist: loguru<0.8.0,>=0.7.0
|
|
42
42
|
Requires-Dist: pydantic<3.0.0,>=2.5.3
|
|
43
|
-
Requires-Dist:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Requires-Dist:
|
|
47
|
-
Requires-Dist:
|
|
48
|
-
Requires-Dist:
|
|
49
|
-
|
|
50
|
-
Requires-Dist:
|
|
51
|
-
Requires-Dist:
|
|
52
|
-
Requires-Dist:
|
|
53
|
-
Requires-Dist:
|
|
54
|
-
Requires-Dist: isort<6.0.0,>=5.0.6; extra == 'dev'
|
|
55
|
-
Requires-Dist: mypy<2.0.0,>=0.982; extra == 'dev'
|
|
56
|
-
Requires-Dist: pdbpp; extra == 'dev'
|
|
57
|
-
Requires-Dist: pre-commit<3.0.0,>=2.17.0; extra == 'dev'
|
|
58
|
-
Requires-Dist: watchfiles<0.22.0,>=0.16.1; extra == 'dev'
|
|
59
|
-
Provides-Extra: doc
|
|
60
|
-
Requires-Dist: mdx-include<2.0.0,>=1.4.2; extra == 'doc'
|
|
61
|
-
Requires-Dist: mkautodoc<0.3.0,>=0.2.0; extra == 'doc'
|
|
62
|
-
Requires-Dist: mkdocs-markdownextradata-plugin<0.3.0,>=0.2.5; extra == 'doc'
|
|
63
|
-
Requires-Dist: mkdocs-material<10.0.0,>=9.0.13; extra == 'doc'
|
|
64
|
-
Requires-Dist: mkdocs<2.0.0,>=1.1.2; extra == 'doc'
|
|
65
|
-
Requires-Dist: mkdocstrings<0.30.0,>=0.20.0; extra == 'doc'
|
|
66
|
-
Requires-Dist: pyyaml<7.0.0,>=6.0; extra == 'doc'
|
|
67
|
-
Provides-Extra: test
|
|
68
|
-
Requires-Dist: mock>=4.0.3; extra == 'test'
|
|
69
|
-
Requires-Dist: pymongo<5.0.0,>=4.3.3; extra == 'test'
|
|
70
|
-
Requires-Dist: pytest-asyncio<1.0.0,>=0.19.0; extra == 'test'
|
|
71
|
-
Requires-Dist: pytest-cov<6.0.0,>=2.12.0; extra == 'test'
|
|
72
|
-
Requires-Dist: pytest-loguru<1,>=0.2.0; extra == 'test'
|
|
73
|
-
Requires-Dist: pytest<9.0.0,>=7.1.3; extra == 'test'
|
|
74
|
-
Requires-Dist: redis<6.0.0,>=4.4.0; extra == 'test'
|
|
75
|
-
Requires-Dist: requests<3.0.0,>=2.27.0; extra == 'test'
|
|
76
|
-
Requires-Dist: ruff<1.0.0,>=0.0.256; extra == 'test'
|
|
43
|
+
Requires-Dist: tzlocal<6.0,>=4.0
|
|
44
|
+
Provides-Extra: testing
|
|
45
|
+
Requires-Dist: esmerald; extra == 'testing'
|
|
46
|
+
Requires-Dist: mypy<2.0.0,>=0.982; extra == 'testing'
|
|
47
|
+
Requires-Dist: pymongo<5.0.0,>=4.3.3; extra == 'testing'
|
|
48
|
+
Requires-Dist: pytest-asyncio<1.0.0,>=0.19.0; extra == 'testing'
|
|
49
|
+
Requires-Dist: pytest-cov<6.0.0,>=2.12.0; extra == 'testing'
|
|
50
|
+
Requires-Dist: pytest-loguru<1,>=0.2.0; extra == 'testing'
|
|
51
|
+
Requires-Dist: pytest<9.0.0,>=7.1.3; extra == 'testing'
|
|
52
|
+
Requires-Dist: pytz>=2022.6; extra == 'testing'
|
|
53
|
+
Requires-Dist: redis<6.0.0,>=4.4.0; extra == 'testing'
|
|
77
54
|
Description-Content-Type: text/markdown
|
|
78
55
|
|
|
79
56
|
# Asyncz
|
|
@@ -87,8 +64,8 @@ Description-Content-Type: text/markdown
|
|
|
87
64
|
</p>
|
|
88
65
|
|
|
89
66
|
<p align="center">
|
|
90
|
-
<a href="https://github.com/
|
|
91
|
-
<img src="https://github.com/
|
|
67
|
+
<a href="https://github.com/dymmond/asyncz/workflows/Test%20Suite/badge.svg?event=push&branch=main" target="_blank">
|
|
68
|
+
<img src="https://github.com/dymmond/asyncz/workflows/Test%20Suite/badge.svg?event=push&branch=main" alt="Test Suite">
|
|
92
69
|
</a>
|
|
93
70
|
|
|
94
71
|
<a href="https://pypi.org/project/asyncz" target="_blank">
|
|
@@ -102,9 +79,9 @@ Description-Content-Type: text/markdown
|
|
|
102
79
|
|
|
103
80
|
---
|
|
104
81
|
|
|
105
|
-
**Documentation**: [https://asyncz.
|
|
82
|
+
**Documentation**: [https://asyncz.dymmond.com](https://asyncz.dymmond.com) 📚
|
|
106
83
|
|
|
107
|
-
**Source Code**: [https://github.com/
|
|
84
|
+
**Source Code**: [https://github.com/dymmond/asyncz](https://github.com/dymmond/asyncz)
|
|
108
85
|
|
|
109
86
|
---
|
|
110
87
|
|
|
@@ -146,16 +123,16 @@ completely indepent from any framework as well as inside ASGI frameworks such as
|
|
|
146
123
|
|
|
147
124
|
Asyncz comes with special support to [Esmerald](https://esmerald.dymmond.com) for the simple reason that the author is
|
|
148
125
|
the same but it can be added more support. If you are interested in adding support to your favourite frameworks then
|
|
149
|
-
see the [contributing](https://asyncz.
|
|
126
|
+
see the [contributing](https://asyncz.dymmond.com/contributing.md) section.
|
|
150
127
|
|
|
151
128
|
## Concepts
|
|
152
129
|
|
|
153
130
|
Like APScheduler, Asyncz also brings four kinds of components:
|
|
154
131
|
|
|
155
|
-
* [Schedulers](https://asyncz.
|
|
156
|
-
* [Triggers](https://asyncz.
|
|
157
|
-
* [Stores](https://asyncz.
|
|
158
|
-
* [Executors](https://asyncz.
|
|
132
|
+
* [Schedulers](https://asyncz.dymmond.com/schedulers.md)
|
|
133
|
+
* [Triggers](https://asyncz.dymmond.com/triggers.md)
|
|
134
|
+
* [Stores](https://asyncz.dymmond.com/stores.md)
|
|
135
|
+
* [Executors](https://asyncz.dymmond.com/executors.md)
|
|
159
136
|
|
|
160
137
|
## Requirements
|
|
161
138
|
|
|
@@ -174,28 +151,28 @@ $ pip install asyncz
|
|
|
174
151
|
|
|
175
152
|
## The right decisions
|
|
176
153
|
|
|
177
|
-
How do you know if you are choosing the right [scheduler](https://asyncz.
|
|
178
|
-
[triggers](https://asyncz.
|
|
179
|
-
and [executors](https://asyncz.
|
|
154
|
+
How do you know if you are choosing the right [scheduler](https://asyncz.dymmond.com/schedulers.md),
|
|
155
|
+
[triggers](https://asyncz.dymmond.com/triggers.md), [stores](https://asyncz.dymmond.com/stores.md)
|
|
156
|
+
and [executors](https://asyncz.dymmond.com/executors.md)?
|
|
180
157
|
|
|
181
158
|
Well, Asyncz is intentionally designed for specific systems and already helps you out with some of
|
|
182
159
|
those questions.
|
|
183
160
|
|
|
184
|
-
* **Schedulers** - Natively only supports the [AsyncIOScheduler](https://asyncz.
|
|
161
|
+
* **Schedulers** - Natively only supports the [AsyncIOScheduler](https://asyncz.dymmond.com/schedulers.md#asyncioscheduler).
|
|
185
162
|
* **Triggers** - Here it will depend of the periocidity of our tasks. Example:
|
|
186
|
-
* [CronTrigger](https://asyncz.
|
|
163
|
+
* [CronTrigger](https://asyncz.dymmond.com/triggers.md#crontrigger) - UNIX like cron and gives you the same feeling as
|
|
187
164
|
scheduling a task on a native UNIX like based system.
|
|
188
|
-
* [DateTrigger](https://asyncz.
|
|
165
|
+
* [DateTrigger](https://asyncz.dymmond.com/triggers.md#datetrigger) - When you need to run a task once on a specific
|
|
189
166
|
point of time.
|
|
190
|
-
* [IntervalTrigger](https://asyncz.
|
|
167
|
+
* [IntervalTrigger](https://asyncz.dymmond.com/triggers.md#intervaltrigger) - When you need to run tasks in specific
|
|
191
168
|
intervals of time.
|
|
192
|
-
* [OrTrigger](https://asyncz.
|
|
169
|
+
* [OrTrigger](https://asyncz.dymmond.com/triggers.md#ortrigger)/[AndTrigger](https://asyncz.dymmond.com/triggers.md#andtrigger) - If you would
|
|
193
170
|
like to combine more than one trigger (cron, interval and date) together.
|
|
194
|
-
* **Stores** - Natively only supports [redis](https://asyncz.
|
|
195
|
-
[mongo](https://asyncz.
|
|
196
|
-
* **Executors** - Natively only supports [AsyncIOExecutor](https://asyncz.
|
|
197
|
-
[ThreadPoolExecutor](https://asyncz.
|
|
198
|
-
[ProcessPoolExecutor](https://asyncz.
|
|
171
|
+
* **Stores** - Natively only supports [redis](https://asyncz.dymmond.com/stores.md#redisstore),
|
|
172
|
+
[mongo](https://asyncz.dymmond.com/stores.md#mongodbstore) and [memory](https://asyncz.dymmond.com/stores.md#memorystore).
|
|
173
|
+
* **Executors** - Natively only supports [AsyncIOExecutor](https://asyncz.dymmond.com/executors.md#asyncioexecutor),
|
|
174
|
+
[ThreadPoolExecutor](https://asyncz.dymmond.com/executors.md#threadpoolexecutor) and
|
|
175
|
+
[ProcessPoolExecutor](https://asyncz.dymmond.com/executors.md#processpoolexecutor).
|
|
199
176
|
|
|
200
177
|
Sometimes having a lot of options makes the decision making very hard and Asyncz is intentionally
|
|
201
178
|
designed and driven to simplify and for specific use cases but is not limited to those. In every
|
|
@@ -222,7 +199,7 @@ scheduler = AsyncIOScheduler()
|
|
|
222
199
|
```
|
|
223
200
|
|
|
224
201
|
Initialize the rest of the application after the `scheduler` initialisation.
|
|
225
|
-
More [details](https://asyncz.
|
|
202
|
+
More [details](https://asyncz.dymmond.com/schedulers.md) can be found with more thorough explanations.
|
|
226
203
|
|
|
227
204
|
This is in simple terms and in a nutshell how to start with Asyncz quickly. For more information,
|
|
228
205
|
details and examples how to leverage Asyncz simply navigate through the documentation and have
|
|
@@ -230,11 +207,11 @@ fun 😁🎉.
|
|
|
230
207
|
|
|
231
208
|
## ASGI support
|
|
232
209
|
|
|
233
|
-
Asyncz currently supports the [Esmerald framework](https://asyncz.
|
|
210
|
+
Asyncz currently supports the [Esmerald framework](https://asyncz.dymmond.com/contrib/esmerald/index.md)
|
|
234
211
|
and brings some batteries that are currently used by the framework and leveraging Asyncz.
|
|
235
212
|
|
|
236
213
|
If you wish to have support to any other framework such as FastAPI, Starlite, Starlette or
|
|
237
|
-
literally any other, check the [contributing](https://asyncz.
|
|
214
|
+
literally any other, check the [contributing](https://asyncz.dymmond.com/contributing.md) section and see how you can
|
|
238
215
|
do it.
|
|
239
216
|
|
|
240
217
|
## Sponsors
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
<a href="https://github.com/
|
|
13
|
-
<img src="https://github.com/
|
|
12
|
+
<a href="https://github.com/dymmond/asyncz/workflows/Test%20Suite/badge.svg?event=push&branch=main" target="_blank">
|
|
13
|
+
<img src="https://github.com/dymmond/asyncz/workflows/Test%20Suite/badge.svg?event=push&branch=main" alt="Test Suite">
|
|
14
14
|
</a>
|
|
15
15
|
|
|
16
16
|
<a href="https://pypi.org/project/asyncz" target="_blank">
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
**Documentation**: [https://asyncz.
|
|
27
|
+
**Documentation**: [https://asyncz.dymmond.com](https://asyncz.dymmond.com) 📚
|
|
28
28
|
|
|
29
|
-
**Source Code**: [https://github.com/
|
|
29
|
+
**Source Code**: [https://github.com/dymmond/asyncz](https://github.com/dymmond/asyncz)
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
@@ -68,16 +68,16 @@ completely indepent from any framework as well as inside ASGI frameworks such as
|
|
|
68
68
|
|
|
69
69
|
Asyncz comes with special support to [Esmerald](https://esmerald.dymmond.com) for the simple reason that the author is
|
|
70
70
|
the same but it can be added more support. If you are interested in adding support to your favourite frameworks then
|
|
71
|
-
see the [contributing](https://asyncz.
|
|
71
|
+
see the [contributing](https://asyncz.dymmond.com/contributing.md) section.
|
|
72
72
|
|
|
73
73
|
## Concepts
|
|
74
74
|
|
|
75
75
|
Like APScheduler, Asyncz also brings four kinds of components:
|
|
76
76
|
|
|
77
|
-
* [Schedulers](https://asyncz.
|
|
78
|
-
* [Triggers](https://asyncz.
|
|
79
|
-
* [Stores](https://asyncz.
|
|
80
|
-
* [Executors](https://asyncz.
|
|
77
|
+
* [Schedulers](https://asyncz.dymmond.com/schedulers.md)
|
|
78
|
+
* [Triggers](https://asyncz.dymmond.com/triggers.md)
|
|
79
|
+
* [Stores](https://asyncz.dymmond.com/stores.md)
|
|
80
|
+
* [Executors](https://asyncz.dymmond.com/executors.md)
|
|
81
81
|
|
|
82
82
|
## Requirements
|
|
83
83
|
|
|
@@ -96,28 +96,28 @@ $ pip install asyncz
|
|
|
96
96
|
|
|
97
97
|
## The right decisions
|
|
98
98
|
|
|
99
|
-
How do you know if you are choosing the right [scheduler](https://asyncz.
|
|
100
|
-
[triggers](https://asyncz.
|
|
101
|
-
and [executors](https://asyncz.
|
|
99
|
+
How do you know if you are choosing the right [scheduler](https://asyncz.dymmond.com/schedulers.md),
|
|
100
|
+
[triggers](https://asyncz.dymmond.com/triggers.md), [stores](https://asyncz.dymmond.com/stores.md)
|
|
101
|
+
and [executors](https://asyncz.dymmond.com/executors.md)?
|
|
102
102
|
|
|
103
103
|
Well, Asyncz is intentionally designed for specific systems and already helps you out with some of
|
|
104
104
|
those questions.
|
|
105
105
|
|
|
106
|
-
* **Schedulers** - Natively only supports the [AsyncIOScheduler](https://asyncz.
|
|
106
|
+
* **Schedulers** - Natively only supports the [AsyncIOScheduler](https://asyncz.dymmond.com/schedulers.md#asyncioscheduler).
|
|
107
107
|
* **Triggers** - Here it will depend of the periocidity of our tasks. Example:
|
|
108
|
-
* [CronTrigger](https://asyncz.
|
|
108
|
+
* [CronTrigger](https://asyncz.dymmond.com/triggers.md#crontrigger) - UNIX like cron and gives you the same feeling as
|
|
109
109
|
scheduling a task on a native UNIX like based system.
|
|
110
|
-
* [DateTrigger](https://asyncz.
|
|
110
|
+
* [DateTrigger](https://asyncz.dymmond.com/triggers.md#datetrigger) - When you need to run a task once on a specific
|
|
111
111
|
point of time.
|
|
112
|
-
* [IntervalTrigger](https://asyncz.
|
|
112
|
+
* [IntervalTrigger](https://asyncz.dymmond.com/triggers.md#intervaltrigger) - When you need to run tasks in specific
|
|
113
113
|
intervals of time.
|
|
114
|
-
* [OrTrigger](https://asyncz.
|
|
114
|
+
* [OrTrigger](https://asyncz.dymmond.com/triggers.md#ortrigger)/[AndTrigger](https://asyncz.dymmond.com/triggers.md#andtrigger) - If you would
|
|
115
115
|
like to combine more than one trigger (cron, interval and date) together.
|
|
116
|
-
* **Stores** - Natively only supports [redis](https://asyncz.
|
|
117
|
-
[mongo](https://asyncz.
|
|
118
|
-
* **Executors** - Natively only supports [AsyncIOExecutor](https://asyncz.
|
|
119
|
-
[ThreadPoolExecutor](https://asyncz.
|
|
120
|
-
[ProcessPoolExecutor](https://asyncz.
|
|
116
|
+
* **Stores** - Natively only supports [redis](https://asyncz.dymmond.com/stores.md#redisstore),
|
|
117
|
+
[mongo](https://asyncz.dymmond.com/stores.md#mongodbstore) and [memory](https://asyncz.dymmond.com/stores.md#memorystore).
|
|
118
|
+
* **Executors** - Natively only supports [AsyncIOExecutor](https://asyncz.dymmond.com/executors.md#asyncioexecutor),
|
|
119
|
+
[ThreadPoolExecutor](https://asyncz.dymmond.com/executors.md#threadpoolexecutor) and
|
|
120
|
+
[ProcessPoolExecutor](https://asyncz.dymmond.com/executors.md#processpoolexecutor).
|
|
121
121
|
|
|
122
122
|
Sometimes having a lot of options makes the decision making very hard and Asyncz is intentionally
|
|
123
123
|
designed and driven to simplify and for specific use cases but is not limited to those. In every
|
|
@@ -144,7 +144,7 @@ scheduler = AsyncIOScheduler()
|
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
Initialize the rest of the application after the `scheduler` initialisation.
|
|
147
|
-
More [details](https://asyncz.
|
|
147
|
+
More [details](https://asyncz.dymmond.com/schedulers.md) can be found with more thorough explanations.
|
|
148
148
|
|
|
149
149
|
This is in simple terms and in a nutshell how to start with Asyncz quickly. For more information,
|
|
150
150
|
details and examples how to leverage Asyncz simply navigate through the documentation and have
|
|
@@ -152,11 +152,11 @@ fun 😁🎉.
|
|
|
152
152
|
|
|
153
153
|
## ASGI support
|
|
154
154
|
|
|
155
|
-
Asyncz currently supports the [Esmerald framework](https://asyncz.
|
|
155
|
+
Asyncz currently supports the [Esmerald framework](https://asyncz.dymmond.com/contrib/esmerald/index.md)
|
|
156
156
|
and brings some batteries that are currently used by the framework and leveraging Asyncz.
|
|
157
157
|
|
|
158
158
|
If you wish to have support to any other framework such as FastAPI, Starlite, Starlette or
|
|
159
|
-
literally any other, check the [contributing](https://asyncz.
|
|
159
|
+
literally any other, check the [contributing](https://asyncz.dymmond.com/contributing.md) section and see how you can
|
|
160
160
|
do it.
|
|
161
161
|
|
|
162
162
|
## Sponsors
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.8.0"
|
|
@@ -27,6 +27,6 @@ class AsynczObjectMapping(BaseModel):
|
|
|
27
27
|
def stores(self) -> Dict[str, str]:
|
|
28
28
|
return {
|
|
29
29
|
"memory": "asyncz.stores.memory:MemoryTaskStore",
|
|
30
|
-
"
|
|
30
|
+
"mongodb": "asyncz.stores.mongo:MongoDBStore",
|
|
31
31
|
"redis": "asyncz.stores.redis:RedisStore",
|
|
32
32
|
}
|
|
@@ -18,7 +18,6 @@ except ImportError:
|
|
|
18
18
|
|
|
19
19
|
if TYPE_CHECKING:
|
|
20
20
|
from esmerald.applications import Esmerald
|
|
21
|
-
from pydantic.typing import AnyCallable
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
class EsmeraldScheduler:
|
|
@@ -93,14 +92,15 @@ class EsmeraldScheduler:
|
|
|
93
92
|
"""
|
|
94
93
|
Registers the scheduler events in the Esmerald application.
|
|
95
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]
|
|
96
99
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
@app.on_event("shutdown")
|
|
102
|
-
def stop_scheduler() -> None:
|
|
103
|
-
self.handler.shutdown()
|
|
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
104
|
|
|
105
105
|
def get_scheduler(
|
|
106
106
|
self,
|
|
@@ -208,7 +208,7 @@ class Task:
|
|
|
208
208
|
except Exception as e:
|
|
209
209
|
raise ImproperlyConfigured(str(e)) from e
|
|
210
210
|
|
|
211
|
-
def __call__(self, fn:
|
|
211
|
+
def __call__(self, fn: Any) -> None:
|
|
212
212
|
"""
|
|
213
213
|
Tricking the object into think it's being instantiated by in reality
|
|
214
214
|
is just returning itself.
|
|
@@ -3,12 +3,12 @@ import traceback
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
4
|
from collections import defaultdict
|
|
5
5
|
from datetime import datetime, timedelta
|
|
6
|
+
from datetime import timezone as tz
|
|
6
7
|
from traceback import format_tb
|
|
7
8
|
from typing import TYPE_CHECKING, Any, List, Optional, Union
|
|
8
9
|
|
|
9
10
|
from loguru import logger
|
|
10
11
|
from loguru._logger import Logger
|
|
11
|
-
from pytz import utc
|
|
12
12
|
|
|
13
13
|
from asyncz.events import TaskExecutionEvent
|
|
14
14
|
from asyncz.events.constants import TASK_ERROR, TASK_EXECUTED, TASK_MISSED
|
|
@@ -97,7 +97,9 @@ 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(
|
|
100
|
+
self.logger.opt(exception=True).error(
|
|
101
|
+
f"Error running task {task_id}", exc_info=True
|
|
102
|
+
)
|
|
101
103
|
|
|
102
104
|
|
|
103
105
|
def run_task(
|
|
@@ -118,7 +120,7 @@ def run_task(
|
|
|
118
120
|
events = []
|
|
119
121
|
for run_time in run_times:
|
|
120
122
|
if getattr(task, "mistrigger_grace_time", None) is not None:
|
|
121
|
-
difference = datetime.now(utc) - run_time
|
|
123
|
+
difference = datetime.now(tz.utc) - run_time
|
|
122
124
|
grace_time = timedelta(seconds=task.mistrigger_grace_time)
|
|
123
125
|
if difference > grace_time:
|
|
124
126
|
events.append(
|
|
@@ -182,7 +184,7 @@ async def run_coroutine_task(
|
|
|
182
184
|
events = []
|
|
183
185
|
for run_time in run_times:
|
|
184
186
|
if getattr(task, "mistrigger_grace_time", None) is not None:
|
|
185
|
-
difference = datetime.now(utc) - run_time
|
|
187
|
+
difference = datetime.now(tz.utc) - run_time
|
|
186
188
|
grace_time = timedelta(seconds=task.mistrigger_grace_time)
|
|
187
189
|
if difference > grace_time:
|
|
188
190
|
events.append(
|
|
@@ -18,11 +18,16 @@ class AsyncIOScheduler(BaseScheduler):
|
|
|
18
18
|
event_loop: AsyncOP event loop to use. Default to the global event loop.
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
+
event_loop: Optional[Any] = None
|
|
22
|
+
timeout: Optional[int] = None
|
|
23
|
+
timezone: Optional[str] = None
|
|
24
|
+
|
|
21
25
|
def __init__(
|
|
22
26
|
self, event_loop: Optional[Any] = None, timeout: Optional[int] = None, **kwargs: Any
|
|
23
27
|
) -> None:
|
|
24
28
|
super().__init__(**kwargs)
|
|
25
|
-
self.event_loop
|
|
29
|
+
if self.event_loop is None:
|
|
30
|
+
self.event_loop = event_loop
|
|
26
31
|
self.timeout = timeout
|
|
27
32
|
|
|
28
33
|
def start(self, paused: bool = False):
|
|
@@ -36,7 +41,7 @@ class AsyncIOScheduler(BaseScheduler):
|
|
|
36
41
|
self.stop_timer()
|
|
37
42
|
|
|
38
43
|
def _setup(self, config: Any) -> None:
|
|
39
|
-
self.event_loop = maybe_ref(config.pop("event_loop",
|
|
44
|
+
self.event_loop = maybe_ref(config.pop("event_loop", asyncio.get_event_loop()))
|
|
40
45
|
super()._setup(config)
|
|
41
46
|
|
|
42
47
|
def start_timer(self, wait_seconds: Optional[int] = None):
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
|
+
from collections.abc import MutableMapping
|
|
3
4
|
from datetime import datetime, timedelta
|
|
4
5
|
from importlib import import_module
|
|
5
6
|
from threading import RLock
|
|
@@ -9,6 +10,7 @@ from loguru import logger
|
|
|
9
10
|
from tzlocal import get_localzone
|
|
10
11
|
|
|
11
12
|
from asyncz._mapping import AsynczObjectMapping
|
|
13
|
+
from asyncz.enums import PluginInstance, SchedulerState
|
|
12
14
|
from asyncz.events.base import SchedulerEvent, TaskEvent, TaskSubmissionEvent
|
|
13
15
|
from asyncz.events.constants import (
|
|
14
16
|
ALL_EVENTS,
|
|
@@ -36,6 +38,8 @@ from asyncz.exceptions import (
|
|
|
36
38
|
)
|
|
37
39
|
from asyncz.executors.base import BaseExecutor
|
|
38
40
|
from asyncz.executors.pool import ThreadPoolExecutor
|
|
41
|
+
from asyncz.schedulers.datastructures import TaskDefaultStruct
|
|
42
|
+
from asyncz.state import BaseStateExtra
|
|
39
43
|
from asyncz.stores.base import BaseStore
|
|
40
44
|
from asyncz.stores.memory import MemoryStore
|
|
41
45
|
from asyncz.tasks import Task
|
|
@@ -43,15 +47,6 @@ from asyncz.triggers.base import BaseTrigger
|
|
|
43
47
|
from asyncz.typing import undefined
|
|
44
48
|
from asyncz.utils import TIMEOUT_MAX, maybe_ref, timedelta_seconds, to_bool, to_int, to_timezone
|
|
45
49
|
|
|
46
|
-
try:
|
|
47
|
-
from collections.abc import MutableMapping
|
|
48
|
-
except ImportError:
|
|
49
|
-
from collections.abc import MutableMapping
|
|
50
|
-
|
|
51
|
-
from asyncz.enums import PluginInstance, SchedulerState
|
|
52
|
-
from asyncz.schedulers.datastructures import TaskDefaultStruct
|
|
53
|
-
from asyncz.state import BaseStateExtra
|
|
54
|
-
|
|
55
50
|
DictAny = Dict[Any, Any]
|
|
56
51
|
|
|
57
52
|
if TYPE_CHECKING:
|
|
@@ -186,7 +181,6 @@ class BaseScheduler(BaseStateExtra, ABC):
|
|
|
186
181
|
if not paused:
|
|
187
182
|
self.wakeup()
|
|
188
183
|
|
|
189
|
-
@abstractmethod
|
|
190
184
|
def shutdown(self, wait: bool = True):
|
|
191
185
|
"""
|
|
192
186
|
Shuts down the scheduler, along with its executors and task stores.
|
|
@@ -821,7 +815,7 @@ class BaseScheduler(BaseStateExtra, ABC):
|
|
|
821
815
|
replace_existing: The flag indicating the replacement of the task.
|
|
822
816
|
"""
|
|
823
817
|
replacements = {}
|
|
824
|
-
for key, value in self.task_defaults.
|
|
818
|
+
for key, value in self.task_defaults.model_dump(exclude_none=True).items():
|
|
825
819
|
replacements[key] = value
|
|
826
820
|
|
|
827
821
|
# Calculate the next run time if there is none defined
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import pickle
|
|
2
2
|
from datetime import datetime
|
|
3
|
+
from datetime import timezone as tz
|
|
3
4
|
from typing import Any, List, Optional, Union
|
|
4
5
|
|
|
5
|
-
from pytz import utc
|
|
6
|
-
|
|
7
6
|
from asyncz.exceptions import AsynczException, ConflictIdError, TaskLookupError
|
|
8
7
|
from asyncz.stores.base import BaseStore
|
|
9
8
|
from asyncz.tasks import Task
|
|
@@ -79,7 +78,9 @@ class RedisStore(BaseStore):
|
|
|
79
78
|
try:
|
|
80
79
|
tasks.append(self.rebuild_task(state))
|
|
81
80
|
except BaseException:
|
|
82
|
-
self.logger.exception(
|
|
81
|
+
self.logger.exception(
|
|
82
|
+
f"Unable to restore task '{task_id}'. Removing it..."
|
|
83
|
+
)
|
|
83
84
|
failed_task_ids.append(task_id)
|
|
84
85
|
|
|
85
86
|
if failed_task_ids:
|
|
@@ -98,7 +99,7 @@ class RedisStore(BaseStore):
|
|
|
98
99
|
def get_all_tasks(self) -> List["TaskType"]:
|
|
99
100
|
states = self.redis.hgetall(self.tasks_key)
|
|
100
101
|
tasks = self.rebuild_tasks(states.items())
|
|
101
|
-
paused_sort_key = datetime(9999, 12, 31, tzinfo=utc)
|
|
102
|
+
paused_sort_key = datetime(9999, 12, 31, tzinfo=tz.utc)
|
|
102
103
|
return sorted(tasks, key=lambda task: task.next_run_time or paused_sort_key)
|
|
103
104
|
|
|
104
105
|
def add_task(self, task: "TaskType"):
|
|
@@ -108,12 +109,15 @@ class RedisStore(BaseStore):
|
|
|
108
109
|
with self.redis.pipeline() as pipe:
|
|
109
110
|
pipe.multi()
|
|
110
111
|
pipe.hset(
|
|
111
|
-
self.tasks_key,
|
|
112
|
+
self.tasks_key,
|
|
113
|
+
task.id,
|
|
114
|
+
pickle.dumps(task.__getstate__(), self.pickle_protocol),
|
|
112
115
|
)
|
|
113
116
|
|
|
114
117
|
if task.next_run_time:
|
|
115
118
|
pipe.zadd(
|
|
116
|
-
self.run_times_key,
|
|
119
|
+
self.run_times_key,
|
|
120
|
+
{task.id: datetime_to_utc_timestamp(task.next_run_time)},
|
|
117
121
|
)
|
|
118
122
|
pipe.execute()
|
|
119
123
|
|
|
@@ -123,11 +127,14 @@ class RedisStore(BaseStore):
|
|
|
123
127
|
|
|
124
128
|
with self.redis.pipeline() as pipe:
|
|
125
129
|
pipe.hset(
|
|
126
|
-
self.tasks_key,
|
|
130
|
+
self.tasks_key,
|
|
131
|
+
task.id,
|
|
132
|
+
pickle.dumps(task.__getstate__(), self.pickle_protocol),
|
|
127
133
|
)
|
|
128
134
|
if task.next_run_time:
|
|
129
135
|
pipe.zadd(
|
|
130
|
-
self.run_times_key,
|
|
136
|
+
self.run_times_key,
|
|
137
|
+
{task.id: datetime_to_utc_timestamp(task.next_run_time)},
|
|
131
138
|
)
|
|
132
139
|
else:
|
|
133
140
|
pipe.zrem(self.run_times_key, task.id)
|
|
@@ -6,7 +6,13 @@ from tzlocal import get_localzone
|
|
|
6
6
|
|
|
7
7
|
from asyncz.datastructures import IntervalState
|
|
8
8
|
from asyncz.triggers.base import BaseTrigger
|
|
9
|
-
from asyncz.utils import
|
|
9
|
+
from asyncz.utils import (
|
|
10
|
+
datetime_repr,
|
|
11
|
+
normalize,
|
|
12
|
+
timedelta_seconds,
|
|
13
|
+
to_datetime,
|
|
14
|
+
to_timezone,
|
|
15
|
+
)
|
|
10
16
|
|
|
11
17
|
|
|
12
18
|
class IntervalTrigger(BaseTrigger):
|
|
@@ -73,7 +79,9 @@ class IntervalTrigger(BaseTrigger):
|
|
|
73
79
|
next_trigger_time = self.start_at
|
|
74
80
|
else:
|
|
75
81
|
time_difference_seconds = timedelta_seconds(now - self.start_at)
|
|
76
|
-
next_interval_number = int(
|
|
82
|
+
next_interval_number = int(
|
|
83
|
+
ceil(time_difference_seconds / self.interval_size)
|
|
84
|
+
)
|
|
77
85
|
next_trigger_time = self.start_at + self.interval * next_interval_number
|
|
78
86
|
|
|
79
87
|
if self.jitter is not None:
|
|
@@ -98,7 +106,10 @@ class IntervalTrigger(BaseTrigger):
|
|
|
98
106
|
return f"interval[{self.interval}]"
|
|
99
107
|
|
|
100
108
|
def __repr__(self) -> str:
|
|
101
|
-
options = [
|
|
109
|
+
options = [
|
|
110
|
+
"interval=%r" % self.interval,
|
|
111
|
+
"start_at=%r" % datetime_repr(self.start_at),
|
|
112
|
+
]
|
|
102
113
|
if self.end_at:
|
|
103
114
|
options.append("end_at=%r" % datetime_repr(self.end_at))
|
|
104
115
|
if self.jitter:
|
|
@@ -3,17 +3,20 @@ import re
|
|
|
3
3
|
from asyncio import iscoroutinefunction
|
|
4
4
|
from calendar import timegm
|
|
5
5
|
from datetime import date, datetime, time, timedelta, tzinfo
|
|
6
|
+
from datetime import timezone as dttz
|
|
6
7
|
from functools import partial
|
|
7
8
|
from typing import Any, Callable, Union
|
|
8
9
|
|
|
9
|
-
from pytz import FixedOffset, timezone, utc
|
|
10
|
-
|
|
11
10
|
from asyncz.exceptions import AsynczException, AsynczLookupError
|
|
12
11
|
|
|
13
12
|
try:
|
|
14
13
|
from threading import TIMEOUT_MAX
|
|
15
14
|
except ImportError:
|
|
16
15
|
TIMEOUT_MAX = 4294967
|
|
16
|
+
try:
|
|
17
|
+
from zoneinfo import ZoneInfo
|
|
18
|
+
except ImportError:
|
|
19
|
+
from backports.zoneinfo import ZoneInfo
|
|
17
20
|
|
|
18
21
|
BOOL_VALIDATION = {
|
|
19
22
|
"true": ["true", "yes", "on", "y", "t", "1", True],
|
|
@@ -61,22 +64,13 @@ def to_bool(value: str) -> bool:
|
|
|
61
64
|
return False
|
|
62
65
|
|
|
63
66
|
|
|
64
|
-
def to_timezone(value: Any) ->
|
|
67
|
+
def to_timezone(value: Any) -> tzinfo:
|
|
65
68
|
"""
|
|
66
69
|
Converts a value to timezone object.
|
|
67
70
|
"""
|
|
68
71
|
if isinstance(value, str):
|
|
69
|
-
return
|
|
72
|
+
return ZoneInfo(value)
|
|
70
73
|
if isinstance(value, tzinfo):
|
|
71
|
-
if not hasattr(value, "localize") or not hasattr(value, "normalize"):
|
|
72
|
-
raise TypeError("Only timezones from the pytz library are supported.")
|
|
73
|
-
if value.tzname(None) == "local":
|
|
74
|
-
raise ValueError(
|
|
75
|
-
"Unable to determine the name of the local timezone -- you must explicitly "
|
|
76
|
-
"specify the name of the local timezone. Please refrain from using timezones like "
|
|
77
|
-
"BST to prevent problems with daylight saving time. Instead, use a locale based "
|
|
78
|
-
"timezone name (such as Europe/London)."
|
|
79
|
-
)
|
|
80
74
|
return value
|
|
81
75
|
if value is not None:
|
|
82
76
|
raise TypeError("Expected tzinfo, got %s instead" % value.__class__.__name__)
|
|
@@ -109,11 +103,11 @@ def to_datetime(
|
|
|
109
103
|
tzname = values.pop("timezone")
|
|
110
104
|
|
|
111
105
|
if tzname == "Z":
|
|
112
|
-
tz = utc
|
|
106
|
+
tz = dttz.utc
|
|
113
107
|
elif tzname:
|
|
114
108
|
hours, minutes = (int(x) for x in tzname[1:].split(":"))
|
|
115
109
|
sign = 1 if tzname[0] == "+" else -1
|
|
116
|
-
tz =
|
|
110
|
+
tz = dttz(sign * timedelta(hours=hours, minutes=minutes))
|
|
117
111
|
|
|
118
112
|
values = {k: int(v or 0) for k, v in values.items()}
|
|
119
113
|
_datetime = datetime(**values) # type: ignore
|
|
@@ -132,7 +126,7 @@ def to_datetime(
|
|
|
132
126
|
)
|
|
133
127
|
|
|
134
128
|
if isinstance(tz, str):
|
|
135
|
-
tz =
|
|
129
|
+
tz = ZoneInfo(tz)
|
|
136
130
|
|
|
137
131
|
return localize(_datetime, tz)
|
|
138
132
|
|
|
@@ -150,7 +144,7 @@ def utc_timestamp_to_datetime(timestamp: Union[int, float]) -> datetime:
|
|
|
150
144
|
Converts the given timestamp to a datetime instance.
|
|
151
145
|
"""
|
|
152
146
|
if timestamp is not None:
|
|
153
|
-
return datetime.fromtimestamp(timestamp, utc)
|
|
147
|
+
return datetime.fromtimestamp(timestamp, dttz.utc)
|
|
154
148
|
|
|
155
149
|
|
|
156
150
|
def timedelta_seconds(delta: Any) -> Any:
|
|
@@ -39,11 +39,10 @@ classifiers = [
|
|
|
39
39
|
"Topic :: Internet :: WWW/HTTP",
|
|
40
40
|
]
|
|
41
41
|
dependencies = [
|
|
42
|
-
"asyncio>=3.4.3,<4.0.0",
|
|
43
42
|
"loguru>=0.7.0,<0.8.0",
|
|
44
43
|
"pydantic>=2.5.3,<3.0.0",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
44
|
+
"tzlocal>=4.0,<6.0",
|
|
45
|
+
'backports.zoneinfo;python_version<"3.9"',
|
|
47
46
|
]
|
|
48
47
|
keywords = [
|
|
49
48
|
"api",
|
|
@@ -66,39 +65,48 @@ keywords = [
|
|
|
66
65
|
]
|
|
67
66
|
|
|
68
67
|
[project.urls]
|
|
69
|
-
Homepage = "https://github.com/
|
|
70
|
-
Documentation = "https://asyncz.
|
|
71
|
-
Changelog = "https://asyncz.
|
|
68
|
+
Homepage = "https://github.com/dymmond/asyncz"
|
|
69
|
+
Documentation = "https://asyncz.dymmond.com/"
|
|
70
|
+
Changelog = "https://asyncz.dymmond.com/release-notes/"
|
|
72
71
|
Funding = "https://github.com/sponsors/tarsil"
|
|
73
|
-
Source = "https://github.com/
|
|
72
|
+
Source = "https://github.com/dymmond/asyncz"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
[tool.hatch.envs.default]
|
|
76
|
+
dependencies = ["ruff", "pre-commit>=2.17.0,<3.0.0", "twine", "ipdb", "pdbpp"]
|
|
74
77
|
|
|
75
78
|
[project.optional-dependencies]
|
|
76
|
-
|
|
77
|
-
# "esmerald==0.4.2",
|
|
78
|
-
"mock>=4.0.3",
|
|
79
|
+
testing = [
|
|
79
80
|
"pymongo>=4.3.3,<5.0.0",
|
|
80
81
|
"pytest>=7.1.3,<9.0.0",
|
|
81
82
|
"pytest-cov >=2.12.0,<6.0.0",
|
|
82
83
|
"pytest-asyncio >=0.19.0,<1.0.0",
|
|
83
84
|
"pytest-loguru>=0.2.0,<1",
|
|
84
85
|
"redis>=4.4.0,<6.0.0",
|
|
85
|
-
"requests >=2.27.0,<3.0.0",
|
|
86
|
-
"ruff>=0.0.256,<1.0.0",
|
|
87
|
-
]
|
|
88
|
-
|
|
89
|
-
dev = [
|
|
90
|
-
"autoflake>=1.4.0,<3.0.0",
|
|
91
|
-
"black==24.4.2",
|
|
92
|
-
"flake8>=3.8.3,<8.0.0",
|
|
93
|
-
"ipdb>=0.13.13",
|
|
94
|
-
"pdbpp",
|
|
95
|
-
"isort>=5.0.6,<6.0.0",
|
|
96
86
|
"mypy>=0.982,<2.0.0",
|
|
97
|
-
"
|
|
98
|
-
"
|
|
87
|
+
"esmerald",
|
|
88
|
+
"pytz>=2022.6",
|
|
99
89
|
]
|
|
100
90
|
|
|
101
|
-
|
|
91
|
+
[tool.hatch.envs.default.scripts]
|
|
92
|
+
clean_pyc = "find . -type f -name \"*.pyc\" -delete"
|
|
93
|
+
clean_pycache = "find . -type d -name \"*__pycache__*\" -delete"
|
|
94
|
+
lint = "ruff check --fix --line-length 99 asyncz tests docs_src {args}"
|
|
95
|
+
build_with_check = "hatch build; twine check dist/*"
|
|
96
|
+
|
|
97
|
+
[tool.hatch.envs.test]
|
|
98
|
+
features = ["testing"]
|
|
99
|
+
|
|
100
|
+
[tool.hatch.envs.test.scripts]
|
|
101
|
+
# needs docker services running
|
|
102
|
+
test = "pytest --disable-pytest-warnings {args}"
|
|
103
|
+
test_man = "pytest --disable-pytest-warnings -s -vv {args}"
|
|
104
|
+
coverage = "pytest --cov=asyncz --cov=tests --cov-report=term-missing:skip-covered --cov-report=html tests {args}"
|
|
105
|
+
check_types = "mypy -p asyncz"
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
[tool.hatch.envs.docs]
|
|
109
|
+
dependencies = [
|
|
102
110
|
"mkautodoc >=0.2.0,<0.3.0",
|
|
103
111
|
"mkdocs >=1.1.2,<2.0.0",
|
|
104
112
|
"mkdocs-material >=9.0.13,<10.0.0",
|
|
@@ -107,16 +115,13 @@ doc = [
|
|
|
107
115
|
"mkdocstrings>=0.20.0,<0.30.0",
|
|
108
116
|
"pyyaml >=6.0,<7.0.0",
|
|
109
117
|
]
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
[tool.hatch.envs.docs.scripts]
|
|
119
|
+
build = "mkdocs build"
|
|
120
|
+
serve = "mkdocs serve --dev-addr localhost:8000"
|
|
112
121
|
|
|
113
122
|
[tool.hatch.version]
|
|
114
123
|
path = "asyncz/__init__.py"
|
|
115
124
|
|
|
116
|
-
[tool.isort]
|
|
117
|
-
profile = "black"
|
|
118
|
-
known_third_party = ["asyncz", "pydantic", "starlette"]
|
|
119
|
-
|
|
120
125
|
[tool.mypy]
|
|
121
126
|
warn_unused_configs = true
|
|
122
127
|
warn_unreachable = true
|
|
@@ -137,6 +142,9 @@ ignore = ["E501", "B008", "C901", "B026"]
|
|
|
137
142
|
|
|
138
143
|
exclude = ["docs_src/*"]
|
|
139
144
|
|
|
145
|
+
[tool.ruff.lint.isort]
|
|
146
|
+
known-third-party = ["esmerald", "pydantic", "starlette"]
|
|
147
|
+
|
|
140
148
|
[[tool.mypy.overrides]]
|
|
141
149
|
module = "asyncz.tests.*"
|
|
142
150
|
ignore_missing_imports = true
|
asyncz-0.6.0/asyncz/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.6.0"
|
|
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
|