celitech-sdk 2.0.6__tar.gz → 2.0.7__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 (84) hide show
  1. {celitech_sdk-2.0.6/src/celitech_sdk.egg-info → celitech_sdk-2.0.7}/PKG-INFO +5 -5
  2. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/PyPI_README.md +4 -4
  3. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/README.md +4 -4
  4. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/pyproject.toml +1 -1
  5. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/request_chain/handlers/http_handler.py +3 -3
  6. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/request_chain/handlers/retry_handler.py +98 -5
  7. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/sdk_config.py +4 -2
  8. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/transport/serializer.py +1 -1
  9. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/sdk.py +33 -3
  10. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/sdk_async.py +8 -1
  11. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/utils/base_service.py +16 -4
  12. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7/src/celitech_sdk.egg-info}/PKG-INFO +5 -5
  13. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/LICENSE +0 -0
  14. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/setup.cfg +0 -0
  15. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/__init__.py +0 -0
  16. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/__init__.py +0 -0
  17. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/bad_request.py +0 -0
  18. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/create_purchase_ok_response.py +0 -0
  19. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/create_purchase_request.py +0 -0
  20. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/create_purchase_v2_ok_response.py +0 -0
  21. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/create_purchase_v2_request.py +0 -0
  22. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/edit_purchase_ok_response.py +0 -0
  23. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/edit_purchase_request.py +0 -0
  24. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/get_esim_device_ok_response.py +0 -0
  25. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/get_esim_history_ok_response.py +0 -0
  26. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/get_esim_ok_response.py +0 -0
  27. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/get_purchase_consumption_ok_response.py +0 -0
  28. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/grant_type.py +0 -0
  29. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/list_destinations_ok_response.py +0 -0
  30. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/list_packages_ok_response.py +0 -0
  31. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/list_purchases_ok_response.py +0 -0
  32. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/o_auth_token_request.py +0 -0
  33. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/o_auth_token_response.py +0 -0
  34. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/token_ok_response.py +0 -0
  35. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/top_up_esim_ok_response.py +0 -0
  36. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/top_up_esim_request.py +0 -0
  37. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/unauthorized.py +0 -0
  38. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/utils/__init__.py +0 -0
  39. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/utils/base_error.py +0 -0
  40. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/utils/base_model.py +0 -0
  41. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/utils/cast_models.py +0 -0
  42. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/utils/json_map.py +0 -0
  43. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/utils/one_of_base_model.py +0 -0
  44. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/models/utils/sentinel.py +0 -0
  45. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/__init__.py +0 -0
  46. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/environment/__init__.py +0 -0
  47. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/environment/environment.py +0 -0
  48. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/headers/__init__.py +0 -0
  49. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/headers/base_header.py +0 -0
  50. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/oauth/token_manager.py +0 -0
  51. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/request_chain/__init__.py +0 -0
  52. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/request_chain/handlers/__init__.py +0 -0
  53. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/request_chain/handlers/base_handler.py +0 -0
  54. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/request_chain/handlers/oauth_handler.py +0 -0
  55. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/request_chain/request_chain.py +0 -0
  56. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/transport/__init__.py +0 -0
  57. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/transport/api_error.py +0 -0
  58. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/transport/request.py +0 -0
  59. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/transport/request_error.py +0 -0
  60. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/transport/response.py +0 -0
  61. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/net/transport/utils.py +0 -0
  62. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/__init__.py +0 -0
  63. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/async_/__init__.py +0 -0
  64. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/async_/destinations.py +0 -0
  65. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/async_/e_sim.py +0 -0
  66. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/async_/i_frame.py +0 -0
  67. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/async_/o_auth.py +0 -0
  68. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/async_/packages.py +0 -0
  69. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/async_/purchases.py +0 -0
  70. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/async_/utils/__init__.py +0 -0
  71. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/async_/utils/to_async.py +0 -0
  72. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/destinations.py +0 -0
  73. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/e_sim.py +0 -0
  74. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/i_frame.py +0 -0
  75. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/o_auth.py +0 -0
  76. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/packages.py +0 -0
  77. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/purchases.py +0 -0
  78. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/utils/__init__.py +0 -0
  79. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/utils/default_headers.py +0 -0
  80. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech/services/utils/validator.py +0 -0
  81. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech_sdk.egg-info/SOURCES.txt +0 -0
  82. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech_sdk.egg-info/dependency_links.txt +0 -0
  83. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech_sdk.egg-info/requires.txt +0 -0
  84. {celitech_sdk-2.0.6 → celitech_sdk-2.0.7}/src/celitech_sdk.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: celitech-sdk
3
- Version: 2.0.6
3
+ Version: 2.0.7
4
4
  Summary: Welcome to the CELITECH API documentation!
5
5
  License: MIT
6
6
  Project-URL: Repository, https://github.com/Celitech/CelitechSDKPython
@@ -11,14 +11,14 @@ Requires-Dist: requests>=2.31.0
11
11
  Requires-Dist: pydantic<3.0.0,>=2.0.0
12
12
  Dynamic: license-file
13
13
 
14
- # Celitech Python SDK 2.0.6<a id="celitech-python-sdk-206"></a>
14
+ # Celitech Python SDK 2.0.7<a id="celitech-python-sdk-207"></a>
15
15
 
16
16
  Welcome to the Celitech SDK documentation. This guide will help you get started with integrating and using the Celitech SDK in your project.
17
17
 
18
18
  ## Versions<a id="versions"></a>
19
19
 
20
- - API version: `2.0.6`
21
- - SDK version: `2.0.6`
20
+ - API version: `2.0.7`
21
+ - SDK version: `2.0.7`
22
22
 
23
23
  ## About the API<a id="about-the-api"></a>
24
24
 
@@ -102,7 +102,7 @@ You can set a custom timeout for the SDK's HTTP requests as follows:
102
102
  ```py
103
103
  from celitech import Celitech
104
104
 
105
- sdk = Celitech(timeout=10000)
105
+ sdk = Celitech(timeout=10)
106
106
  ```
107
107
 
108
108
  # Sample Usage<a id="sample-usage"></a>
@@ -1,11 +1,11 @@
1
- # Celitech Python SDK 2.0.6<a id="celitech-python-sdk-206"></a>
1
+ # Celitech Python SDK 2.0.7<a id="celitech-python-sdk-207"></a>
2
2
 
3
3
  Welcome to the Celitech SDK documentation. This guide will help you get started with integrating and using the Celitech SDK in your project.
4
4
 
5
5
  ## Versions<a id="versions"></a>
6
6
 
7
- - API version: `2.0.6`
8
- - SDK version: `2.0.6`
7
+ - API version: `2.0.7`
8
+ - SDK version: `2.0.7`
9
9
 
10
10
  ## About the API<a id="about-the-api"></a>
11
11
 
@@ -89,7 +89,7 @@ You can set a custom timeout for the SDK's HTTP requests as follows:
89
89
  ```py
90
90
  from celitech import Celitech
91
91
 
92
- sdk = Celitech(timeout=10000)
92
+ sdk = Celitech(timeout=10)
93
93
  ```
94
94
 
95
95
  # Sample Usage<a id="sample-usage"></a>
@@ -1,11 +1,11 @@
1
- # Celitech Python SDK 2.0.6
1
+ # Celitech Python SDK 2.0.7
2
2
 
3
3
  Welcome to the Celitech SDK documentation. This guide will help you get started with integrating and using the Celitech SDK in your project.
4
4
 
5
5
  ## Versions
6
6
 
7
- - API version: `2.0.6`
8
- - SDK version: `2.0.6`
7
+ - API version: `2.0.7`
8
+ - SDK version: `2.0.7`
9
9
 
10
10
  ## About the API
11
11
 
@@ -90,7 +90,7 @@ You can set a custom timeout for the SDK's HTTP requests as follows:
90
90
  ```py
91
91
  from celitech import Celitech
92
92
 
93
- sdk = Celitech(timeout=10000)
93
+ sdk = Celitech(timeout=10)
94
94
  ```
95
95
 
96
96
  # Sample Usage
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "celitech-sdk"
7
- version = "2.0.6"
7
+ version = "2.0.7"
8
8
  license = { text = "MIT" }
9
9
  description = """Welcome to the CELITECH API documentation!\n\nUseful links: [Homepage](https://www.celitech.com) | [Support email](mailto:support@celitech.com) | [Blog](https://www.celitech.com/blog/)\n"""
10
10
  readme = "PyPI_README.md"
@@ -17,12 +17,12 @@ class HttpHandler(BaseHandler):
17
17
  :ivar int _timeout_in_seconds: The timeout for the HTTP request in seconds.
18
18
  """
19
19
 
20
- def __init__(self, timeout=60000):
20
+ def __init__(self, timeout=60):
21
21
  """
22
22
  Initialize a new instance of HttpHandler.
23
23
  """
24
24
  super().__init__()
25
- self._timeout_in_seconds = timeout / 1000
25
+ self._timeout_in_seconds = timeout
26
26
 
27
27
  def handle(
28
28
  self, request: Request
@@ -191,5 +191,5 @@ class HttpHandler(BaseHandler):
191
191
  :rtype: float
192
192
  """
193
193
  if request.config and "timeout" in request.config:
194
- return request.config["timeout"] / 1000
194
+ return request.config["timeout"]
195
195
  return self._timeout_in_seconds
@@ -1,5 +1,8 @@
1
1
  import random
2
+ import re
2
3
 
4
+ from datetime import datetime, timezone
5
+ from email.utils import parsedate_to_datetime
3
6
  from typing import Generator, Optional, Tuple
4
7
  from time import sleep
5
8
  from .base_handler import BaseHandler
@@ -31,6 +34,7 @@ class RetryHandler(BaseHandler):
31
34
  self._max_attempts = 3
32
35
  self._delay_in_milliseconds = 150
33
36
  self._max_delay_in_milliseconds = 5000
37
+ self._max_retry_after_delay_in_milliseconds = 60000
34
38
  self._backoff_factor = 2
35
39
  self._jitter_in_milliseconds = 50
36
40
  self._status_codes_to_retry = None
@@ -62,7 +66,7 @@ class RetryHandler(BaseHandler):
62
66
 
63
67
  try_count = 0
64
68
  while try_count < max_attempts and self._should_retry(error, request):
65
- self._delay(try_count, request)
69
+ self._delay(try_count, request, error)
66
70
  response, error = self._next_handler.handle(request)
67
71
  try_count += 1
68
72
 
@@ -92,7 +96,7 @@ class RetryHandler(BaseHandler):
92
96
  while True:
93
97
  response, error = next(stream)
94
98
  if try_count < max_attempts and self._should_retry(error, request):
95
- self._delay(try_count, request)
99
+ self._delay(try_count, request, error)
96
100
  try_count += 1
97
101
  stream = self._next_handler.stream(request) # Retry the request
98
102
  elif try_count >= max_attempts:
@@ -104,16 +108,29 @@ class RetryHandler(BaseHandler):
104
108
  except StopIteration:
105
109
  pass
106
110
 
107
- def _delay(self, try_count: int, request: Request) -> None:
111
+ def _delay(
112
+ self, try_count: int, request: Request, error: Optional[ApiError] = None
113
+ ) -> None:
108
114
  """
109
- Calculate and apply delay before next retry attempt using exponential backoff.
110
- Delay is capped at maximum delay and optional jitter is added.
115
+ Calculate and apply delay before next retry attempt.
116
+ A server rate-limit timing header (Retry-After / X-RateLimit-Reset) on the error,
117
+ when present, overrides the computed exponential backoff; otherwise exponential
118
+ backoff (capped at max delay, with optional jitter) is used.
111
119
  Per-request retry config overrides SDK defaults.
112
120
 
113
121
  :param int try_count: Current retry attempt number (0-indexed).
114
122
  :param Request request: The request being retried, used to read per-request retry config.
123
+ :param Optional[ApiError] error: The error that triggered the retry (carries headers).
115
124
  """
116
125
  retry_config = (request.config or {}).get("retry") or {}
126
+ max_retry_after = retry_config.get(
127
+ "max_retry_after_delay_ms", self._max_retry_after_delay_in_milliseconds
128
+ )
129
+ header_delay_ms = self._retry_after_delay(error, max_retry_after)
130
+ if header_delay_ms is not None:
131
+ sleep(header_delay_ms / 1000)
132
+ return
133
+
117
134
  base_delay = retry_config.get("delay_ms", self._delay_in_milliseconds)
118
135
  max_delay = retry_config.get("max_delay_ms", self._max_delay_in_milliseconds)
119
136
  backoff_factor = retry_config.get("backoff_factor", self._backoff_factor)
@@ -132,6 +149,82 @@ class RetryHandler(BaseHandler):
132
149
  # Convert to seconds and sleep
133
150
  sleep(delay / 1000)
134
151
 
152
+ def _retry_after_delay(
153
+ self, error: Optional[ApiError], max_retry_after_ms: float
154
+ ) -> Optional[float]:
155
+ """
156
+ Return the server-directed retry delay (in milliseconds) from rate-limit response
157
+ headers, honoring Retry-After (delta-seconds or HTTP-date) and, when absent,
158
+ X-RateLimit-Reset (epoch seconds), clamped to max_retry_after_ms. Returns None when
159
+ no usable header is present so the caller falls back to exponential backoff.
160
+
161
+ :param Optional[ApiError] error: The error that triggered the retry.
162
+ :param float max_retry_after_ms: Upper bound for a server-directed delay.
163
+ :return: The delay in milliseconds, or None to use exponential backoff.
164
+ :rtype: Optional[float]
165
+ """
166
+ headers = getattr(getattr(error, "response", None), "headers", None)
167
+ if headers is None or max_retry_after_ms <= 0:
168
+ return None
169
+
170
+ # retry-after-ms (milliseconds) is a non-standard but finer-grained hint some APIs
171
+ # send (e.g. OpenAI); it takes precedence over the whole-second Retry-After.
172
+ retry_after_ms = headers.get("retry-after-ms")
173
+ if retry_after_ms is not None and re.fullmatch(
174
+ r"\d+(\.\d+)?", str(retry_after_ms).strip()
175
+ ):
176
+ return min(float(str(retry_after_ms).strip()), max_retry_after_ms)
177
+
178
+ seconds = self._parse_retry_after(headers.get("Retry-After"))
179
+ if seconds is not None:
180
+ return min(max(seconds * 1000, 0), max_retry_after_ms)
181
+
182
+ # X-RateLimit-Reset is interpreted as epoch seconds (the common convention).
183
+ reset = headers.get("X-RateLimit-Reset")
184
+ if reset is not None and str(reset).strip() != "":
185
+ try:
186
+ epoch = float(reset)
187
+ except (TypeError, ValueError):
188
+ epoch = None
189
+ if epoch is not None:
190
+ delta_ms = epoch * 1000 - datetime.now(timezone.utc).timestamp() * 1000
191
+ if delta_ms > 0:
192
+ return min(delta_ms, max_retry_after_ms)
193
+
194
+ return None
195
+
196
+ def _parse_retry_after(self, value: Optional[str]) -> Optional[float]:
197
+ """
198
+ Parse a Retry-After header value: an integer/float number of seconds, or an
199
+ HTTP-date (a past date yields 0). Returns the delay in seconds, or None if the
200
+ value is empty or unparseable.
201
+
202
+ :param Optional[str] value: The raw Retry-After header value.
203
+ :return: The delay in seconds, or None.
204
+ :rtype: Optional[float]
205
+ """
206
+ if value is None:
207
+ return None
208
+ trimmed = str(value).strip()
209
+ if trimmed == "":
210
+ return None
211
+ if re.fullmatch(r"\d+(\.\d+)?", trimmed):
212
+ return float(trimmed)
213
+ # Parsing and the timestamp math both run under the guard: a pathological but
214
+ # well-formed HTTP-date (e.g. year 9999) can raise OverflowError/OSError from
215
+ # timestamp(), and a malformed value can raise beyond TypeError/ValueError. A bad
216
+ # server header must never crash the retry layer, so treat any failure as "no delay".
217
+ try:
218
+ parsed = parsedate_to_datetime(trimmed)
219
+ if parsed is None:
220
+ return None
221
+ if parsed.tzinfo is None:
222
+ parsed = parsed.replace(tzinfo=timezone.utc)
223
+ delta = parsed.timestamp() - datetime.now(timezone.utc).timestamp()
224
+ except (TypeError, ValueError, OverflowError, OSError):
225
+ return None
226
+ return delta if delta > 0 else 0.0
227
+
135
228
  def _should_retry(self, error: Optional[ApiError], request: Request) -> bool:
136
229
  """
137
230
  Determine whether the request should be retried based on status code and HTTP method.
@@ -14,6 +14,7 @@ class RetryConfig(TypedDict, total=False):
14
14
  :ivar int jitter_ms: Maximum random jitter in milliseconds to add to retry delays.
15
15
  :ivar list[int] status_codes_to_retry: Specific HTTP status codes to retry (overrides default 5xx + 408, 429).
16
16
  :ivar list[str] http_methods_to_retry: HTTP methods to retry (e.g., ['GET', 'POST']).
17
+ :ivar int max_retry_after_delay_ms: Upper bound (ms) for a server-directed retry delay parsed from Retry-After / X-RateLimit-Reset response headers.
17
18
  """
18
19
 
19
20
  attempts: int
@@ -23,6 +24,7 @@ class RetryConfig(TypedDict, total=False):
23
24
  jitter_ms: int
24
25
  status_codes_to_retry: list[int]
25
26
  http_methods_to_retry: list[str]
27
+ max_retry_after_delay_ms: int
26
28
 
27
29
 
28
30
  class ValidationConfig(TypedDict, total=False):
@@ -47,7 +49,7 @@ class SdkConfig(TypedDict, total=False):
47
49
 
48
50
  :ivar str base_url: Base URL for API requests. Can be a string URL or Environment enum.
49
51
  :ivar Environment environment: Environment enum value for base URL.
50
- :ivar int timeout: Request timeout in milliseconds.
52
+ :ivar float timeout: Request timeout in seconds.
51
53
  :ivar str client_id: OAuth client ID.
52
54
  :ivar str client_secret: OAuth client secret.
53
55
  :ivar RetryConfig retry: Retry configuration.
@@ -56,7 +58,7 @@ class SdkConfig(TypedDict, total=False):
56
58
 
57
59
  base_url: str
58
60
  environment: Environment
59
- timeout: int
61
+ timeout: float
60
62
  client_id: str
61
63
  client_secret: str
62
64
  retry: RetryConfig
@@ -45,7 +45,7 @@ class Serializer:
45
45
  self.errors: dict[int, ApiError] = {}
46
46
  self.config: Optional["SdkConfig"] = config
47
47
 
48
- self.headers["User-Agent"] = "postman-codegen/1.7.0 celitech-sdk/2.0.6 (python)"
48
+ self.headers["User-Agent"] = "postman-codegen/2.6.0 celitech-sdk/2.0.7 (python)"
49
49
 
50
50
  # Apply default headers
51
51
  for header in default_headers:
@@ -1,3 +1,4 @@
1
+ import warnings
1
2
  from typing import Union
2
3
  from .services.destinations import DestinationsService
3
4
  from .services.packages import PackagesService
@@ -17,10 +18,13 @@ class Celitech:
17
18
 
18
19
  def __init__(
19
20
  self,
21
+ *,
20
22
  client_id: str = None,
21
23
  client_secret: str = None,
22
24
  base_url: Union[Environment, str, None] = None,
23
- timeout: int = 60000,
25
+ timeout: float = None,
26
+ timeout_ms: int = None,
27
+ retry: "RetryConfig" = None,
24
28
  base_oauth_url: str = None,
25
29
  ):
26
30
  """
@@ -52,7 +56,18 @@ class Celitech:
52
56
  )
53
57
  self.set_client_id(client_id)
54
58
  self.set_client_secret(client_secret)
59
+ if timeout_ms is not None:
60
+ warnings.warn(
61
+ "`timeout_ms` is deprecated; use `timeout` (in seconds) instead.",
62
+ DeprecationWarning,
63
+ stacklevel=2,
64
+ )
65
+ timeout = timeout_ms / 1000 if timeout is None else timeout
66
+ if timeout is None:
67
+ timeout = 60
55
68
  self.set_timeout(timeout)
69
+ if retry is not None:
70
+ self.set_retry(retry)
56
71
 
57
72
  def set_base_url(self, base_url: Union[Environment, str]):
58
73
  """
@@ -83,11 +98,11 @@ class Celitech:
83
98
 
84
99
  return self
85
100
 
86
- def set_timeout(self, timeout: int):
101
+ def set_timeout(self, timeout: float):
87
102
  """
88
103
  Sets the timeout for the entire SDK.
89
104
 
90
- :param int timeout: The timeout (ms) to be set.
105
+ :param float timeout: The timeout (in seconds) to be set.
91
106
  :return: The SDK instance.
92
107
  """
93
108
  self.destinations.set_timeout(timeout)
@@ -98,6 +113,21 @@ class Celitech:
98
113
 
99
114
  return self
100
115
 
116
+ def set_retry(self, retry: "RetryConfig"):
117
+ """
118
+ Sets the retry configuration for the entire SDK.
119
+
120
+ :param RetryConfig retry: The retry configuration to be set.
121
+ :return: The SDK instance.
122
+ """
123
+ self.destinations.set_retry(retry)
124
+ self.packages.set_retry(retry)
125
+ self.purchases.set_retry(retry)
126
+ self.e_sim.set_retry(retry)
127
+ self.i_frame.set_retry(retry)
128
+
129
+ return self
130
+
101
131
  def set_client_id(self, client_id: str):
102
132
  """
103
133
  Sets the client_id for the entire SDK.
@@ -16,10 +16,13 @@ class CelitechAsync(Celitech):
16
16
 
17
17
  def __init__(
18
18
  self,
19
+ *,
19
20
  client_id: str = None,
20
21
  client_secret: str = None,
21
22
  base_url: Union[Environment, str, None] = None,
22
- timeout: int = 60000,
23
+ timeout: float = None,
24
+ timeout_ms: int = None,
25
+ retry: "RetryConfig" = None,
23
26
  base_oauth_url: str = None,
24
27
  ):
25
28
  super().__init__(
@@ -27,6 +30,8 @@ class CelitechAsync(Celitech):
27
30
  client_secret=client_secret,
28
31
  base_url=base_url,
29
32
  timeout=timeout,
33
+ timeout_ms=timeout_ms,
34
+ retry=retry,
30
35
  base_oauth_url=base_oauth_url,
31
36
  )
32
37
 
@@ -48,3 +53,5 @@ class CelitechAsync(Celitech):
48
53
  self.o_auth = OAuthServiceAsync(
49
54
  base_url=self._base_url, token_manager=self._token_manager
50
55
  )
56
+ if retry is not None:
57
+ self.set_retry(retry)
@@ -11,7 +11,7 @@ from ...net.oauth.token_manager import TokenManager
11
11
  from ...net.request_chain.handlers.oauth_handler import OauthHandler
12
12
 
13
13
  if TYPE_CHECKING:
14
- from ...net.sdk_config import SdkConfig
14
+ from ...net.sdk_config import SdkConfig, RetryConfig
15
15
 
16
16
 
17
17
  class BaseService:
@@ -30,18 +30,18 @@ class BaseService:
30
30
  """
31
31
  self.base_url = base_url.rstrip("/") if base_url else base_url
32
32
  self._default_headers = DefaultHeaders()
33
- self._timeout = 60000
33
+ self._timeout = 60
34
34
  self._service_config: "SdkConfig" = {}
35
35
 
36
36
  self._token_manager = token_manager
37
37
 
38
38
  self._update_request_handler()
39
39
 
40
- def set_timeout(self, timeout: int):
40
+ def set_timeout(self, timeout: float):
41
41
  """
42
42
  Sets the timeout for the service.
43
43
 
44
- :param int timeout: The timeout (ms) to be set.
44
+ :param float timeout: The timeout (in seconds) to be set.
45
45
  :return: The service instance.
46
46
  """
47
47
  self._timeout = timeout
@@ -69,6 +69,18 @@ class BaseService:
69
69
  self._service_config = config
70
70
  return self
71
71
 
72
+ def set_retry(self, retry: "RetryConfig"):
73
+ """
74
+ Sets the service-level retry configuration, merging it into any existing config.
75
+
76
+ :param RetryConfig retry: The retry configuration to be set.
77
+ :return: The service instance for method chaining.
78
+ """
79
+ self._service_config = self._deep_merge(
80
+ self._service_config or {}, {"retry": retry}
81
+ )
82
+ return self
83
+
72
84
  @staticmethod
73
85
  def _deep_merge(base: dict, override: dict) -> dict:
74
86
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: celitech-sdk
3
- Version: 2.0.6
3
+ Version: 2.0.7
4
4
  Summary: Welcome to the CELITECH API documentation!
5
5
  License: MIT
6
6
  Project-URL: Repository, https://github.com/Celitech/CelitechSDKPython
@@ -11,14 +11,14 @@ Requires-Dist: requests>=2.31.0
11
11
  Requires-Dist: pydantic<3.0.0,>=2.0.0
12
12
  Dynamic: license-file
13
13
 
14
- # Celitech Python SDK 2.0.6<a id="celitech-python-sdk-206"></a>
14
+ # Celitech Python SDK 2.0.7<a id="celitech-python-sdk-207"></a>
15
15
 
16
16
  Welcome to the Celitech SDK documentation. This guide will help you get started with integrating and using the Celitech SDK in your project.
17
17
 
18
18
  ## Versions<a id="versions"></a>
19
19
 
20
- - API version: `2.0.6`
21
- - SDK version: `2.0.6`
20
+ - API version: `2.0.7`
21
+ - SDK version: `2.0.7`
22
22
 
23
23
  ## About the API<a id="about-the-api"></a>
24
24
 
@@ -102,7 +102,7 @@ You can set a custom timeout for the SDK's HTTP requests as follows:
102
102
  ```py
103
103
  from celitech import Celitech
104
104
 
105
- sdk = Celitech(timeout=10000)
105
+ sdk = Celitech(timeout=10)
106
106
  ```
107
107
 
108
108
  # Sample Usage<a id="sample-usage"></a>
File without changes
File without changes