Skip to content

Commit b789290

Browse files
committed
Limit empty acquire parsing to its response model
1 parent 9e3084a commit b789290

4 files changed

Lines changed: 26 additions & 4 deletions

File tree

‎src/kernel/_response.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import httpx
2525
import pydantic
2626

27-
from ._types import NoneType
27+
from ._types import NoneType, NoContentAsNone
2828
from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type, extract_type_var_from_base
2929
from ._models import BaseModel, is_basemodel
3030
from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER
@@ -185,7 +185,12 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
185185
return cast(R, None)
186186

187187
response = self.http_response
188-
if response.status_code == 204 and to is None and is_basemodel(cast_to):
188+
if (
189+
response.status_code == 204
190+
and to is None
191+
and isinstance(origin, type)
192+
and issubclass(origin, NoContentAsNone)
193+
):
189194
return cast(R, None)
190195
if cast_to == str:
191196
return cast(R, response.text)

‎src/kernel/_types.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@
4444
Query = Mapping[str, object]
4545
Body = object
4646
AnyMapping = Mapping[str, object]
47+
48+
49+
class NoContentAsNone:
50+
pass
51+
52+
4753
ModelT = TypeVar("ModelT", bound=pydantic.BaseModel)
4854
_T = TypeVar("_T")
4955

‎src/kernel/types/browser_pool_acquire_response.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from typing_extensions import Literal
66

77
from .tags import Tags
8+
from .._types import NoContentAsNone
89
from .profile import Profile
910
from .._models import BaseModel
1011
from .browser_proxy import BrowserProxy
@@ -20,7 +21,7 @@
2021
__all__ = ["BrowserPoolAcquireResponse"]
2122

2223

23-
class BrowserPoolAcquireResponse(BaseModel):
24+
class BrowserPoolAcquireResponse(NoContentAsNone, BaseModel):
2425
cdp_ws_url: str
2526
"""Websocket URL for Chrome DevTools Protocol connections to the browser session"""
2627

‎tests/test_browser_pool_acquire_response.py‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import httpx
22
import pytest
33

4-
from kernel import Kernel, AsyncKernel, NotFoundError
4+
from kernel import Kernel, AsyncKernel, NotFoundError, APIResponseValidationError
55

66

77
def test_acquire_returns_browser() -> None:
@@ -58,3 +58,13 @@ def test_acquire_still_raises_not_found() -> None:
5858
) as client:
5959
with pytest.raises(NotFoundError):
6060
client.browser_pools.acquire("missing")
61+
62+
63+
def test_unexpected_204_still_fails_strict_validation() -> None:
64+
with Kernel(
65+
api_key="test",
66+
_strict_response_validation=True,
67+
http_client=httpx.Client(transport=httpx.MockTransport(lambda _request: httpx.Response(204))),
68+
) as client:
69+
with pytest.raises(APIResponseValidationError):
70+
client.browser_pools.retrieve("pool")

0 commit comments

Comments
 (0)