-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample.py
More file actions
160 lines (116 loc) · 3.86 KB
/
example.py
File metadata and controls
160 lines (116 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
from abc import ABC, abstractmethod
from pydantic import BaseModel
from starlette.applications import Starlette
from starlette.endpoints import HTTPEndpoint
from starlette.middleware import Middleware
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.routing import Route
from starlette.testclient import TestClient
from starlette_di import (
DependencyInjectionMiddleware,
ServiceCollection,
inject,
inject_class,
inject_method,
)
# Models
class User(BaseModel):
name: str
age: int
class Product(BaseModel):
name: str
price: float
# Services
class IGreeter(ABC):
@abstractmethod
def greet(self) -> str: ...
class Greeter(IGreeter):
def greet(self) -> str:
return 'Hello!'
class ICounter(ABC):
@abstractmethod
def count(self) -> int: ...
class Counter(ICounter):
def __init__(self, greeter: IGreeter):
self._count = 0
self._greeter = greeter
def count(self) -> int:
self._count += 1
return self._count
class IServicesTester(ABC):
@abstractmethod
def test(self) -> None: ...
class ServicesTester(IServicesTester):
def __init__(self, greeter: IGreeter, counter: ICounter):
self._greeter = greeter
self._counter = counter
def test(self):
return {
'greeter_id': id(self._greeter),
'counter_id': id(self._counter),
}
# Factories
def services_tester_factory(greeter: IGreeter, counter: ICounter):
return ServicesTester(greeter, counter)
# Service collection
services = ServiceCollection()
services.add_transient(IGreeter, Greeter)
services.add_singleton(ICounter, Counter)
services.add_scoped(IServicesTester, ServicesTester)
provider = services.build_provider()
# Endpoints
@inject
async def greet(request: Request, greeter: IGreeter):
return JSONResponse({'message': greeter.greet()})
@inject_class
class CounterEndpoint(HTTPEndpoint):
async def get(self, request: Request, counter: ICounter):
return JSONResponse({'value': counter.count()})
class ServicesTesterEndpoint(HTTPEndpoint):
@inject_method
async def get(self, request: Request, services_tester: IServicesTester):
return JSONResponse(services_tester.test())
@inject
async def create_user(request: Request, user: User):
return JSONResponse({'name': user.name, 'age': user.age})
@inject
async def update_product(request: Request, user: User, product: Product):
return JSONResponse({'user_name': user.name, 'product_name': product.name})
# Application
app = Starlette(
routes=[
Route('/greet', greet),
Route('/counter', CounterEndpoint),
Route('/test-services', ServicesTesterEndpoint),
Route('/users', create_user, methods=['POST']),
Route('/products', update_product, methods=['POST']),
],
middleware=[
Middleware(DependencyInjectionMiddleware, service_provider=provider),
],
)
# Test client
client = TestClient(app)
response = client.get('/greet')
assert response.json() == {'message': 'Hello!'}
response = client.get('/counter')
assert response.json() == {'value': 1}
response = client.get('/counter')
assert response.json() == {'value': 2}
response = client.get('/test-services')
service_ids1 = response.json()
response = client.get('/test-services')
service_ids2 = response.json()
assert service_ids1['greeter_id'] != service_ids2['greeter_id']
assert service_ids1['counter_id'] == service_ids2['counter_id']
data = {'name': 'Jane Doe', 'age': 25}
response = client.post('/users', json=data)
assert response.json() == {'name': 'Jane Doe', 'age': 25}
data = {
'user': {'name': 'Jane Doe', 'age': 25},
'product': {'name': 'Computer', 'price': 225.0},
}
response = client.post('/products', json=data)
assert response.json() == {'user_name': 'Jane Doe', 'product_name': 'Computer'}
print('All tests passed!')