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 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
+ ]
@@ -0,0 +1,3 @@
1
+ from prion.syringe import Syringe, factory, single
2
+
3
+ __all__ = ["Syringe", "factory", "single"]
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")