Skip to content

Commit c9a5e02

Browse files
committed
fix: satisfy browser-scoped lint checks
Tighten browser-scoped helper typing and test casts so the Python SDK passes the repository's lint and pyright checks cleanly. Made-with: Cursor
1 parent 33811f9 commit c9a5e02

File tree

3 files changed

+31
-20
lines changed

3 files changed

+31
-20
lines changed

src/kernel/lib/browser_scoped/browser_session_kernel.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
from __future__ import annotations
44

5-
from typing import Any, cast
5+
from typing import Any, Mapping, cast
6+
from typing_extensions import override
67

78
from ..._client import Kernel, AsyncKernel
89
from ..._compat import model_copy
@@ -18,19 +19,18 @@ def __init__(self, *, browser_session_id: str, **kwargs: Any) -> None:
1819
self._scoped_session_id = browser_session_id
1920
super().__init__(**kwargs)
2021

22+
@override
2123
def _prepare_options(self, options: FinalRequestOptions) -> FinalRequestOptions:
2224
options = super()._prepare_options(options)
2325
url = options.url
24-
if not isinstance(url, str):
25-
return options
2626
prefix = f"/browsers/{self._scoped_session_id}/"
2727
if not url.startswith(prefix):
2828
return options
2929
suffix = url[len(prefix) :].lstrip("/")
3030
new_url = f"/{suffix}" if suffix else "/"
3131
out = model_copy(options)
3232
out.url = new_url
33-
return cast(FinalRequestOptions, out)
33+
return out
3434

3535

3636
class _BrowserSessionAsyncKernel(AsyncKernel):
@@ -40,27 +40,30 @@ def __init__(self, *, browser_session_id: str, **kwargs: Any) -> None:
4040
self._scoped_session_id = browser_session_id
4141
super().__init__(**kwargs)
4242

43+
@override
4344
async def _prepare_options(self, options: FinalRequestOptions) -> FinalRequestOptions:
4445
options = await super()._prepare_options(options)
4546
url = options.url
46-
if not isinstance(url, str):
47-
return options
4847
prefix = f"/browsers/{self._scoped_session_id}/"
4948
if not url.startswith(prefix):
5049
return options
5150
suffix = url[len(prefix) :].lstrip("/")
5251
new_url = f"/{suffix}" if suffix else "/"
5352
out = model_copy(options)
5453
out.url = new_url
55-
return cast(FinalRequestOptions, out)
54+
return out
5655

5756

5857
def build_browser_session_kernel(
5958
parent: Kernel, *, session_id: str, session_base_url: str, jwt: str
6059
) -> _BrowserSessionKernel:
6160
"""Build a sync client sharing the parent's httpx transport; requests use session_base_url."""
62-
base_q = getattr(parent, "_custom_query", None) or {}
63-
dq = {str(k): v for k, v in dict(base_q).items()}
61+
base_q_raw = getattr(parent, "_custom_query", None)
62+
if isinstance(base_q_raw, Mapping):
63+
base_q = {str(k): v for k, v in cast(Mapping[str, object], base_q_raw).items()}
64+
else:
65+
base_q = {}
66+
dq = dict(base_q)
6467
dq["jwt"] = jwt
6568
return _BrowserSessionKernel(
6669
browser_session_id=session_id,
@@ -78,8 +81,12 @@ def build_browser_session_kernel(
7881
def build_async_browser_session_kernel(
7982
parent: AsyncKernel, *, session_id: str, session_base_url: str, jwt: str
8083
) -> _BrowserSessionAsyncKernel:
81-
base_q = getattr(parent, "_custom_query", None) or {}
82-
dq = {str(k): v for k, v in dict(base_q).items()}
84+
base_q_raw = getattr(parent, "_custom_query", None)
85+
if isinstance(base_q_raw, Mapping):
86+
base_q = {str(k): v for k, v in cast(Mapping[str, object], base_q_raw).items()}
87+
else:
88+
base_q = {}
89+
dq = dict(base_q)
8390
dq["jwt"] = jwt
8491
return _BrowserSessionAsyncKernel(
8592
browser_session_id=session_id,

src/kernel/lib/browser_scoped/client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
from __future__ import annotations
44

55
import inspect
6-
from typing import TYPE_CHECKING, Any, Mapping, cast
6+
from typing import IO, TYPE_CHECKING, Any, Mapping, cast
77
from contextlib import contextmanager, asynccontextmanager
8-
from collections.abc import Iterator, AsyncIterator
8+
from collections.abc import Iterable, Iterator, AsyncIterator
99

1010
import httpx
1111

@@ -316,11 +316,11 @@ def _normalize_timeout(timeout: float | Timeout | None | NotGiven) -> float | Ti
316316
return None if isinstance(timeout, NotGiven) else timeout
317317

318318

319-
def _normalize_binary_content(content: BinaryTypes | None) -> httpx._types.RequestContent | None:
319+
def _normalize_binary_content(content: BinaryTypes | None) -> bytes | IO[bytes] | Iterable[bytes] | None:
320320
if content is None:
321321
return None
322322
if isinstance(content, bytearray):
323323
return bytes(content)
324324
if isinstance(content, memoryview):
325325
return content.tobytes()
326-
return cast(httpx._types.RequestContent, content)
326+
return content

tests/test_browser_scoped.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import os
44
import json
5-
from typing import cast
5+
from typing import Any, cast
66

77
import httpx
88
import respx
@@ -48,7 +48,8 @@ def test_for_browser_process_exec_routes_to_session_base() -> None:
4848
b = client.for_browser(_fake_browser())
4949
out = b.process.exec(command="echo", args=["hi"])
5050
assert route.called
51-
request = cast(httpx.Request, route.calls[0].request)
51+
call = cast(Any, route.calls[0])
52+
request = cast(httpx.Request, call.request)
5253
sent = request.read().decode()
5354
body = json.loads(sent)
5455
assert body["command"] == "echo"
@@ -67,7 +68,8 @@ def test_browser_request_uses_curl_raw() -> None:
6768
assert r.status_code == 200
6869
assert r.content == b"ok"
6970
assert route.called
70-
request = cast(httpx.Request, route.calls[0].request)
71+
call = cast(Any, route.calls[0])
72+
request = cast(httpx.Request, call.request)
7173
assert "curl/raw" in str(request.url)
7274
assert "jwt=token-abc" in str(request.url)
7375

@@ -85,7 +87,8 @@ def test_browser_request_params_cannot_override_target_url_or_jwt() -> None:
8587
params={"url": "https://evil.example", "jwt": "other", "timeout_ms": 1},
8688
)
8789
assert route.called
88-
request = cast(httpx.Request, route.calls[0].request)
90+
call = cast(Any, route.calls[0])
91+
request = cast(httpx.Request, call.request)
8992
req_url = request.url
9093
assert str(req_url.params.get("url")) == "https://example.com"
9194
assert str(req_url.params.get("jwt")) == "token-abc"
@@ -107,7 +110,8 @@ def test_browser_stream_params_cannot_override_target_url_or_jwt() -> None:
107110
assert resp.status_code == 200
108111
assert resp.read() == b"streamed"
109112
assert route.called
110-
request = cast(httpx.Request, route.calls[0].request)
113+
call = cast(Any, route.calls[0])
114+
request = cast(httpx.Request, call.request)
111115
req_url = request.url
112116
assert str(req_url.params.get("url")) == "https://example.com"
113117
assert str(req_url.params.get("jwt")) == "token-abc"

0 commit comments

Comments
 (0)