coiled 1.135.4.dev17__tar.gz → 1.135.4.dev18__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.
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/PKG-INFO +1 -1
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/batch.py +36 -18
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/batch/run.py +14 -2
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/filestore.py +38 -4
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/.gitignore +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/LICENSE +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/README.md +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/__main__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/analytics.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/auth.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/capture_environment.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/batch/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/batch/list.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/batch/logs.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/batch/status.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/batch/util.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/batch/wait.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/cluster/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/cluster/azure_logs.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/cluster/better_logs.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/cluster/crud.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/cluster/get_address.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/cluster/list.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/cluster/logs.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/cluster/metrics.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/cluster/ssh.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/cluster/utils.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/config.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/core.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/curl.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/diagnostics.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/env.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/file.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/examples/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/examples/exit.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/examples/hello_world.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/examples/nyc_parquet.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/examples/pytorch.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/examples/xarray_nwm.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/hello.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/scripts/fill_ipython.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/scripts/nyc_parquet.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/scripts/pytorch.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/scripts/xarray_nwm.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/hello/utils.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/login.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/mpi.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/notebook/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/notebook/notebook.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/package_sync.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/prefect.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/prefect_serve.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/run.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/setup/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/setup/amp.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/setup/aws.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/setup/azure.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/setup/entry.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/setup/gcp.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/setup/prometheus.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/setup/util.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/sync.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cli/utils.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/cluster.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/coiled.yaml +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/compatibility.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/config.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/context.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/core.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/credentials/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/credentials/aws.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/credentials/google.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/errors.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/exceptions.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/extensions/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/extensions/prefect/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/extensions/prefect/runners.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/extensions/prefect/workers.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/function.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/plugins.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/prefect.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/pypi_conda_map.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/scan.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/software.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/software_utils.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/spans.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/spark.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/types.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/utils.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/v2/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/v2/cluster.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/v2/cluster_comms.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/v2/core.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/v2/cwi_log_link.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/v2/states.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/v2/widgets/__init__.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/v2/widgets/interface.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/v2/widgets/rich.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/v2/widgets/util.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/coiled/websockets.py +0 -0
- {coiled-1.135.4.dev17 → coiled-1.135.4.dev18}/pyproject.toml +0 -0
|
@@ -2,8 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import shlex
|
|
4
4
|
import time
|
|
5
|
+
from contextlib import nullcontext
|
|
5
6
|
|
|
6
7
|
from aiohttp import ServerDisconnectedError
|
|
8
|
+
from typing_extensions import Literal
|
|
7
9
|
|
|
8
10
|
import coiled
|
|
9
11
|
from coiled.cli.curl import sync_request
|
|
@@ -15,6 +17,7 @@ def run(
|
|
|
15
17
|
*,
|
|
16
18
|
name: str | None = None,
|
|
17
19
|
workspace: str | None = None,
|
|
20
|
+
cloud: coiled.Cloud[Literal[False]] | None = None,
|
|
18
21
|
software: str | None = None,
|
|
19
22
|
container: str | None = None,
|
|
20
23
|
run_on_host: bool | None = None,
|
|
@@ -64,6 +67,11 @@ def run(
|
|
|
64
67
|
|
|
65
68
|
Additional Parameters
|
|
66
69
|
---------------------
|
|
70
|
+
cloud
|
|
71
|
+
Authenticated Coiled Cloud client to use for this submission. If not
|
|
72
|
+
provided, a client is created from the current Coiled configuration.
|
|
73
|
+
The client's default workspace is used. ``cloud`` and ``workspace``
|
|
74
|
+
are mutually exclusive.
|
|
67
75
|
map_over_task_var_dicts
|
|
68
76
|
takes a list of dictionaries, so you can specify multiple environment variables for each task.
|
|
69
77
|
For example, ``[{"FOO": 1, "BAR": 2}, {"FOO": 3, "BAR": 4}]`` will pass ``FOO=1 BAR=2`` to one task and
|
|
@@ -81,6 +89,9 @@ def run(
|
|
|
81
89
|
tag = dict_to_key_val_list(tag)
|
|
82
90
|
vm_type = [vm_type] if isinstance(vm_type, str) else vm_type
|
|
83
91
|
|
|
92
|
+
if cloud is not None and workspace is not None:
|
|
93
|
+
raise ValueError("cloud and workspace are mutually exclusive")
|
|
94
|
+
|
|
84
95
|
kwargs = dict(
|
|
85
96
|
name=name,
|
|
86
97
|
command=command,
|
|
@@ -144,25 +155,32 @@ def run(
|
|
|
144
155
|
**default_kwargs,
|
|
145
156
|
}
|
|
146
157
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
158
|
+
with coiled.Cloud(workspace=workspace) if cloud is None else nullcontext(cloud) as cloud:
|
|
159
|
+
success = True
|
|
160
|
+
exception = None
|
|
161
|
+
try:
|
|
162
|
+
return _batch_run(default_kwargs, cloud=cloud, **kwargs)
|
|
163
|
+
except Exception as e:
|
|
164
|
+
success = False
|
|
165
|
+
exception = e
|
|
166
|
+
raise
|
|
167
|
+
finally:
|
|
168
|
+
tracking_info = error_info_for_tracking(exception)
|
|
169
|
+
_ = cloud.add_interaction(
|
|
170
|
+
action="coiled-batch-python",
|
|
171
|
+
success=success,
|
|
172
|
+
error_message=tracking_info.pop("error_message", None),
|
|
173
|
+
additional_data=tracking_info or None,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def wait_for_job_done(
|
|
178
|
+
job_id: int,
|
|
179
|
+
timeout: int | None = None,
|
|
180
|
+
cloud: coiled.Cloud[Literal[False]] | None = None,
|
|
181
|
+
) -> str | None:
|
|
164
182
|
timeout_at = time.monotonic() + timeout if timeout is not None else None
|
|
165
|
-
with coiled.Cloud() as cloud:
|
|
183
|
+
with coiled.Cloud() if cloud is None else nullcontext(cloud) as cloud:
|
|
166
184
|
url = f"{cloud.server}/api/v2/jobs/{job_id}"
|
|
167
185
|
while timeout_at is None or time.monotonic() < timeout_at:
|
|
168
186
|
try:
|
|
@@ -7,12 +7,14 @@ import logging
|
|
|
7
7
|
import os
|
|
8
8
|
import re
|
|
9
9
|
import shlex
|
|
10
|
+
from contextlib import nullcontext
|
|
10
11
|
|
|
11
12
|
import click
|
|
12
13
|
import dask.config
|
|
13
14
|
from dask.utils import format_bytes, format_time, parse_timedelta
|
|
14
15
|
from rich.console import Console
|
|
15
16
|
from rich.panel import Panel
|
|
17
|
+
from typing_extensions import Literal
|
|
16
18
|
|
|
17
19
|
import coiled
|
|
18
20
|
from coiled.cli.batch.util import load_sidecar_spec
|
|
@@ -524,7 +526,13 @@ def batch_run_cli(ctx, **kwargs):
|
|
|
524
526
|
)
|
|
525
527
|
|
|
526
528
|
|
|
527
|
-
def _batch_run(
|
|
529
|
+
def _batch_run(
|
|
530
|
+
default_kwargs,
|
|
531
|
+
logger=None,
|
|
532
|
+
from_cli=False,
|
|
533
|
+
cloud: coiled.Cloud[Literal[False]] | None = None,
|
|
534
|
+
**kwargs,
|
|
535
|
+
) -> dict:
|
|
528
536
|
command = kwargs["command"]
|
|
529
537
|
user_files = []
|
|
530
538
|
|
|
@@ -868,8 +876,9 @@ def _batch_run(default_kwargs, logger=None, from_cli=False, **kwargs) -> dict:
|
|
|
868
876
|
"max_retries": kwargs.get("max_retries") or 0,
|
|
869
877
|
}
|
|
870
878
|
|
|
871
|
-
with coiled.Cloud(workspace=kwargs["workspace"]) as cloud:
|
|
879
|
+
with coiled.Cloud(workspace=kwargs["workspace"]) if cloud is None else nullcontext(cloud) as cloud:
|
|
872
880
|
job_spec["workspace"] = cloud.default_workspace
|
|
881
|
+
cluster_kwargs["workspace"] = cloud.default_workspace
|
|
873
882
|
|
|
874
883
|
compressed_data = gzip.compress(json.dumps(job_spec).encode())
|
|
875
884
|
if len(compressed_data) > 2_400_000:
|
|
@@ -914,6 +923,7 @@ def _batch_run(default_kwargs, logger=None, from_cli=False, **kwargs) -> dict:
|
|
|
914
923
|
names=[in_fs_name, out_fs_name],
|
|
915
924
|
workspace=job_spec["workspace"],
|
|
916
925
|
region=kwargs["region"],
|
|
926
|
+
cloud=cloud,
|
|
917
927
|
)
|
|
918
928
|
|
|
919
929
|
in_fs = filestores[0]
|
|
@@ -929,6 +939,7 @@ def _batch_run(default_kwargs, logger=None, from_cli=False, **kwargs) -> dict:
|
|
|
929
939
|
fs=in_fs,
|
|
930
940
|
local_dir=kwargs.get("local_upload_path") or kwargs.get("local_sync_path"),
|
|
931
941
|
file_buffers=kwargs.get("buffers_to_upload"),
|
|
942
|
+
cloud=cloud,
|
|
932
943
|
)
|
|
933
944
|
|
|
934
945
|
# Run the job on a cluster
|
|
@@ -944,6 +955,7 @@ def _batch_run(default_kwargs, logger=None, from_cli=False, **kwargs) -> dict:
|
|
|
944
955
|
FilestoreManager.attach_filestores_to_cluster(
|
|
945
956
|
cluster_id=cluster.cluster_id,
|
|
946
957
|
attachments=filestores_to_attach,
|
|
958
|
+
cloud=cloud,
|
|
947
959
|
)
|
|
948
960
|
|
|
949
961
|
if logger:
|
|
@@ -3,13 +3,16 @@ from __future__ import annotations
|
|
|
3
3
|
import io
|
|
4
4
|
import os
|
|
5
5
|
import time
|
|
6
|
+
from contextlib import nullcontext
|
|
6
7
|
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
7
9
|
|
|
8
10
|
import httpx
|
|
9
11
|
from rich.align import Align
|
|
10
12
|
from rich.console import Group
|
|
11
13
|
from rich.prompt import Confirm
|
|
12
14
|
from rich.status import Status
|
|
15
|
+
from typing_extensions import Literal
|
|
13
16
|
|
|
14
17
|
import coiled
|
|
15
18
|
from coiled.cli.curl import sync_request
|
|
@@ -111,7 +114,7 @@ def download_from_filestore_with_ui(fs, into=".", name_includes=None):
|
|
|
111
114
|
)
|
|
112
115
|
|
|
113
116
|
|
|
114
|
-
def upload_to_filestore_with_ui(fs, local_dir, file_buffers=None):
|
|
117
|
+
def upload_to_filestore_with_ui(fs, local_dir, file_buffers=None, cloud=None):
|
|
115
118
|
# TODO (future enhancement) send write status
|
|
116
119
|
# this is tricky because status is stored on the "attachment" object, which might not exist yet
|
|
117
120
|
# because we want to be able to upload files before cluster has been created
|
|
@@ -160,7 +163,7 @@ def upload_to_filestore_with_ui(fs, local_dir, file_buffers=None):
|
|
|
160
163
|
])
|
|
161
164
|
|
|
162
165
|
# files_for_upload is type list[dict] where each dict has "relative_path" key
|
|
163
|
-
upload_info = FilestoreManager.get_signed_upload_urls(fs["id"], files_for_upload=files)
|
|
166
|
+
upload_info = FilestoreManager.get_signed_upload_urls(fs["id"], files_for_upload=files, cloud=cloud)
|
|
164
167
|
|
|
165
168
|
upload_urls = upload_info.get("urls")
|
|
166
169
|
existing_blobs = upload_info.get("existing")
|
|
@@ -440,10 +443,41 @@ class FilestoreManagerWithoutHttp:
|
|
|
440
443
|
class FilestoreManager(FilestoreManagerWithoutHttp):
|
|
441
444
|
http2 = True
|
|
442
445
|
|
|
446
|
+
@classmethod
|
|
447
|
+
def get_or_create_filestores(cls, names, workspace, region, cloud=None):
|
|
448
|
+
return cls.make_req(
|
|
449
|
+
"/api/v2/filestore/list",
|
|
450
|
+
post=True,
|
|
451
|
+
data={"names": names, "workspace": workspace, "region": region},
|
|
452
|
+
cloud=cloud,
|
|
453
|
+
).get("filestores")
|
|
454
|
+
|
|
455
|
+
@classmethod
|
|
456
|
+
def get_signed_upload_urls(cls, fs_id, files_for_upload, cloud=None):
|
|
457
|
+
paths = [f["relative_path"] for f in files_for_upload] # relative paths
|
|
458
|
+
return cls.make_req(
|
|
459
|
+
f"/api/v2/filestore/fs/{fs_id}/signed-urls/upload",
|
|
460
|
+
post=True,
|
|
461
|
+
data={"paths": paths},
|
|
462
|
+
cloud=cloud,
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
@classmethod
|
|
466
|
+
def attach_filestores_to_cluster(cls, cluster_id, attachments, cloud=None):
|
|
467
|
+
return cls.make_req(
|
|
468
|
+
"/api/v2/filestore/attach",
|
|
469
|
+
post=True,
|
|
470
|
+
data={
|
|
471
|
+
"cluster_id": cluster_id,
|
|
472
|
+
"attachments": attachments,
|
|
473
|
+
},
|
|
474
|
+
cloud=cloud,
|
|
475
|
+
)
|
|
476
|
+
|
|
443
477
|
@staticmethod
|
|
444
|
-
def make_req(api_path, post=False, data=None):
|
|
478
|
+
def make_req(api_path, post=False, data=None, cloud: coiled.Cloud[Literal[False]] | None = None) -> Any:
|
|
445
479
|
workspace = (data or {}).get("workspace")
|
|
446
|
-
with coiled.Cloud(workspace=workspace) as cloud:
|
|
480
|
+
with coiled.Cloud(workspace=workspace) if cloud is None else nullcontext(cloud) as cloud:
|
|
447
481
|
url = f"{cloud.server}{api_path}"
|
|
448
482
|
response = sync_request(
|
|
449
483
|
cloud=cloud,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|