podstack 1.3.1__tar.gz → 1.3.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.
- {podstack-1.3.1 → podstack-1.3.3}/PKG-INFO +1 -1
- {podstack-1.3.1 → podstack-1.3.3}/podstack/__init__.py +3 -1
- {podstack-1.3.1 → podstack-1.3.3}/podstack/annotations.py +15 -11
- {podstack-1.3.1 → podstack-1.3.3}/podstack/gpu_runner.py +39 -9
- {podstack-1.3.1 → podstack-1.3.3}/podstack.egg-info/PKG-INFO +1 -1
- {podstack-1.3.1 → podstack-1.3.3}/pyproject.toml +1 -1
- {podstack-1.3.1 → podstack-1.3.3}/LICENSE +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/README.md +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/client.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/exceptions.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/execution.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/models.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/notebook.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/registry/__init__.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/registry/client.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/registry/exceptions.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/registry/experiment.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/registry/model.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack/registry/model_utils.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack.egg-info/SOURCES.txt +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack.egg-info/dependency_links.txt +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack.egg-info/requires.txt +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack.egg-info/top_level.txt +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack_gpu/__init__.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack_gpu/app.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack_gpu/exceptions.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack_gpu/image.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack_gpu/runner.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack_gpu/secret.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack_gpu/utils.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/podstack_gpu/volume.py +0 -0
- {podstack-1.3.1 → podstack-1.3.3}/setup.cfg +0 -0
|
@@ -54,7 +54,7 @@ Decorators:
|
|
|
54
54
|
...
|
|
55
55
|
"""
|
|
56
56
|
|
|
57
|
-
__version__ = "1.3.
|
|
57
|
+
__version__ = "1.3.2"
|
|
58
58
|
|
|
59
59
|
from .client import Client
|
|
60
60
|
from .notebook import Notebook, NotebookStatus
|
|
@@ -83,6 +83,7 @@ from . import gpu_runner
|
|
|
83
83
|
from .gpu_runner import (
|
|
84
84
|
GPURunner,
|
|
85
85
|
GPUExecutionResult,
|
|
86
|
+
RunnerList,
|
|
86
87
|
run as run_on_gpu,
|
|
87
88
|
list_runners,
|
|
88
89
|
)
|
|
@@ -209,6 +210,7 @@ __all__ = [
|
|
|
209
210
|
"gpu_runner",
|
|
210
211
|
"GPURunner",
|
|
211
212
|
"GPUExecutionResult",
|
|
213
|
+
"RunnerList",
|
|
212
214
|
"run_on_gpu",
|
|
213
215
|
"list_runners",
|
|
214
216
|
# Annotations
|
|
@@ -142,6 +142,12 @@ class GPUConfig:
|
|
|
142
142
|
|
|
143
143
|
def __call__(self, func: Callable) -> Callable:
|
|
144
144
|
"""Decorator usage - executes function on remote GPU."""
|
|
145
|
+
# Capture runner config at decoration time so it survives across
|
|
146
|
+
# multiple calls (the global is cleared after the first call).
|
|
147
|
+
global _current_runner_config
|
|
148
|
+
_captured_runner_config = _current_runner_config
|
|
149
|
+
_current_runner_config = None # clear here, not inside wrapper
|
|
150
|
+
|
|
145
151
|
@functools.wraps(func)
|
|
146
152
|
def wrapper(*args, **kwargs):
|
|
147
153
|
if not self.remote:
|
|
@@ -213,22 +219,20 @@ if __podstack_result__ is not None:
|
|
|
213
219
|
print(repr(__podstack_result__))
|
|
214
220
|
"""
|
|
215
221
|
|
|
216
|
-
#
|
|
217
|
-
global _current_runner_config
|
|
222
|
+
# Use the runner config captured at decoration time
|
|
218
223
|
runner_name = None
|
|
219
224
|
effective_pip = self.pip
|
|
220
225
|
effective_uv = self.uv
|
|
221
226
|
effective_conda = self.conda
|
|
222
|
-
if
|
|
223
|
-
runner_name =
|
|
227
|
+
if _captured_runner_config is not None:
|
|
228
|
+
runner_name = _captured_runner_config.get("image")
|
|
224
229
|
# Merge package lists from runner config
|
|
225
|
-
if
|
|
226
|
-
effective_pip =
|
|
227
|
-
if
|
|
228
|
-
effective_uv =
|
|
229
|
-
if
|
|
230
|
-
effective_conda =
|
|
231
|
-
_current_runner_config = None # Clear after use
|
|
230
|
+
if _captured_runner_config.get("pip") and not effective_pip:
|
|
231
|
+
effective_pip = _captured_runner_config["pip"]
|
|
232
|
+
if _captured_runner_config.get("uv") and not effective_uv:
|
|
233
|
+
effective_uv = _captured_runner_config["uv"]
|
|
234
|
+
if _captured_runner_config.get("conda") and not effective_conda:
|
|
235
|
+
effective_conda = _captured_runner_config["conda"]
|
|
232
236
|
|
|
233
237
|
# Execute on remote GPU with improved error handling
|
|
234
238
|
# Auto-enable streaming in Jupyter notebooks for real-time output
|
|
@@ -35,6 +35,33 @@ def is_jupyter() -> bool:
|
|
|
35
35
|
return False
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
class RunnerList(list):
|
|
39
|
+
"""A list of runners with a .show() method for tabular display."""
|
|
40
|
+
|
|
41
|
+
def show(self):
|
|
42
|
+
"""Print runners in a formatted table with S.NO."""
|
|
43
|
+
if not self:
|
|
44
|
+
print("No runners available.")
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
# Column widths
|
|
48
|
+
no_w = 5
|
|
49
|
+
name_w = 45
|
|
50
|
+
type_w = 6
|
|
51
|
+
desc_w = 50
|
|
52
|
+
|
|
53
|
+
header = f"{'S.NO':<{no_w}} {'Name':<{name_w}} {'Type':<{type_w}} {'Description'}"
|
|
54
|
+
print(header)
|
|
55
|
+
print("-" * (no_w + name_w + type_w + desc_w + 3))
|
|
56
|
+
for i, r in enumerate(self, 1):
|
|
57
|
+
name = r.get("name", "")
|
|
58
|
+
rtype = r.get("type", "")
|
|
59
|
+
desc = r.get("description", "")
|
|
60
|
+
if len(desc) > desc_w:
|
|
61
|
+
desc = desc[:desc_w - 3] + "..."
|
|
62
|
+
print(f"{i:<{no_w}} {name:<{name_w}} {rtype:<{type_w}} {desc}")
|
|
63
|
+
|
|
64
|
+
|
|
38
65
|
class OutputStreamer:
|
|
39
66
|
"""Handles real-time output streaming from GPU executions."""
|
|
40
67
|
|
|
@@ -184,7 +211,7 @@ class GPUExecutionResult:
|
|
|
184
211
|
output=data.get("output", ""),
|
|
185
212
|
error=data.get("error"),
|
|
186
213
|
gpu_seconds=data.get("gpu_seconds", 0.0),
|
|
187
|
-
cost_paise=data.get("actual_cost_paise", 0),
|
|
214
|
+
cost_paise=data.get("cost_cents", data.get("cost_paise", data.get("actual_cost_paise", 0))),
|
|
188
215
|
gpu_type=data.get("gpu_type", ""),
|
|
189
216
|
gpu_count=data.get("gpu_count", 1),
|
|
190
217
|
success=data.get("status") == "completed"
|
|
@@ -978,12 +1005,16 @@ _stream_install(
|
|
|
978
1005
|
# Fallback: use the same base URL
|
|
979
1006
|
return self.api_url
|
|
980
1007
|
|
|
981
|
-
def list_runners(self) ->
|
|
1008
|
+
def list_runners(self) -> RunnerList:
|
|
982
1009
|
"""
|
|
983
1010
|
List available GPU/CPU runners.
|
|
984
1011
|
|
|
985
1012
|
Returns:
|
|
986
|
-
|
|
1013
|
+
RunnerList of runner dictionaries. Call .show() for tabular display.
|
|
1014
|
+
|
|
1015
|
+
Example:
|
|
1016
|
+
podstack.list_runners().show() # Print table with S.NO
|
|
1017
|
+
runners = podstack.list_runners() # Just fetch list
|
|
987
1018
|
"""
|
|
988
1019
|
platform_url = self._get_platform_url()
|
|
989
1020
|
url = f"{platform_url}/api/v1/runners"
|
|
@@ -1004,7 +1035,7 @@ _stream_install(
|
|
|
1004
1035
|
raise RuntimeError(f"Failed to list runners: {error_msg}")
|
|
1005
1036
|
|
|
1006
1037
|
try:
|
|
1007
|
-
return response.json()
|
|
1038
|
+
return RunnerList(response.json())
|
|
1008
1039
|
except Exception:
|
|
1009
1040
|
raise RuntimeError(f"Invalid JSON response: {response.text[:200]}")
|
|
1010
1041
|
|
|
@@ -1181,17 +1212,16 @@ def run(
|
|
|
1181
1212
|
)
|
|
1182
1213
|
|
|
1183
1214
|
|
|
1184
|
-
def list_runners() ->
|
|
1215
|
+
def list_runners() -> RunnerList:
|
|
1185
1216
|
"""
|
|
1186
1217
|
List available GPU/CPU runners.
|
|
1187
1218
|
|
|
1188
1219
|
Returns:
|
|
1189
|
-
|
|
1220
|
+
RunnerList of runner dicts. Call .show() for tabular display.
|
|
1190
1221
|
|
|
1191
1222
|
Example:
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
print(f"{r['name']} ({r['type']}): {r['description']}")
|
|
1223
|
+
podstack.list_runners().show() # Print table with S.NO
|
|
1224
|
+
runners = podstack.list_runners() # Just fetch list
|
|
1195
1225
|
"""
|
|
1196
1226
|
return get_runner().list_runners()
|
|
1197
1227
|
|
|
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
|