drukbox-python-sdk 0.3.0__py3-none-any.whl → 0.4.0__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: drukbox-python-sdk
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: Async Python client for Drukbox.
5
5
  Project-URL: Homepage, https://github.com/clawhaven/drukbox-python-sdk
6
6
  Project-URL: Repository, https://github.com/clawhaven/drukbox-python-sdk
@@ -59,6 +59,8 @@ finally:
59
59
  few minutes worst case. The SDK's default `timeout` (300s) covers this. Pass
60
60
  an `idempotency_key` for retry safety: a retry with the same key after a
61
61
  successful provision returns the original host instead of creating a duplicate.
62
+ A provider at its host limit raises `SandboxCapacityError`, a
63
+ `SandboxUnavailableError` whose `retry_after` gives the seconds to wait.
62
64
 
63
65
  `SandboxAPI.from_env(prefix="SANDBOX_")` reads
64
66
  `SANDBOX_SERVICE_URL`, `SANDBOX_SERVICE_TOKEN`, and optional
@@ -0,0 +1,7 @@
1
+ drukbox_sdk/__init__.py,sha256=OgssAANGnl49_1N_EKMXSDlgWfedO9jUAnLVxgkJY2Q,1066
2
+ drukbox_sdk/api.py,sha256=Xd_UhCYsE_kRojDEBIacHGHrOB2msDHfrE1WfOBbOBc,24501
3
+ drukbox_sdk/exceptions.py,sha256=0CKbb0Ec4RSWPB8t31WJgO1yQQ10BwTPqoqS1_EieB4,2599
4
+ drukbox_python_sdk-0.4.0.dist-info/METADATA,sha256=kFilTF-v_ongltIWRUJrc1TLboG29gWCLCwABTPTmGo,6734
5
+ drukbox_python_sdk-0.4.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
6
+ drukbox_python_sdk-0.4.0.dist-info/licenses/LICENSE,sha256=zM66rWL3BWGJBa_mZPnM0WUomSSZ1xtWVtGQovQ71M8,1078
7
+ drukbox_python_sdk-0.4.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.32.0
2
+ Generator: hatchling 1.32.4
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
drukbox_sdk/__init__.py CHANGED
@@ -19,6 +19,7 @@ from .api import (
19
19
  from .exceptions import (
20
20
  SandboxAPIError,
21
21
  SandboxAuthError,
22
+ SandboxCapacityError,
22
23
  SandboxConflictError,
23
24
  SandboxNotFoundError,
24
25
  SandboxProvisioningError,
@@ -36,6 +37,7 @@ __all__ = [
36
37
  "SandboxAPI",
37
38
  "SandboxAPIError",
38
39
  "SandboxAuthError",
40
+ "SandboxCapacityError",
39
41
  "SandboxConflictError",
40
42
  "SandboxHost",
41
43
  "SandboxNotFoundError",
drukbox_sdk/api.py CHANGED
@@ -47,6 +47,7 @@ import httpx
47
47
 
48
48
  from .exceptions import (
49
49
  SandboxAuthError,
50
+ SandboxCapacityError,
50
51
  SandboxConflictError,
51
52
  SandboxNotFoundError,
52
53
  SandboxProvisioningError,
@@ -435,14 +436,15 @@ class SandboxAPI:
435
436
  base_image: str | None = None,
436
437
  label: str | None = None,
437
438
  ) -> SandboxTemplate:
438
- """Start a template build and return immediately.
439
-
440
- The service responds 202 with ``status="building"``. Poll
441
- :meth:`get_template` until the status becomes ``"available"`` or
442
- ``"failed"``. A failed record carries the reason in
443
- ``last_error``. A repeated post with the same provider, base
444
- image, and setup script returns the existing record without a
445
- rebuild.
439
+ """Start a template build.
440
+
441
+ The service pulls the base image, then responds 202 with
442
+ ``status="building"``. Poll :meth:`get_template` until the status
443
+ becomes ``"available"`` or ``"failed"``. A failed record carries the
444
+ reason in ``last_error``. A repeated post with the same provider,
445
+ base image digest, and setup script returns the existing record. A
446
+ ``"failed"`` record builds again and keeps its ``last_error`` until
447
+ that build ends.
446
448
  """
447
449
 
448
450
  payload: dict[str, Any] = {"setup_script": setup_script}
@@ -614,6 +616,11 @@ class SandboxAPI:
614
616
  raise SandboxProvisioningError(json_response.get("detail", "provisioning failed"))
615
617
 
616
618
  if response.status_code == 503:
619
+ if json_response.get("error_code") == "CAPACITY":
620
+ raise SandboxCapacityError(
621
+ json_response.get("detail", "provider at host limit"),
622
+ retry_after=int(response.headers["Retry-After"]),
623
+ )
617
624
  raise SandboxUnavailableError(json_response.get("detail", "service unavailable"))
618
625
 
619
626
  if response.status_code == 422:
drukbox_sdk/exceptions.py CHANGED
@@ -18,6 +18,18 @@ class SandboxUnavailableError(RuntimeError):
18
18
  """
19
19
 
20
20
 
21
+ class SandboxCapacityError(SandboxUnavailableError):
22
+ """503 — the provider is at its host limit.
23
+
24
+ ``retry_after`` is the service's ``Retry-After`` value in seconds:
25
+ wait at least that long before the next create.
26
+ """
27
+
28
+ def __init__(self, message: str, retry_after: int) -> None:
29
+ super().__init__(message)
30
+ self.retry_after = retry_after
31
+
32
+
21
33
  class SandboxAPIError(RuntimeError):
22
34
  """Base for any error the sandbox service returned via HTTP."""
23
35
 
@@ -1,7 +0,0 @@
1
- drukbox_sdk/__init__.py,sha256=bU2rOTzC3GMXSpiXvoMVwFOuKJUPZWSXhnteaRFxT_Y,1012
2
- drukbox_sdk/api.py,sha256=eoXXnK8mkrSK9Q4tRSuVbN-6mSjbBTTeEsH_jF3U_wY,24118
3
- drukbox_sdk/exceptions.py,sha256=Vzs4zVOywWsWfiZm6vgQ65ScI3Nn7zLGVj-8eT1YAR0,2224
4
- drukbox_python_sdk-0.3.0.dist-info/METADATA,sha256=KL-_BzJPSEVgimNohBs8BIxhwcU8dreFTdVSihBlUaI,6599
5
- drukbox_python_sdk-0.3.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
6
- drukbox_python_sdk-0.3.0.dist-info/licenses/LICENSE,sha256=zM66rWL3BWGJBa_mZPnM0WUomSSZ1xtWVtGQovQ71M8,1078
7
- drukbox_python_sdk-0.3.0.dist-info/RECORD,,