engin 0.1a1__py3-none-any.whl → 0.1.0a2__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/_engin.py CHANGED
@@ -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
- if self._shutdown_task:
122
- self._shutdown_task.cancel("redundant")
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
- self._stop_requested_event.set()
184
- if self._shutdown_task is None:
185
- return
186
- await self._stop_complete_event.wait()
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: engin
3
- Version: 0.1a1
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 zero-dependency application framework for modern Python.
23
+ Engin is a lightweight application framework for modern Python.
24
24
 
25
25
  **Documentation**: https://engin.readthedocs.io/
26
26
 
@@ -2,7 +2,7 @@ engin/__init__.py,sha256=v5OWwQoxTtqh2sB2E5iSMg3gATJoXKOuJLq28aZX6C8,642
2
2
  engin/_assembler.py,sha256=-ENSrXPMWacionIYrTSQO7th9DDBOPyAT8ybPbBRtQw,11318
3
3
  engin/_block.py,sha256=IacP4PoJKRhSQCbQSdoyCtmu362a4vj6qoUQKyaJwzI,3062
4
4
  engin/_dependency.py,sha256=xINk3sudxzsTmkUkNAKQwzBc0G0DfhpnrZli4z3ALBY,9459
5
- engin/_engin.py,sha256=UGS-dIMGcdhRWvsQBuwIH6I7XFxYMlgSZeuvl3ur3Eo,8417
5
+ engin/_engin.py,sha256=XkGUG3D7z8X31rZhbu02_NFhFwSKB4JPSoma5jv6nq4,9135
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
@@ -20,8 +20,8 @@ engin/_cli/_inspect.py,sha256=0jm25d4wcbXVNJkyaeECSKY-irsxd-EIYBH1GDW_Yjc,3163
20
20
  engin/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  engin/extensions/asgi.py,sha256=d5Z6gtMVWDZdAlvrTaMt987sKyiq__A0X4gJQ7IETmA,3247
22
22
  engin/extensions/fastapi.py,sha256=7N6i-eZUEZRPo7kcvjS7kbRSY5QAPyKJXSeongSQ-OA,6371
23
- engin-0.1a1.dist-info/METADATA,sha256=f5atVNZHxnofJLnnf2upFC_MYjAJv3lVkQIxe62z1TA,2410
24
- engin-0.1a1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
- engin-0.1a1.dist-info/entry_points.txt,sha256=sW247zZUMxm0b5UKYvPuqQQljYDtU-j2zK3cu7gHwM0,41
26
- engin-0.1a1.dist-info/licenses/LICENSE,sha256=XHh5LPUPKZWTBqBv2xxN2RU7D59nHoiJGb5RIt8f45w,1070
27
- engin-0.1a1.dist-info/RECORD,,
23
+ engin-0.1.0a2.dist-info/METADATA,sha256=eg-rPpaGOV1MDNenGqSGCldPlTHh2yZ3CcZ0b5agakc,2408
24
+ engin-0.1.0a2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
+ engin-0.1.0a2.dist-info/entry_points.txt,sha256=sW247zZUMxm0b5UKYvPuqQQljYDtU-j2zK3cu7gHwM0,41
26
+ engin-0.1.0a2.dist-info/licenses/LICENSE,sha256=XHh5LPUPKZWTBqBv2xxN2RU7D59nHoiJGb5RIt8f45w,1070
27
+ engin-0.1.0a2.dist-info/RECORD,,
File without changes