oneshot-python 0.26.0__tar.gz → 0.27.0__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. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/PKG-INFO +1 -1
  2. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/oneshot/_errors.py +6 -0
  3. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/oneshot/client.py +9 -3
  4. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/pyproject.toml +1 -1
  5. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_payment_rejection.py +22 -0
  6. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/uv.lock +1 -1
  7. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/.gitignore +0 -0
  8. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/README.md +0 -0
  9. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/oneshot/__init__.py +0 -0
  10. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/oneshot/_types.py +0 -0
  11. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/oneshot/physical_mail.py +0 -0
  12. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/oneshot/x402.py +0 -0
  13. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/__init__.py +0 -0
  14. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_access_token.py +0 -0
  15. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_balance.py +0 -0
  16. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_browser.py +0 -0
  17. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_budgets.py +0 -0
  18. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_charge_amount.py +0 -0
  19. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_compute.py +0 -0
  20. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_domains.py +0 -0
  21. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_email_payload.py +0 -0
  22. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_emergency_error.py +0 -0
  23. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_linkedin.py +0 -0
  24. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_max_cost_header.py +0 -0
  25. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_phones_pending.py +0 -0
  26. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_physical_mail.py +0 -0
  27. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_poll_backoff.py +0 -0
  28. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_request_id.py +0 -0
  29. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_tag_receipt_value.py +0 -0
  30. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_top_up_credits.py +0 -0
  31. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_wait_false.py +0 -0
  32. {oneshot_python-0.26.0 → oneshot_python-0.27.0}/tests/test_x402.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: oneshot-python
3
- Version: 0.26.0
3
+ Version: 0.27.0
4
4
  Summary: Core Python SDK for the OneShot API — HTTP client with x402 payment handling — 43 tools
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.10
@@ -33,12 +33,18 @@ class PaymentError(OneShotError):
33
33
  expected: dict | None = None,
34
34
  received: dict | None = None,
35
35
  quote_id: str | None = None,
36
+ payment_attempt_id: str | None = None,
37
+ stage: str | None = None,
38
+ diagnostics: dict | None = None,
36
39
  ) -> None:
37
40
  super().__init__(message)
38
41
  self.reason = reason
39
42
  self.expected = expected or {}
40
43
  self.received = received or {}
41
44
  self.quote_id = quote_id
45
+ self.payment_attempt_id = payment_attempt_id
46
+ self.stage = stage
47
+ self.diagnostics = diagnostics
42
48
 
43
49
 
44
50
  class JobError(OneShotError):
@@ -56,7 +56,7 @@ try:
56
56
 
57
57
  SDK_VERSION = _pkg_version("oneshot-python")
58
58
  except Exception: # pragma: no cover - editable/source runs without dist metadata
59
- SDK_VERSION = "0.26.0"
59
+ SDK_VERSION = "0.27.0"
60
60
 
61
61
  # ---------------------------------------------------------------------------
62
62
  # Environment configuration
@@ -206,13 +206,13 @@ def _parse_payment_rejection(resp: Any) -> Optional[PaymentError]:
206
206
  payment is refused. Returns None for any other response so the caller can
207
207
  fall back to ``ToolError``.
208
208
  """
209
- if resp.status_code != 402:
209
+ if resp.status_code not in (402, 500):
210
210
  return None
211
211
  try:
212
212
  data = resp.json()
213
213
  except Exception: # noqa: BLE001 - non-JSON body
214
214
  return None
215
- if not isinstance(data, dict) or data.get("error") != "payment_verification_failed":
215
+ if not isinstance(data, dict) or data.get("error") not in ("payment_verification_failed", "payment_processing_error"):
216
216
  return None
217
217
 
218
218
  reason = data.get("reason") or "unknown"
@@ -230,6 +230,9 @@ def _parse_payment_rejection(resp: Any) -> Optional[PaymentError]:
230
230
  if data.get("message"):
231
231
  message += f" ({data['message']})"
232
232
 
233
+ if data.get("payment_attempt_id"):
234
+ message += f" [payment attempt {data['payment_attempt_id']}]"
235
+
233
236
  return PaymentError(
234
237
  message,
235
238
  reason,
@@ -241,6 +244,9 @@ def _parse_payment_rejection(resp: Any) -> Optional[PaymentError]:
241
244
  },
242
245
  received={"amount": received.get("amount")},
243
246
  quote_id=data.get("quote_id"),
247
+ payment_attempt_id=data.get("payment_attempt_id"),
248
+ stage=data.get("stage"),
249
+ diagnostics=data.get("diagnostics"),
244
250
  )
245
251
 
246
252
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "oneshot-python"
3
- version = "0.26.0"
3
+ version = "0.27.0"
4
4
  description = "Core Python SDK for the OneShot API — HTTP client with x402 payment handling — 43 tools"
5
5
  readme = {text = "Core Python SDK for the OneShot API", content-type = "text/plain"}
6
6
  license = "MIT"
@@ -86,3 +86,25 @@ class TestParsePaymentRejection:
86
86
  err = _parse_payment_rejection(_Resp(402, REJECTION))
87
87
  assert isinstance(err, OneShotError)
88
88
  assert isinstance(err, Exported)
89
+
90
+
91
+ def test_diagnostics_and_attempt_correlation():
92
+ diagnostics = {"status": "complete", "findings": [{"code": "unknown"}]}
93
+ error = _parse_payment_rejection(_Resp(402, {
94
+ **REJECTION, "payment_attempt_id": "attempt-123", "stage": "verification", "diagnostics": diagnostics,
95
+ }))
96
+ assert error.payment_attempt_id == "attempt-123"
97
+ assert "attempt-123" in str(error)
98
+ assert error.stage == "verification"
99
+ assert error.diagnostics == diagnostics
100
+ assert PaymentError("old", "unknown").diagnostics is None
101
+
102
+
103
+ def test_transport_and_settlement_correlation():
104
+ error = _parse_payment_rejection(_Resp(500, {
105
+ "error": "payment_processing_error", "payment_attempt_id": "transport-123", "stage": "verification_transport",
106
+ }))
107
+ assert error.payment_attempt_id == "transport-123"
108
+ assert error.stage == "verification_transport"
109
+ error = _parse_payment_rejection(_Resp(402, {**REJECTION, "stage": "settlement"}))
110
+ assert error.stage == "settlement"
@@ -549,7 +549,7 @@ wheels = [
549
549
 
550
550
  [[package]]
551
551
  name = "oneshot-python"
552
- version = "0.24.0"
552
+ version = "0.27.0"
553
553
  source = { editable = "." }
554
554
  dependencies = [
555
555
  { name = "eth-account" },