podstack 1.3.2__tar.gz → 1.3.4__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.
Files changed (32) hide show
  1. {podstack-1.3.2 → podstack-1.3.4}/PKG-INFO +1 -1
  2. {podstack-1.3.2 → podstack-1.3.4}/podstack/annotations.py +15 -11
  3. {podstack-1.3.2 → podstack-1.3.4}/podstack/gpu_runner.py +1 -1
  4. {podstack-1.3.2 → podstack-1.3.4}/podstack/registry/experiment.py +9 -0
  5. {podstack-1.3.2 → podstack-1.3.4}/podstack.egg-info/PKG-INFO +1 -1
  6. {podstack-1.3.2 → podstack-1.3.4}/pyproject.toml +1 -1
  7. {podstack-1.3.2 → podstack-1.3.4}/LICENSE +0 -0
  8. {podstack-1.3.2 → podstack-1.3.4}/README.md +0 -0
  9. {podstack-1.3.2 → podstack-1.3.4}/podstack/__init__.py +0 -0
  10. {podstack-1.3.2 → podstack-1.3.4}/podstack/client.py +0 -0
  11. {podstack-1.3.2 → podstack-1.3.4}/podstack/exceptions.py +0 -0
  12. {podstack-1.3.2 → podstack-1.3.4}/podstack/execution.py +0 -0
  13. {podstack-1.3.2 → podstack-1.3.4}/podstack/models.py +0 -0
  14. {podstack-1.3.2 → podstack-1.3.4}/podstack/notebook.py +0 -0
  15. {podstack-1.3.2 → podstack-1.3.4}/podstack/registry/__init__.py +0 -0
  16. {podstack-1.3.2 → podstack-1.3.4}/podstack/registry/client.py +0 -0
  17. {podstack-1.3.2 → podstack-1.3.4}/podstack/registry/exceptions.py +0 -0
  18. {podstack-1.3.2 → podstack-1.3.4}/podstack/registry/model.py +0 -0
  19. {podstack-1.3.2 → podstack-1.3.4}/podstack/registry/model_utils.py +0 -0
  20. {podstack-1.3.2 → podstack-1.3.4}/podstack.egg-info/SOURCES.txt +0 -0
  21. {podstack-1.3.2 → podstack-1.3.4}/podstack.egg-info/dependency_links.txt +0 -0
  22. {podstack-1.3.2 → podstack-1.3.4}/podstack.egg-info/requires.txt +0 -0
  23. {podstack-1.3.2 → podstack-1.3.4}/podstack.egg-info/top_level.txt +0 -0
  24. {podstack-1.3.2 → podstack-1.3.4}/podstack_gpu/__init__.py +0 -0
  25. {podstack-1.3.2 → podstack-1.3.4}/podstack_gpu/app.py +0 -0
  26. {podstack-1.3.2 → podstack-1.3.4}/podstack_gpu/exceptions.py +0 -0
  27. {podstack-1.3.2 → podstack-1.3.4}/podstack_gpu/image.py +0 -0
  28. {podstack-1.3.2 → podstack-1.3.4}/podstack_gpu/runner.py +0 -0
  29. {podstack-1.3.2 → podstack-1.3.4}/podstack_gpu/secret.py +0 -0
  30. {podstack-1.3.2 → podstack-1.3.4}/podstack_gpu/utils.py +0 -0
  31. {podstack-1.3.2 → podstack-1.3.4}/podstack_gpu/volume.py +0 -0
  32. {podstack-1.3.2 → podstack-1.3.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: podstack
3
- Version: 1.3.2
3
+ Version: 1.3.4
4
4
  Summary: Official Python SDK for Podstack GPU Notebook Platform
5
5
  Author-email: Podstack <support@podstack.ai>
6
6
  License-Expression: MIT
@@ -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
- # Check for active runner config from @podstack.runner() decorator
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 _current_runner_config is not None:
223
- runner_name = _current_runner_config.get("image")
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 _current_runner_config.get("pip") and not effective_pip:
226
- effective_pip = _current_runner_config["pip"]
227
- if _current_runner_config.get("uv") and not effective_uv:
228
- effective_uv = _current_runner_config["uv"]
229
- if _current_runner_config.get("conda") and not effective_conda:
230
- effective_conda = _current_runner_config["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
@@ -211,7 +211,7 @@ class GPUExecutionResult:
211
211
  output=data.get("output", ""),
212
212
  error=data.get("error"),
213
213
  gpu_seconds=data.get("gpu_seconds", 0.0),
214
- 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))),
215
215
  gpu_type=data.get("gpu_type", ""),
216
216
  gpu_count=data.get("gpu_count", 1),
217
217
  success=data.get("status") == "completed"
@@ -197,6 +197,11 @@ class Run:
197
197
  if self._client:
198
198
  self._client.log_artifact(local_path, artifact_path)
199
199
 
200
+ def log_model(self, model, artifact_path: str = "model", framework: str = None, metadata: Dict[str, str] = None):
201
+ """Serialize and log a model for this run."""
202
+ if self._client:
203
+ self._client.log_model(model, artifact_path=artifact_path, framework=framework, metadata=metadata)
204
+
200
205
  def set_tag(self, key: str, value: str):
201
206
  """Set a tag on this run."""
202
207
  if self._client:
@@ -209,6 +214,10 @@ class Run:
209
214
  self._client.end_run(status)
210
215
  self.status = status
211
216
 
217
+ def end_run(self, status: str = "completed"):
218
+ """End this run (alias for end())."""
219
+ self.end(status)
220
+
212
221
 
213
222
  def _parse_datetime(value: Any) -> Optional[datetime]:
214
223
  """Parse a datetime from string or return None."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: podstack
3
- Version: 1.3.2
3
+ Version: 1.3.4
4
4
  Summary: Official Python SDK for Podstack GPU Notebook Platform
5
5
  Author-email: Podstack <support@podstack.ai>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "podstack"
7
- version = "1.3.2"
7
+ version = "1.3.4"
8
8
  description = "Official Python SDK for Podstack GPU Notebook Platform"
9
9
  readme = "README.md"
10
10
  license = "MIT"
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