prion 0.1.0__tar.gz
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.
- prion-0.1.0/PKG-INFO +72 -0
- prion-0.1.0/README.md +59 -0
- prion-0.1.0/pyproject.toml +29 -0
- prion-0.1.0/src/prion/__init__.py +3 -0
- prion-0.1.0/src/prion/_internal/__init__.py +0 -0
- prion-0.1.0/src/prion/_internal/dependency.py +52 -0
- prion-0.1.0/src/prion/py.typed +0 -0
- prion-0.1.0/src/prion/syringe.py +19 -0
prion-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: prion
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Dependency injection framework using pure Python
|
|
5
|
+
Author: Geunryeol Park
|
|
6
|
+
Author-email: Geunryeol Park <pkr5207@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Topic :: Utilities
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# Prion
|
|
15
|
+
|
|
16
|
+
A dependency injection framework using pure Python. No external dependencies.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
pip install prion
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
Define a container by subclassing `Syringe` and declaring dependencies with `single()` or `factory()`.
|
|
27
|
+
|
|
28
|
+
```pycon
|
|
29
|
+
>>> from prion import Syringe, single, factory
|
|
30
|
+
|
|
31
|
+
>>> class AppSyringe(Syringe):
|
|
32
|
+
... config: dict = single()
|
|
33
|
+
... session: dict = factory()
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Create an instance and register providers using decorators.
|
|
38
|
+
|
|
39
|
+
```pycon
|
|
40
|
+
>>> syringe = AppSyringe()
|
|
41
|
+
|
|
42
|
+
>>> @syringe.config
|
|
43
|
+
... def create_config() -> dict:
|
|
44
|
+
... return {"debug": True}
|
|
45
|
+
|
|
46
|
+
>>> @syringe.session
|
|
47
|
+
... def create_session() -> dict:
|
|
48
|
+
... return {}
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Access dependencies as attributes.
|
|
53
|
+
|
|
54
|
+
```pycon
|
|
55
|
+
>>> syringe.config is syringe.config
|
|
56
|
+
True
|
|
57
|
+
|
|
58
|
+
>>> syringe.session is not syringe.session
|
|
59
|
+
True
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Strategies
|
|
64
|
+
|
|
65
|
+
| Strategy | Behavior |
|
|
66
|
+
| ----------- | --------------------------------- |
|
|
67
|
+
| `single()` | Creates once, returns cached |
|
|
68
|
+
| `factory()` | Creates a new instance each time |
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
MIT
|
prion-0.1.0/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Prion
|
|
2
|
+
|
|
3
|
+
A dependency injection framework using pure Python. No external dependencies.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pip install prion
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Define a container by subclassing `Syringe` and declaring dependencies with `single()` or `factory()`.
|
|
14
|
+
|
|
15
|
+
```pycon
|
|
16
|
+
>>> from prion import Syringe, single, factory
|
|
17
|
+
|
|
18
|
+
>>> class AppSyringe(Syringe):
|
|
19
|
+
... config: dict = single()
|
|
20
|
+
... session: dict = factory()
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Create an instance and register providers using decorators.
|
|
25
|
+
|
|
26
|
+
```pycon
|
|
27
|
+
>>> syringe = AppSyringe()
|
|
28
|
+
|
|
29
|
+
>>> @syringe.config
|
|
30
|
+
... def create_config() -> dict:
|
|
31
|
+
... return {"debug": True}
|
|
32
|
+
|
|
33
|
+
>>> @syringe.session
|
|
34
|
+
... def create_session() -> dict:
|
|
35
|
+
... return {}
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Access dependencies as attributes.
|
|
40
|
+
|
|
41
|
+
```pycon
|
|
42
|
+
>>> syringe.config is syringe.config
|
|
43
|
+
True
|
|
44
|
+
|
|
45
|
+
>>> syringe.session is not syringe.session
|
|
46
|
+
True
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Strategies
|
|
51
|
+
|
|
52
|
+
| Strategy | Behavior |
|
|
53
|
+
| ----------- | --------------------------------- |
|
|
54
|
+
| `single()` | Creates once, returns cached |
|
|
55
|
+
| `factory()` | Creates a new instance each time |
|
|
56
|
+
|
|
57
|
+
## License
|
|
58
|
+
|
|
59
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "prion"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Dependency injection framework using pure Python"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
authors = [{name = "Geunryeol Park", email = "pkr5207@gmail.com"}]
|
|
8
|
+
classifiers = [
|
|
9
|
+
"License :: OSI Approved :: MIT License",
|
|
10
|
+
"Programming Language :: Python",
|
|
11
|
+
"Topic :: Utilities"
|
|
12
|
+
]
|
|
13
|
+
license = "MIT"
|
|
14
|
+
|
|
15
|
+
[build-system]
|
|
16
|
+
requires = ["uv_build>=0.9.26,<0.10.0"]
|
|
17
|
+
build-backend = "uv_build"
|
|
18
|
+
|
|
19
|
+
[tool.uv]
|
|
20
|
+
managed = true
|
|
21
|
+
resolution = "highest"
|
|
22
|
+
|
|
23
|
+
[tool.pytest.ini_options]
|
|
24
|
+
addopts = ["--doctest-glob=*.md"]
|
|
25
|
+
|
|
26
|
+
[dependency-groups]
|
|
27
|
+
dev = [
|
|
28
|
+
"pytest>=9.0.2",
|
|
29
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Callable
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from prion.syringe import Syringe
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DependencyState:
|
|
10
|
+
__slots__ = ("_strategy", "_provider", "_value", "_resolved")
|
|
11
|
+
|
|
12
|
+
def __init__(self, strategy: str) -> None:
|
|
13
|
+
self._strategy = strategy
|
|
14
|
+
self._provider: Callable[..., Any] | None = None
|
|
15
|
+
self._value: Any = None
|
|
16
|
+
self._resolved = False
|
|
17
|
+
|
|
18
|
+
def __call__(self, provider: Callable[..., Any]) -> Callable[..., Any]:
|
|
19
|
+
self._provider = provider
|
|
20
|
+
return provider
|
|
21
|
+
|
|
22
|
+
def resolve(self) -> Any:
|
|
23
|
+
if self._provider is None:
|
|
24
|
+
raise RuntimeError("no provider registered for this dependency")
|
|
25
|
+
if self._strategy == "single":
|
|
26
|
+
if not self._resolved:
|
|
27
|
+
self._value = self._provider()
|
|
28
|
+
self._resolved = True
|
|
29
|
+
return self._value
|
|
30
|
+
return self._provider()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Dependency:
|
|
34
|
+
__slots__ = ("_strategy", "_attr")
|
|
35
|
+
|
|
36
|
+
def __init__(self, strategy: str) -> None:
|
|
37
|
+
self._strategy = strategy
|
|
38
|
+
self._attr: str = ""
|
|
39
|
+
|
|
40
|
+
def __set_name__(self, owner: type, name: str) -> None:
|
|
41
|
+
self._attr = name
|
|
42
|
+
|
|
43
|
+
def __get__(self, obj: Syringe | None, objtype: type | None = None) -> Any:
|
|
44
|
+
if obj is None:
|
|
45
|
+
return self
|
|
46
|
+
state = obj._dependencies.get(self._attr)
|
|
47
|
+
if state is None:
|
|
48
|
+
state = DependencyState(self._strategy)
|
|
49
|
+
obj._dependencies[self._attr] = state
|
|
50
|
+
if state._provider is None:
|
|
51
|
+
return state
|
|
52
|
+
return state.resolve()
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from prion._internal.dependency import Dependency, DependencyState
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Syringe:
|
|
9
|
+
|
|
10
|
+
def __init__(self) -> None:
|
|
11
|
+
self._dependencies: dict[str, DependencyState] = {}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def single() -> Any:
|
|
15
|
+
return Dependency("single")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def factory() -> Any:
|
|
19
|
+
return Dependency("factory")
|