podstack 1.3.17__tar.gz → 1.3.18__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 (33) hide show
  1. {podstack-1.3.17 → podstack-1.3.18}/PKG-INFO +1 -1
  2. {podstack-1.3.17 → podstack-1.3.18}/podstack/annotations.py +6 -0
  3. {podstack-1.3.17 → podstack-1.3.18}/podstack/gpu_runner.py +10 -1
  4. {podstack-1.3.17 → podstack-1.3.18}/podstack/registry/__init__.py +17 -3
  5. {podstack-1.3.17 → podstack-1.3.18}/podstack/registry/client.py +30 -7
  6. {podstack-1.3.17 → podstack-1.3.18}/podstack.egg-info/PKG-INFO +1 -1
  7. {podstack-1.3.17 → podstack-1.3.18}/pyproject.toml +1 -1
  8. {podstack-1.3.17 → podstack-1.3.18}/LICENSE +0 -0
  9. {podstack-1.3.17 → podstack-1.3.18}/README.md +0 -0
  10. {podstack-1.3.17 → podstack-1.3.18}/podstack/__init__.py +0 -0
  11. {podstack-1.3.17 → podstack-1.3.18}/podstack/client.py +0 -0
  12. {podstack-1.3.17 → podstack-1.3.18}/podstack/exceptions.py +0 -0
  13. {podstack-1.3.17 → podstack-1.3.18}/podstack/execution.py +0 -0
  14. {podstack-1.3.17 → podstack-1.3.18}/podstack/models.py +0 -0
  15. {podstack-1.3.17 → podstack-1.3.18}/podstack/notebook.py +0 -0
  16. {podstack-1.3.17 → podstack-1.3.18}/podstack/registry/autolog.py +0 -0
  17. {podstack-1.3.17 → podstack-1.3.18}/podstack/registry/exceptions.py +0 -0
  18. {podstack-1.3.17 → podstack-1.3.18}/podstack/registry/experiment.py +0 -0
  19. {podstack-1.3.17 → podstack-1.3.18}/podstack/registry/model.py +0 -0
  20. {podstack-1.3.17 → podstack-1.3.18}/podstack/registry/model_utils.py +0 -0
  21. {podstack-1.3.17 → podstack-1.3.18}/podstack.egg-info/SOURCES.txt +0 -0
  22. {podstack-1.3.17 → podstack-1.3.18}/podstack.egg-info/dependency_links.txt +0 -0
  23. {podstack-1.3.17 → podstack-1.3.18}/podstack.egg-info/requires.txt +0 -0
  24. {podstack-1.3.17 → podstack-1.3.18}/podstack.egg-info/top_level.txt +0 -0
  25. {podstack-1.3.17 → podstack-1.3.18}/podstack_gpu/__init__.py +0 -0
  26. {podstack-1.3.17 → podstack-1.3.18}/podstack_gpu/app.py +0 -0
  27. {podstack-1.3.17 → podstack-1.3.18}/podstack_gpu/exceptions.py +0 -0
  28. {podstack-1.3.17 → podstack-1.3.18}/podstack_gpu/image.py +0 -0
  29. {podstack-1.3.17 → podstack-1.3.18}/podstack_gpu/runner.py +0 -0
  30. {podstack-1.3.17 → podstack-1.3.18}/podstack_gpu/secret.py +0 -0
  31. {podstack-1.3.17 → podstack-1.3.18}/podstack_gpu/utils.py +0 -0
  32. {podstack-1.3.17 → podstack-1.3.18}/podstack_gpu/volume.py +0 -0
  33. {podstack-1.3.17 → podstack-1.3.18}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: podstack
3
- Version: 1.3.17
3
+ Version: 1.3.18
4
4
  Summary: Official Python SDK for Podstack GPU Notebook Platform
5
5
  Author-email: Podstack <support@podstack.ai>
6
6
  License-Expression: MIT
@@ -90,6 +90,7 @@ class GPUConfig:
90
90
  conda: Union[str, list] = None,
91
91
  requirements: str = None,
92
92
  use_uv: bool = False,
93
+ env_vars: Optional[Dict[str, str]] = None,
93
94
  remote: bool = None
94
95
  ):
95
96
  """
@@ -121,6 +122,7 @@ class GPUConfig:
121
122
  self.conda = conda
122
123
  self.requirements = requirements
123
124
  self.use_uv = use_uv
125
+ self.env_vars = env_vars or {}
124
126
  self.remote = remote if remote is not None else _remote_execution_enabled
125
127
 
126
128
  # Store in global config
@@ -138,6 +140,7 @@ class GPUConfig:
138
140
  "conda": conda,
139
141
  "requirements": requirements,
140
142
  "use_uv": use_uv,
143
+ "env_vars": env_vars or {},
141
144
  }
142
145
 
143
146
  def __call__(self, func: Callable) -> Callable:
@@ -249,6 +252,7 @@ if __podstack_result__ is not None:
249
252
  conda=effective_conda,
250
253
  requirements=self.requirements,
251
254
  use_uv=self.use_uv,
255
+ env_vars=self.env_vars,
252
256
  runner=runner_name,
253
257
  wait=True,
254
258
  stream=None # Auto-detect: True in Jupyter, False otherwise
@@ -340,6 +344,7 @@ def gpu(
340
344
  conda: Union[str, list] = None,
341
345
  requirements: str = None,
342
346
  use_uv: bool = False,
347
+ env_vars: Optional[Dict[str, str]] = None,
343
348
  remote: bool = None
344
349
  ) -> GPUConfig:
345
350
  """
@@ -421,6 +426,7 @@ def gpu(
421
426
  conda=conda,
422
427
  requirements=requirements,
423
428
  use_uv=use_uv,
429
+ env_vars=env_vars,
424
430
  remote=remote
425
431
  )
426
432
 
@@ -361,6 +361,7 @@ class GPURunner:
361
361
  conda: Union[str, list] = None,
362
362
  requirements: str = None,
363
363
  use_uv: bool = False,
364
+ env_vars: Dict[str, str] = None,
364
365
  add_annotation: bool = True,
365
366
  runner: str = None
366
367
  ) -> Dict[str, Any]:
@@ -395,6 +396,13 @@ class GPURunner:
395
396
  annotation = self._build_annotation(gpu, count, fraction, timeout, env, pip, uv, conda, requirements, use_uv, runner)
396
397
  code = f"{annotation}\n\n{code}"
397
398
 
399
+ # Inject environment variables
400
+ if env_vars:
401
+ env_lines = ["import os"]
402
+ for k, v in env_vars.items():
403
+ env_lines.append(f"os.environ[{repr(k)}] = {repr(str(v))}")
404
+ code = "\n".join(env_lines) + "\n\n" + code
405
+
398
406
  # Build installation code for packages
399
407
  install_parts = []
400
408
 
@@ -672,6 +680,7 @@ _stream_install(
672
680
  conda: Union[str, list] = None,
673
681
  requirements: str = None,
674
682
  use_uv: bool = False,
683
+ env_vars: Dict[str, str] = None,
675
684
  wait: bool = True,
676
685
  poll_interval: float = 2.0,
677
686
  max_retries: int = 3,
@@ -713,7 +722,7 @@ _stream_install(
713
722
  ValueError: If parameters are invalid
714
723
  """
715
724
  # Submit the code
716
- submission = self.submit(code, gpu, count, fraction, timeout, env, pip, uv, conda, requirements, use_uv, runner=runner)
725
+ submission = self.submit(code, gpu, count, fraction, timeout, env, pip, uv, conda, requirements, use_uv, env_vars=env_vars, runner=runner)
717
726
  execution_id = submission.get("execution_id")
718
727
 
719
728
  if not execution_id:
@@ -558,9 +558,23 @@ def create_trial(sweep_id: str, run_id: str, params: dict) -> dict:
558
558
  return _get_client().create_trial(sweep_id, run_id, params)
559
559
 
560
560
 
561
- def complete_trial(sweep_id: str, trial_id: str, value: float) -> None:
562
- """Mark a trial as completed with its objective metric value."""
563
- _get_client().complete_trial(sweep_id, trial_id, value)
561
+ def complete_trial(
562
+ sweep_id: str,
563
+ trial_id: str,
564
+ value: float = None,
565
+ metrics: dict = None,
566
+ run_id: str = None,
567
+ ) -> None:
568
+ """Mark a trial as completed with its objective metric value.
569
+
570
+ Args:
571
+ sweep_id: Sweep ID.
572
+ trial_id: Trial ID (from suggest_trial_params).
573
+ value: Scalar objective value.
574
+ metrics: Dict of metric name → value; first entry used if value not set.
575
+ run_id: Optional run ID to link to this trial.
576
+ """
577
+ _get_client().complete_trial(sweep_id, trial_id, value, metrics, run_id)
564
578
 
565
579
 
566
580
  def list_trials(sweep_id: str) -> list:
@@ -1372,9 +1372,12 @@ class RegistryClient:
1372
1372
  return data.get("sweeps", [])
1373
1373
 
1374
1374
  def suggest_trial_params(self, sweep_id: str) -> Dict[str, Any]:
1375
- """Get suggested hyperparameter values for the next trial."""
1375
+ """Get suggested hyperparameter values for the next trial.
1376
+
1377
+ Returns a dict with ``id`` (trial ID) and ``params`` (hyperparameter map).
1378
+ """
1376
1379
  data = self._request("GET", f"/sweeps/{sweep_id}/suggest")
1377
- return data.get("params", data)
1380
+ return data.get("trial", data)
1378
1381
 
1379
1382
  def create_trial(
1380
1383
  self,
@@ -1389,11 +1392,31 @@ class RegistryClient:
1389
1392
  })
1390
1393
  return data.get("trial", data)
1391
1394
 
1392
- def complete_trial(self, sweep_id: str, trial_id: str, value: float) -> None:
1393
- """Mark a trial as completed with its objective metric value."""
1394
- self._request("POST", f"/sweeps/{sweep_id}/trials/{trial_id}/complete", json={
1395
- "value": value
1396
- })
1395
+ def complete_trial(
1396
+ self,
1397
+ sweep_id: str,
1398
+ trial_id: str,
1399
+ value: float = None,
1400
+ metrics: Dict[str, float] = None,
1401
+ run_id: str = None,
1402
+ ) -> None:
1403
+ """Mark a trial as completed with its objective metric value.
1404
+
1405
+ Args:
1406
+ sweep_id: Sweep ID.
1407
+ trial_id: Trial ID (from suggest_trial_params).
1408
+ value: Scalar objective value.
1409
+ metrics: Dict of metric name → value; first entry used if value not set.
1410
+ run_id: Optional run ID to link to this trial.
1411
+ """
1412
+ body: Dict[str, Any] = {}
1413
+ if value is not None:
1414
+ body["value"] = value
1415
+ if metrics:
1416
+ body["metrics"] = metrics
1417
+ if run_id:
1418
+ body["run_id"] = run_id
1419
+ self._request("POST", f"/sweeps/{sweep_id}/trials/{trial_id}/complete", json=body)
1397
1420
 
1398
1421
  def list_trials(self, sweep_id: str) -> List[Dict[str, Any]]:
1399
1422
  """List all trials for a sweep."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: podstack
3
- Version: 1.3.17
3
+ Version: 1.3.18
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.17"
7
+ version = "1.3.18"
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