flowmesh-sdk-stack 0.1.2__tar.gz → 0.1.3__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.
- {flowmesh_sdk_stack-0.1.2/src/flowmesh_sdk_stack.egg-info → flowmesh_sdk_stack-0.1.3}/PKG-INFO +2 -2
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/pyproject.toml +2 -2
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3/src/flowmesh_sdk_stack.egg-info}/PKG-INFO +2 -2
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_sdk_stack.egg-info/requires.txt +1 -1
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_stack/workers.py +93 -41
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/LICENSE +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/README.md +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/setup.cfg +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_sdk_stack.egg-info/SOURCES.txt +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_sdk_stack.egg-info/dependency_links.txt +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_sdk_stack.egg-info/top_level.txt +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_stack/__init__.py +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_stack/docker.py +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_stack/doctor.py +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_stack/env.py +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_stack/env_schema.py +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_stack/images.py +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_stack/node_client.py +0 -0
- {flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_stack/paths.py +0 -0
{flowmesh_sdk_stack-0.1.2/src/flowmesh_sdk_stack.egg-info → flowmesh_sdk_stack-0.1.3}/PKG-INFO
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flowmesh-sdk-stack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: FlowMesh SDK stack client
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.12
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist: flowmesh-sdk==0.1.
|
|
9
|
+
Requires-Dist: flowmesh-sdk==0.1.3
|
|
10
10
|
Requires-Dist: httpx>=0.27.0
|
|
11
11
|
Requires-Dist: pyyaml>=6.0.0
|
|
12
12
|
Requires-Dist: docker>=7.1.0
|
|
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "flowmesh-sdk-stack"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.3"
|
|
8
8
|
description = "FlowMesh SDK stack client"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
license-files = ["LICENSE"]
|
|
13
13
|
dependencies = [
|
|
14
|
-
"flowmesh-sdk==0.1.
|
|
14
|
+
"flowmesh-sdk==0.1.3",
|
|
15
15
|
"httpx>=0.27.0",
|
|
16
16
|
"pyyaml>=6.0.0",
|
|
17
17
|
"docker>=7.1.0",
|
{flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3/src/flowmesh_sdk_stack.egg-info}/PKG-INFO
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flowmesh-sdk-stack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: FlowMesh SDK stack client
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.12
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist: flowmesh-sdk==0.1.
|
|
9
|
+
Requires-Dist: flowmesh-sdk==0.1.3
|
|
10
10
|
Requires-Dist: httpx>=0.27.0
|
|
11
11
|
Requires-Dist: pyyaml>=6.0.0
|
|
12
12
|
Requires-Dist: docker>=7.1.0
|
|
@@ -65,12 +65,20 @@ def create_workers(
|
|
|
65
65
|
targets: str = "all",
|
|
66
66
|
config_paths: list[Path] | None = None,
|
|
67
67
|
config_raw: list[str] | None = None,
|
|
68
|
+
name_template: str | None = None,
|
|
69
|
+
slug: str | None = None,
|
|
68
70
|
) -> list[tuple[str, dict[str, Any]]]:
|
|
69
71
|
"""Create node workers from configs or built-in cpu/gpu presets.
|
|
70
72
|
|
|
71
73
|
When ``kind`` is "gpu", if ``count`` is equal to 1, a single worker with the
|
|
72
74
|
specified GPU targets will be created. If ``count`` is greater than 1, one worker
|
|
73
75
|
will be created per GPU target, and the number of targets must match ``count``.
|
|
76
|
+
|
|
77
|
+
For the built-in cpu/gpu presets, ``slug`` prefixes the generated worker
|
|
78
|
+
aliases so names are scoped to a stack, and ``name_template`` overrides the
|
|
79
|
+
naming entirely (placeholders ``{slug}``, ``{kind}``, ``{idx}``, ``{gpu}``).
|
|
80
|
+
Both are ignored when ``config_paths`` / ``config_raw`` are provided, since
|
|
81
|
+
those payloads carry their own aliases.
|
|
74
82
|
"""
|
|
75
83
|
payloads = _payloads_for_worker_create(
|
|
76
84
|
kind=kind,
|
|
@@ -78,6 +86,8 @@ def create_workers(
|
|
|
78
86
|
targets=targets,
|
|
79
87
|
config_paths=config_paths,
|
|
80
88
|
config_raw=config_raw,
|
|
89
|
+
name_template=name_template,
|
|
90
|
+
slug=slug,
|
|
81
91
|
)
|
|
82
92
|
if not payloads:
|
|
83
93
|
return []
|
|
@@ -162,12 +172,47 @@ def detect_gpu_targets(targets: str) -> list[str]:
|
|
|
162
172
|
return [item.strip() for item in result.stdout.splitlines() if item.strip()]
|
|
163
173
|
|
|
164
174
|
|
|
175
|
+
_ALIAS_FIELDS = "{slug}, {kind}, {idx}, {gpu}"
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class _StrictFormatDict(dict[str, Any]):
|
|
179
|
+
def __missing__(self, key: str) -> Any:
|
|
180
|
+
raise KeyError(key)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _worker_alias(
|
|
184
|
+
kind: str,
|
|
185
|
+
idx: int,
|
|
186
|
+
slug: str | None,
|
|
187
|
+
template: str | None,
|
|
188
|
+
gpu: str | None = None,
|
|
189
|
+
) -> str:
|
|
190
|
+
if template is None:
|
|
191
|
+
template = (
|
|
192
|
+
("{slug}_" if slug else "")
|
|
193
|
+
+ f"worker_{kind}_"
|
|
194
|
+
+ ("{idx}" if gpu is None else "{gpu}")
|
|
195
|
+
)
|
|
196
|
+
fields: dict[str, Any] = {"slug": slug or "", "kind": kind, "idx": idx}
|
|
197
|
+
if gpu is not None:
|
|
198
|
+
fields["gpu"] = gpu
|
|
199
|
+
try:
|
|
200
|
+
return template.format_map(_StrictFormatDict(fields))
|
|
201
|
+
except (KeyError, IndexError, ValueError) as exc:
|
|
202
|
+
raise FlowMeshError(
|
|
203
|
+
f"invalid --name-template ({exc}); "
|
|
204
|
+
f"available placeholders: {_ALIAS_FIELDS}"
|
|
205
|
+
) from exc
|
|
206
|
+
|
|
207
|
+
|
|
165
208
|
def _payloads_for_worker_create(
|
|
166
209
|
kind: str,
|
|
167
210
|
count: int,
|
|
168
211
|
targets: str,
|
|
169
212
|
config_paths: list[Path] | None,
|
|
170
213
|
config_raw: list[str] | None,
|
|
214
|
+
name_template: str | None = None,
|
|
215
|
+
slug: str | None = None,
|
|
171
216
|
) -> list[tuple[str, str]]:
|
|
172
217
|
if count < 1:
|
|
173
218
|
raise FlowMeshError("Worker count must be at least 1.")
|
|
@@ -183,25 +228,17 @@ def _payloads_for_worker_create(
|
|
|
183
228
|
_extend_payloads(payloads, f"worker from raw#{idx}", raw)
|
|
184
229
|
return payloads
|
|
185
230
|
|
|
231
|
+
specs: list[tuple[str, dict[str, Any], str]] # alias, worker_config, label
|
|
186
232
|
if kind == "cpu":
|
|
187
|
-
|
|
233
|
+
specs = [
|
|
188
234
|
(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
"provider": "docker",
|
|
192
|
-
"init_on_start": True,
|
|
193
|
-
"worker_config": {
|
|
194
|
-
"worker_type": "cpu",
|
|
195
|
-
"worker_alias": f"worker_cpu_{idx}",
|
|
196
|
-
},
|
|
197
|
-
}
|
|
198
|
-
),
|
|
235
|
+
(alias := _worker_alias("cpu", idx, slug, name_template)),
|
|
236
|
+
{"worker_type": "cpu", "worker_alias": alias},
|
|
199
237
|
"CPU worker",
|
|
200
238
|
)
|
|
201
239
|
for idx in range(count)
|
|
202
240
|
]
|
|
203
|
-
|
|
204
|
-
if kind == "gpu":
|
|
241
|
+
elif kind == "gpu":
|
|
205
242
|
raw_gpu_ids = detect_gpu_targets(targets)
|
|
206
243
|
gpu_ids: list[int] = []
|
|
207
244
|
for raw_gpu_id in raw_gpu_ids:
|
|
@@ -217,47 +254,62 @@ def _payloads_for_worker_create(
|
|
|
217
254
|
f"Consider setting count={len(gpu_ids)} or specifying exactly "
|
|
218
255
|
f"{count} GPU targets."
|
|
219
256
|
)
|
|
220
|
-
|
|
257
|
+
specs = [
|
|
221
258
|
(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
"
|
|
225
|
-
|
|
226
|
-
"worker_config": {
|
|
227
|
-
"worker_type": "gpu",
|
|
228
|
-
"cuda_devices": [gpu_id],
|
|
229
|
-
"worker_alias": f"worker_gpu_{gpu_id}",
|
|
230
|
-
},
|
|
231
|
-
}
|
|
259
|
+
(
|
|
260
|
+
alias := _worker_alias(
|
|
261
|
+
"gpu", idx, slug, name_template, gpu=str(gpu_id)
|
|
262
|
+
)
|
|
232
263
|
),
|
|
264
|
+
{
|
|
265
|
+
"worker_type": "gpu",
|
|
266
|
+
"cuda_devices": [gpu_id],
|
|
267
|
+
"worker_alias": alias,
|
|
268
|
+
},
|
|
233
269
|
f"GPU worker for GPU {gpu_id}",
|
|
234
270
|
)
|
|
235
|
-
for gpu_id in gpu_ids
|
|
271
|
+
for idx, gpu_id in enumerate(gpu_ids)
|
|
236
272
|
]
|
|
237
273
|
else:
|
|
238
274
|
worker_suffix = "all" if targets == "all" else "_".join(raw_gpu_ids)
|
|
239
|
-
|
|
275
|
+
specs = [
|
|
240
276
|
(
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
"
|
|
244
|
-
|
|
245
|
-
"worker_config": {
|
|
246
|
-
"worker_type": "gpu",
|
|
247
|
-
"cuda_devices": gpu_ids,
|
|
248
|
-
"worker_alias": f"worker_gpu_{worker_suffix}",
|
|
249
|
-
},
|
|
250
|
-
}
|
|
277
|
+
(
|
|
278
|
+
alias := _worker_alias(
|
|
279
|
+
"gpu", 0, slug, name_template, gpu=worker_suffix
|
|
280
|
+
)
|
|
251
281
|
),
|
|
282
|
+
{
|
|
283
|
+
"worker_type": "gpu",
|
|
284
|
+
"cuda_devices": gpu_ids,
|
|
285
|
+
"worker_alias": alias,
|
|
286
|
+
},
|
|
252
287
|
f"GPU worker for GPUs {', '.join(raw_gpu_ids)}",
|
|
253
288
|
)
|
|
254
289
|
]
|
|
290
|
+
else:
|
|
291
|
+
raise FlowMeshError("worker up expects kind cpu|gpu or use --config")
|
|
292
|
+
|
|
293
|
+
aliases = [alias for alias, _, _ in specs]
|
|
294
|
+
if len(set(aliases)) != len(aliases):
|
|
295
|
+
raise FlowMeshError(
|
|
296
|
+
"--name-template produced duplicate worker names; "
|
|
297
|
+
"include {idx} or {gpu} to disambiguate"
|
|
298
|
+
)
|
|
255
299
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
300
|
+
return [
|
|
301
|
+
(
|
|
302
|
+
json.dumps(
|
|
303
|
+
{
|
|
304
|
+
"provider": "docker",
|
|
305
|
+
"init_on_start": True,
|
|
306
|
+
"worker_config": worker_config,
|
|
307
|
+
}
|
|
308
|
+
),
|
|
309
|
+
label,
|
|
310
|
+
)
|
|
311
|
+
for _, worker_config, label in specs
|
|
312
|
+
]
|
|
261
313
|
|
|
262
314
|
|
|
263
315
|
def _extend_payloads(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_sdk_stack.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{flowmesh_sdk_stack-0.1.2 → flowmesh_sdk_stack-0.1.3}/src/flowmesh_sdk_stack.egg-info/top_level.txt
RENAMED
|
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
|