Skip to content

Commit 233a04c

Browse files
authored
feat: ✨ BlackSheep integration
1 parent 13bbd83 commit 233a04c

File tree

9 files changed

+534
-6
lines changed

9 files changed

+534
-6
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ pip install python-injection
1919
* [**Basic usage**](documentation/basic-usage.md)
2020
* [**Advanced usage**](documentation/advanced-usage.md)
2121
* [**Utils**](documentation/utils.md)
22+
* [**Integrations**](documentation/integrations.md)

documentation/integrations.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Integrations
2+
3+
**Integrations make it easy to connect `python-injection` to other frameworks.**
4+
5+
## [BlackSheep](https://github.com/Neoteroi/BlackSheep)
6+
7+
_[See more](https://www.neoteroi.dev/blacksheep/dependency-injection) about BlackSheep and its dependency injection._
8+
9+
Example:
10+
11+
```python
12+
from blacksheep import Application
13+
from injection.integrations.blacksheep import InjectionServices
14+
15+
app = Application(
16+
services=InjectionServices(),
17+
)
18+
```
19+
20+
Example with a custom injection module:
21+
22+
```python
23+
from blacksheep import Application
24+
from injection import Module
25+
from injection.integrations.blacksheep import InjectionServices
26+
27+
custom_module = Module(f"{__name__}:custom_module")
28+
29+
app = Application(
30+
services=InjectionServices(custom_module),
31+
)
32+
```

injection/integrations/__init__.py

Whitespace-only changes.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from typing import Any, TypeVar
2+
3+
from injection import Module, default_module
4+
from injection.exceptions import NoInjectable
5+
6+
_T = TypeVar("_T")
7+
8+
9+
class InjectionServices:
10+
"""
11+
BlackSheep dependency injection container implemented with `python-injection`.
12+
"""
13+
14+
__slots__ = ("__module",)
15+
16+
def __init__(self, module: Module = default_module):
17+
self.__module = module
18+
19+
def __contains__(self, cls: type | Any, /) -> bool:
20+
return cls in self.__module
21+
22+
def register(self, cls: type | Any, *__args, **__kwargs):
23+
self.__module.injectable(cls)
24+
return self
25+
26+
def resolve(self, cls: type[_T] | Any, *__args, **__kwargs) -> _T:
27+
instance = self.__module.get_instance(cls)
28+
29+
if instance is None:
30+
raise NoInjectable(cls)
31+
32+
return instance

poetry.lock

Lines changed: 424 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ python = ">=3.10, <4"
1414

1515
[tool.poetry.group.dev.dependencies]
1616
black = "*"
17+
blacksheep = "^2.0.4"
1718
flake8 = "*"
1819
isort = "*"
1920
pytest = "*"
21+
pytest-asyncio = "*"
2022
pytest-cov = "*"
2123

2224
[build-system]

setup.cfg

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@ exclude_lines =
44
raise NotImplementedError
55

66

7-
[coverage:run]
8-
omit =
9-
__init__.py
10-
11-
127
[flake8]
138
max-line-length=88
149
per-file-ignores =
@@ -23,4 +18,5 @@ profile=black
2318
[tool:pytest]
2419
python_files = test_*.py
2520
addopts = -p no:warnings --tb=short
21+
asyncio_mode = auto
2622
testpaths = tests/

tests/integrations/__init__.py

Whitespace-only changes.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import pytest
2+
from blacksheep import Application, Response
3+
from blacksheep.server.controllers import APIController, post
4+
from blacksheep.testing import TestClient
5+
6+
from injection import singleton
7+
from injection.integrations.blacksheep import InjectionServices
8+
9+
application = Application(
10+
services=InjectionServices(),
11+
)
12+
13+
14+
@singleton
15+
class Dependency:
16+
...
17+
18+
19+
class TestController(APIController):
20+
def __init__(self, dependency: Dependency):
21+
self.__dependency = dependency
22+
23+
@classmethod
24+
def class_name(cls) -> str:
25+
return "tests"
26+
27+
@post("/integration")
28+
async def test_integration(self) -> Response:
29+
assert isinstance(self.__dependency, Dependency)
30+
return self.no_content()
31+
32+
33+
class TestBlackSheepIntegration:
34+
@pytest.fixture(scope="class")
35+
async def client(self) -> TestClient:
36+
await application.start()
37+
yield TestClient(application)
38+
await application.stop()
39+
40+
async def test_blacksheep_integration_with_success(self, client):
41+
response = await client.post("/api/tests/integration")
42+
assert response.status == 204

0 commit comments

Comments
 (0)