Skip to content

Commit b7f1065

Browse files
🐛 Fix handling non-primitive parameter values.
1 parent 3dea954 commit b7f1065

File tree

3 files changed

+40
-4
lines changed

3 files changed

+40
-4
lines changed

ChangeLog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ All notable changes to this project will be documented in this file.
55
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
66
and the format of this file is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
77

8+
## [Unreleased]
9+
10+
### Fixed
11+
12+
- Use pydantic to serialize non-encapsulated non-primitive method parameters.
13+
14+
815
## [0.12.1] - 2024-11-19
916

1017
### Fixed
1118

1219
- Don't raise exception on responses without content-type header if an empty response map was provided.
1320

21+
1422
## [0.12.0] - 2024-10-21
1523

1624
### Added

src/lapidary/runtime/model/request.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def http_name(self) -> str:
8989
return self.param.alias or self.python_name
9090

9191

92-
class DictParamContributor(ParamContributor):
92+
class DictParamContributor(ParamContributor, abc.ABC):
9393
def update_builder(self, builder: RequestBuilder, value: typing.Any) -> None:
9494
part = self._get_builder_part(builder)
9595
http_name = self.http_name()
@@ -141,10 +141,11 @@ class ParamsContributor(RequestContributor):
141141
contributors: Mapping[str, RequestContributor]
142142

143143
def update_builder(self, builder: RequestBuilder, headers_model: pydantic.BaseModel) -> None:
144-
raw_model = headers_model.model_dump()
145-
for field_name, field_info in headers_model.model_fields.items():
144+
raw_model = headers_model.model_dump(mode='json', exclude_unset=True)
145+
for field_name in headers_model.model_fields_set:
146+
assert field_name in headers_model.model_fields
146147
value = raw_model[field_name]
147-
if not value and field_name not in headers_model.model_fields_set:
148+
if value is None:
148149
continue
149150
contributor = self.contributors[field_name]
150151
contributor.update_builder(builder, value)

tests/test_request.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import datetime as dt
12
from collections.abc import Awaitable
23
from unittest.mock import AsyncMock, Mock
34

@@ -143,3 +144,29 @@ async def op(
143144
async with Client(client=mock_http_client) as client:
144145
with pytest.raises(TypeError):
145146
await client.op()
147+
148+
149+
@pytest.mark.asyncio
150+
async def test_build_request_param_date(mock_http_client):
151+
class Client(ClientTestBase):
152+
@get('/request_date')
153+
async def request_date(
154+
self: typing.Self,
155+
date: typing.Annotated[dt.date, Query()],
156+
) -> typing.Annotated[tuple[dt.date, None], Responses({})]:
157+
pass
158+
159+
today = dt.date.today()
160+
161+
async with Client(client=mock_http_client) as client:
162+
with pytest.raises(UnexpectedResponse):
163+
await client.request_date(date=today)
164+
165+
mock_http_client.build_request.assert_called_with(
166+
'GET',
167+
'/request_date',
168+
content=None,
169+
params=httpx.QueryParams({'date': today.isoformat()}),
170+
headers=httpx.Headers(),
171+
cookies=httpx.Cookies(),
172+
)

0 commit comments

Comments
 (0)