Skip to content

Commit b2dbc8b

Browse files
committed
bump pydantic dep and linting fixes
1 parent 745dd4d commit b2dbc8b

File tree

4 files changed

+136
-226
lines changed

4 files changed

+136
-226
lines changed

pyproject.toml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ authors = [
1010

1111
dependencies = [
1212
"httpx>=0.23.0, <1",
13-
"pydantic>=1.9.0, <3",
13+
"pydantic>=2.0.0, <3",
1414
"typing-extensions>=4.14, <5",
1515
"anyio>=3.5.0, <5",
1616
"distro>=1.7.0, <2",
@@ -46,12 +46,7 @@ aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"]
4646
[tool.uv]
4747
managed = true
4848
required-version = ">=0.9"
49-
conflicts = [
50-
[
51-
{ group = "pydantic-v1" },
52-
{ group = "pydantic-v2" },
53-
],
54-
]
49+
conflicts = []
5550

5651
[dependency-groups]
5752
# version pins are in uv.lock
@@ -69,9 +64,6 @@ dev = [
6964
"pytest-xdist>=3.6.1",
7065
"dotenv>=0.9.9",
7166
]
72-
pydantic-v1 = [
73-
"pydantic>=1.9.0,<2",
74-
]
7567
pydantic-v2 = [
7668
"pydantic~=2.0 ; python_full_version < '3.14'",
7769
"pydantic~=2.12 ; python_full_version >= '3.14'",

src/stagehand/_pydantic_extract.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ def _convert_dict_keys_to_snake_case(data: Any) -> Any:
6666
if isinstance(data, dict):
6767
return {
6868
_camel_to_snake(k) if isinstance(k, str) else k: _convert_dict_keys_to_snake_case(v)
69-
for k, v in data.items()
69+
for k, v in data.items() # type: ignore[union-attr]
7070
}
7171
if isinstance(data, list):
72-
return [_convert_dict_keys_to_snake_case(item) for item in data]
72+
return [_convert_dict_keys_to_snake_case(item) for item in data] # type: ignore[union-attr]
7373
return data

src/stagehand/session.py

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
)
1818
from ._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
1919
from ._exceptions import StagehandError
20-
from ._pydantic_extract import is_pydantic_model, pydantic_model_to_json_schema, validate_extract_response
20+
from ._pydantic_extract import is_pydantic_model, validate_extract_response, pydantic_model_to_json_schema
2121
from .types.session_act_response import SessionActResponse
2222
from .types.session_end_response import SessionEndResponse
2323
from .types.session_start_response import Data as SessionStartResponseData, SessionStartResponse
@@ -201,7 +201,7 @@ def observe(
201201
),
202202
)
203203

204-
def extract(
204+
def extract( # type: ignore[misc]
205205
self,
206206
*,
207207
schema: dict[str, object] | type | None = None,
@@ -210,36 +210,37 @@ def extract(
210210
extra_query: Query | None = None,
211211
extra_body: Body | None = None,
212212
timeout: float | httpx.Timeout | None | NotGiven = not_given,
213-
**params: Unpack[session_extract_params.SessionExtractParamsNonStreaming],
213+
**params: Unpack[session_extract_params.SessionExtractParamsNonStreaming], # pyright: ignore[reportGeneralTypeIssues]
214214
) -> SessionExtractResponse:
215215
# If the caller passed schema via **params (TypedDict), prefer the explicit kwarg.
216216
params_schema = params.pop("schema", None) # type: ignore[misc]
217217
resolved_schema = schema if schema is not None else params_schema
218218

219-
pydantic_cls = None
219+
pydantic_cls: type[Any] | None = None
220220
if is_pydantic_model(resolved_schema):
221-
pydantic_cls = resolved_schema
222-
resolved_schema = pydantic_model_to_json_schema(resolved_schema)
221+
pydantic_cls = resolved_schema # type: ignore[assignment]
222+
resolved_schema = pydantic_model_to_json_schema(pydantic_cls) # type: ignore[arg-type]
223223

224224
api_params: dict[str, Any] = _maybe_inject_frame_id(dict(params), page)
225225
if resolved_schema is not None:
226226
api_params["schema"] = resolved_schema
227227

228-
response = self._client.sessions.extract(
229-
id=self.id,
230-
extra_headers=extra_headers,
231-
extra_query=extra_query,
232-
extra_body=extra_body,
233-
timeout=timeout,
234-
**api_params,
228+
response: SessionExtractResponse = cast(
229+
SessionExtractResponse,
230+
self._client.sessions.extract(
231+
id=self.id,
232+
extra_headers=extra_headers,
233+
extra_query=extra_query,
234+
extra_body=extra_body,
235+
timeout=timeout,
236+
**api_params,
237+
),
235238
)
236239

237-
# Pydantic validation only applies to non-streaming responses.
238-
if pydantic_cls is not None and isinstance(response, SessionExtractResponse):
239-
if response.data and response.data.result is not None:
240-
response.data.result = validate_extract_response(response.data.result, pydantic_cls)
240+
if pydantic_cls is not None and response.data and response.data.result is not None:
241+
response.data.result = validate_extract_response(response.data.result, pydantic_cls)
241242

242-
return cast(SessionExtractResponse, response)
243+
return response
243244

244245
def execute(
245246
self,
@@ -354,7 +355,7 @@ async def observe(
354355
),
355356
)
356357

357-
async def extract(
358+
async def extract( # type: ignore[misc]
358359
self,
359360
*,
360361
schema: dict[str, object] | type | None = None,
@@ -363,36 +364,37 @@ async def extract(
363364
extra_query: Query | None = None,
364365
extra_body: Body | None = None,
365366
timeout: float | httpx.Timeout | None | NotGiven = not_given,
366-
**params: Unpack[session_extract_params.SessionExtractParamsNonStreaming],
367+
**params: Unpack[session_extract_params.SessionExtractParamsNonStreaming], # pyright: ignore[reportGeneralTypeIssues]
367368
) -> SessionExtractResponse:
368369
# If the caller passed schema via **params (TypedDict), prefer the explicit kwarg.
369370
params_schema = params.pop("schema", None) # type: ignore[misc]
370371
resolved_schema = schema if schema is not None else params_schema
371372

372-
pydantic_cls = None
373+
pydantic_cls: type[Any] | None = None
373374
if is_pydantic_model(resolved_schema):
374-
pydantic_cls = resolved_schema
375-
resolved_schema = pydantic_model_to_json_schema(resolved_schema)
375+
pydantic_cls = resolved_schema # type: ignore[assignment]
376+
resolved_schema = pydantic_model_to_json_schema(pydantic_cls) # type: ignore[arg-type]
376377

377378
api_params: dict[str, Any] = await _maybe_inject_frame_id_async(dict(params), page)
378379
if resolved_schema is not None:
379380
api_params["schema"] = resolved_schema
380381

381-
response = await self._client.sessions.extract(
382-
id=self.id,
383-
extra_headers=extra_headers,
384-
extra_query=extra_query,
385-
extra_body=extra_body,
386-
timeout=timeout,
387-
**api_params,
382+
response: SessionExtractResponse = cast(
383+
SessionExtractResponse,
384+
await self._client.sessions.extract(
385+
id=self.id,
386+
extra_headers=extra_headers,
387+
extra_query=extra_query,
388+
extra_body=extra_body,
389+
timeout=timeout,
390+
**api_params,
391+
),
388392
)
389393

390-
# Pydantic validation only applies to non-streaming responses.
391-
if pydantic_cls is not None and isinstance(response, SessionExtractResponse):
392-
if response.data and response.data.result is not None:
393-
response.data.result = validate_extract_response(response.data.result, pydantic_cls)
394+
if pydantic_cls is not None and response.data and response.data.result is not None:
395+
response.data.result = validate_extract_response(response.data.result, pydantic_cls)
394396

395-
return cast(SessionExtractResponse, response)
397+
return response
396398

397399
async def execute(
398400
self,

0 commit comments

Comments
 (0)