Skip to content

Commit 9e95b35

Browse files
authored
Update the client generator (dmontagu#23)
1 parent f534fe5 commit 9e95b35

29 files changed

+1409
-111
lines changed

example/client/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
1+
import inspect
2+
3+
from pydantic import BaseModel
4+
5+
from example.client import models
16
from example.client.api_client import ApiClient, AsyncApis, SyncApis # noqa F401
7+
8+
for model in inspect.getmembers(models, inspect.isclass):
9+
if model[1].__module__ == "example.client.models":
10+
model_class = model[1]
11+
if isinstance(model_class, BaseModel):
12+
model_class.update_forward_refs()

example/client/api/pet_api.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ def _build_for_delete_pet(self, pet_id: int, api_key: str = None) -> Awaitable[N
2727
headers["api_key"] = str(api_key)
2828

2929
return self.api_client.request(
30-
type_=None, method="DELETE", url="/pet/{petId}", path_params=path_params, headers=headers
30+
type_=None,
31+
method="DELETE",
32+
url="/pet/{petId}",
33+
path_params=path_params,
34+
headers=headers,
3135
)
3236

3337
def _build_for_find_pets_by_status(self, status: List[str]) -> Awaitable[List[m.Pet]]:
@@ -36,23 +40,38 @@ def _build_for_find_pets_by_status(self, status: List[str]) -> Awaitable[List[m.
3640
"""
3741
query_params = {"status": str(status)}
3842

39-
return self.api_client.request(type_=List[m.Pet], method="GET", url="/pet/findByStatus", params=query_params)
43+
return self.api_client.request(
44+
type_=List[m.Pet],
45+
method="GET",
46+
url="/pet/findByStatus",
47+
params=query_params,
48+
)
4049

4150
def _build_for_find_pets_by_tags(self, tags: List[str]) -> Awaitable[List[m.Pet]]:
4251
"""
4352
Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
4453
"""
4554
query_params = {"tags": str(tags)}
4655

47-
return self.api_client.request(type_=List[m.Pet], method="GET", url="/pet/findByTags", params=query_params)
56+
return self.api_client.request(
57+
type_=List[m.Pet],
58+
method="GET",
59+
url="/pet/findByTags",
60+
params=query_params,
61+
)
4862

4963
def _build_for_get_pet_by_id(self, pet_id: int) -> Awaitable[m.Pet]:
5064
"""
5165
Returns a single pet
5266
"""
5367
path_params = {"petId": str(pet_id)}
5468

55-
return self.api_client.request(type_=m.Pet, method="GET", url="/pet/{petId}", path_params=path_params)
69+
return self.api_client.request(
70+
type_=m.Pet,
71+
method="GET",
72+
url="/pet/{petId}",
73+
path_params=path_params,
74+
)
5675

5776
def _build_for_update_pet(self, body: m.Pet) -> Awaitable[None]:
5877
body = jsonable_encoder(body)

example/client/api/store_api.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,23 @@ def _build_for_delete_order(self, order_id: int) -> Awaitable[None]:
2121
path_params = {"orderId": str(order_id)}
2222

2323
return self.api_client.request(
24-
type_=None, method="DELETE", url="/store/order/{orderId}", path_params=path_params
24+
type_=None,
25+
method="DELETE",
26+
url="/store/order/{orderId}",
27+
path_params=path_params,
2528
)
2629

27-
def _build_for_get_inventory(self,) -> Awaitable[Dict[str, int]]:
30+
def _build_for_get_inventory(
31+
self,
32+
) -> Awaitable[Dict[str, int]]:
2833
"""
2934
Returns a map of status codes to quantities
3035
"""
31-
return self.api_client.request(type_=Dict[str, int], method="GET", url="/store/inventory")
36+
return self.api_client.request(
37+
type_=Dict[str, int],
38+
method="GET",
39+
url="/store/inventory",
40+
)
3241

3342
def _build_for_get_order_by_id(self, order_id: int) -> Awaitable[m.Order]:
3443
"""
@@ -37,7 +46,10 @@ def _build_for_get_order_by_id(self, order_id: int) -> Awaitable[m.Order]:
3746
path_params = {"orderId": str(order_id)}
3847

3948
return self.api_client.request(
40-
type_=m.Order, method="GET", url="/store/order/{orderId}", path_params=path_params
49+
type_=m.Order,
50+
method="GET",
51+
url="/store/order/{orderId}",
52+
path_params=path_params,
4153
)
4254

4355
def _build_for_place_order(self, body: m.Order) -> Awaitable[m.Order]:
@@ -53,7 +65,9 @@ async def delete_order(self, order_id: int) -> None:
5365
"""
5466
return await self._build_for_delete_order(order_id=order_id)
5567

56-
async def get_inventory(self,) -> Dict[str, int]:
68+
async def get_inventory(
69+
self,
70+
) -> Dict[str, int]:
5771
"""
5872
Returns a map of status codes to quantities
5973
"""
@@ -77,7 +91,9 @@ def delete_order(self, order_id: int) -> None:
7791
coroutine = self._build_for_delete_order(order_id=order_id)
7892
return get_event_loop().run_until_complete(coroutine)
7993

80-
def get_inventory(self,) -> Dict[str, int]:
94+
def get_inventory(
95+
self,
96+
) -> Dict[str, int]:
8197
"""
8298
Returns a map of status codes to quantities
8399
"""

example/client/api/user_api.py

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,41 @@ def _build_for_delete_user(self, username: str) -> Awaitable[None]:
3838
"""
3939
path_params = {"username": str(username)}
4040

41-
return self.api_client.request(type_=None, method="DELETE", url="/user/{username}", path_params=path_params)
41+
return self.api_client.request(
42+
type_=None,
43+
method="DELETE",
44+
url="/user/{username}",
45+
path_params=path_params,
46+
)
4247

4348
def _build_for_get_user_by_name(self, username: str) -> Awaitable[m.User]:
4449
path_params = {"username": str(username)}
4550

46-
return self.api_client.request(type_=m.User, method="GET", url="/user/{username}", path_params=path_params)
51+
return self.api_client.request(
52+
type_=m.User,
53+
method="GET",
54+
url="/user/{username}",
55+
path_params=path_params,
56+
)
4757

4858
def _build_for_login_user(self, username: str, password: str) -> Awaitable[str]:
4959
query_params = {"username": str(username), "password": str(password)}
5060

51-
return self.api_client.request(type_=str, method="GET", url="/user/login", params=query_params)
61+
return self.api_client.request(
62+
type_=str,
63+
method="GET",
64+
url="/user/login",
65+
params=query_params,
66+
)
5267

53-
def _build_for_logout_user(self,) -> Awaitable[None]:
54-
return self.api_client.request(type_=None, method="GET", url="/user/logout")
68+
def _build_for_logout_user(
69+
self,
70+
) -> Awaitable[None]:
71+
return self.api_client.request(
72+
type_=None,
73+
method="GET",
74+
url="/user/logout",
75+
)
5576

5677
def _build_for_update_user(self, username: str, body: m.User) -> Awaitable[None]:
5778
"""
@@ -91,7 +112,9 @@ async def get_user_by_name(self, username: str) -> m.User:
91112
async def login_user(self, username: str, password: str) -> str:
92113
return await self._build_for_login_user(username=username, password=password)
93114

94-
async def logout_user(self,) -> None:
115+
async def logout_user(
116+
self,
117+
) -> None:
95118
return await self._build_for_logout_user()
96119

97120
async def update_user(self, username: str, body: m.User) -> None:
@@ -132,7 +155,9 @@ def login_user(self, username: str, password: str) -> str:
132155
coroutine = self._build_for_login_user(username=username, password=password)
133156
return get_event_loop().run_until_complete(coroutine)
134157

135-
def logout_user(self,) -> None:
158+
def logout_user(
159+
self,
160+
) -> None:
136161
coroutine = self._build_for_logout_user()
137162
return get_event_loop().run_until_complete(coroutine)
138163

example/client/api_client.py

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from asyncio import get_event_loop
2-
from functools import lru_cache
32
from typing import Any, Awaitable, Callable, Dict, Generic, Type, TypeVar, overload
43

5-
from httpx import AsyncClient, AsyncRequest, AsyncResponse
6-
from pydantic import ValidationError
4+
from httpx import AsyncClient, Request, Response
5+
from pydantic import ValidationError, parse_obj_as
76

87
from example.client.api.pet_api import AsyncPetApi, SyncPetApi
98
from example.client.api.store_api import AsyncStoreApi, SyncStoreApi
@@ -32,8 +31,8 @@ def __init__(self, client: ClientT):
3231

3332

3433
T = TypeVar("T")
35-
Send = Callable[[AsyncRequest], Awaitable[AsyncResponse]]
36-
MiddlewareT = Callable[[AsyncRequest, Send], Awaitable[AsyncResponse]]
34+
Send = Callable[[Request], Awaitable[Response]]
35+
MiddlewareT = Callable[[Request, Send], Awaitable[Response]]
3736

3837

3938
class ApiClient:
@@ -60,7 +59,7 @@ async def request( # noqa F811
6059
if path_params is None:
6160
path_params = {}
6261
url = (self.host or "") + url.format(**path_params)
63-
request = AsyncRequest(method, url, **kwargs)
62+
request = Request(method, url, **kwargs)
6463
return await self.send(request, type_)
6564

6665
@overload
@@ -77,16 +76,16 @@ def request_sync(self, *, type_: Any, **kwargs: Any) -> Any: # noqa F811
7776
"""
7877
return get_event_loop().run_until_complete(self.request(type_=type_, **kwargs))
7978

80-
async def send(self, request: AsyncRequest, type_: Type[T]) -> T:
79+
async def send(self, request: Request, type_: Type[T]) -> T:
8180
response = await self.middleware(request, self.send_inner)
82-
if response.status_code == 200:
81+
if response.status_code in [200, 201]:
8382
try:
84-
return parse_as_type(response.json(), type_)
83+
return parse_obj_as(type_, response.json())
8584
except ValidationError as e:
8685
raise ResponseHandlingException(e)
8786
raise UnexpectedResponse.for_response(response)
8887

89-
async def send_inner(self, request: AsyncRequest) -> AsyncResponse:
88+
async def send_inner(self, request: Request) -> Response:
9089
try:
9190
response = await self._async_client.send(request)
9291
except Exception as e:
@@ -96,8 +95,8 @@ async def send_inner(self, request: AsyncRequest) -> AsyncResponse:
9695
def add_middleware(self, middleware: MiddlewareT) -> None:
9796
current_middleware = self.middleware
9897

99-
async def new_middleware(request: AsyncRequest, call_next: Send) -> AsyncResponse:
100-
async def inner_send(request: AsyncRequest) -> AsyncResponse:
98+
async def new_middleware(request: Request, call_next: Send) -> Response:
99+
async def inner_send(request: Request) -> Response:
101100
return await current_middleware(request, call_next)
102101

103102
return await middleware(request, inner_send)
@@ -106,18 +105,5 @@ async def inner_send(request: AsyncRequest) -> AsyncResponse:
106105

107106

108107
class BaseMiddleware:
109-
async def __call__(self, request: AsyncRequest, call_next: Send) -> AsyncResponse:
108+
async def __call__(self, request: Request, call_next: Send) -> Response:
110109
return await call_next(request)
111-
112-
113-
@lru_cache(maxsize=None)
114-
def _get_parsing_type(type_: Any, source: str) -> Any:
115-
from pydantic.main import create_model
116-
117-
type_name = getattr(type_, "__name__", str(type_))
118-
return create_model(f"ParsingModel[{type_name}] (for {source})", obj=(type_, ...))
119-
120-
121-
def parse_as_type(obj: Any, type_: Type[T]) -> T:
122-
model_type = _get_parsing_type(type_, source=parse_as_type.__name__)
123-
return model_type(obj=obj).obj

example/client/auth.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Optional
44

55
from fastapi.openapi.models import OAuthFlowPassword
6-
from httpx import AsyncRequest, AsyncResponse
6+
from httpx import Request, Response
77
from pydantic import BaseModel
88

99
from example.client.api_client import Send
@@ -55,7 +55,7 @@ def __init__(self, auth_state: AuthState, flow: OAuthFlowPassword) -> None:
5555
self.flow_client = PasswordFlowClient(flow)
5656

5757
@staticmethod
58-
def set_access_header(token: str, request: AsyncRequest, *, replace: bool) -> None:
58+
def set_access_header(token: str, request: Request, *, replace: bool) -> None:
5959
key = "authorization"
6060
value = f"bearer {token}"
6161
if replace:
@@ -85,7 +85,7 @@ async def refresh(self) -> Optional[TokenSuccessResponse]:
8585
return token_response
8686
return None
8787

88-
async def __call__(self, request: AsyncRequest, call_next: Send) -> AsyncResponse:
88+
async def __call__(self, request: Request, call_next: Send) -> Response:
8989
if self.auth_state.is_expired():
9090
await self.refresh()
9191
access_token = self.auth_state.access_token

example/client/docs/ApiResponse.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# ApiResponse
2+
3+
## Properties
4+
Name | Type | Description | Notes
5+
------------ | ------------- | ------------- | -------------
6+
**code** | **int** | | [optional]
7+
**type** | **str** | | [optional]
8+
**message** | **str** | | [optional]
9+
10+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
11+
12+

example/client/docs/Category.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Category
2+
3+
## Properties
4+
Name | Type | Description | Notes
5+
------------ | ------------- | ------------- | -------------
6+
**id** | **int** | | [optional]
7+
**name** | **str** | | [optional]
8+
9+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
10+
11+

example/client/docs/Order.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Order
2+
3+
## Properties
4+
Name | Type | Description | Notes
5+
------------ | ------------- | ------------- | -------------
6+
**id** | **int** | | [optional]
7+
**pet_id** | **int** | | [optional]
8+
**quantity** | **int** | | [optional]
9+
**ship_date** | **datetime** | | [optional]
10+
**status** | **str** | Order Status | [optional]
11+
**complete** | **bool** | | [optional]
12+
13+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
14+
15+

example/client/docs/Pet.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Pet
2+
3+
## Properties
4+
Name | Type | Description | Notes
5+
------------ | ------------- | ------------- | -------------
6+
**id** | **int** | | [optional]
7+
**category** | [**Category**](Category.md) | | [optional]
8+
**name** | **str** | |
9+
**photo_urls** | **List[str]** | |
10+
**tags** | [**List[Tag]**](Tag.md) | | [optional]
11+
**status** | **str** | pet status in the store | [optional]
12+
13+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
14+
15+

0 commit comments

Comments
 (0)