runcloud-sdk 0.8.3__tar.gz → 0.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {runcloud_sdk-0.8.3/runcloud_sdk.egg-info → runcloud_sdk-0.9.0}/PKG-INFO +16 -1
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/README.md +15 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/pyproject.toml +1 -1
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud/client.py +26 -2
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0/runcloud_sdk.egg-info}/PKG-INFO +16 -1
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/tests/test_sdk.py +29 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/LICENSE +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud/__init__.py +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud/compat/__init__.py +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud/compat/blaxel.py +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud/compat/daytona.py +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud/compat/e2b.py +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud/compat/modal.py +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud/compat/sprites.py +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud/compat/vercel.py +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud_sdk.egg-info/SOURCES.txt +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud_sdk.egg-info/dependency_links.txt +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud_sdk.egg-info/requires.txt +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/runcloud_sdk.egg-info/top_level.txt +0 -0
- {runcloud_sdk-0.8.3 → runcloud_sdk-0.9.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: runcloud-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Python SDK for run.cloud, including sandbox-provider compatibility adapters
|
|
5
5
|
Author: Newly
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -62,6 +62,21 @@ finally:
|
|
|
62
62
|
automation, set `RUN_CLOUD_API_KEY` and optionally `RUN_CLOUD_API_URL`, or pass
|
|
63
63
|
`api_key` and `api_url` directly.
|
|
64
64
|
|
|
65
|
+
A sandbox's name is a label you own: set it at create, change it later, and
|
|
66
|
+
filter on it. Naming plus `resume` is how the same sandbox goes back to the same
|
|
67
|
+
piece of work instead of booting a new one:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
matches = cloud.list(name=f"project-{project_id}")
|
|
71
|
+
box = matches[0].resume() if matches else cloud.create(name=f"project-{project_id}")
|
|
72
|
+
|
|
73
|
+
box.rename(f"project-{project_id}-v2")
|
|
74
|
+
box.rename("") # clears the label
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Names are not unique and mean nothing to the platform, so check `state` on a
|
|
78
|
+
match before using it. Renaming works in any state but `destroyed`.
|
|
79
|
+
|
|
65
80
|
## Compatibility adapters
|
|
66
81
|
|
|
67
82
|
The same distribution includes migration adapters:
|
|
@@ -44,6 +44,21 @@ finally:
|
|
|
44
44
|
automation, set `RUN_CLOUD_API_KEY` and optionally `RUN_CLOUD_API_URL`, or pass
|
|
45
45
|
`api_key` and `api_url` directly.
|
|
46
46
|
|
|
47
|
+
A sandbox's name is a label you own: set it at create, change it later, and
|
|
48
|
+
filter on it. Naming plus `resume` is how the same sandbox goes back to the same
|
|
49
|
+
piece of work instead of booting a new one:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
matches = cloud.list(name=f"project-{project_id}")
|
|
53
|
+
box = matches[0].resume() if matches else cloud.create(name=f"project-{project_id}")
|
|
54
|
+
|
|
55
|
+
box.rename(f"project-{project_id}-v2")
|
|
56
|
+
box.rename("") # clears the label
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Names are not unique and mean nothing to the platform, so check `state` on a
|
|
60
|
+
match before using it. Renaming works in any state but `destroyed`.
|
|
61
|
+
|
|
47
62
|
## Compatibility adapters
|
|
48
63
|
|
|
49
64
|
The same distribution includes migration adapters:
|
|
@@ -372,8 +372,17 @@ class Client:
|
|
|
372
372
|
sid = urllib.parse.quote(sandbox_id, safe="")
|
|
373
373
|
return Sandbox(self, self.request("GET", f"/run-cloud/sandboxes/{sid}"))
|
|
374
374
|
|
|
375
|
-
def list(
|
|
376
|
-
|
|
375
|
+
def list(
|
|
376
|
+
self, state: Optional[str] = None, name: Optional[str] = None
|
|
377
|
+
) -> list["Sandbox"]:
|
|
378
|
+
# Both filters are applied server-side, so finding a sandbox by the name
|
|
379
|
+
# you gave it does not mean paging the whole fleet and matching locally.
|
|
380
|
+
filters = [
|
|
381
|
+
(key, value)
|
|
382
|
+
for key, value in (("state", state), ("name", name))
|
|
383
|
+
if value
|
|
384
|
+
]
|
|
385
|
+
query = "?" + urllib.parse.urlencode(filters) if filters else ""
|
|
377
386
|
payload = self.request("GET", "/run-cloud/sandboxes" + query) or {}
|
|
378
387
|
return [Sandbox(self, item) for item in payload.get("items", [])]
|
|
379
388
|
|
|
@@ -548,6 +557,21 @@ class Sandbox:
|
|
|
548
557
|
)
|
|
549
558
|
return self
|
|
550
559
|
|
|
560
|
+
def rename(self, name: str) -> "Sandbox":
|
|
561
|
+
"""Relabel the sandbox.
|
|
562
|
+
|
|
563
|
+
The name is a label you own and the filter ``list(name=...)`` matches on,
|
|
564
|
+
so this is how a sandbox gets re-tagged without destroying it. Works in
|
|
565
|
+
any state but destroyed; an empty name clears the label. Names are not
|
|
566
|
+
unique and are capped at 128 characters.
|
|
567
|
+
"""
|
|
568
|
+
self._data = self._client.request(
|
|
569
|
+
"POST",
|
|
570
|
+
f"/run-cloud/sandboxes/{urllib.parse.quote(self.id, safe='')}/name",
|
|
571
|
+
{"name": name},
|
|
572
|
+
)
|
|
573
|
+
return self
|
|
574
|
+
|
|
551
575
|
def set_timeout(self, seconds: int) -> "Sandbox":
|
|
552
576
|
self._data = self._client.request(
|
|
553
577
|
"POST",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: runcloud-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Python SDK for run.cloud, including sandbox-provider compatibility adapters
|
|
5
5
|
Author: Newly
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -62,6 +62,21 @@ finally:
|
|
|
62
62
|
automation, set `RUN_CLOUD_API_KEY` and optionally `RUN_CLOUD_API_URL`, or pass
|
|
63
63
|
`api_key` and `api_url` directly.
|
|
64
64
|
|
|
65
|
+
A sandbox's name is a label you own: set it at create, change it later, and
|
|
66
|
+
filter on it. Naming plus `resume` is how the same sandbox goes back to the same
|
|
67
|
+
piece of work instead of booting a new one:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
matches = cloud.list(name=f"project-{project_id}")
|
|
71
|
+
box = matches[0].resume() if matches else cloud.create(name=f"project-{project_id}")
|
|
72
|
+
|
|
73
|
+
box.rename(f"project-{project_id}-v2")
|
|
74
|
+
box.rename("") # clears the label
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Names are not unique and mean nothing to the platform, so check `state` on a
|
|
78
|
+
match before using it. Renaming works in any state but `destroyed`.
|
|
79
|
+
|
|
65
80
|
## Compatibility adapters
|
|
66
81
|
|
|
67
82
|
The same distribution includes migration adapters:
|
|
@@ -114,6 +114,35 @@ class SDKTests(unittest.TestCase):
|
|
|
114
114
|
self.recorder.calls,
|
|
115
115
|
)
|
|
116
116
|
|
|
117
|
+
def test_rename_posts_the_label_and_list_filters_on_it(self):
|
|
118
|
+
box = self.client.create()
|
|
119
|
+
box.rename("proj_42")
|
|
120
|
+
self.assertIn(
|
|
121
|
+
("POST", "/run-cloud/sandboxes/sb_python/name", {"name": "proj_42"}),
|
|
122
|
+
self.recorder.calls,
|
|
123
|
+
)
|
|
124
|
+
# The response replaces the cached record, so the new name is readable
|
|
125
|
+
# without a second get().
|
|
126
|
+
self.assertEqual(box.name, "compat")
|
|
127
|
+
|
|
128
|
+
# An empty name clears the label rather than being rejected client-side.
|
|
129
|
+
box.rename("")
|
|
130
|
+
self.assertIn(
|
|
131
|
+
("POST", "/run-cloud/sandboxes/sb_python/name", {"name": ""}),
|
|
132
|
+
self.recorder.calls,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
self.client.list(name="proj_42")
|
|
136
|
+
self.assertIn(
|
|
137
|
+
("GET", "/run-cloud/sandboxes?name=proj_42", None),
|
|
138
|
+
self.recorder.calls,
|
|
139
|
+
)
|
|
140
|
+
self.client.list(state="running", name="proj 42")
|
|
141
|
+
self.assertIn(
|
|
142
|
+
("GET", "/run-cloud/sandboxes?state=running&name=proj+42", None),
|
|
143
|
+
self.recorder.calls,
|
|
144
|
+
)
|
|
145
|
+
|
|
117
146
|
def test_exec_contract_defaults_legacy_true_and_preserves_false(self):
|
|
118
147
|
for frame, expected in [
|
|
119
148
|
({"stream": "exit"}, 0),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|