codeocean 0.1.6__tar.gz → 0.2.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.
- {codeocean-0.1.6 → codeocean-0.2.0}/CHANGELOG.md +8 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/PKG-INFO +1 -1
- {codeocean-0.1.6 → codeocean-0.2.0}/pyproject.toml +1 -1
- {codeocean-0.1.6 → codeocean-0.2.0}/src/codeocean/client.py +6 -3
- {codeocean-0.1.6 → codeocean-0.2.0}/src/codeocean/computation.py +21 -2
- {codeocean-0.1.6 → codeocean-0.2.0}/src/codeocean/data_asset.py +21 -2
- {codeocean-0.1.6 → codeocean-0.2.0}/.flake8 +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/.gitignore +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/LICENSE +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/README.md +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/examples/create_data_asset.py +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/examples/run_capsule.py +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/examples/run_pipeline.py +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/src/codeocean/__init__.py +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/src/codeocean/capsule.py +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/src/codeocean/components.py +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/src/codeocean/enum.py +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/tests/__init__.py +0 -0
- {codeocean-0.1.6 → codeocean-0.2.0}/tests/test_package.py +0 -0
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
CHANGELOG
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
## 0.2.0 (2024-10-21)
|
|
5
|
+
|
|
6
|
+
- [#15](https://github.com/codeocean/codeocean-sdk-python/pull/15) feat: Add option for custom retries
|
|
7
|
+
|
|
8
|
+
## 0.1.7 (2024-10-17)
|
|
9
|
+
|
|
10
|
+
- [#14](https://github.com/codeocean/codeocean-sdk-python/pull/14) feat: Add an optional timeout parameter to polling while loops
|
|
11
|
+
|
|
4
12
|
## 0.1.6 (2024-10-15)
|
|
5
13
|
|
|
6
14
|
- [#13](https://github.com/codeocean/codeocean-sdk-python/pull/13) feat: makes polling interval configurable
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from requests_toolbelt.sessions import BaseUrlSession
|
|
2
|
-
from requests_toolbelt.adapters.socket_options import TCPKeepAliveAdapter
|
|
3
1
|
from dataclasses import dataclass
|
|
2
|
+
from requests_toolbelt.adapters.socket_options import TCPKeepAliveAdapter
|
|
3
|
+
from requests_toolbelt.sessions import BaseUrlSession
|
|
4
|
+
from typing import Optional
|
|
5
|
+
from urllib3.util import Retry
|
|
4
6
|
|
|
5
7
|
from codeocean.capsule import Capsules
|
|
6
8
|
from codeocean.computation import Computations
|
|
@@ -12,15 +14,16 @@ class CodeOcean:
|
|
|
12
14
|
|
|
13
15
|
domain: str
|
|
14
16
|
token: str
|
|
17
|
+
retries: Optional[Retry] = None
|
|
15
18
|
|
|
16
19
|
def __post_init__(self):
|
|
17
20
|
self.session = BaseUrlSession(base_url=f"{self.domain}/api/v1/")
|
|
18
21
|
self.session.auth = (self.token, "")
|
|
19
|
-
self.session.mount(self.domain, TCPKeepAliveAdapter())
|
|
20
22
|
self.session.headers.update({"Content-Type": "application/json"})
|
|
21
23
|
self.session.hooks["response"] = [
|
|
22
24
|
lambda response, *args, **kwargs: response.raise_for_status()
|
|
23
25
|
]
|
|
26
|
+
self.session.mount(self.domain, TCPKeepAliveAdapter(max_retries=self.retries))
|
|
24
27
|
|
|
25
28
|
self.capsules = Capsules(client=self.session)
|
|
26
29
|
self.computations = Computations(client=self.session)
|
|
@@ -4,7 +4,7 @@ from dataclasses import dataclass
|
|
|
4
4
|
from dataclasses_json import dataclass_json
|
|
5
5
|
from requests_toolbelt.sessions import BaseUrlSession
|
|
6
6
|
from typing import Optional
|
|
7
|
-
from time import sleep
|
|
7
|
+
from time import sleep, time
|
|
8
8
|
|
|
9
9
|
from codeocean.enum import StrEnum
|
|
10
10
|
|
|
@@ -141,20 +141,39 @@ class Computations:
|
|
|
141
141
|
|
|
142
142
|
return Computation.from_dict(res.json())
|
|
143
143
|
|
|
144
|
-
def wait_until_completed(
|
|
144
|
+
def wait_until_completed(
|
|
145
|
+
self,
|
|
146
|
+
computation: Computation,
|
|
147
|
+
polling_interval: float = 5,
|
|
148
|
+
timeout: Optional[float] = None,
|
|
149
|
+
) -> Computation:
|
|
145
150
|
"""
|
|
146
151
|
Polls the given computation until it reaches the 'Completed' or 'Failed' state.
|
|
152
|
+
|
|
153
|
+
- `polling_interval` and `timeout` are in seconds
|
|
147
154
|
"""
|
|
148
155
|
if polling_interval < 5:
|
|
149
156
|
raise ValueError(
|
|
150
157
|
f"Polling interval {polling_interval} should be greater than or equal to 5"
|
|
151
158
|
)
|
|
159
|
+
if timeout is not None and timeout < polling_interval:
|
|
160
|
+
raise ValueError(
|
|
161
|
+
f"Timeout {timeout} should be greater than or equal to polling interval {polling_interval}"
|
|
162
|
+
)
|
|
163
|
+
if timeout is not None and timeout < 0:
|
|
164
|
+
raise ValueError(
|
|
165
|
+
f"Timeout {timeout} should be greater than or equal to 0 (seconds), or None"
|
|
166
|
+
)
|
|
167
|
+
t0 = time()
|
|
152
168
|
while True:
|
|
153
169
|
comp = self.get_computation(computation.id)
|
|
154
170
|
|
|
155
171
|
if comp.state in [ComputationState.Completed, ComputationState.Failed]:
|
|
156
172
|
return comp
|
|
157
173
|
|
|
174
|
+
if timeout is not None and (time() - t0) > timeout:
|
|
175
|
+
raise TimeoutError(f"Computation {computation.id} did not complete within {timeout} seconds")
|
|
176
|
+
|
|
158
177
|
sleep(polling_interval)
|
|
159
178
|
|
|
160
179
|
def list_computation_results(self, computation_id: str, path: str = "") -> Folder:
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from dataclasses_json import dataclass_json
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
from requests_toolbelt.sessions import BaseUrlSession
|
|
6
|
-
from time import sleep
|
|
6
|
+
from time import sleep, time
|
|
7
7
|
from typing import Optional
|
|
8
8
|
|
|
9
9
|
from codeocean.components import SortOrder, SearchFilter, Permissions
|
|
@@ -237,20 +237,39 @@ class DataAssets:
|
|
|
237
237
|
|
|
238
238
|
return DataAsset.from_dict(res.json())
|
|
239
239
|
|
|
240
|
-
def wait_until_ready(
|
|
240
|
+
def wait_until_ready(
|
|
241
|
+
self,
|
|
242
|
+
data_asset: DataAsset,
|
|
243
|
+
polling_interval: float = 5,
|
|
244
|
+
timeout: float | None = None,
|
|
245
|
+
) -> DataAsset:
|
|
241
246
|
"""
|
|
242
247
|
Polls the given data asset until it reaches the 'Ready' or 'Failed' state.
|
|
248
|
+
|
|
249
|
+
- `polling_interval` and `timeout` are in seconds
|
|
243
250
|
"""
|
|
244
251
|
if polling_interval < 5:
|
|
245
252
|
raise ValueError(
|
|
246
253
|
f"Polling interval {polling_interval} should be greater than or equal to 5"
|
|
247
254
|
)
|
|
255
|
+
if timeout is not None and timeout < polling_interval:
|
|
256
|
+
raise ValueError(
|
|
257
|
+
f"Timeout {timeout} should be greater than or equal to polling interval {polling_interval}"
|
|
258
|
+
)
|
|
259
|
+
if timeout is not None and timeout < 0:
|
|
260
|
+
raise ValueError(
|
|
261
|
+
f"Timeout {timeout} should be greater than or equal to 0 (seconds), or None"
|
|
262
|
+
)
|
|
263
|
+
t0 = time()
|
|
248
264
|
while True:
|
|
249
265
|
da = self.get_data_asset(data_asset.id)
|
|
250
266
|
|
|
251
267
|
if da.state in [DataAssetState.Ready, DataAssetState.Failed]:
|
|
252
268
|
return da
|
|
253
269
|
|
|
270
|
+
if timeout is not None and (time() - t0) > timeout:
|
|
271
|
+
raise TimeoutError(f"Data asset {data_asset.id} was not ready within {timeout} seconds")
|
|
272
|
+
|
|
254
273
|
sleep(polling_interval)
|
|
255
274
|
|
|
256
275
|
def delete_data_asset(self, data_asset_id: str):
|
|
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
|