engin 0.0.17__py3-none-any.whl → 0.0.18__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/_assembler.py +6 -1
- engin/_cli/__init__.py +11 -0
- engin/_cli/_common.py +51 -0
- engin/_cli/_graph.py +4 -35
- engin/_cli/_inspect.py +94 -0
- {engin-0.0.17.dist-info → engin-0.0.18.dist-info}/METADATA +1 -1
- {engin-0.0.17.dist-info → engin-0.0.18.dist-info}/RECORD +10 -9
- engin/_cli/_utils.py +0 -18
- {engin-0.0.17.dist-info → engin-0.0.18.dist-info}/WHEEL +0 -0
- {engin-0.0.17.dist-info → engin-0.0.18.dist-info}/entry_points.txt +0 -0
- {engin-0.0.17.dist-info → engin-0.0.18.dist-info}/licenses/LICENSE +0 -0
engin/_assembler.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import asyncio
|
2
2
|
import logging
|
3
3
|
from collections import defaultdict
|
4
|
-
from collections.abc import Iterable
|
4
|
+
from collections.abc import Iterable, Sequence
|
5
5
|
from contextvars import ContextVar
|
6
6
|
from dataclasses import dataclass
|
7
7
|
from inspect import BoundArguments, Signature
|
@@ -75,6 +75,11 @@ class Assembler:
|
|
75
75
|
else:
|
76
76
|
self._multiproviders[type_id].append(provider)
|
77
77
|
|
78
|
+
@property
|
79
|
+
def providers(self) -> Sequence[Provide[Any]]:
|
80
|
+
multi_providers = [p for multi in self._multiproviders.values() for p in multi]
|
81
|
+
return [*self._providers.values(), *multi_providers]
|
82
|
+
|
78
83
|
async def assemble(self, dependency: Dependency[Any, T]) -> AssembledDependency[T]:
|
79
84
|
"""
|
80
85
|
Assemble a dependency.
|
engin/_cli/__init__.py
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
import logging
|
2
|
+
import sys
|
3
|
+
|
1
4
|
try:
|
2
5
|
import typer
|
3
6
|
except ImportError:
|
@@ -7,7 +10,15 @@ except ImportError:
|
|
7
10
|
) from None
|
8
11
|
|
9
12
|
from engin._cli._graph import cli as graph_cli
|
13
|
+
from engin._cli._inspect import cli as inspect_cli
|
14
|
+
|
15
|
+
# mute logging from importing of files + engin's debug logging.
|
16
|
+
logging.disable()
|
17
|
+
|
18
|
+
# add cwd to path to enable local package imports
|
19
|
+
sys.path.insert(0, "")
|
10
20
|
|
11
21
|
app = typer.Typer()
|
12
22
|
|
13
23
|
app.add_typer(graph_cli)
|
24
|
+
app.add_typer(inspect_cli)
|
engin/_cli/_common.py
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
import importlib
|
2
|
+
from typing import Never
|
3
|
+
|
4
|
+
import typer
|
5
|
+
from rich import print
|
6
|
+
from rich.panel import Panel
|
7
|
+
|
8
|
+
from engin import Engin
|
9
|
+
|
10
|
+
|
11
|
+
def print_error(msg: str) -> Never:
|
12
|
+
print(
|
13
|
+
Panel(
|
14
|
+
title="Error",
|
15
|
+
renderable=msg,
|
16
|
+
title_align="left",
|
17
|
+
border_style="red",
|
18
|
+
highlight=True,
|
19
|
+
)
|
20
|
+
)
|
21
|
+
raise typer.Exit(code=1)
|
22
|
+
|
23
|
+
|
24
|
+
COMMON_HELP = {
|
25
|
+
"app": (
|
26
|
+
"The import path of your Engin instance, in the form 'package:application'"
|
27
|
+
", e.g. 'app.main:engin'"
|
28
|
+
)
|
29
|
+
}
|
30
|
+
|
31
|
+
|
32
|
+
def get_engin_instance(app: str) -> tuple[str, str, Engin]:
|
33
|
+
try:
|
34
|
+
module_name, engin_name = app.split(":", maxsplit=1)
|
35
|
+
except ValueError:
|
36
|
+
print_error("Expected an argument of the form 'module:attribute', e.g. 'myapp:engin'")
|
37
|
+
|
38
|
+
try:
|
39
|
+
module = importlib.import_module(module_name)
|
40
|
+
except ModuleNotFoundError:
|
41
|
+
print_error(f"Unable to find module '{module_name}'")
|
42
|
+
|
43
|
+
try:
|
44
|
+
instance = getattr(module, engin_name)
|
45
|
+
except AttributeError:
|
46
|
+
print_error(f"Module '{module_name}' has no attribute '{engin_name}'")
|
47
|
+
|
48
|
+
if not isinstance(instance, Engin):
|
49
|
+
print_error(f"'{app}' is not an Engin instance")
|
50
|
+
|
51
|
+
return module_name, engin_name, instance
|
engin/_cli/_graph.py
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
import contextlib
|
2
|
-
import importlib
|
3
|
-
import logging
|
4
2
|
import socketserver
|
5
|
-
import sys
|
6
3
|
import threading
|
7
4
|
from http.server import BaseHTTPRequestHandler
|
8
5
|
from pathlib import Path
|
@@ -12,8 +9,8 @@ from typing import Annotated, Any
|
|
12
9
|
import typer
|
13
10
|
from rich import print
|
14
11
|
|
15
|
-
from engin import
|
16
|
-
from engin._cli.
|
12
|
+
from engin import Entrypoint, Invoke, TypeId
|
13
|
+
from engin._cli._common import COMMON_HELP, get_engin_instance
|
17
14
|
from engin._dependency import Dependency, Provide, Supply
|
18
15
|
from engin.ext.asgi import ASGIEngin
|
19
16
|
|
@@ -24,53 +21,25 @@ except ImportError:
|
|
24
21
|
|
25
22
|
cli = typer.Typer()
|
26
23
|
|
27
|
-
# mute logging from importing of files + engin's debug logging.
|
28
|
-
logging.disable()
|
29
24
|
|
30
25
|
_APP_ORIGIN = ""
|
31
26
|
|
32
|
-
_CLI_HELP = {
|
33
|
-
"app": (
|
34
|
-
"The import path of your Engin instance, in the form 'package:application'"
|
35
|
-
", e.g. 'app.main:engin'"
|
36
|
-
)
|
37
|
-
}
|
38
|
-
|
39
27
|
|
40
28
|
@cli.command(name="graph")
|
41
29
|
def serve_graph(
|
42
30
|
app: Annotated[
|
43
31
|
str,
|
44
|
-
typer.Argument(help=
|
32
|
+
typer.Argument(help=COMMON_HELP["app"]),
|
45
33
|
],
|
46
34
|
) -> None:
|
47
35
|
"""
|
48
36
|
Creates a visualisation of your application's dependencies.
|
49
37
|
"""
|
50
|
-
|
51
|
-
sys.path.insert(0, "")
|
52
|
-
|
53
|
-
try:
|
54
|
-
module_name, engin_name = app.split(":", maxsplit=1)
|
55
|
-
except ValueError:
|
56
|
-
print_error("Expected an argument of the form 'module:attribute', e.g. 'myapp:engin'")
|
38
|
+
module_name, _, instance = get_engin_instance(app)
|
57
39
|
|
58
40
|
global _APP_ORIGIN
|
59
41
|
_APP_ORIGIN = module_name.split(".", maxsplit=1)[0]
|
60
42
|
|
61
|
-
try:
|
62
|
-
module = importlib.import_module(module_name)
|
63
|
-
except ModuleNotFoundError:
|
64
|
-
print_error(f"unable to find module '{module_name}'")
|
65
|
-
|
66
|
-
try:
|
67
|
-
instance = getattr(module, engin_name)
|
68
|
-
except AttributeError:
|
69
|
-
print_error(f"module '{module_name}' has no attribute '{engin_name}'")
|
70
|
-
|
71
|
-
if not isinstance(instance, Engin):
|
72
|
-
print_error(f"'{app}' is not an Engin instance")
|
73
|
-
|
74
43
|
nodes = instance.graph()
|
75
44
|
|
76
45
|
# transform dependencies into mermaid syntax
|
engin/_cli/_inspect.py
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
from typing import Annotated
|
2
|
+
|
3
|
+
import typer
|
4
|
+
from rich import box
|
5
|
+
from rich.console import Console
|
6
|
+
from rich.table import Table
|
7
|
+
|
8
|
+
from engin import Supply
|
9
|
+
from engin._cli._common import COMMON_HELP, get_engin_instance, print_error
|
10
|
+
|
11
|
+
cli = typer.Typer()
|
12
|
+
_CLI_HELP = {
|
13
|
+
"type": "Filter providers by the provided type, e.g. `AsyncClient` or `float[]`",
|
14
|
+
"module": "Filter providers by the provided types' module, e.g. `engin` or `httpx`",
|
15
|
+
"verbose": "Enables verbose output",
|
16
|
+
}
|
17
|
+
|
18
|
+
|
19
|
+
@cli.command(name="inspect")
|
20
|
+
def serve_graph(
|
21
|
+
app: Annotated[
|
22
|
+
str,
|
23
|
+
typer.Argument(help=COMMON_HELP["app"]),
|
24
|
+
],
|
25
|
+
type_: Annotated[
|
26
|
+
str | None,
|
27
|
+
typer.Option("--type", help=_CLI_HELP["type"]),
|
28
|
+
] = None,
|
29
|
+
module: Annotated[
|
30
|
+
str | None,
|
31
|
+
typer.Option(help=_CLI_HELP["module"]),
|
32
|
+
] = None,
|
33
|
+
verbose: Annotated[
|
34
|
+
bool, typer.Option("--verbose", "-v", help=_CLI_HELP["verbose"])
|
35
|
+
] = False,
|
36
|
+
) -> None:
|
37
|
+
"""
|
38
|
+
Shows metadata for all matching providers.
|
39
|
+
|
40
|
+
Examples:
|
41
|
+
|
42
|
+
1. `engin inspect examples.simple.main:engin --module httpx`
|
43
|
+
|
44
|
+
2. `engin inspect examples.simple.main:engin --type AsyncClient`
|
45
|
+
"""
|
46
|
+
module_name, _, instance = get_engin_instance(app)
|
47
|
+
|
48
|
+
console = Console()
|
49
|
+
|
50
|
+
providers = []
|
51
|
+
for provider in instance.assembler.providers:
|
52
|
+
type_id = provider.return_type_id
|
53
|
+
if type_ is not None:
|
54
|
+
type_name = str(type_id).rsplit(".", maxsplit=1)[-1]
|
55
|
+
if type_ != type_name:
|
56
|
+
if verbose:
|
57
|
+
console.print(
|
58
|
+
f"Ignoring '{provider.return_type_id}' as `{type_} != {type_name}",
|
59
|
+
style="dim",
|
60
|
+
)
|
61
|
+
continue
|
62
|
+
if module is not None:
|
63
|
+
module_name = str(type_id).split(".", maxsplit=1)[0]
|
64
|
+
if module != module_name:
|
65
|
+
if verbose:
|
66
|
+
console.print(
|
67
|
+
f"Ignoring '{provider.return_type_id}' as `{module} != {module_name}",
|
68
|
+
style="dim",
|
69
|
+
)
|
70
|
+
continue
|
71
|
+
providers.append(provider)
|
72
|
+
|
73
|
+
matching_provider_count = len(providers)
|
74
|
+
if matching_provider_count == 0:
|
75
|
+
available = sorted(map(str, instance.assembler.providers))
|
76
|
+
print_error(f"No matching providers, available: {available}")
|
77
|
+
|
78
|
+
if matching_provider_count > 1:
|
79
|
+
console.print(f"Found {matching_provider_count} matching providers", style="dim")
|
80
|
+
|
81
|
+
table = Table(show_header=False, show_lines=False, box=box.ASCII)
|
82
|
+
|
83
|
+
for provider in sorted(providers, key=lambda p: p.source_module):
|
84
|
+
is_supply = isinstance(provider, Supply)
|
85
|
+
|
86
|
+
table.add_row("name", str(provider), style="bold", end_section=True)
|
87
|
+
table.add_row("scope", provider.scope or "N/A")
|
88
|
+
table.add_row("func", provider.func_name if not is_supply else "N/A")
|
89
|
+
table.add_row("block", provider.block_name or "N/A")
|
90
|
+
table.add_row("source module", provider.source_module or "N/A")
|
91
|
+
table.add_row("source package", provider.source_package or "N/A")
|
92
|
+
table.add_section()
|
93
|
+
|
94
|
+
console.print(table)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
engin/__init__.py,sha256=rBTteMLAVKg4TJSaMElJUwz72BA_X7nBTREg-I-bWhA,584
|
2
|
-
engin/_assembler.py,sha256=
|
2
|
+
engin/_assembler.py,sha256=saxYTjT67WR2HLJAFXyDsDeQmLGp1uyDboTDiKTaZ_s,11177
|
3
3
|
engin/_block.py,sha256=8ysWrmHkWpTm6bmSc6jZVoO0Ax5Svu1HwxpZwAtIF_o,2617
|
4
4
|
engin/_dependency.py,sha256=5x4_0QvHtqv6R_brKHRc-INKE4oMh1JU8-9RCmulp4Q,8976
|
5
5
|
engin/_engin.py,sha256=yIpZdeqvm8hv0RxOV0veFuvyu9xQ054JSaeuUWwHdOQ,7380
|
@@ -10,15 +10,16 @@ engin/_lifecycle.py,sha256=cSWe3euZkmpxmUPFvph2lsTtvuZbxttEfBL-RnOI7lo,5325
|
|
10
10
|
engin/_option.py,sha256=nZcdrehp1QwgxMUoIpsM0PJuu1q1pbXzhcVsetbsHpc,223
|
11
11
|
engin/_type_utils.py,sha256=Pmm4m1_WdevT5KTe8tzY_BseNxPyhu_nKsLGgyNcPpo,2247
|
12
12
|
engin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
engin/_cli/__init__.py,sha256=
|
13
|
+
engin/_cli/__init__.py,sha256=koD5WTkZXb8QQIiVU5bJiSR1wwPGb5rv2iwd-v-BA7A,564
|
14
|
+
engin/_cli/_common.py,sha256=zMYb1Bs1yUuR3qf3r6WuVozYzDwHJvTVthVbTQfTF9w,1261
|
14
15
|
engin/_cli/_graph.html,sha256=rR5dnDKoz7KtSff0ERCi2UKuoH_Z03MRYiXI_W03G5k,2430
|
15
|
-
engin/_cli/_graph.py,sha256=
|
16
|
-
engin/_cli/
|
16
|
+
engin/_cli/_graph.py,sha256=S0HKWb3PlC1ygYTdsFzEm-eYmrbHhOOMZ7nApOe7ac8,4645
|
17
|
+
engin/_cli/_inspect.py,sha256=0jm25d4wcbXVNJkyaeECSKY-irsxd-EIYBH1GDW_Yjc,3163
|
17
18
|
engin/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
19
|
engin/ext/asgi.py,sha256=d5Z6gtMVWDZdAlvrTaMt987sKyiq__A0X4gJQ7IETmA,3247
|
19
20
|
engin/ext/fastapi.py,sha256=TGNf0LFLaTLMLlAycH7GgP_GcBld262v9xboGOwhvgE,6362
|
20
|
-
engin-0.0.
|
21
|
-
engin-0.0.
|
22
|
-
engin-0.0.
|
23
|
-
engin-0.0.
|
24
|
-
engin-0.0.
|
21
|
+
engin-0.0.18.dist-info/METADATA,sha256=4d8IsPLHnEekTIP5Qdy2LfNYHHZ-G0DLWcjB2RRQdSs,2354
|
22
|
+
engin-0.0.18.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
23
|
+
engin-0.0.18.dist-info/entry_points.txt,sha256=sW247zZUMxm0b5UKYvPuqQQljYDtU-j2zK3cu7gHwM0,41
|
24
|
+
engin-0.0.18.dist-info/licenses/LICENSE,sha256=XHh5LPUPKZWTBqBv2xxN2RU7D59nHoiJGb5RIt8f45w,1070
|
25
|
+
engin-0.0.18.dist-info/RECORD,,
|
engin/_cli/_utils.py
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
from typing import Never
|
2
|
-
|
3
|
-
import typer
|
4
|
-
from rich import print
|
5
|
-
from rich.panel import Panel
|
6
|
-
|
7
|
-
|
8
|
-
def print_error(msg: str) -> Never:
|
9
|
-
print(
|
10
|
-
Panel(
|
11
|
-
title="Error",
|
12
|
-
renderable=msg.capitalize(),
|
13
|
-
title_align="left",
|
14
|
-
border_style="red",
|
15
|
-
highlight=True,
|
16
|
-
)
|
17
|
-
)
|
18
|
-
raise typer.Exit(code=1)
|
File without changes
|
File without changes
|
File without changes
|