engin 0.1.0rc2__py3-none-any.whl → 0.2.0a1__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.
- engin/_cli/_check.py +0 -7
- engin/_cli/_graph.html +1 -1
- engin/_dependency.py +3 -0
- engin/_engin.py +4 -1
- engin/_supervisor.py +19 -6
- {engin-0.1.0rc2.dist-info → engin-0.2.0a1.dist-info}/METADATA +2 -2
- {engin-0.1.0rc2.dist-info → engin-0.2.0a1.dist-info}/RECORD +10 -10
- {engin-0.1.0rc2.dist-info → engin-0.2.0a1.dist-info}/WHEEL +0 -0
- {engin-0.1.0rc2.dist-info → engin-0.2.0a1.dist-info}/entry_points.txt +0 -0
- {engin-0.1.0rc2.dist-info → engin-0.2.0a1.dist-info}/licenses/LICENSE +0 -0
engin/_cli/_check.py
CHANGED
@@ -50,13 +50,6 @@ def check_dependencies(
|
|
50
50
|
for missing_type in sorted_missing:
|
51
51
|
console.print(f" • {missing_type}", style="red")
|
52
52
|
|
53
|
-
available_providers = sorted(
|
54
|
-
str(provider.return_type_id) for provider in assembler.providers
|
55
|
-
)
|
56
|
-
console.print("\nAvailable providers:", style="yellow")
|
57
|
-
for available_type in available_providers:
|
58
|
-
console.print(f" • {available_type}", style="yellow")
|
59
|
-
|
60
53
|
raise typer.Exit(code=1)
|
61
54
|
else:
|
62
55
|
console.print("✅ All dependencies are satisfied!", style="green bold")
|
engin/_cli/_graph.html
CHANGED
engin/_dependency.py
CHANGED
@@ -171,6 +171,9 @@ class Provide(Dependency[Any, T]):
|
|
171
171
|
override: (optional) allow this provider to override other providers for the
|
172
172
|
same type from the same package.
|
173
173
|
"""
|
174
|
+
if not callable(factory):
|
175
|
+
msg = "Provided value is not callable, did you mean to use Supply instead?"
|
176
|
+
raise ValueError(msg)
|
174
177
|
super().__init__(func=factory)
|
175
178
|
self._scope = scope
|
176
179
|
self._override = override
|
engin/_engin.py
CHANGED
@@ -179,7 +179,9 @@ class Engin:
|
|
179
179
|
try:
|
180
180
|
async with supervisor:
|
181
181
|
await self._stop_requested_event.wait()
|
182
|
-
|
182
|
+
|
183
|
+
# shutdown after stopping supervised tasks
|
184
|
+
await self._shutdown()
|
183
185
|
except BaseException:
|
184
186
|
await self._shutdown()
|
185
187
|
|
@@ -262,6 +264,7 @@ async def _stop_engin_on_signal(stop_requested_event: Event) -> None:
|
|
262
264
|
|
263
265
|
# windows does not support signal_handlers, so this is the workaround
|
264
266
|
def ctrlc_handler(sig: int, frame: FrameType | None) -> None:
|
267
|
+
LOG.debug(f"received {signal.SIGINT.name} signal")
|
265
268
|
nonlocal should_stop
|
266
269
|
if should_stop:
|
267
270
|
raise KeyboardInterrupt("Forced keyboard interrupt")
|
engin/_supervisor.py
CHANGED
@@ -15,7 +15,7 @@ if typing.TYPE_CHECKING:
|
|
15
15
|
|
16
16
|
LOG = logging.getLogger("engin")
|
17
17
|
|
18
|
-
|
18
|
+
AsyncFunction: TypeAlias = Callable[[], Awaitable[None]]
|
19
19
|
|
20
20
|
|
21
21
|
class OnException(Enum):
|
@@ -41,15 +41,16 @@ class _SupervisorTask:
|
|
41
41
|
"""
|
42
42
|
Attributes:
|
43
43
|
- factory: a coroutine function that can create the task.
|
44
|
-
- on_exception: determines the behaviour when task raises an exception.
|
44
|
+
- on_exception: determines the behaviour when the task raises an exception.
|
45
45
|
- complete: will be set to true if task stops for any reason except cancellation.
|
46
46
|
- last_exception: the last exception raised by the task.
|
47
47
|
"""
|
48
48
|
|
49
|
-
factory:
|
49
|
+
factory: AsyncFunction
|
50
50
|
on_exception: OnException
|
51
51
|
complete: bool = False
|
52
52
|
last_exception: Exception | None = None
|
53
|
+
shutdown_hook: AsyncFunction | None = None
|
53
54
|
|
54
55
|
async def __call__(self) -> None:
|
55
56
|
# loop to allow for restarting erroring tasks
|
@@ -63,7 +64,6 @@ class _SupervisorTask:
|
|
63
64
|
raise
|
64
65
|
except Exception as err:
|
65
66
|
self.last_exception = err
|
66
|
-
|
67
67
|
if self.on_exception == OnException.IGNORE:
|
68
68
|
LOG.warning(
|
69
69
|
f"supervisor task '{self.name}' raised {type(err).__name__} "
|
@@ -107,9 +107,17 @@ class Supervisor:
|
|
107
107
|
self._task_group: TaskGroup | None = None
|
108
108
|
|
109
109
|
def supervise(
|
110
|
-
self,
|
110
|
+
self,
|
111
|
+
func: AsyncFunction,
|
112
|
+
*,
|
113
|
+
on_exception: OnException = OnException.SHUTDOWN,
|
114
|
+
shutdown_hook: AsyncFunction | None = None,
|
111
115
|
) -> None:
|
112
|
-
self._tasks.append(
|
116
|
+
self._tasks.append(
|
117
|
+
_SupervisorTask(
|
118
|
+
factory=func, on_exception=on_exception, shutdown_hook=shutdown_hook
|
119
|
+
)
|
120
|
+
)
|
113
121
|
|
114
122
|
@property
|
115
123
|
def empty(self) -> bool:
|
@@ -122,6 +130,7 @@ class Supervisor:
|
|
122
130
|
self._task_group = await anyio.create_task_group().__aenter__()
|
123
131
|
|
124
132
|
for task in self._tasks:
|
133
|
+
LOG.info(f"supervising task: {task.name}")
|
125
134
|
self._task_group.start_soon(task, name=task.name)
|
126
135
|
|
127
136
|
async def __aexit__(
|
@@ -132,6 +141,10 @@ class Supervisor:
|
|
132
141
|
/,
|
133
142
|
) -> None:
|
134
143
|
if self._task_group:
|
144
|
+
for task in self._tasks:
|
145
|
+
if task.shutdown_hook is not None:
|
146
|
+
LOG.debug(f"supervised task shutdown hook: {task.name}")
|
147
|
+
await task.shutdown_hook()
|
135
148
|
if not self._task_group.cancel_scope.cancel_called:
|
136
149
|
self._task_group.cancel_scope.cancel()
|
137
150
|
await self._task_group.__aexit__(exc_type, exc_value, traceback)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: engin
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.2.0a1
|
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/
|
@@ -39,7 +39,7 @@ The Engin framework gives you:
|
|
39
39
|
|
40
40
|
- A fully-featured dependency injection system.
|
41
41
|
- A robust application runtime with lifecycle hooks and supervised background tasks.
|
42
|
-
- Zero
|
42
|
+
- Zero boilerplate code reuse across applications.
|
43
43
|
- Integrations for other frameworks such as FastAPI.
|
44
44
|
- Full async support.
|
45
45
|
- CLI commands to aid local development.
|
@@ -1,27 +1,27 @@
|
|
1
1
|
engin/__init__.py,sha256=O0vS570kZFBq7Kwy4FgeJFIhfo4aIg5mv_Z_9vAQRio,577
|
2
2
|
engin/_assembler.py,sha256=0uXgtcO5M3EHg0I-TQK9y7LOzfxkLFmKia-zLyVHaxA,11178
|
3
3
|
engin/_block.py,sha256=IacP4PoJKRhSQCbQSdoyCtmu362a4vj6qoUQKyaJwzI,3062
|
4
|
-
engin/_dependency.py,sha256=
|
5
|
-
engin/_engin.py,sha256=
|
4
|
+
engin/_dependency.py,sha256=Ie-z0obe7Ut6TF1O7BjP3Z7i216ufKqSeT_D82krdAc,9615
|
5
|
+
engin/_engin.py,sha256=1bgZmdmRlwHIZ9pz5rysYgvFu5s8e0gzlc9iq-Of97c,9651
|
6
6
|
engin/_graph.py,sha256=y1g7Lm_Zy5GPEgRsggCKV5DDaDzcwUl8v3IZCK8jyGI,1631
|
7
7
|
engin/_introspect.py,sha256=VdREX6Lhhga5SnEP9G7mjHkgJR4mpqk_SMnmL2zTcqY,966
|
8
8
|
engin/_lifecycle.py,sha256=cSWe3euZkmpxmUPFvph2lsTtvuZbxttEfBL-RnOI7lo,5325
|
9
9
|
engin/_option.py,sha256=nZcdrehp1QwgxMUoIpsM0PJuu1q1pbXzhcVsetbsHpc,223
|
10
|
-
engin/_supervisor.py,sha256=
|
10
|
+
engin/_supervisor.py,sha256=WGio-mfPHo2Wdfqo5ZB66WAoAU2ey0urwM0Dl4vRUTA,4824
|
11
11
|
engin/_type_utils.py,sha256=H3Tl-kJr2wY2RhaTXP9GrMqa2RsXMijHbjHKe1AxGmc,2276
|
12
12
|
engin/exceptions.py,sha256=lSMOJI4Yl-VIM0yDzFWbPhC0mQm4f0WvGULr9SldIaY,2353
|
13
13
|
engin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
14
|
engin/_cli/__init__.py,sha256=Ixk3NoZeIN8Bj53I625uqJdLyyT9Gpbe_4GtNy-KQwM,636
|
15
|
-
engin/_cli/_check.py,sha256=
|
15
|
+
engin/_cli/_check.py,sha256=w9GA9RmCgSflvSU7EQqXKiOCqgrZB-pLS_UoJOqV56E,1666
|
16
16
|
engin/_cli/_common.py,sha256=6tyjxAkROCViw0LOFdx-X1U-iSXKyeW5CoE9UxWRybI,3282
|
17
|
-
engin/_cli/_graph.html,sha256=
|
17
|
+
engin/_cli/_graph.html,sha256=5Dw5eyhsrU8KrpdhGn1mxo5kTUTJLMSzT-MBKvSv13g,29073
|
18
18
|
engin/_cli/_graph.py,sha256=MsxsNpL1v0v1AUT57ZS97l1diwacqRaPdVBObHHIGJE,6753
|
19
19
|
engin/_cli/_inspect.py,sha256=_uzldpHA51IX4srpUGzL4lZNiepqucsO9M3Zo83XBBM,3159
|
20
20
|
engin/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
21
|
engin/extensions/asgi.py,sha256=7vQFaVs1jxq1KbhHGN8k7x2UFab6SPUq2_hXfX6HiXU,3329
|
22
22
|
engin/extensions/fastapi.py,sha256=7N6i-eZUEZRPo7kcvjS7kbRSY5QAPyKJXSeongSQ-OA,6371
|
23
|
-
engin-0.
|
24
|
-
engin-0.
|
25
|
-
engin-0.
|
26
|
-
engin-0.
|
27
|
-
engin-0.
|
23
|
+
engin-0.2.0a1.dist-info/METADATA,sha256=OntxY2pdrpJuvpqb-zvj2SJwpohHmEjbjLmqc7w1zqE,3949
|
24
|
+
engin-0.2.0a1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
25
|
+
engin-0.2.0a1.dist-info/entry_points.txt,sha256=sW247zZUMxm0b5UKYvPuqQQljYDtU-j2zK3cu7gHwM0,41
|
26
|
+
engin-0.2.0a1.dist-info/licenses/LICENSE,sha256=XHh5LPUPKZWTBqBv2xxN2RU7D59nHoiJGb5RIt8f45w,1070
|
27
|
+
engin-0.2.0a1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|