engin 0.0.20__py3-none-any.whl → 0.1.0__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/__init__.py +3 -0
- engin/_assembler.py +12 -12
- engin/_cli/__init__.py +2 -0
- engin/_cli/_check.py +56 -0
- engin/_cli/_common.py +72 -2
- engin/_cli/_graph.html +878 -73
- engin/_cli/_graph.py +128 -65
- engin/_cli/_inspect.py +10 -8
- engin/_engin.py +142 -71
- engin/_supervisor.py +137 -0
- engin/exceptions.py +21 -6
- engin/extensions/asgi.py +2 -0
- engin/extensions/fastapi.py +2 -2
- engin-0.1.0.dist-info/METADATA +122 -0
- engin-0.1.0.dist-info/RECORD +27 -0
- engin-0.0.20.dist-info/METADATA +0 -71
- engin-0.0.20.dist-info/RECORD +0 -25
- {engin-0.0.20.dist-info → engin-0.1.0.dist-info}/WHEEL +0 -0
- {engin-0.0.20.dist-info → engin-0.1.0.dist-info}/entry_points.txt +0 -0
- {engin-0.0.20.dist-info → engin-0.1.0.dist-info}/licenses/LICENSE +0 -0
engin/_supervisor.py
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
import inspect
|
2
|
+
import logging
|
3
|
+
import typing
|
4
|
+
from collections.abc import Awaitable, Callable
|
5
|
+
from dataclasses import dataclass
|
6
|
+
from enum import Enum
|
7
|
+
from types import TracebackType
|
8
|
+
from typing import TypeAlias, assert_never
|
9
|
+
|
10
|
+
import anyio
|
11
|
+
from anyio import get_cancelled_exc_class
|
12
|
+
|
13
|
+
if typing.TYPE_CHECKING:
|
14
|
+
from anyio.abc import TaskGroup
|
15
|
+
|
16
|
+
LOG = logging.getLogger("engin")
|
17
|
+
|
18
|
+
TaskFactory: TypeAlias = Callable[[], Awaitable[None]]
|
19
|
+
|
20
|
+
|
21
|
+
class OnException(Enum):
|
22
|
+
SHUTDOWN = 0
|
23
|
+
"""
|
24
|
+
Cancel all other supervised tasks and shutdown the Engin.
|
25
|
+
"""
|
26
|
+
|
27
|
+
RETRY = 1
|
28
|
+
"""
|
29
|
+
Retry the task.
|
30
|
+
"""
|
31
|
+
|
32
|
+
IGNORE = 2
|
33
|
+
"""
|
34
|
+
The task will be not be retried and the engin will not be stopped, other tasks will
|
35
|
+
continue to run.
|
36
|
+
"""
|
37
|
+
|
38
|
+
|
39
|
+
@dataclass(kw_only=True, slots=True, eq=False)
|
40
|
+
class _SupervisorTask:
|
41
|
+
"""
|
42
|
+
Attributes:
|
43
|
+
- factory: a coroutine function that can create the task.
|
44
|
+
- on_exception: determines the behaviour when task raises an exception.
|
45
|
+
- complete: will be set to true if task stops for any reason except cancellation.
|
46
|
+
- last_exception: the last exception raised by the task.
|
47
|
+
"""
|
48
|
+
|
49
|
+
factory: TaskFactory
|
50
|
+
on_exception: OnException
|
51
|
+
complete: bool = False
|
52
|
+
last_exception: Exception | None = None
|
53
|
+
|
54
|
+
async def __call__(self) -> None:
|
55
|
+
# loop to allow for restarting erroring tasks
|
56
|
+
while True:
|
57
|
+
try:
|
58
|
+
await self.factory()
|
59
|
+
self.complete = True
|
60
|
+
return
|
61
|
+
except get_cancelled_exc_class() as err:
|
62
|
+
LOG.debug(f"supervised task '{self.name}' was cancelled", exc_info=err)
|
63
|
+
raise
|
64
|
+
except Exception as err:
|
65
|
+
self.last_exception = err
|
66
|
+
if self.on_exception == OnException.IGNORE:
|
67
|
+
LOG.warning(
|
68
|
+
f"supervisor task '{self.name}' raised {type(err).__name__} "
|
69
|
+
"which will be ignored",
|
70
|
+
exc_info=err,
|
71
|
+
)
|
72
|
+
self.complete = True
|
73
|
+
return
|
74
|
+
if self.on_exception == OnException.RETRY:
|
75
|
+
LOG.warning(
|
76
|
+
f"supervisor task '{self.name}' raised {type(err).__name__} "
|
77
|
+
"which will be retried",
|
78
|
+
exc_info=err,
|
79
|
+
)
|
80
|
+
continue
|
81
|
+
if self.on_exception == OnException.SHUTDOWN:
|
82
|
+
LOG.error(
|
83
|
+
f"supervisor task '{self.name}' raised {type(err).__name__}, "
|
84
|
+
"starting shutdown",
|
85
|
+
exc_info=err,
|
86
|
+
)
|
87
|
+
self.complete = True
|
88
|
+
raise get_cancelled_exc_class() from None
|
89
|
+
assert_never(self.on_exception)
|
90
|
+
|
91
|
+
@property
|
92
|
+
def name(self) -> str:
|
93
|
+
factory = self.factory
|
94
|
+
if inspect.ismethod(factory):
|
95
|
+
return f"{factory.__self__.__class__.__name__}.{factory.__func__.__name__}"
|
96
|
+
if inspect.isclass(factory):
|
97
|
+
return type(factory).__name__
|
98
|
+
if inspect.isfunction(factory):
|
99
|
+
return factory.__name__
|
100
|
+
return str(factory)
|
101
|
+
|
102
|
+
|
103
|
+
class Supervisor:
|
104
|
+
def __init__(self) -> None:
|
105
|
+
self._tasks: list[_SupervisorTask] = []
|
106
|
+
self._task_group: TaskGroup | None = None
|
107
|
+
|
108
|
+
def supervise(
|
109
|
+
self, func: TaskFactory, *, on_exception: OnException = OnException.SHUTDOWN
|
110
|
+
) -> None:
|
111
|
+
self._tasks.append(_SupervisorTask(factory=func, on_exception=on_exception))
|
112
|
+
|
113
|
+
@property
|
114
|
+
def empty(self) -> bool:
|
115
|
+
return not self._tasks
|
116
|
+
|
117
|
+
async def __aenter__(self) -> None:
|
118
|
+
if not self._tasks:
|
119
|
+
return
|
120
|
+
|
121
|
+
self._task_group = await anyio.create_task_group().__aenter__()
|
122
|
+
|
123
|
+
for task in self._tasks:
|
124
|
+
LOG.info(f"supervising task: {task.name}")
|
125
|
+
self._task_group.start_soon(task, name=task.name)
|
126
|
+
|
127
|
+
async def __aexit__(
|
128
|
+
self,
|
129
|
+
exc_type: type[BaseException] | None,
|
130
|
+
exc_value: BaseException | None,
|
131
|
+
traceback: TracebackType | None,
|
132
|
+
/,
|
133
|
+
) -> None:
|
134
|
+
if self._task_group:
|
135
|
+
if not self._task_group.cancel_scope.cancel_called:
|
136
|
+
self._task_group.cancel_scope.cancel()
|
137
|
+
await self._task_group.__aexit__(exc_type, exc_value, traceback)
|
engin/exceptions.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import TYPE_CHECKING, Any
|
2
2
|
|
3
3
|
from engin._dependency import Provide
|
4
|
+
from engin._type_utils import TypeId
|
4
5
|
|
5
6
|
if TYPE_CHECKING:
|
6
7
|
from engin._block import Block
|
@@ -12,12 +13,6 @@ class EnginError(Exception):
|
|
12
13
|
"""
|
13
14
|
|
14
15
|
|
15
|
-
class AssemblerError(EnginError):
|
16
|
-
"""
|
17
|
-
Base class for all custom exceptions raised by the Assembler.
|
18
|
-
"""
|
19
|
-
|
20
|
-
|
21
16
|
class InvalidBlockError(EnginError):
|
22
17
|
"""
|
23
18
|
Raised when an invalid block is instantiated.
|
@@ -32,6 +27,25 @@ class InvalidBlockError(EnginError):
|
|
32
27
|
return self.message
|
33
28
|
|
34
29
|
|
30
|
+
class AssemblerError(EnginError):
|
31
|
+
"""
|
32
|
+
Base class for all custom exceptions raised by the Assembler.
|
33
|
+
"""
|
34
|
+
|
35
|
+
|
36
|
+
class TypeNotProvidedError(AssemblerError):
|
37
|
+
"""
|
38
|
+
Raised when the Assembler cannot assemble a type due to a missing Provider.
|
39
|
+
"""
|
40
|
+
|
41
|
+
def __init__(self, type_id: TypeId) -> None:
|
42
|
+
self.type_id = type_id
|
43
|
+
self.message = f"no provider found for '{type_id}'"
|
44
|
+
|
45
|
+
def __str__(self) -> str:
|
46
|
+
return self.message
|
47
|
+
|
48
|
+
|
35
49
|
class ProviderError(AssemblerError):
|
36
50
|
"""
|
37
51
|
Raised when a Provider errors during Assembly.
|
@@ -77,4 +91,5 @@ __all__ = [
|
|
77
91
|
"InvalidBlockError",
|
78
92
|
"NotInScopeError",
|
79
93
|
"ProviderError",
|
94
|
+
"TypeNotProvidedError",
|
80
95
|
]
|
engin/extensions/asgi.py
CHANGED
engin/extensions/fastapi.py
CHANGED
@@ -24,12 +24,12 @@ except ImportError as err:
|
|
24
24
|
__all__ = ["APIRouteDependency", "FastAPIEngin", "Inject"]
|
25
25
|
|
26
26
|
|
27
|
-
def _attach_assembler(app: FastAPI,
|
27
|
+
def _attach_assembler(app: FastAPI, assembler: Assembler) -> None:
|
28
28
|
"""
|
29
29
|
An invocation that attaches the Engin's Assembler to the FastAPI application, enabling
|
30
30
|
the Inject marker.
|
31
31
|
"""
|
32
|
-
app.state.assembler =
|
32
|
+
app.state.assembler = assembler
|
33
33
|
|
34
34
|
|
35
35
|
class FastAPIEngin(ASGIEngin):
|
@@ -0,0 +1,122 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: engin
|
3
|
+
Version: 0.1.0
|
4
|
+
Summary: An async-first modular application framework
|
5
|
+
Project-URL: Homepage, https://github.com/invokermain/engin
|
6
|
+
Project-URL: Documentation, https://engin.readthedocs.io/en/latest/
|
7
|
+
Project-URL: Repository, https://github.com/invokermain/engin.git
|
8
|
+
Project-URL: Changelog, https://github.com/invokermain/engin/blob/main/CHANGELOG.md
|
9
|
+
License-Expression: MIT
|
10
|
+
License-File: LICENSE
|
11
|
+
Keywords: Application Framework,Dependency Injection
|
12
|
+
Requires-Python: >=3.10
|
13
|
+
Requires-Dist: anyio>=4
|
14
|
+
Requires-Dist: exceptiongroup>=1
|
15
|
+
Provides-Extra: cli
|
16
|
+
Requires-Dist: tomli>=2.0; (python_version < '3.11') and extra == 'cli'
|
17
|
+
Requires-Dist: typer>=0.15; extra == 'cli'
|
18
|
+
Description-Content-Type: text/markdown
|
19
|
+
|
20
|
+
# Engin 🏎️
|
21
|
+
|
22
|
+
[](https://codecov.io/gh/invokermain/engin)
|
23
|
+
|
24
|
+
---
|
25
|
+
|
26
|
+
**Documentation**: [https://engin.readthedocs.io/](https://engin.readthedocs.io/)
|
27
|
+
|
28
|
+
**Source Code**: [https://github.com/invokermain/engin](https://github.com/invokermain/engin)
|
29
|
+
|
30
|
+
---
|
31
|
+
|
32
|
+
Engin is a lightweight application framework powered by dependency injection, it helps
|
33
|
+
you build and maintain large monoliths and many microservices.
|
34
|
+
|
35
|
+
|
36
|
+
## Feature
|
37
|
+
|
38
|
+
The Engin framework gives you:
|
39
|
+
|
40
|
+
- A fully-featured dependency injection system.
|
41
|
+
- A robust application runtime with lifecycle hooks and supervised background tasks.
|
42
|
+
- Zero boilerplate code reuse across applications.
|
43
|
+
- Integrations for other frameworks such as FastAPI.
|
44
|
+
- Full async support.
|
45
|
+
- CLI commands to aid local development.
|
46
|
+
|
47
|
+
|
48
|
+
## Installation
|
49
|
+
|
50
|
+
Engin is available on PyPI, install it using your favourite dependency manager:
|
51
|
+
|
52
|
+
- `pip install engin`
|
53
|
+
- `poetry add engin`
|
54
|
+
- `uv add engin`
|
55
|
+
|
56
|
+
## Example
|
57
|
+
|
58
|
+
A small example which shows some of the features of Engin. This application
|
59
|
+
makes 3 http requests and shuts itself down.
|
60
|
+
|
61
|
+
```python
|
62
|
+
import asyncio
|
63
|
+
from httpx import AsyncClient
|
64
|
+
from engin import Engin, Invoke, Lifecycle, OnException, Provide, Supervisor
|
65
|
+
|
66
|
+
|
67
|
+
def httpx_client_factory(lifecycle: Lifecycle) -> AsyncClient:
|
68
|
+
# create our http client
|
69
|
+
client = AsyncClient()
|
70
|
+
# this will open and close the AsyncClient as part of the application's lifecycle
|
71
|
+
lifecycle.append(client)
|
72
|
+
return client
|
73
|
+
|
74
|
+
|
75
|
+
async def main(
|
76
|
+
httpx_client: AsyncClient,
|
77
|
+
supervisor: Supervisor,
|
78
|
+
) -> None:
|
79
|
+
async def http_requests_task():
|
80
|
+
# simulate a background task
|
81
|
+
for x in range(3):
|
82
|
+
await httpx_client.get("https://httpbin.org/get")
|
83
|
+
await asyncio.sleep(1.0)
|
84
|
+
# raise an error to shutdown the application, normally you wouldn't do this!
|
85
|
+
raise RuntimeError("Forcing shutdown")
|
86
|
+
|
87
|
+
# supervise the http requests as part of the application's lifecycle
|
88
|
+
supervisor.supervise(http_requests_task, on_exception=OnException.SHUTDOWN)
|
89
|
+
|
90
|
+
|
91
|
+
# define our modular application
|
92
|
+
engin = Engin(Provide(httpx_client_factory), Invoke(main))
|
93
|
+
|
94
|
+
# run it!
|
95
|
+
asyncio.run(engin.run())
|
96
|
+
```
|
97
|
+
|
98
|
+
With logs enabled this will output:
|
99
|
+
|
100
|
+
```shell
|
101
|
+
INFO:engin:starting engin
|
102
|
+
INFO:engin:startup complete
|
103
|
+
INFO:httpx:HTTP Request: GET https://httpbin.org/get "HTTP/1.1 200 OK"
|
104
|
+
INFO:httpx:HTTP Request: GET https://httpbin.org/get "HTTP/1.1 200 OK"
|
105
|
+
INFO:httpx:HTTP Request: GET https://httpbin.org/get "HTTP/1.1 200 OK"
|
106
|
+
ERROR:engin:supervisor task 'http_requests_task' raised RuntimeError, starting shutdown
|
107
|
+
Traceback (most recent call last):
|
108
|
+
File "C:\dev\python\engin\src\engin\_supervisor.py", line 58, in __call__
|
109
|
+
await self.factory()
|
110
|
+
File "C:\dev\python\engin\readme_example.py", line 29, in http_requests_task
|
111
|
+
raise RuntimeError("Forcing shutdown")
|
112
|
+
RuntimeError: Forcing shutdown
|
113
|
+
INFO:engin:stopping engin
|
114
|
+
INFO:engin:shutdown complete
|
115
|
+
```
|
116
|
+
|
117
|
+
## Inspiration
|
118
|
+
|
119
|
+
Engin is heavily inspired by [Uber's Fx framework for Go](https://github.com/uber-go/fx)
|
120
|
+
and the [Injector framework for Python](https://github.com/python-injector/injector).
|
121
|
+
|
122
|
+
They are both great projects, go check them out.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
engin/__init__.py,sha256=O0vS570kZFBq7Kwy4FgeJFIhfo4aIg5mv_Z_9vAQRio,577
|
2
|
+
engin/_assembler.py,sha256=0uXgtcO5M3EHg0I-TQK9y7LOzfxkLFmKia-zLyVHaxA,11178
|
3
|
+
engin/_block.py,sha256=IacP4PoJKRhSQCbQSdoyCtmu362a4vj6qoUQKyaJwzI,3062
|
4
|
+
engin/_dependency.py,sha256=xINk3sudxzsTmkUkNAKQwzBc0G0DfhpnrZli4z3ALBY,9459
|
5
|
+
engin/_engin.py,sha256=1bgZmdmRlwHIZ9pz5rysYgvFu5s8e0gzlc9iq-Of97c,9651
|
6
|
+
engin/_graph.py,sha256=y1g7Lm_Zy5GPEgRsggCKV5DDaDzcwUl8v3IZCK8jyGI,1631
|
7
|
+
engin/_introspect.py,sha256=VdREX6Lhhga5SnEP9G7mjHkgJR4mpqk_SMnmL2zTcqY,966
|
8
|
+
engin/_lifecycle.py,sha256=cSWe3euZkmpxmUPFvph2lsTtvuZbxttEfBL-RnOI7lo,5325
|
9
|
+
engin/_option.py,sha256=nZcdrehp1QwgxMUoIpsM0PJuu1q1pbXzhcVsetbsHpc,223
|
10
|
+
engin/_supervisor.py,sha256=nRz8GMFBJ5dAzMBO94HL_U1W2c89ZXg_LPeoD4H-s-4,4397
|
11
|
+
engin/_type_utils.py,sha256=H3Tl-kJr2wY2RhaTXP9GrMqa2RsXMijHbjHKe1AxGmc,2276
|
12
|
+
engin/exceptions.py,sha256=lSMOJI4Yl-VIM0yDzFWbPhC0mQm4f0WvGULr9SldIaY,2353
|
13
|
+
engin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
+
engin/_cli/__init__.py,sha256=Ixk3NoZeIN8Bj53I625uqJdLyyT9Gpbe_4GtNy-KQwM,636
|
15
|
+
engin/_cli/_check.py,sha256=w9GA9RmCgSflvSU7EQqXKiOCqgrZB-pLS_UoJOqV56E,1666
|
16
|
+
engin/_cli/_common.py,sha256=6tyjxAkROCViw0LOFdx-X1U-iSXKyeW5CoE9UxWRybI,3282
|
17
|
+
engin/_cli/_graph.html,sha256=5Dw5eyhsrU8KrpdhGn1mxo5kTUTJLMSzT-MBKvSv13g,29073
|
18
|
+
engin/_cli/_graph.py,sha256=MsxsNpL1v0v1AUT57ZS97l1diwacqRaPdVBObHHIGJE,6753
|
19
|
+
engin/_cli/_inspect.py,sha256=_uzldpHA51IX4srpUGzL4lZNiepqucsO9M3Zo83XBBM,3159
|
20
|
+
engin/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
+
engin/extensions/asgi.py,sha256=7vQFaVs1jxq1KbhHGN8k7x2UFab6SPUq2_hXfX6HiXU,3329
|
22
|
+
engin/extensions/fastapi.py,sha256=7N6i-eZUEZRPo7kcvjS7kbRSY5QAPyKJXSeongSQ-OA,6371
|
23
|
+
engin-0.1.0.dist-info/METADATA,sha256=Eny-piAImwQB6Ij3djngjTqvg0ILyGlbr9aprE28bNE,3947
|
24
|
+
engin-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
25
|
+
engin-0.1.0.dist-info/entry_points.txt,sha256=sW247zZUMxm0b5UKYvPuqQQljYDtU-j2zK3cu7gHwM0,41
|
26
|
+
engin-0.1.0.dist-info/licenses/LICENSE,sha256=XHh5LPUPKZWTBqBv2xxN2RU7D59nHoiJGb5RIt8f45w,1070
|
27
|
+
engin-0.1.0.dist-info/RECORD,,
|
engin-0.0.20.dist-info/METADATA
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: engin
|
3
|
-
Version: 0.0.20
|
4
|
-
Summary: An async-first modular application framework
|
5
|
-
Project-URL: Homepage, https://github.com/invokermain/engin
|
6
|
-
Project-URL: Documentation, https://engin.readthedocs.io/en/latest/
|
7
|
-
Project-URL: Repository, https://github.com/invokermain/engin.git
|
8
|
-
Project-URL: Changelog, https://github.com/invokermain/engin/blob/main/CHANGELOG.md
|
9
|
-
License-Expression: MIT
|
10
|
-
License-File: LICENSE
|
11
|
-
Keywords: Application Framework,Dependency Injection
|
12
|
-
Requires-Python: >=3.10
|
13
|
-
Provides-Extra: cli
|
14
|
-
Requires-Dist: typer>=0.15; extra == 'cli'
|
15
|
-
Description-Content-Type: text/markdown
|
16
|
-
|
17
|
-
[](https://codecov.io/gh/invokermain/engin)
|
18
|
-
|
19
|
-
# Engin 🏎️
|
20
|
-
|
21
|
-
Engin is a zero-dependency application framework for modern Python.
|
22
|
-
|
23
|
-
**Documentation**: https://engin.readthedocs.io/
|
24
|
-
|
25
|
-
## Features ✨
|
26
|
-
|
27
|
-
- **Dependency Injection** - Engin includes a fully-featured Dependency Injection system,
|
28
|
-
powered by type hints.
|
29
|
-
- **Lifecycle Management** - Engin provides a simple & portable approach for attaching
|
30
|
-
startup and shutdown tasks to the application's lifecycle.
|
31
|
-
- **Code Reuse** - Engin's modular components, called Blocks, work great as distributed
|
32
|
-
packages allowing zero boiler-plate code reuse across multiple applications. Perfect for
|
33
|
-
maintaining many services across your organisation.
|
34
|
-
- **Ecosystem Compatability** - Engin ships with integrations for popular frameworks that
|
35
|
-
provide their own Dependency Injection, for example FastAPI, allowing you to integrate
|
36
|
-
Engin into existing code bases incrementally.
|
37
|
-
- **Async Native**: Engin is an async framework, meaning first class support for async
|
38
|
-
dependencies. However Engin will happily run synchronous code as well.
|
39
|
-
|
40
|
-
## Installation
|
41
|
-
|
42
|
-
Engin is available on PyPI, install using your favourite dependency manager:
|
43
|
-
|
44
|
-
- **pip**:`pip install engin`
|
45
|
-
- **poetry**: `poetry add engin`
|
46
|
-
- **uv**: `uv add engin`
|
47
|
-
|
48
|
-
## Getting Started
|
49
|
-
|
50
|
-
A minimal example:
|
51
|
-
|
52
|
-
```python
|
53
|
-
import asyncio
|
54
|
-
|
55
|
-
from httpx import AsyncClient
|
56
|
-
|
57
|
-
from engin import Engin, Invoke, Provide
|
58
|
-
|
59
|
-
|
60
|
-
def httpx_client() -> AsyncClient:
|
61
|
-
return AsyncClient()
|
62
|
-
|
63
|
-
|
64
|
-
async def main(http_client: AsyncClient) -> None:
|
65
|
-
print(await http_client.get("https://httpbin.org/get"))
|
66
|
-
|
67
|
-
engin = Engin(Provide(httpx_client), Invoke(main))
|
68
|
-
|
69
|
-
asyncio.run(engin.run())
|
70
|
-
```
|
71
|
-
|
engin-0.0.20.dist-info/RECORD
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
engin/__init__.py,sha256=A8TE_ci7idoR683535YoBrWZbYTgXXS-q7Y2y51nZ5M,486
|
2
|
-
engin/_assembler.py,sha256=-ENSrXPMWacionIYrTSQO7th9DDBOPyAT8ybPbBRtQw,11318
|
3
|
-
engin/_block.py,sha256=IacP4PoJKRhSQCbQSdoyCtmu362a4vj6qoUQKyaJwzI,3062
|
4
|
-
engin/_dependency.py,sha256=xINk3sudxzsTmkUkNAKQwzBc0G0DfhpnrZli4z3ALBY,9459
|
5
|
-
engin/_engin.py,sha256=yIpZdeqvm8hv0RxOV0veFuvyu9xQ054JSaeuUWwHdOQ,7380
|
6
|
-
engin/_graph.py,sha256=y1g7Lm_Zy5GPEgRsggCKV5DDaDzcwUl8v3IZCK8jyGI,1631
|
7
|
-
engin/_introspect.py,sha256=VdREX6Lhhga5SnEP9G7mjHkgJR4mpqk_SMnmL2zTcqY,966
|
8
|
-
engin/_lifecycle.py,sha256=cSWe3euZkmpxmUPFvph2lsTtvuZbxttEfBL-RnOI7lo,5325
|
9
|
-
engin/_option.py,sha256=nZcdrehp1QwgxMUoIpsM0PJuu1q1pbXzhcVsetbsHpc,223
|
10
|
-
engin/_type_utils.py,sha256=H3Tl-kJr2wY2RhaTXP9GrMqa2RsXMijHbjHKe1AxGmc,2276
|
11
|
-
engin/exceptions.py,sha256=-VPwPReZb9YEIkrWMR9TW2K5HEwmHHgEO7QWH6wfV8c,1946
|
12
|
-
engin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
engin/_cli/__init__.py,sha256=koD5WTkZXb8QQIiVU5bJiSR1wwPGb5rv2iwd-v-BA7A,564
|
14
|
-
engin/_cli/_common.py,sha256=zMYb1Bs1yUuR3qf3r6WuVozYzDwHJvTVthVbTQfTF9w,1261
|
15
|
-
engin/_cli/_graph.html,sha256=rR5dnDKoz7KtSff0ERCi2UKuoH_Z03MRYiXI_W03G5k,2430
|
16
|
-
engin/_cli/_graph.py,sha256=HMC91nWvTOr6_czPBNx1RU55Ib3qesJRCmbnL2DsdDk,4659
|
17
|
-
engin/_cli/_inspect.py,sha256=0jm25d4wcbXVNJkyaeECSKY-irsxd-EIYBH1GDW_Yjc,3163
|
18
|
-
engin/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
-
engin/extensions/asgi.py,sha256=d5Z6gtMVWDZdAlvrTaMt987sKyiq__A0X4gJQ7IETmA,3247
|
20
|
-
engin/extensions/fastapi.py,sha256=e8F4L_nZ9dU9j8mb9lXKwJG6CTu5aIk4N5faRj4EyUA,6369
|
21
|
-
engin-0.0.20.dist-info/METADATA,sha256=KiKW4DvikfKJJNzoXh7oC4RMdr02W0PkhtxXB8DN6bo,2354
|
22
|
-
engin-0.0.20.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
23
|
-
engin-0.0.20.dist-info/entry_points.txt,sha256=sW247zZUMxm0b5UKYvPuqQQljYDtU-j2zK3cu7gHwM0,41
|
24
|
-
engin-0.0.20.dist-info/licenses/LICENSE,sha256=XHh5LPUPKZWTBqBv2xxN2RU7D59nHoiJGb5RIt8f45w,1070
|
25
|
-
engin-0.0.20.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|