Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ jobs:
- name: Run lints
run: ./scripts/lint

- name: Run type checking
run: uv run ty check

build:
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
timeout-minutes: 10
Expand Down
21 changes: 21 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ dev = [
"pytest-xdist>=3.6.1",
"uuid-utils>=0.11.0",
"pytest-cov>=7.0.0",
"ty>=0.0.1a32",
]
docs = [
"furo>=2025.9.25",
Expand Down Expand Up @@ -285,3 +286,23 @@ known-first-party = ["runloop_api_client", "tests"]
"scripts/**.py" = ["T201", "T203"]
"tests/**.py" = ["T201", "T203"]
"examples/**.py" = ["T201", "T203"]

[tool.ty.src]
# External libraries with known stub issues
exclude = [
"tests",
"src/runloop_api_client/resources",
"src/runloop_api_client/_utils",
]

[tool.ty.rules]
invalid-assignment = "ignore"
call-non-callable = "ignore"
invalid-argument-type = "ignore"
unresolved-attribute = "ignore"
not-iterable = "ignore"
non-subscriptable = "ignore"
invalid-return-type = "ignore"
unresolved-import = "ignore"
possibly-missing-attribute = "ignore"
invalid-parameter-default = "ignore"
7 changes: 2 additions & 5 deletions src/runloop_api_client/_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,7 @@ def _parser(resp: AsyncPageT) -> AsyncPageT:

async def __aiter__(self) -> AsyncIterator[_T]:
# https://github.com/microsoft/pyright/issues/3464
page = cast(
AsyncPageT,
await self, # type: ignore
)
page = await self
async for item in page:
yield item

Expand Down Expand Up @@ -590,7 +587,7 @@ def _maybe_override_cast_to(self, cast_to: type[ResponseT], options: FinalReques
return cast_to

# make a copy of the headers so we don't mutate user-input
headers = dict(options.headers)
headers = dict(options.headers) # type: ignore[no-matching-overload]

# we internally support defining a temporary header to override the
# default `cast_to` type for use with `.with_raw_response` and `.with_streaming_response`
Expand Down
7 changes: 2 additions & 5 deletions src/runloop_api_client/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,11 @@ def model_dump(
# warnings are not supported in Pydantic v1
warnings=True if PYDANTIC_V1 else warnings,
)
return cast(
"dict[str, Any]",
model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
return model.dict(
exclude=exclude,
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
),
)
)


def model_parse(model: type[_ModelT], data: Any) -> _ModelT:
Expand Down
5 changes: 1 addition & 4 deletions src/runloop_api_client/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ class BaseModel(pydantic.BaseModel):
if PYDANTIC_V1:

@property
@override
def model_fields_set(self) -> set[str]:
# a forwards-compat shim for pydantic v2
return self.__fields_set__ # type: ignore
Expand Down Expand Up @@ -250,7 +249,6 @@ def construct( # pyright: ignore[reportIncompatibleMethodOverride]
# a specific pydantic version as some users may not know which
# pydantic version they are currently using

@override
def model_dump(
self,
*,
Expand Down Expand Up @@ -321,7 +319,6 @@ def model_dump(

return cast("dict[str, Any]", json_safe(dumped)) if mode == "json" else dumped

@override
def model_dump_json(
self,
*,
Expand Down Expand Up @@ -499,7 +496,7 @@ def construct_type(*, value: object, type_: object, metadata: Optional[List[Any]

if is_union(origin):
try:
return validate_type(type_=cast("type[object]", original_type or type_), value=value)
return validate_type(type_=original_type or type_, value=value)
except Exception:
pass

Expand Down
6 changes: 3 additions & 3 deletions src/runloop_api_client/_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncResponseContextManager[As

make_request = func(*args, **kwargs)

return AsyncResponseContextManager(cast(Awaitable[AsyncAPIResponse[R]], make_request))
return AsyncResponseContextManager(make_request)

return wrapped

Expand Down Expand Up @@ -729,7 +729,7 @@ def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncResponseContextManager[_A

make_request = func(*args, **kwargs)

return AsyncResponseContextManager(cast(Awaitable[_AsyncAPIResponseT], make_request))
return AsyncResponseContextManager(make_request)

return wrapped

Expand Down Expand Up @@ -809,7 +809,7 @@ def wrapped(*args: P.args, **kwargs: P.kwargs) -> Awaitable[_AsyncAPIResponseT]:

kwargs["extra_headers"] = extra_headers

return cast(Awaitable[_AsyncAPIResponseT], func(*args, **kwargs))
return func(*args, **kwargs)

return wrapped

Expand Down
26 changes: 13 additions & 13 deletions src/runloop_api_client/sdk/async_.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

import asyncio
from typing import Dict, Mapping, Optional
from typing import Dict, List, Mapping, Optional
from pathlib import Path
from datetime import timedelta
from typing_extensions import Unpack
Expand Down Expand Up @@ -150,7 +150,7 @@ def from_id(self, devbox_id: str) -> AsyncDevbox:
async def list(
self,
**params: Unpack[SDKDevboxListParams],
) -> list[AsyncDevbox]:
) -> List[AsyncDevbox]:
"""List devboxes accessible to the caller.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDevboxListParams` for available parameters
Expand Down Expand Up @@ -186,7 +186,7 @@ def __init__(self, client: AsyncRunloop) -> None:
async def list(
self,
**params: Unpack[SDKDiskSnapshotListParams],
) -> list[AsyncSnapshot]:
) -> List[AsyncSnapshot]:
"""List snapshots created from devboxes.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDiskSnapshotListParams` for available parameters
Expand Down Expand Up @@ -277,7 +277,7 @@ def from_id(self, blueprint_id: str) -> AsyncBlueprint:
async def list(
self,
**params: Unpack[SDKBlueprintListParams],
) -> list[AsyncBlueprint]:
) -> List[AsyncBlueprint]:
"""List available blueprints.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBlueprintListParams` for available parameters
Expand Down Expand Up @@ -338,7 +338,7 @@ def from_id(self, object_id: str) -> AsyncStorageObject:
async def list(
self,
**params: Unpack[SDKObjectListParams],
) -> list[AsyncStorageObject]:
) -> List[AsyncStorageObject]:
"""List storage objects owned by the caller.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKObjectListParams` for available parameters
Expand Down Expand Up @@ -541,12 +541,12 @@ def from_id(self, scorer_id: str) -> AsyncScorer:
"""
return AsyncScorer(self._client, scorer_id)

async def list(self, **params: Unpack[SDKScorerListParams]) -> list[AsyncScorer]:
async def list(self, **params: Unpack[SDKScorerListParams]) -> List[AsyncScorer]:
"""List all scorers, optionally filtered by parameters.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKScorerListParams` for available parameters
:return: List of scorers
:rtype: list[AsyncScorer]
:rtype: List[AsyncScorer]
"""
page = await self._client.scenarios.scorers.list(**params)
return [AsyncScorer(self._client, item.id) async for item in page]
Expand Down Expand Up @@ -599,7 +599,7 @@ async def create_from_npm(
package_name: str,
npm_version: Optional[str] = None,
registry_url: Optional[str] = None,
agent_setup: Optional[list[str]] = None,
agent_setup: Optional[List[str]] = None,
**params: Unpack[SDKAgentCreateParams],
) -> AsyncAgent:
"""Create an agent from an NPM package.
Expand Down Expand Up @@ -641,7 +641,7 @@ async def create_from_pip(
package_name: str,
pip_version: Optional[str] = None,
registry_url: Optional[str] = None,
agent_setup: Optional[list[str]] = None,
agent_setup: Optional[List[str]] = None,
**params: Unpack[SDKAgentCreateParams],
) -> AsyncAgent:
"""Create an agent from a Pip package.
Expand Down Expand Up @@ -682,7 +682,7 @@ async def create_from_git(
*,
repository: str,
ref: Optional[str] = None,
agent_setup: Optional[list[str]] = None,
agent_setup: Optional[List[str]] = None,
**params: Unpack[SDKAgentCreateParams],
) -> AsyncAgent:
"""Create an agent from a Git repository.
Expand Down Expand Up @@ -718,7 +718,7 @@ async def create_from_object(
self,
*,
object_id: str,
agent_setup: Optional[list[str]] = None,
agent_setup: Optional[List[str]] = None,
**params: Unpack[SDKAgentCreateParams],
) -> AsyncAgent:
"""Create an agent from a storage object.
Expand Down Expand Up @@ -759,7 +759,7 @@ def from_id(self, agent_id: str) -> AsyncAgent:
async def list(
self,
**params: Unpack[SDKAgentListParams],
) -> list[AsyncAgent]:
) -> List[AsyncAgent]:
"""List agents accessible to the caller.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentListParams` for available parameters
Expand Down Expand Up @@ -800,7 +800,7 @@ def from_id(self, scenario_id: str) -> AsyncScenario:
"""
return AsyncScenario(self._client, scenario_id)

async def list(self, **params: Unpack[SDKScenarioListParams]) -> list[AsyncScenario]:
async def list(self, **params: Unpack[SDKScenarioListParams]) -> List[AsyncScenario]:
"""List all scenarios, optionally filtered by parameters.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKScenarioListParams` for available parameters
Expand Down
24 changes: 12 additions & 12 deletions src/runloop_api_client/sdk/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import annotations

from typing import Dict, Mapping, Optional
from typing import Dict, List, Mapping, Optional
from pathlib import Path
from datetime import timedelta
from typing_extensions import Unpack
Expand Down Expand Up @@ -149,7 +149,7 @@ def from_id(self, devbox_id: str) -> Devbox:
def list(
self,
**params: Unpack[SDKDevboxListParams],
) -> list[Devbox]:
) -> List[Devbox]:
"""List devboxes accessible to the caller.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDevboxListParams` for available parameters
Expand Down Expand Up @@ -185,7 +185,7 @@ def __init__(self, client: Runloop) -> None:
def list(
self,
**params: Unpack[SDKDiskSnapshotListParams],
) -> list[Snapshot]:
) -> List[Snapshot]:
"""List snapshots created from devboxes.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDiskSnapshotListParams` for available parameters
Expand Down Expand Up @@ -275,7 +275,7 @@ def from_id(self, blueprint_id: str) -> Blueprint:
def list(
self,
**params: Unpack[SDKBlueprintListParams],
) -> list[Blueprint]:
) -> List[Blueprint]:
"""List available blueprints.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBlueprintListParams` for available parameters
Expand Down Expand Up @@ -336,7 +336,7 @@ def from_id(self, object_id: str) -> StorageObject:
def list(
self,
**params: Unpack[SDKObjectListParams],
) -> list[StorageObject]:
) -> List[StorageObject]:
"""List storage objects owned by the caller.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKObjectListParams` for available parameters
Expand Down Expand Up @@ -536,7 +536,7 @@ def from_id(self, scorer_id: str) -> Scorer:
"""
return Scorer(self._client, scorer_id)

def list(self, **params: Unpack[SDKScorerListParams]) -> list[Scorer]:
def list(self, **params: Unpack[SDKScorerListParams]) -> List[Scorer]:
"""List all scorers, optionally filtered by parameters.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKScorerListParams` for available parameters
Expand Down Expand Up @@ -594,7 +594,7 @@ def create_from_npm(
package_name: str,
npm_version: Optional[str] = None,
registry_url: Optional[str] = None,
agent_setup: Optional[list[str]] = None,
agent_setup: Optional[List[str]] = None,
**params: Unpack[SDKAgentCreateParams],
) -> Agent:
"""Create an agent from an NPM package.
Expand Down Expand Up @@ -641,7 +641,7 @@ def create_from_pip(
package_name: str,
pip_version: Optional[str] = None,
registry_url: Optional[str] = None,
agent_setup: Optional[list[str]] = None,
agent_setup: Optional[List[str]] = None,
**params: Unpack[SDKAgentCreateParams],
) -> Agent:
"""Create an agent from a Pip package.
Expand Down Expand Up @@ -687,7 +687,7 @@ def create_from_git(
*,
repository: str,
ref: Optional[str] = None,
agent_setup: Optional[list[str]] = None,
agent_setup: Optional[List[str]] = None,
**params: Unpack[SDKAgentCreateParams],
) -> Agent:
"""Create an agent from a Git repository.
Expand Down Expand Up @@ -731,7 +731,7 @@ def create_from_object(
self,
*,
object_id: str,
agent_setup: Optional[list[str]] = None,
agent_setup: Optional[List[str]] = None,
**params: Unpack[SDKAgentCreateParams],
) -> Agent:
"""Create an agent from a storage object.
Expand Down Expand Up @@ -780,7 +780,7 @@ def from_id(self, agent_id: str) -> Agent:
def list(
self,
**params: Unpack[SDKAgentListParams],
) -> list[Agent]:
) -> List[Agent]:
"""List agents accessible to the caller.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentListParams` for available parameters
Expand Down Expand Up @@ -821,7 +821,7 @@ def from_id(self, scenario_id: str) -> Scenario:
"""
return Scenario(self._client, scenario_id)

def list(self, **params: Unpack[SDKScenarioListParams]) -> list[Scenario]:
def list(self, **params: Unpack[SDKScenarioListParams]) -> List[Scenario]:
"""List all scenarios, optionally filtered by parameters.

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKScenarioListParams` for available parameters
Expand Down
Loading