Skip to content

Commit 2a7fc17

Browse files
committed
added some type hints and override flags
1 parent 136ad7e commit 2a7fc17

6 files changed

Lines changed: 70 additions & 62 deletions

File tree

README-SDK.md

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,34 @@ The `RunloopSDK` builds on top of the underlying REST client and provides a Pyth
44

55
## Table of Contents
66

7-
- [Runloop SDK – Python Object-Oriented Client](#runloop-sdk--python-object-oriented-client)
8-
- [Table of Contents](#table-of-contents)
9-
- [Installation](#installation)
10-
- [Quickstart (synchronous)](#quickstart-synchronous)
11-
- [Quickstart (asynchronous)](#quickstart-asynchronous)
12-
- [Core Concepts](#core-concepts)
13-
- [RunloopSDK](#runloopsdk)
14-
- [Available Resources](#available-resources)
15-
- [Devbox](#devbox)
16-
- [Command Execution](#command-execution)
17-
- [Execution Management](#execution-management)
18-
- [Execution Results](#execution-results)
19-
- [Streaming Command Output](#streaming-command-output)
20-
- [File Operations](#file-operations)
21-
- [Network Operations](#network-operations)
22-
- [Snapshot Operations](#snapshot-operations)
23-
- [Devbox Lifecycle Management](#devbox-lifecycle-management)
24-
- [Context Manager Support](#context-manager-support)
25-
- [Blueprint](#blueprint)
26-
- [Snapshot](#snapshot)
27-
- [StorageObject](#storageobject)
28-
- [Storage Object Upload Helpers](#storage-object-upload-helpers)
29-
- [Mounting Storage Objects to Devboxes](#mounting-storage-objects-to-devboxes)
30-
- [Accessing the Underlying REST Client](#accessing-the-underlying-rest-client)
31-
- [Error Handling](#error-handling)
32-
- [Advanced Configuration](#advanced-configuration)
33-
- [Async Usage](#async-usage)
34-
- [Polling Configuration](#polling-configuration)
35-
- [Complete API Reference](#complete-api-reference)
36-
- [Feedback](#feedback)
7+
- [Installation](#installation)
8+
- [Quickstart (synchronous)](#quickstart-synchronous)
9+
- [Quickstart (asynchronous)](#quickstart-asynchronous)
10+
- [Core Concepts](#core-concepts)
11+
- [RunloopSDK](#runloopsdk)
12+
- [Available Resources](#available-resources)
13+
- [Devbox](#devbox)
14+
- [Command Execution](#command-execution)
15+
- [Execution Management](#execution-management)
16+
- [Execution Results](#execution-results)
17+
- [Streaming Command Output](#streaming-command-output)
18+
- [File Operations](#file-operations)
19+
- [Network Operations](#network-operations)
20+
- [Snapshot Operations](#snapshot-operations)
21+
- [Devbox Lifecycle Management](#devbox-lifecycle-management)
22+
- [Context Manager Support](#context-manager-support)
23+
- [Blueprint](#blueprint)
24+
- [Snapshot](#snapshot)
25+
- [StorageObject](#storageobject)
26+
- [Storage Object Upload Helpers](#storage-object-upload-helpers)
27+
- [Mounting Storage Objects to Devboxes](#mounting-storage-objects-to-devboxes)
28+
- [Accessing the Underlying REST Client](#accessing-the-underlying-rest-client)
29+
- [Error Handling](#error-handling)
30+
- [Advanced Configuration](#advanced-configuration)
31+
- [Async Usage](#async-usage)
32+
- [Polling Configuration](#polling-configuration)
33+
- [Complete API Reference](#complete-api-reference)
34+
- [Feedback](#feedback)
3735

3836
## Installation
3937

@@ -447,7 +445,7 @@ shared_ctx_obj = runloop.storage_object.upload_from_bytes(
447445

448446
blueprint_with_context = runloop.blueprint.create(
449447
name="my-blueprint-with-context",
450-
dockerfile=\"\"\"\
448+
dockerfile="""\
451449
FROM node:22
452450
WORKDIR /usr/src/app
453451
@@ -460,7 +458,7 @@ COPY --from=shared / ./libs
460458
461459
RUN npm install --only=production
462460
CMD ["node", "src/app.js"]
463-
\"\"\",
461+
""",
464462
# Primary build context
465463
build_context=build_ctx_obj.as_build_context(),
466464
# Additional named build contexts (for Docker buildx-style usage)

src/runloop_api_client/lib/_ignore.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from typing import Iterable, Optional, Sequence
66
from pathlib import Path, PurePosixPath
77
from dataclasses import dataclass
8+
from typing_extensions import override
89

910
__all__ = [
1011
"IgnorePattern",
@@ -320,6 +321,7 @@ class DockerIgnoreMatcher(IgnoreMatcher):
320321
extra_ignorefile: str | Path | None = None
321322
patterns: Sequence[str] | None = None
322323

324+
@override
323325
def iter_paths(self, root: Path) -> Iterable[Path]:
324326
"""Yield non-ignored files under ``root`` honoring Docker-style patterns."""
325327
root = root.resolve()
@@ -380,6 +382,7 @@ def __post_init__(self) -> None:
380382
if isinstance(self.patterns, str):
381383
object.__setattr__(self, "patterns", [self.patterns])
382384

385+
@override
383386
def iter_paths(self, root: Path) -> Iterable[Path]:
384387
"""Yield non-ignored files under ``root`` based only on ``patterns``."""
385388

src/runloop_api_client/sdk/async_.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,8 @@ async def upload_from_dir(
421421
for available options
422422
:return: Wrapper for the uploaded object
423423
:rtype: AsyncStorageObject
424-
:raises OSError: If the local file cannot be read
424+
:raises OSError: If the local directory cannot be read
425+
:raises ValueError: If ``dir_path`` does not point to a directory
425426
"""
426427
path = Path(dir_path)
427428
if not path.is_dir():

src/runloop_api_client/sdk/async_storage_object.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,10 @@ async def delete(
151151
async def upload_content(self, content: str | bytes | Iterable[bytes]) -> None:
152152
"""Upload content to the object's pre-signed URL.
153153
154-
:param content: Bytes or text payload to upload
155-
:type content: str | bytes
154+
:param content: Bytes payload, text payload, or an iterable streaming bytes
155+
:type content: str | bytes | Iterable[bytes]
156+
:return: None
157+
:rtype: None
156158
:raises RuntimeError: If no upload URL is available
157159
:raises httpx.HTTPStatusError: Propagated from the underlying ``httpx`` client when the upload fails
158160
"""
@@ -165,6 +167,9 @@ def as_build_context(self) -> BuildContext:
165167
166168
The returned mapping can be passed directly to ``build_context`` or
167169
``named_build_contexts`` when creating a blueprint.
170+
171+
:return: Mapping suitable for use as a blueprint build context
172+
:rtype: BuildContext
168173
"""
169174
return {
170175
"object_id": self._id,

src/runloop_api_client/sdk/storage_object.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,10 @@ def delete(
151151
def upload_content(self, content: str | bytes | Iterable[bytes]) -> None:
152152
"""Upload content to the object's pre-signed URL.
153153
154-
:param content: Bytes or text payload to upload
155-
:type content: str | bytes
154+
:param content: Bytes payload, text payload, or an iterable streaming bytes
155+
:type content: str | bytes | Iterable[bytes]
156+
:return: None
157+
:rtype: None
156158
:raises RuntimeError: If no upload URL is available
157159
:raises httpx.HTTPStatusError: Propagated from the underlying ``httpx`` client when the upload fails
158160
"""
@@ -165,6 +167,9 @@ def as_build_context(self) -> BuildContext:
165167
166168
The returned mapping can be passed directly to ``build_context`` or
167169
``named_build_contexts`` when creating a blueprint.
170+
171+
:return: Mapping suitable for use as a blueprint build context
172+
:rtype: BuildContext
168173
"""
169174
return {
170175
"object_id": self._id,

src/runloop_api_client/sdk/sync.py

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ def create_from_blueprint_id(
8383
:param blueprint_id: Blueprint ID to create from
8484
:type blueprint_id: str
8585
:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDevboxCreateFromImageParams` for available parameters
86-
:type params:
8786
:return: Wrapper bound to the newly created devbox
8887
:rtype: Devbox
8988
"""
@@ -226,11 +225,10 @@ class BlueprintOps:
226225
Example:
227226
>>> from datetime import timedelta
228227
>>> from runloop_api_client.types.blueprint_build_parameters import BuildContext
229-
>>>
230228
>>> runloop = RunloopSDK()
231229
>>> obj = runloop.object_storage.upload_from_dir(
232230
... "./",
233-
... ttl=timedelta(hours=1),
231+
... ttl=timedelta(hours=1),
234232
... )
235233
>>> blueprint = runloop.blueprint.create(
236234
... name="my-blueprint",
@@ -421,6 +419,7 @@ def upload_from_dir(
421419
:return: Wrapper for the uploaded object
422420
:rtype: StorageObject
423421
:raises OSError: If the local file cannot be read
422+
:raises ValueError: If ``dir_path`` does not point to a directory
424423
"""
425424
path = Path(dir_path)
426425
if not path.is_dir():
@@ -545,7 +544,7 @@ def list(self, **params: Unpack[SDKScorerListParams]) -> list[Scorer]:
545544
page = self._client.scenarios.scorers.list(**params)
546545
return [Scorer(self._client, item.id) for item in page]
547546

548-
547+
549548
class AgentOps:
550549
"""High-level manager for creating and managing agents.
551550
@@ -555,15 +554,10 @@ class AgentOps:
555554
Example:
556555
>>> runloop = RunloopSDK()
557556
>>> # Create agent from NPM package
558-
>>> agent = runloop.agent.create_from_npm(
559-
... name="my-agent",
560-
... package_name="@runloop/example-agent"
561-
... )
557+
>>> agent = runloop.agent.create_from_npm(name="my-agent", package_name="@runloop/example-agent")
562558
>>> # Create agent from Git repository
563559
>>> agent = runloop.agent.create_from_git(
564-
... name="git-agent",
565-
... repository="https://github.com/user/agent-repo",
566-
... ref="main"
560+
... name="git-agent", repository="https://github.com/user/agent-repo", ref="main"
567561
... )
568562
>>> # List all agents
569563
>>> agents = runloop.agent.list(limit=10)
@@ -605,9 +599,7 @@ def create_from_npm(
605599
606600
Example:
607601
>>> agent = runloop.agent.create_from_npm(
608-
... name="my-npm-agent",
609-
... package_name="@runloop/example-agent",
610-
... npm_version="^1.0.0"
602+
... name="my-npm-agent", package_name="@runloop/example-agent", npm_version="^1.0.0"
611603
... )
612604
613605
:param package_name: NPM package name
@@ -624,7 +616,9 @@ def create_from_npm(
624616
:raises ValueError: If 'source' is provided in params
625617
"""
626618
if "source" in params:
627-
raise ValueError("Cannot specify 'source' when using create_from_npm(); source is automatically set to npm configuration")
619+
raise ValueError(
620+
"Cannot specify 'source' when using create_from_npm(); source is automatically set to npm configuration"
621+
)
628622

629623
npm_config: dict = {"package_name": package_name}
630624
if npm_version is not None:
@@ -652,9 +646,7 @@ def create_from_pip(
652646
653647
Example:
654648
>>> agent = runloop.agent.create_from_pip(
655-
... name="my-pip-agent",
656-
... package_name="runloop-example-agent",
657-
... pip_version=">=1.0.0"
649+
... name="my-pip-agent", package_name="runloop-example-agent", pip_version=">=1.0.0"
658650
... )
659651
660652
:param package_name: Pip package name
@@ -671,7 +663,9 @@ def create_from_pip(
671663
:raises ValueError: If 'source' is provided in params
672664
"""
673665
if "source" in params:
674-
raise ValueError("Cannot specify 'source' when using create_from_pip(); source is automatically set to pip configuration")
666+
raise ValueError(
667+
"Cannot specify 'source' when using create_from_pip(); source is automatically set to pip configuration"
668+
)
675669

676670
pip_config: dict = {"package_name": package_name}
677671
if pip_version is not None:
@@ -701,7 +695,7 @@ def create_from_git(
701695
... name="my-git-agent",
702696
... repository="https://github.com/user/agent-repo",
703697
... ref="main",
704-
... agent_setup=["npm install", "npm run build"]
698+
... agent_setup=["npm install", "npm run build"],
705699
... )
706700
707701
:param repository: Git repository URL
@@ -716,7 +710,9 @@ def create_from_git(
716710
:raises ValueError: If 'source' is provided in params
717711
"""
718712
if "source" in params:
719-
raise ValueError("Cannot specify 'source' when using create_from_git(); source is automatically set to git configuration")
713+
raise ValueError(
714+
"Cannot specify 'source' when using create_from_git(); source is automatically set to git configuration"
715+
)
720716

721717
git_config: dict = {"repository": repository}
722718
if ref is not None:
@@ -743,9 +739,7 @@ def create_from_object(
743739
>>> obj = runloop.storage_object.upload_from_dir("./my-agent")
744740
>>> # Then create agent from the object
745741
>>> agent = runloop.agent.create_from_object(
746-
... name="my-object-agent",
747-
... object_id=obj.id,
748-
... agent_setup=["chmod +x setup.sh", "./setup.sh"]
742+
... name="my-object-agent", object_id=obj.id, agent_setup=["chmod +x setup.sh", "./setup.sh"]
749743
... )
750744
751745
:param object_id: Storage object ID
@@ -758,7 +752,9 @@ def create_from_object(
758752
:raises ValueError: If 'source' is provided in params
759753
"""
760754
if "source" in params:
761-
raise ValueError("Cannot specify 'source' when using create_from_object(); source is automatically set to object configuration")
755+
raise ValueError(
756+
"Cannot specify 'source' when using create_from_object(); source is automatically set to object configuration"
757+
)
762758

763759
object_config: dict = {"object_id": object_id}
764760
if agent_setup is not None:

0 commit comments

Comments
 (0)