-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
235 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
::: wireup.integration.django.apps | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,12 @@ | |
|
||
Dependency injection container with a focus on developer experience, type safety and ease of use. | ||
|
||
!!! note "New: Dependency injection for Flask" | ||
Simplify usage in Flask applications by using the new [Flask integration](integrations/flask.md)! | ||
|
||
* Automatically inject dependencies on views without having to manually decorate. | ||
* Expose Flask application configuration in the container. | ||
!!! note "New: First-party integrations" | ||
Simplify Dependency injection using the first-party integrations | ||
|
||
* [Django Integration](integrations/django.md) | ||
* [Flask Integration](integrations/flask.md) | ||
* [FastAPI Integration](integrations/fastapi.md) | ||
## Key features | ||
|
||
<div class="card-container"> | ||
|
@@ -67,7 +67,7 @@ Dependency injection container with a focus on developer experience, type safety | |
<img src="https://cdn.jsdelivr.net/gh/jdecked/[email protected]/assets/72x72/2753.png" /> | ||
Framework Agnostic | ||
</div> | ||
Seamlessly integrate with popular web frameworks like Django, Flask and FastAPI | ||
Seamlessly integrate with popular web frameworks such as Django, Flask and FastAPI | ||
to simplify dependency management. | ||
</div> | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
Dependency injection for Django is available via the first-party integration wireup provides, available in | ||
`wireup.integration.django`. | ||
|
||
## Installation | ||
|
||
To install the integration, add `wireup.integration.django` to `INSTALLED_APPS` and define a new `WIREUP` setting. | ||
|
||
```python title="settings.py" | ||
INSTALLED_APPS = [ | ||
..., | ||
"wireup.integration.django" | ||
] | ||
|
||
WIREUP = { | ||
# This is a list of top-level modules containing service registrations. | ||
# It can be either a list of strings or module types. | ||
"SERVICE_MODULES": ["mysite.polls.services"] | ||
}, | ||
``` | ||
|
||
|
||
## Usage | ||
|
||
### Define some services | ||
|
||
```python title="mysite/polls/services/s3_manager.py" | ||
@container.register | ||
class S3Manager: | ||
# Reference configuration by name. | ||
# This is the same name this appears in settings. | ||
def __init__(self, token: Annotated[str, Wire(parameter="S3_BUCKET_ACCESS_TOKEN")]): | ||
self.access_token = token | ||
|
||
def upload(self, file: File) -> None: ... | ||
``` | ||
|
||
It is also possible to use django settings in factories. | ||
|
||
```python title="mysite/polls/services/github_client.py" | ||
@dataclass | ||
class GithubClient: | ||
api_key: str | ||
``` | ||
|
||
|
||
```python title="mysite/polls/services/factories.py" | ||
@container.register | ||
def github_client_factory() -> GithubClient: | ||
return GithubClient(settings.GH_API_KEY) | ||
``` | ||
|
||
### Use in views | ||
```python title="app/views.py" | ||
@container.autowire | ||
def upload_file(request: HttpRequest, s3_manager: S3Manager) -> HttpResponse: | ||
return HttpResponse(...) | ||
``` | ||
|
||
Class-based views are also supported. You autowire both `__init__` and the handler method as necessary. | ||
|
||
|
||
For more examples see the [Wireup Django integration tests](https://github.com/maldoinc/wireup/tree/master/test/integration/django). | ||
|
||
|
||
## Api Reference | ||
|
||
* [django_integration](../class/django_integration.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from test.integration.django.service.random_service import RandomService | ||
|
||
from django.conf import settings | ||
from wireup import container | ||
|
||
|
||
@container.register | ||
def _make_random_service() -> RandomService: | ||
return RandomService(settings.START_NUM) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from test.integration.django.service.greeter_interface import GreeterService | ||
|
||
from wireup import container | ||
|
||
|
||
@container.register | ||
class GreeterServiceImpl(GreeterService): | ||
def greet(self, name: str) -> str: | ||
return f"Hello {name}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import abc | ||
|
||
from wireup import container | ||
|
||
|
||
@container.abstract | ||
class GreeterService(abc.ABC): | ||
@abc.abstractmethod | ||
def greet(self, name: str) -> str: | ||
raise NotImplementedError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class RandomService: | ||
def __init__(self, num: int) -> None: | ||
self.num = num | ||
|
||
def get_random(self) -> int: | ||
return self.num |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import os | ||
import sys | ||
import unittest | ||
from test.integration.django import view | ||
|
||
import django | ||
from django.test import Client | ||
from django.urls import path | ||
|
||
INSTALLED_APPS = ["wireup.integration.django"] | ||
DEBUG = True | ||
ROOT_URLCONF = sys.modules[__name__] | ||
WIREUP = {"SERVICE_MODULES": ["test.integration.django.service", "test.integration.django.factory"]} | ||
SECRET_KEY = "not_actually_a_secret" # noqa: S105 | ||
START_NUM = 4 | ||
|
||
urlpatterns = [ | ||
path(r"", view.index), | ||
path(r"classbased", view.RandomNumberView.as_view()), | ||
] | ||
|
||
|
||
class TestDjango(unittest.TestCase): | ||
def setUp(self): | ||
os.environ["DJANGO_SETTINGS_MODULE"] = "test.integration.django.test_django_integration" | ||
django.setup() | ||
|
||
def test_django_thing(self): | ||
c = Client() | ||
res = c.get("/?name=World") | ||
|
||
self.assertEqual(res.status_code, 200) | ||
self.assertEqual(res.content.decode("utf8"), "Hello World! Debug = True. Your lucky number is 4") | ||
|
||
def test_get_random(self): | ||
c = Client() | ||
res = c.get("/classbased?name=Test") | ||
|
||
self.assertEqual(res.status_code, 200) | ||
self.assertEqual(res.content.decode("utf8"), "Hello Test! Debug = True. Your lucky number is 4") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from test.integration.django.service.greeter_interface import GreeterService | ||
from test.integration.django.service.random_service import RandomService | ||
|
||
from django.http import HttpRequest, HttpResponse | ||
from django.views import View | ||
from typing_extensions import Annotated | ||
from wireup import Wire, container | ||
|
||
|
||
@container.autowire | ||
def index( | ||
request: HttpRequest, | ||
greeter: GreeterService, | ||
is_debug: Annotated[bool, Wire(param="DEBUG")], | ||
random_service: RandomService, | ||
) -> HttpResponse: | ||
name = request.GET.get("name") | ||
greeting = greeter.greet(name) | ||
|
||
return HttpResponse(f"{greeting}! Debug = {is_debug}. Your lucky number is {random_service.get_random()}") | ||
|
||
|
||
class RandomNumberView(View): | ||
@container.autowire | ||
def __init__( | ||
self, | ||
greeter: GreeterService, | ||
is_debug: Annotated[bool, Wire(param="DEBUG")], | ||
random_service: RandomService, | ||
) -> None: | ||
self.random_service = random_service | ||
self.is_debug = is_debug | ||
self.greeter = greeter | ||
|
||
def get( | ||
self, | ||
request: HttpRequest, | ||
) -> HttpResponse: | ||
name = request.GET.get("name") | ||
greeting = self.greeter.greet(name) | ||
|
||
return HttpResponse( | ||
f"{greeting}! Debug = {self.is_debug}. Your lucky number is {self.random_service.get_random()}" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from __future__ import annotations | ||
|
||
import importlib | ||
|
||
from django.apps import AppConfig | ||
from django.conf import settings | ||
|
||
from wireup import container, warmup_container | ||
|
||
|
||
class WireupConfig(AppConfig): | ||
"""Integrate wireup with Django.""" | ||
|
||
name = "wireup.integration.django" | ||
|
||
def ready(self) -> None: # noqa: D102 | ||
service_modules = settings.WIREUP.get("SERVICE_MODULES", []) | ||
|
||
for entry in dir(settings): | ||
if not entry.startswith("__") and hasattr(settings, entry): | ||
container.params.put(entry, getattr(settings, entry)) | ||
|
||
warmup_container(container, [importlib.import_module(m) if isinstance(m, str) else m for m in service_modules]) |