engin 0.0.10__py3-none-any.whl → 0.0.11__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/_dependency.py +24 -10
- engin/ext/fastapi.py +17 -4
- engin/scripts/graph.py +28 -3
- {engin-0.0.10.dist-info → engin-0.0.11.dist-info}/METADATA +3 -1
- {engin-0.0.10.dist-info → engin-0.0.11.dist-info}/RECORD +8 -8
- {engin-0.0.10.dist-info → engin-0.0.11.dist-info}/WHEEL +0 -0
- {engin-0.0.10.dist-info → engin-0.0.11.dist-info}/entry_points.txt +0 -0
- {engin-0.0.10.dist-info → engin-0.0.11.dist-info}/licenses/LICENSE +0 -0
engin/_dependency.py
CHANGED
@@ -3,6 +3,7 @@ import typing
|
|
3
3
|
from abc import ABC
|
4
4
|
from collections.abc import Awaitable, Callable
|
5
5
|
from inspect import Parameter, Signature, isclass, iscoroutinefunction
|
6
|
+
from types import FrameType
|
6
7
|
from typing import (
|
7
8
|
Any,
|
8
9
|
Generic,
|
@@ -23,22 +24,43 @@ Func: TypeAlias = Callable[P, T]
|
|
23
24
|
def _noop(*args: Any, **kwargs: Any) -> None: ...
|
24
25
|
|
25
26
|
|
27
|
+
def _walk_stack() -> FrameType:
|
28
|
+
stack = inspect.stack()[1]
|
29
|
+
frame = stack.frame
|
30
|
+
while True:
|
31
|
+
if frame.f_globals["__package__"] != "engin" or frame.f_back is None:
|
32
|
+
return frame
|
33
|
+
else:
|
34
|
+
frame = frame.f_back
|
35
|
+
|
36
|
+
|
26
37
|
class Dependency(ABC, Generic[P, T]):
|
27
38
|
def __init__(self, func: Func[P, T], block_name: str | None = None) -> None:
|
28
39
|
self._func = func
|
29
40
|
self._is_async = iscoroutinefunction(func)
|
30
41
|
self._signature = inspect.signature(self._func)
|
31
42
|
self._block_name = block_name
|
43
|
+
self._source_frame = _walk_stack()
|
32
44
|
|
33
45
|
@property
|
34
|
-
def
|
46
|
+
def source_module(self) -> str:
|
35
47
|
"""
|
36
48
|
The module that this Dependency originated from.
|
37
49
|
|
38
50
|
Returns:
|
39
51
|
A string, e.g. "examples.fastapi.app"
|
40
52
|
"""
|
41
|
-
return self.
|
53
|
+
return self._source_frame.f_globals["__name__"] # type: ignore[no-any-return]
|
54
|
+
|
55
|
+
@property
|
56
|
+
def source_package(self) -> str:
|
57
|
+
"""
|
58
|
+
The package that this Dependency originated from.
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
A string, e.g. "engin"
|
62
|
+
"""
|
63
|
+
return self._source_frame.f_globals["__package__"] # type: ignore[no-any-return]
|
42
64
|
|
43
65
|
@property
|
44
66
|
def block_name(self) -> str | None:
|
@@ -115,10 +137,6 @@ class Entrypoint(Invoke):
|
|
115
137
|
self._type = type_
|
116
138
|
super().__init__(invocation=_noop, block_name=block_name)
|
117
139
|
|
118
|
-
@property
|
119
|
-
def origin(self) -> str:
|
120
|
-
return self._type.__module__
|
121
|
-
|
122
140
|
@property
|
123
141
|
def parameter_types(self) -> list[TypeId]:
|
124
142
|
return [type_id_of(self._type)]
|
@@ -186,10 +204,6 @@ class Supply(Provide, Generic[T]):
|
|
186
204
|
self._get_val.__annotations__["return"] = type_hint
|
187
205
|
super().__init__(builder=self._get_val, block_name=block_name)
|
188
206
|
|
189
|
-
@property
|
190
|
-
def origin(self) -> str:
|
191
|
-
return self._value.__module__
|
192
|
-
|
193
207
|
@property
|
194
208
|
def return_type(self) -> type[T]:
|
195
209
|
if self._type_hint is not None:
|
engin/ext/fastapi.py
CHANGED
@@ -7,7 +7,7 @@ from typing import ClassVar, TypeVar
|
|
7
7
|
from fastapi.routing import APIRoute
|
8
8
|
|
9
9
|
from engin import Engin, Entrypoint, Invoke, Option
|
10
|
-
from engin._dependency import Dependency, Supply
|
10
|
+
from engin._dependency import Dependency, Supply, _noop
|
11
11
|
from engin._graph import DependencyGrapher, Node
|
12
12
|
from engin._type_utils import TypeId, type_id_of
|
13
13
|
from engin.ext.asgi import ASGIEngin
|
@@ -113,7 +113,7 @@ def _extract_routes_from_supply(supply: Supply) -> list[Dependency]:
|
|
113
113
|
inner = supply._value[0]
|
114
114
|
if isinstance(inner, APIRouter):
|
115
115
|
return [
|
116
|
-
APIRouteDependency(
|
116
|
+
APIRouteDependency(supply, route)
|
117
117
|
for route in inner.routes
|
118
118
|
if isinstance(route, APIRoute)
|
119
119
|
]
|
@@ -128,13 +128,26 @@ class APIRouteDependency(Dependency):
|
|
128
128
|
This class should never be constructed in application code.
|
129
129
|
"""
|
130
130
|
|
131
|
-
def __init__(
|
131
|
+
def __init__(
|
132
|
+
self,
|
133
|
+
wraps: Dependency,
|
134
|
+
route: APIRoute,
|
135
|
+
) -> None:
|
132
136
|
"""
|
133
137
|
Warning: this should never be constructed in application code.
|
134
138
|
"""
|
139
|
+
super().__init__(_noop, wraps.block_name)
|
140
|
+
self._wrapped = wraps
|
135
141
|
self._route = route
|
136
142
|
self._signature = inspect.signature(route.endpoint)
|
137
|
-
|
143
|
+
|
144
|
+
@property
|
145
|
+
def source_module(self) -> str:
|
146
|
+
return self._wrapped.source_module
|
147
|
+
|
148
|
+
@property
|
149
|
+
def source_package(self) -> str:
|
150
|
+
return self._wrapped.source_package
|
138
151
|
|
139
152
|
@property
|
140
153
|
def route(self) -> APIRoute:
|
engin/scripts/graph.py
CHANGED
@@ -28,6 +28,8 @@ args.add_argument(
|
|
28
28
|
),
|
29
29
|
)
|
30
30
|
|
31
|
+
_APP_ORIGIN = ""
|
32
|
+
|
31
33
|
|
32
34
|
def serve_graph() -> None:
|
33
35
|
# add cwd to path to enable local package imports
|
@@ -44,6 +46,9 @@ def serve_graph() -> None:
|
|
44
46
|
"Expected an argument of the form 'module:attribute', e.g. 'myapp:engin'"
|
45
47
|
) from None
|
46
48
|
|
49
|
+
global _APP_ORIGIN
|
50
|
+
_APP_ORIGIN = module_name.split(".", maxsplit=1)[0]
|
51
|
+
|
47
52
|
module = importlib.import_module(module_name)
|
48
53
|
|
49
54
|
try:
|
@@ -112,7 +117,17 @@ def _render_node(node: Dependency) -> str:
|
|
112
117
|
if n not in _BLOCK_IDX:
|
113
118
|
_BLOCK_IDX[n] = len(_SEEN_BLOCKS) % 8
|
114
119
|
_SEEN_BLOCKS.append(n)
|
115
|
-
style = f"
|
120
|
+
style = f"b{_BLOCK_IDX[n]}"
|
121
|
+
|
122
|
+
node_root_package = node.source_package.split(".", maxsplit=1)[0]
|
123
|
+
if node_root_package != _APP_ORIGIN:
|
124
|
+
if style:
|
125
|
+
style += "E"
|
126
|
+
else:
|
127
|
+
style = "external"
|
128
|
+
|
129
|
+
if style:
|
130
|
+
style = f":::{style}"
|
116
131
|
|
117
132
|
if isinstance(node, Supply):
|
118
133
|
md += f"{node.return_type_id}"
|
@@ -144,6 +159,7 @@ _GRAPH_HTML = """
|
|
144
159
|
graph LR
|
145
160
|
%%LEGEND%%
|
146
161
|
classDef b0 fill:#7fc97f;
|
162
|
+
classDef external stroke-dasharray: 5 5;
|
147
163
|
</pre>
|
148
164
|
</div>
|
149
165
|
<pre class="mermaid">
|
@@ -157,6 +173,15 @@ _GRAPH_HTML = """
|
|
157
173
|
classDef b5 fill:#f0027f;
|
158
174
|
classDef b6 fill:#bf5b17;
|
159
175
|
classDef b7 fill:#666666;
|
176
|
+
classDef b0E fill:#7fc97f,stroke-dasharray: 5 5;
|
177
|
+
classDef b1E fill:#beaed4,stroke-dasharray: 5 5;
|
178
|
+
classDef b2E fill:#fdc086,stroke-dasharray: 5 5;
|
179
|
+
classDef b3E fill:#ffff99,stroke-dasharray: 5 5;
|
180
|
+
classDef b4E fill:#386cb0,stroke-dasharray: 5 5;
|
181
|
+
classDef b5E fill:#f0027f,stroke-dasharray: 5 5;
|
182
|
+
classDef b6E fill:#bf5b17,stroke-dasharray: 5 5;
|
183
|
+
classDef b7E fill:#666666,stroke-dasharray: 5 5;
|
184
|
+
classDef external stroke-dasharray: 5 5;
|
160
185
|
</pre>
|
161
186
|
<script type="module">
|
162
187
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
@@ -169,6 +194,6 @@ _GRAPH_HTML = """
|
|
169
194
|
|
170
195
|
DEFAULT_LEGEND = (
|
171
196
|
"0[/Invoke/] ~~~ 1[/Entrypoint\\] ~~~ 2[Provide] ~~~ 3(Supply)"
|
172
|
-
' ~~~ 4["`Block Grouping`"]:::b0'
|
197
|
+
' ~~~ 4["`Block Grouping`"]:::b0 ~~~ 5[External Dependency]:::external'
|
173
198
|
)
|
174
|
-
ASGI_ENGIN_LEGEND = DEFAULT_LEGEND + " ~~~
|
199
|
+
ASGI_ENGIN_LEGEND = DEFAULT_LEGEND + " ~~~ 6[[API Route]]"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: engin
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.11
|
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/
|
@@ -12,6 +12,8 @@ Keywords: Application Framework,Dependency Injection
|
|
12
12
|
Requires-Python: >=3.10
|
13
13
|
Description-Content-Type: text/markdown
|
14
14
|
|
15
|
+
[](https://codecov.io/gh/invokermain/engin)
|
16
|
+
|
15
17
|
# Engin 🏎️
|
16
18
|
|
17
19
|
Engin is a zero-dependency application framework for modern Python.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
engin/__init__.py,sha256=yTc8k0HDGMIrxDdEEA90qGD_dExQjVIbXCyaOFRrnMg,508
|
2
2
|
engin/_assembler.py,sha256=6n8RBOwano3U3WM1P8Y6HLHo8IuPD_7jUMoTHBJoEA8,7713
|
3
3
|
engin/_block.py,sha256=0QJtqyP5uTFjXsdVGr4ZONLI2LhfzUKmQGnNQWouB3o,2121
|
4
|
-
engin/_dependency.py,sha256=
|
4
|
+
engin/_dependency.py,sha256=URAuzA8pfLxAnwhrEZQGqO1wNCVN-WQLlFg1j1Kn-vs,6380
|
5
5
|
engin/_engin.py,sha256=MTE4MkLrK45h0Nv7p5H92Kv5URa1nX246B9Pp1JkM3A,9134
|
6
6
|
engin/_exceptions.py,sha256=fsc4pTOIGHUh0x7oZhEXPJUTE268sIhswLoiqXaudiw,635
|
7
7
|
engin/_graph.py,sha256=1pMB0cr--uS0XJycDb1rS_X45RBpoyA6NkKqbeSuz1Q,1628
|
@@ -10,11 +10,11 @@ engin/_type_utils.py,sha256=C71kX2Dr-gluGSL018K4uihX3zkTe7QNWaHhFU10ZmA,2127
|
|
10
10
|
engin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
engin/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
12
|
engin/ext/asgi.py,sha256=PCnemGVVB0jUZVcphz7y283sZ7D5Gog1o6rJ6g2TuCQ,2944
|
13
|
-
engin/ext/fastapi.py,sha256=
|
13
|
+
engin/ext/fastapi.py,sha256=whlzhkyG0l-fF2JQ0IeBBtg1NjwjaIUxKrM3FuAgKyE,5885
|
14
14
|
engin/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
-
engin/scripts/graph.py,sha256=
|
16
|
-
engin-0.0.
|
17
|
-
engin-0.0.
|
18
|
-
engin-0.0.
|
19
|
-
engin-0.0.
|
20
|
-
engin-0.0.
|
15
|
+
engin/scripts/graph.py,sha256=por62FkzcWx72V2Ha9sIoki-o99fe2Ifm1w-mdoHZIQ,5922
|
16
|
+
engin-0.0.11.dist-info/METADATA,sha256=p63ZZiEGzl4jLTj6mQc0n7t-rLoStbp-c5vKI49cF2Y,2291
|
17
|
+
engin-0.0.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
18
|
+
engin-0.0.11.dist-info/entry_points.txt,sha256=Dehk4j5nK6zyuQtgOSRAoLE609V6eLzEp32bjqhO62Q,64
|
19
|
+
engin-0.0.11.dist-info/licenses/LICENSE,sha256=XHh5LPUPKZWTBqBv2xxN2RU7D59nHoiJGb5RIt8f45w,1070
|
20
|
+
engin-0.0.11.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|