engin 0.1a1__tar.gz → 0.1.0a2__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.
- {engin-0.1a1 → engin-0.1.0a2}/PKG-INFO +2 -2
- {engin-0.1a1 → engin-0.1.0a2}/README.md +1 -1
- {engin-0.1a1 → engin-0.1.0a2}/docs/index.md +1 -1
- {engin-0.1a1 → engin-0.1.0a2}/pyproject.toml +1 -1
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_engin.py +49 -12
- engin-0.1.0a2/tests/acceptance/test_engin_signal_handling.py +17 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/acceptance/test_error_in_start_up.py +8 -0
- engin-0.1.0a2/tests/acceptance/test_error_in_supervised_task.py +21 -0
- {engin-0.1a1 → engin-0.1.0a2}/uv.lock +15 -14
- engin-0.1a1/tests/acceptance/test_error_in_supervised_task.py +0 -17
- {engin-0.1a1 → engin-0.1.0a2}/.github/workflows/benchmark.yaml +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/.github/workflows/check.yaml +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/.github/workflows/publish.yaml +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/.gitignore +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/.readthedocs.yaml +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/CHANGELOG.md +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/LICENSE +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/concepts/blocks.md +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/concepts/engin.md +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/concepts/invocations.md +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/concepts/lifecycle.md +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/concepts/providers.md +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/getting-started.md +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/guides/fastapi-graph.png +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/guides/fastapi.md +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/js/readthedocs.js +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/overrides/main.html +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/docs/reference.md +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/app.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/common/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/common/db/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/common/db/adapaters/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/common/db/adapaters/memory.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/common/db/block.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/common/db/ports.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/common/starlette/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/common/starlette/endpoint.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/features/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/features/cats/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/features/cats/api/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/features/cats/api/get.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/features/cats/api/post.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/features/cats/block.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/features/cats/domain.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/asgi/main.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/app.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/main.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/routes/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/routes/cats/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/routes/cats/adapters/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/routes/cats/adapters/repository.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/routes/cats/api.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/routes/cats/block.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/routes/cats/domain.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/fastapi/routes/cats/ports.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/simple/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/examples/simple/main.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/mkdocs.yaml +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_assembler.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_block.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_cli/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_cli/_common.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_cli/_graph.html +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_cli/_graph.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_cli/_inspect.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_dependency.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_graph.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_introspect.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_lifecycle.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_option.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_shutdown.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_supervisor.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/_type_utils.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/exceptions.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/extensions/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/extensions/asgi.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/extensions/fastapi.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/src/engin/py.typed +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/acceptance/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/acceptance/test_error_in_shutdown.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/acceptance/test_fastapi.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/benchmarks/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/benchmarks/conftest.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/benchmarks/test_bench_assembler.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/cli/__init__.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/cli/test_graph.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/cli/test_inspect.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/conftest.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/deps.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/test_assembler.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/test_block.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/test_dependencies.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/test_engin.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/test_graph.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/test_lifecycle.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/test_supervisor.py +0 -0
- {engin-0.1a1 → engin-0.1.0a2}/tests/test_type_id.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: engin
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.1.0a2
|
4
4
|
Summary: An async-first modular application framework
|
5
5
|
Project-URL: Homepage, https://github.com/invokermain/engin
|
6
6
|
Project-URL: Documentation, https://engin.readthedocs.io/en/latest/
|
@@ -20,7 +20,7 @@ Description-Content-Type: text/markdown
|
|
20
20
|
|
21
21
|
# Engin 🏎️
|
22
22
|
|
23
|
-
Engin is a
|
23
|
+
Engin is a lightweight application framework for modern Python.
|
24
24
|
|
25
25
|
**Documentation**: https://engin.readthedocs.io/
|
26
26
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Introduction
|
2
2
|
|
3
|
-
Engin is a
|
3
|
+
Engin is a lightweight application framework for modern Python.
|
4
4
|
|
5
5
|
Engin is inspired by [Uber's Fx framework for Go](https://github.com/uber-go/fx) and the
|
6
6
|
[Injector framework for Python](https://github.com/python-injector/injector).
|
@@ -5,6 +5,7 @@ import signal
|
|
5
5
|
from asyncio import Event, Task
|
6
6
|
from collections import defaultdict
|
7
7
|
from contextlib import AsyncExitStack
|
8
|
+
from enum import Enum
|
8
9
|
from itertools import chain
|
9
10
|
from types import FrameType
|
10
11
|
from typing import ClassVar
|
@@ -19,11 +20,39 @@ from engin._option import Option
|
|
19
20
|
from engin._shutdown import ShutdownSwitch
|
20
21
|
from engin._supervisor import Supervisor
|
21
22
|
from engin._type_utils import TypeId
|
23
|
+
from engin.exceptions import EnginError
|
22
24
|
|
23
25
|
_OS_IS_WINDOWS = os.name == "nt"
|
24
26
|
LOG = logging.getLogger("engin")
|
25
27
|
|
26
28
|
|
29
|
+
class _EnginState(Enum):
|
30
|
+
IDLE = 0
|
31
|
+
"""
|
32
|
+
Not yet started.
|
33
|
+
"""
|
34
|
+
|
35
|
+
STARTED = 1
|
36
|
+
"""
|
37
|
+
Engin started via .start() call
|
38
|
+
"""
|
39
|
+
|
40
|
+
RUNNING = 2
|
41
|
+
"""
|
42
|
+
Engin running via .run() call
|
43
|
+
"""
|
44
|
+
|
45
|
+
STOPPING = 3
|
46
|
+
"""
|
47
|
+
Engin stopped via .stop() call
|
48
|
+
"""
|
49
|
+
|
50
|
+
SHUTDOWN = 4
|
51
|
+
"""
|
52
|
+
Engin has performed shutdown
|
53
|
+
"""
|
54
|
+
|
55
|
+
|
27
56
|
class Engin:
|
28
57
|
"""
|
29
58
|
The Engin is a modular application defined by a collection of options.
|
@@ -83,6 +112,7 @@ class Engin:
|
|
83
112
|
Args:
|
84
113
|
*options: an instance of Provide, Supply, Invoke, Entrypoint or a Block.
|
85
114
|
"""
|
115
|
+
self._state = _EnginState.IDLE
|
86
116
|
self._stop_requested_event = ShutdownSwitch()
|
87
117
|
self._stop_complete_event = Event()
|
88
118
|
self._exit_stack: AsyncExitStack = AsyncExitStack()
|
@@ -118,8 +148,13 @@ class Engin:
|
|
118
148
|
SIGINT), the `stop` method is called on the engin, or a lifecycle task errors.
|
119
149
|
"""
|
120
150
|
await self.start()
|
121
|
-
|
122
|
-
|
151
|
+
|
152
|
+
# engin failed to start, so exit early
|
153
|
+
if self._state != _EnginState.STARTED:
|
154
|
+
return
|
155
|
+
|
156
|
+
self._state = _EnginState.RUNNING
|
157
|
+
|
123
158
|
async with create_task_group() as tg:
|
124
159
|
tg.start_soon(_stop_engin_on_signal, self._stop_requested_event)
|
125
160
|
try:
|
@@ -137,6 +172,9 @@ class Engin:
|
|
137
172
|
lifecycle to complete and then returns. The caller is then responsible for
|
138
173
|
calling `stop`.
|
139
174
|
"""
|
175
|
+
if self._state != _EnginState.IDLE:
|
176
|
+
raise EnginError("Engin is not idle, unable to start")
|
177
|
+
|
140
178
|
LOG.info("starting engin")
|
141
179
|
assembled_invocations: list[AssembledDependency] = [
|
142
180
|
await self._assembler.assemble(invocation) for invocation in self._invocations
|
@@ -169,8 +207,7 @@ class Engin:
|
|
169
207
|
return
|
170
208
|
|
171
209
|
LOG.info("startup complete")
|
172
|
-
|
173
|
-
self._shutdown_task = asyncio.create_task(self._shutdown_when_stopped())
|
210
|
+
self._state = _EnginState.STARTED
|
174
211
|
|
175
212
|
async def stop(self) -> None:
|
176
213
|
"""
|
@@ -180,10 +217,13 @@ class Engin:
|
|
180
217
|
Note this method can be safely called at any point, even before the engin is
|
181
218
|
started.
|
182
219
|
"""
|
183
|
-
|
184
|
-
if self.
|
185
|
-
|
186
|
-
|
220
|
+
# If the Engin was ran via `start()` perform shutdown directly
|
221
|
+
if self._state == _EnginState.STARTED:
|
222
|
+
await self._shutdown()
|
223
|
+
# If the Engin was ran via `run()` notify via event
|
224
|
+
elif self._state == _EnginState.RUNNING:
|
225
|
+
self._stop_requested_event.set()
|
226
|
+
await self._stop_complete_event.wait()
|
187
227
|
|
188
228
|
def graph(self) -> list[Node]:
|
189
229
|
grapher = DependencyGrapher({**self._providers, **self._multiproviders})
|
@@ -194,10 +234,7 @@ class Engin:
|
|
194
234
|
await self._exit_stack.aclose()
|
195
235
|
self._stop_complete_event.set()
|
196
236
|
LOG.info("shutdown complete")
|
197
|
-
|
198
|
-
async def _shutdown_when_stopped(self) -> None:
|
199
|
-
await self._stop_requested_event.wait()
|
200
|
-
await self._shutdown()
|
237
|
+
self._state = _EnginState.SHUTDOWN
|
201
238
|
|
202
239
|
|
203
240
|
async def _stop_engin_on_signal(stop_requested_event: Event) -> None:
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import asyncio
|
2
|
+
from asyncio import TaskGroup
|
3
|
+
|
4
|
+
from engin import Engin
|
5
|
+
from engin._engin import _EnginState
|
6
|
+
|
7
|
+
|
8
|
+
async def test_engin_signal_handling():
|
9
|
+
engin = Engin()
|
10
|
+
|
11
|
+
async with TaskGroup() as tg:
|
12
|
+
tg.create_task(engin.run())
|
13
|
+
# give it time to startup
|
14
|
+
await asyncio.sleep(0.1)
|
15
|
+
assert engin._state == _EnginState.RUNNING
|
16
|
+
await engin.stop()
|
17
|
+
assert engin._state == _EnginState.SHUTDOWN
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import asyncio
|
1
2
|
from contextlib import asynccontextmanager
|
2
3
|
|
3
4
|
from starlette.applications import Starlette
|
@@ -35,6 +36,13 @@ async def test_error_in_startup():
|
|
35
36
|
assert not B_LIFECYCLE_STATE
|
36
37
|
|
37
38
|
|
39
|
+
async def test_error_in_startup_handled_when_run():
|
40
|
+
engin = Engin(Invoke(a), Invoke(b))
|
41
|
+
|
42
|
+
await asyncio.wait_for(engin.run(), timeout=0.5)
|
43
|
+
assert not B_LIFECYCLE_STATE
|
44
|
+
|
45
|
+
|
38
46
|
async def test_error_in_startup_asgi():
|
39
47
|
def asgi_type() -> ASGIType:
|
40
48
|
return Starlette()
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import asyncio
|
2
|
+
|
3
|
+
from engin import Engin, Invoke, Supervisor
|
4
|
+
|
5
|
+
|
6
|
+
async def delayed_error_task():
|
7
|
+
raise RuntimeError("Process errored")
|
8
|
+
|
9
|
+
|
10
|
+
def supervise(supervisor: Supervisor) -> None:
|
11
|
+
supervisor.supervise(delayed_error_task)
|
12
|
+
|
13
|
+
|
14
|
+
async def test_error_in_supervised_task_handled_when_run(caplog):
|
15
|
+
engin = Engin(Invoke(supervise))
|
16
|
+
await asyncio.wait_for(engin.run(), timeout=0.5)
|
17
|
+
|
18
|
+
|
19
|
+
async def test_error_in_supervised_task_handled_when_start(caplog):
|
20
|
+
engin = Engin(Invoke(supervise))
|
21
|
+
await asyncio.wait_for(engin.start(), timeout=0.5)
|
@@ -37,15 +37,16 @@ wheels = [
|
|
37
37
|
|
38
38
|
[[package]]
|
39
39
|
name = "backrefs"
|
40
|
-
version = "5.
|
40
|
+
version = "5.9"
|
41
41
|
source = { registry = "https://pypi.org/simple" }
|
42
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
42
|
+
sdist = { url = "https://files.pythonhosted.org/packages/eb/a7/312f673df6a79003279e1f55619abbe7daebbb87c17c976ddc0345c04c7b/backrefs-5.9.tar.gz", hash = "sha256:808548cb708d66b82ee231f962cb36faaf4f2baab032f2fbb783e9c2fdddaa59", size = 5765857, upload-time = "2025-06-22T19:34:13.97Z" }
|
43
43
|
wheels = [
|
44
|
-
{ url = "https://files.pythonhosted.org/packages/
|
45
|
-
{ url = "https://files.pythonhosted.org/packages/
|
46
|
-
{ url = "https://files.pythonhosted.org/packages/
|
47
|
-
{ url = "https://files.pythonhosted.org/packages/
|
48
|
-
{ url = "https://files.pythonhosted.org/packages/
|
44
|
+
{ url = "https://files.pythonhosted.org/packages/19/4d/798dc1f30468134906575156c089c492cf79b5a5fd373f07fe26c4d046bf/backrefs-5.9-py310-none-any.whl", hash = "sha256:db8e8ba0e9de81fcd635f440deab5ae5f2591b54ac1ebe0550a2ca063488cd9f", size = 380267, upload-time = "2025-06-22T19:34:05.252Z" },
|
45
|
+
{ url = "https://files.pythonhosted.org/packages/55/07/f0b3375bf0d06014e9787797e6b7cc02b38ac9ff9726ccfe834d94e9991e/backrefs-5.9-py311-none-any.whl", hash = "sha256:6907635edebbe9b2dc3de3a2befff44d74f30a4562adbb8b36f21252ea19c5cf", size = 392072, upload-time = "2025-06-22T19:34:06.743Z" },
|
46
|
+
{ url = "https://files.pythonhosted.org/packages/9d/12/4f345407259dd60a0997107758ba3f221cf89a9b5a0f8ed5b961aef97253/backrefs-5.9-py312-none-any.whl", hash = "sha256:7fdf9771f63e6028d7fee7e0c497c81abda597ea45d6b8f89e8ad76994f5befa", size = 397947, upload-time = "2025-06-22T19:34:08.172Z" },
|
47
|
+
{ url = "https://files.pythonhosted.org/packages/10/bf/fa31834dc27a7f05e5290eae47c82690edc3a7b37d58f7fb35a1bdbf355b/backrefs-5.9-py313-none-any.whl", hash = "sha256:cc37b19fa219e93ff825ed1fed8879e47b4d89aa7a1884860e2db64ccd7c676b", size = 399843, upload-time = "2025-06-22T19:34:09.68Z" },
|
48
|
+
{ url = "https://files.pythonhosted.org/packages/fc/24/b29af34b2c9c41645a9f4ff117bae860291780d73880f449e0b5d948c070/backrefs-5.9-py314-none-any.whl", hash = "sha256:df5e169836cc8acb5e440ebae9aad4bf9d15e226d3bad049cf3f6a5c20cc8dc9", size = 411762, upload-time = "2025-06-22T19:34:11.037Z" },
|
49
|
+
{ url = "https://files.pythonhosted.org/packages/41/ff/392bff89415399a979be4a65357a41d92729ae8580a66073d8ec8d810f98/backrefs-5.9-py39-none-any.whl", hash = "sha256:f48ee18f6252b8f5777a22a00a09a85de0ca931658f1dd96d4406a34f3748c60", size = 380265, upload-time = "2025-06-22T19:34:12.405Z" },
|
49
50
|
]
|
50
51
|
|
51
52
|
[[package]]
|
@@ -210,7 +211,7 @@ toml = [
|
|
210
211
|
|
211
212
|
[[package]]
|
212
213
|
name = "engin"
|
213
|
-
version = "0.
|
214
|
+
version = "0.1a1"
|
214
215
|
source = { editable = "." }
|
215
216
|
dependencies = [
|
216
217
|
{ name = "anyio" },
|
@@ -841,16 +842,16 @@ wheels = [
|
|
841
842
|
|
842
843
|
[[package]]
|
843
844
|
name = "pydantic-settings"
|
844
|
-
version = "2.10.
|
845
|
+
version = "2.10.1"
|
845
846
|
source = { registry = "https://pypi.org/simple" }
|
846
847
|
dependencies = [
|
847
848
|
{ name = "pydantic" },
|
848
849
|
{ name = "python-dotenv" },
|
849
850
|
{ name = "typing-inspection" },
|
850
851
|
]
|
851
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
852
|
+
sdist = { url = "https://files.pythonhosted.org/packages/68/85/1ea668bbab3c50071ca613c6ab30047fb36ab0da1b92fa8f17bbc38fd36c/pydantic_settings-2.10.1.tar.gz", hash = "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", size = 172583, upload-time = "2025-06-24T13:26:46.841Z" }
|
852
853
|
wheels = [
|
853
|
-
{ url = "https://files.pythonhosted.org/packages/
|
854
|
+
{ url = "https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796", size = 45235, upload-time = "2025-06-24T13:26:45.485Z" },
|
854
855
|
]
|
855
856
|
|
856
857
|
[[package]]
|
@@ -958,11 +959,11 @@ wheels = [
|
|
958
959
|
|
959
960
|
[[package]]
|
960
961
|
name = "python-dotenv"
|
961
|
-
version = "1.1.
|
962
|
+
version = "1.1.1"
|
962
963
|
source = { registry = "https://pypi.org/simple" }
|
963
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
964
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" }
|
964
965
|
wheels = [
|
965
|
-
{ url = "https://files.pythonhosted.org/packages/
|
966
|
+
{ url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" },
|
966
967
|
]
|
967
968
|
|
968
969
|
[[package]]
|
@@ -1,17 +0,0 @@
|
|
1
|
-
import asyncio
|
2
|
-
|
3
|
-
from engin import Engin, Invoke, Supervisor
|
4
|
-
|
5
|
-
|
6
|
-
async def delayed_error_task():
|
7
|
-
await asyncio.sleep(0.5)
|
8
|
-
raise RuntimeError("Process errored")
|
9
|
-
|
10
|
-
|
11
|
-
def supervise(supervisor: Supervisor) -> None:
|
12
|
-
supervisor.supervise(delayed_error_task)
|
13
|
-
|
14
|
-
|
15
|
-
async def test_error_in_task(caplog):
|
16
|
-
engin = Engin(Invoke(supervise))
|
17
|
-
await engin.run()
|
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
|
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
|
File without changes
|
File without changes
|