Skip to content
Merged
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
22 changes: 2 additions & 20 deletions examples/desktop.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,19 @@
from __future__ import annotations

import sys
import time
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))

from leap0 import Leap0, Leap0APIError, Leap0Client, Leap0Config, Leap0Error
from leap0.models import SandboxRef


def wait_for_desktop(client: Leap0Client, sandbox: SandboxRef, *, timeout_seconds: float = 60.0) -> None:
deadline = time.monotonic() + timeout_seconds
while time.monotonic() < deadline:
sandbox_status = client.sandboxes.get(sandbox)
if sandbox_status.state == "running":
try:
health = client.desktop.health(sandbox)
except Leap0APIError:
pass
else:
if health.ok and health.state == "ready":
return
time.sleep(0.25)
raise TimeoutError(f"Sandbox {sandbox} did not become ready within {timeout_seconds:.0f}s")
from leap0 import Leap0, Leap0Config, Leap0Error


def main() -> None:
client = Leap0(Leap0Config())
sandbox = client.sandboxes.create(template_name="system/desktop:v0.1.0")

try:
wait_for_desktop(client, sandbox)
client.desktop.wait_until_ready(sandbox, timeout=60.0)
print("Desktop:", client.desktop.desktop_url(sandbox))

display = client.desktop.display_info(sandbox)
Expand Down
198 changes: 117 additions & 81 deletions leap0/__init__.py
Original file line number Diff line number Diff line change
@@ -1,85 +1,100 @@
from .client import Leap0, Leap0Client
from .config import Leap0Config
from .exceptions import Leap0APIError, Leap0Error, Leap0WebSocketError
from .models import (
CodeContext,
CodeExecutionError,
CodeExecutionOutput,
CodeExecutionResult,
DesktopDisplayInfo,
DesktopHealth,
DesktopPointerPosition,
DesktopProcessErrors,
DesktopProcessLogs,
DesktopProcessRestart,
DesktopProcessStatus,
DesktopProcessStatusList,
DesktopRecordingStatus,
DesktopRecordingSummary,
DesktopWindow,
EditFileResult,
EditResult,
ExecutionLogs,
FileEdit,
FileInfo,
GitCommitResult,
GitResult,
ImageConfig,
LsResult,
LspResponse,
ProcessResult,
PtyConnection,
PtySession,
Sandbox,
SandboxStatus,
SearchMatch,
Snapshot,
SshAccess,
SshValidation,
StreamEvent,
Template,
TreeEntry,
TreeResult,
from .code_interpreter import CodeInterpreterClient
from .desktop import DesktopClient
from .filesystem import FilesystemClient
from .git import GitClient
from .lsp import LspClient
from .process import ProcessClient
from .pty import PtyClient
from .sandboxes import SandboxesClient
from .snapshots import SnapshotsClient
from .ssh import SshClient
from .templates import TemplatesClient
from .common.config import Leap0Config
from .common.errors import (
Leap0ConflictError,
Leap0Error,
Leap0NotFoundError,
Leap0PermissionError,
Leap0RateLimitError,
Leap0TimeoutError,
Leap0WebSocketError,
)
from ._types import (
CodeContextDict,
CodeExecutionOutputDict,
CodeExecutionResultDict,
DesktopDisplayInfoDict,
DesktopHealthDict,
DesktopPointerPositionDict,
DesktopProcessErrorsDict,
DesktopProcessLogsDict,
DesktopProcessRestartDict,
DesktopProcessStatusDict,
DesktopProcessStatusListDict,
DesktopRecordingStatusDict,
DesktopRecordingSummaryDict,
DesktopWindowDict,
EditFileResponseDict,
EditResultDict,
ExecutionErrorDict,
ExecutionLogsDict,
FileInfoDict,
GitCommitResponseDict,
GitResultDict,
ImageConfigDict,
LsResponseDict,
LspSuccessResponseDict,
ProcessResultDict,
PtySessionInfoDict,
RegistryCredentialsDict,
SandboxCreateResponseDict,
SandboxState,
SandboxStatusResponseDict,
SearchMatchDict,
SnapshotCreateResponseDict,
SshAccessValidationDict,
SshCreateAccessDict,
StreamEventDict,
TreeEntryDict,
TreeResponseDict,
UploadTemplateResponseDict,
from .common.sandbox import Sandbox, SandboxStatus
from .common.snapshot import Snapshot
from .common.filesystem import (
EditFileResult, EditResult, FileEdit, FileInfo, LsResult, SearchMatch, TreeEntry, TreeResult,
)
from .common.git import GitCommitResult, GitResult
from .common.process import ProcessResult
from .common.pty import PtyConnection, PtySession
from .common.lsp import LspJsonRpcError, LspJsonRpcErrorDict, LspJsonRpcResponse, LspJsonRpcResponseDict, LspResponse
from .common.ssh import SshAccess, SshValidation
from .common.template import ImageConfig, Template
from .common.code_interpreter import (
CodeContext, CodeExecutionError, CodeExecutionOutput, CodeExecutionResult, ExecutionLogs, StreamEvent,
)
from .common.desktop import (
DesktopDisplayInfo, DesktopHealth, DesktopPointerPosition, DesktopProcessErrors,
DesktopProcessLogs, DesktopProcessRestart, DesktopProcessStatus, DesktopProcessStatusList,
DesktopRecordingStatus, DesktopRecordingSummary, DesktopWindow,
)

# TypedDicts
from .common.sandbox import (
NetworkPolicyDict as NetworkPolicyDict,
SandboxCreateResponseDict as SandboxCreateResponseDict,
SandboxState as SandboxState,
SandboxStatusResponseDict as SandboxStatusResponseDict,
)
from .common.snapshot import SnapshotCreateResponseDict as SnapshotCreateResponseDict
from .common.filesystem import (
EditFileResponseDict as EditFileResponseDict,
EditResultDict as EditResultDict,
FileInfoDict as FileInfoDict,
GlobResponseDict as GlobResponseDict,
GrepResponseDict as GrepResponseDict,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
LsResponseDict as LsResponseDict,
SearchMatchDict as SearchMatchDict,
TreeEntryDict as TreeEntryDict,
TreeResponseDict as TreeResponseDict,
)
from .common.git import (
GitCommitResponseDict as GitCommitResponseDict,
GitResultDict as GitResultDict,
)
from .common.process import ProcessResultDict as ProcessResultDict
from .common.pty import PtySessionInfoDict as PtySessionInfoDict
from .common.lsp import LspSuccessResponseDict as LspSuccessResponseDict
from .common.ssh import (
SshAccessValidationDict as SshAccessValidationDict,
SshCreateAccessDict as SshCreateAccessDict,
)
from .common.template import (
ImageConfigDict as ImageConfigDict,
RegistryCredentialsDict as RegistryCredentialsDict,
UploadTemplateResponseDict as UploadTemplateResponseDict,
)
from .common.code_interpreter import (
CodeContextDict as CodeContextDict,
CodeExecutionOutputDict as CodeExecutionOutputDict,
CodeExecutionResultDict as CodeExecutionResultDict,
ExecutionErrorDict as ExecutionErrorDict,
ExecutionLogsDict as ExecutionLogsDict,
StreamEventDict as StreamEventDict,
)
from .common.desktop import (
DesktopDisplayInfoDict as DesktopDisplayInfoDict,
DesktopHealthDict as DesktopHealthDict,
DesktopPointerPositionDict as DesktopPointerPositionDict,
DesktopProcessErrorsDict as DesktopProcessErrorsDict,
DesktopProcessLogsDict as DesktopProcessLogsDict,
DesktopProcessRestartDict as DesktopProcessRestartDict,
DesktopProcessStatusDict as DesktopProcessStatusDict,
DesktopProcessStatusListDict as DesktopProcessStatusListDict,
DesktopRecordingStatusDict as DesktopRecordingStatusDict,
DesktopRecordingSummaryDict as DesktopRecordingSummaryDict,
DesktopWindowDict as DesktopWindowDict,
)

__all__ = [
Expand All @@ -88,6 +103,7 @@
"CodeExecutionOutput",
"CodeExecutionResult",
"DesktopDisplayInfo",
"DesktopClient",
"DesktopHealth",
"DesktopPointerPosition",
"DesktopProcessErrors",
Expand All @@ -103,30 +119,46 @@
"ExecutionLogs",
"FileEdit",
"FileInfo",
"FilesystemClient",
"GitClient",
"GitCommitResult",
"GitResult",
"ImageConfig",
"Leap0",
"Leap0APIError",
"Leap0ConflictError",
"Leap0Config",
"Leap0Client",
"Leap0Error",
"Leap0NotFoundError",
"Leap0PermissionError",
"Leap0RateLimitError",
"Leap0TimeoutError",
"Leap0WebSocketError",
"LsResult",
"LspClient",
"LspJsonRpcError",
"LspJsonRpcResponse",
"LspResponse",
"ProcessClient",
"ProcessResult",
"PtyClient",
"PtyConnection",
"PtySession",
"Sandbox",
"SandboxesClient",
"SandboxStatus",
"SearchMatch",
"Snapshot",
"SnapshotsClient",
"SshClient",
"SshAccess",
"SshValidation",
"StreamEvent",
"Template",
"TemplatesClient",
"TreeEntry",
"TreeResult",
"CodeInterpreterClient",
"CodeContextDict",
"CodeExecutionOutputDict",
"CodeExecutionResultDict",
Expand All @@ -148,8 +180,12 @@
"FileInfoDict",
"GitCommitResponseDict",
"GitResultDict",
"GlobResponseDict",
"GrepResponseDict",
"ImageConfigDict",
"LsResponseDict",
"LspJsonRpcErrorDict",
"LspJsonRpcResponseDict",
"LspSuccessResponseDict",
"ProcessResultDict",
"PtySessionInfoDict",
Expand Down
14 changes: 10 additions & 4 deletions leap0/_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

import httpx

from .config import DEFAULT_CLIENT_TIMEOUT
from .exceptions import Leap0APIError
from .common.config import DEFAULT_CLIENT_TIMEOUT
from .common.errors import raise_api_error


class Transport:
Expand Down Expand Up @@ -51,7 +51,12 @@ def _target_url(self, target: str) -> str:
def _check_response(self, response: httpx.Response, method: str, target: str, expected_status: int | tuple[int, ...]) -> httpx.Response:
expected = self._expected(expected_status)
if response.status_code not in expected:
raise Leap0APIError(response.status_code, f"Request failed: {method} {target}", body=response.text)
raise_api_error(
response.status_code,
f"Request failed: {method} {target}",
body=response.text,
headers=dict(response.headers),
)
return response

def _request(
Expand Down Expand Up @@ -100,8 +105,9 @@ def _stream(
response = self._client.send(request, stream=True)
if response.status_code >= 400:
body = response.read().decode("utf-8", errors="replace")
hdrs = dict(response.headers)
response.close()
raise Leap0APIError(response.status_code, f"Request failed: {method} {target}", body=body)
raise_api_error(response.status_code, f"Request failed: {method} {target}", body=body, headers=hdrs)
return response

def request(
Expand Down
Loading