celitech-sdk 1.0.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.
Files changed (53) hide show
  1. celitech/__init__.py +2 -0
  2. celitech/hooks/__init__.py +0 -0
  3. celitech/hooks/hook.py +95 -0
  4. celitech/models/__init__.py +14 -0
  5. celitech/models/base.py +251 -0
  6. celitech/models/create_purchase_ok_response.py +85 -0
  7. celitech/models/create_purchase_request.py +54 -0
  8. celitech/models/edit_purchase_ok_response.py +41 -0
  9. celitech/models/edit_purchase_request.py +41 -0
  10. celitech/models/get_esim_device_ok_response.py +41 -0
  11. celitech/models/get_esim_history_ok_response.py +50 -0
  12. celitech/models/get_esim_mac_ok_response.py +39 -0
  13. celitech/models/get_esim_ok_response.py +43 -0
  14. celitech/models/get_purchase_consumption_ok_response.py +17 -0
  15. celitech/models/list_destinations_ok_response.py +38 -0
  16. celitech/models/list_packages_ok_response.py +61 -0
  17. celitech/models/list_purchases_ok_response.py +129 -0
  18. celitech/models/top_up_esim_ok_response.py +82 -0
  19. celitech/models/top_up_esim_request.py +49 -0
  20. celitech/models/utils/cast_models.py +81 -0
  21. celitech/models/utils/json_map.py +80 -0
  22. celitech/net/__init__.py +0 -0
  23. celitech/net/environment/__init__.py +1 -0
  24. celitech/net/environment/environment.py +11 -0
  25. celitech/net/headers/__init__.py +0 -0
  26. celitech/net/headers/base_header.py +9 -0
  27. celitech/net/request_chain/__init__.py +0 -0
  28. celitech/net/request_chain/handlers/__init__.py +0 -0
  29. celitech/net/request_chain/handlers/base_handler.py +39 -0
  30. celitech/net/request_chain/handlers/hook_handler.py +47 -0
  31. celitech/net/request_chain/handlers/http_handler.py +80 -0
  32. celitech/net/request_chain/handlers/retry_handler.py +65 -0
  33. celitech/net/request_chain/request_chain.py +57 -0
  34. celitech/net/transport/__init__.py +0 -0
  35. celitech/net/transport/request.py +89 -0
  36. celitech/net/transport/request_error.py +53 -0
  37. celitech/net/transport/response.py +57 -0
  38. celitech/net/transport/serializer.py +249 -0
  39. celitech/net/transport/utils.py +28 -0
  40. celitech/sdk.py +30 -0
  41. celitech/services/__init__.py +0 -0
  42. celitech/services/destinations.py +29 -0
  43. celitech/services/e_sim.py +121 -0
  44. celitech/services/packages.py +72 -0
  45. celitech/services/purchases.py +189 -0
  46. celitech/services/utils/base_service.py +63 -0
  47. celitech/services/utils/default_headers.py +57 -0
  48. celitech/services/utils/validator.py +170 -0
  49. celitech_sdk-1.0.0.dist-info/LICENSE +21 -0
  50. celitech_sdk-1.0.0.dist-info/METADATA +482 -0
  51. celitech_sdk-1.0.0.dist-info/RECORD +53 -0
  52. celitech_sdk-1.0.0.dist-info/WHEEL +5 -0
  53. celitech_sdk-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,249 @@
1
+ from typing import Any, List
2
+ from urllib.parse import quote
3
+
4
+ from ...net.headers.base_header import BaseHeader
5
+ from .request import Request
6
+ from .utils import extract_original_data
7
+
8
+
9
+ class Serializer:
10
+ """
11
+ A class for handling serialization of URL components such as headers, cookies, path parameters, and query parameters.
12
+
13
+ :ivar str url: The base URL to be serialized.
14
+ :ivar dict[str, str] headers: A dictionary containing headers for the request.
15
+ :ivar list[str] cookies: A list containing cookie strings for the request.
16
+ :ivar dict[str, str] path: A dictionary containing path parameters for the request.
17
+ :ivar list[str] query: A list containing query parameters for the request.
18
+ """
19
+
20
+ def __init__(self, url: str, default_headers: List[BaseHeader] = []):
21
+ """
22
+ Initializes a Serializer instance with the base URL.
23
+
24
+ :param str url: The base URL to be serialized.
25
+ :param list[BaseHeader] default_headers: A list of default headers to be added to the request. Defaults to an empty list.
26
+ """
27
+ self.url: str = url
28
+ self.headers: dict[str, str] = {}
29
+ self.cookies: list[str] = []
30
+ self.path: dict[str, str] = {}
31
+ self.query: list[str] = []
32
+
33
+ for header in default_headers:
34
+ for key, value in header.get_headers().items():
35
+ self.add_header(key, value)
36
+
37
+ def add_header(
38
+ self, key: str, data: Any, explode: bool = False, nullable: bool = False
39
+ ) -> "Serializer":
40
+ """
41
+ Adds a header to the request.
42
+
43
+ :param str key: The header key.
44
+ :param Any data: The data to be serialized as the header value.
45
+ :param bool explode: Flag indicating whether to explode the data.
46
+ :return: The Serializer instance for method chaining.
47
+ :rtype: Serializer
48
+ """
49
+ if not nullable and data is None:
50
+ return self
51
+
52
+ data = extract_original_data(data)
53
+
54
+ self.headers[key] = self._serialize_value(
55
+ data, explode=explode, quote_str_values=False
56
+ )
57
+ return self
58
+
59
+ def add_cookie(
60
+ self, key: str, data: Any, explode: bool = False, nullable: bool = False
61
+ ) -> "Serializer":
62
+ """
63
+ Adds a cookie to the request.
64
+
65
+ :param str key: The cookie key.
66
+ :param Any data: The data to be serialized as the cookie value.
67
+ :param bool explode: Flag indicating whether to explode the data.
68
+ :return: The Serializer instance for method chaining.
69
+ :rtype: Serializer
70
+ """
71
+ if not nullable and data is None:
72
+ return self
73
+
74
+ data = extract_original_data(data)
75
+
76
+ self.cookies.append(
77
+ f"{key}={self._serialize_value(data, explode=explode, quote_str_values=False)}"
78
+ )
79
+ return self
80
+
81
+ def add_path(
82
+ self,
83
+ key: str,
84
+ data: Any,
85
+ explode: bool = False,
86
+ style: str = "simple",
87
+ nullable: bool = False,
88
+ ) -> "Serializer":
89
+ """
90
+ Adds a path parameter to the request.
91
+
92
+ :param str key: The path parameter key.
93
+ :param Any data: The data to be serialized as the path parameter value.
94
+ :param bool explode: Flag indicating whether to explode the data.
95
+ :param str style: The style of serialization for the path parameter.
96
+ :return: The Serializer instance for method chaining.
97
+ :rtype: Serializer
98
+ """
99
+ if not nullable and data is None:
100
+ return self
101
+
102
+ data = extract_original_data(data)
103
+
104
+ if style == "simple":
105
+ self.path[key] = self._serialize_value(data=data, explode=explode)
106
+ elif style == "label":
107
+ separator = "." if explode else ","
108
+ self.path[key] = "." + self._serialize_value(
109
+ data=data, explode=explode, separator=separator
110
+ )
111
+ elif style == "matrix":
112
+ separator = ","
113
+
114
+ if isinstance(data, list) and explode:
115
+ separator = f";{key}="
116
+ elif explode:
117
+ separator = ";"
118
+
119
+ prefix = ";" if isinstance(data, dict) and explode else f";{key}="
120
+ self.path[key] = prefix + self._serialize_value(
121
+ data, explode=explode, separator=separator
122
+ )
123
+ else:
124
+ raise ValueError(f"Unsupported path style: {style}")
125
+
126
+ return self
127
+
128
+ def add_query(
129
+ self,
130
+ key: str,
131
+ data: Any,
132
+ explode: bool = True,
133
+ style: str = "form",
134
+ nullable: bool = False,
135
+ ) -> "Serializer":
136
+ """
137
+ Adds a query parameter to the request.
138
+
139
+ :param str key: The query parameter key.
140
+ :param Any data: The data to be serialized as the query parameter value.
141
+ :param bool explode: Flag indicating whether to explode the data.
142
+ :param str style: The style of serialization for the query parameter.
143
+ :return: The Serializer instance for method chaining.
144
+ :rtype: Serializer
145
+ """
146
+ if not nullable and data is None:
147
+ return self
148
+
149
+ data = extract_original_data(data)
150
+
151
+ if style == "form":
152
+ separator = "&" if explode else ","
153
+ prefix = "" if (explode and isinstance(data, dict)) else f"{key}="
154
+ query_param = f"{prefix}{self._serialize_value(data=data, explode=explode, separator=separator)}"
155
+ elif style == "spaceDelimited":
156
+ separator = f"&{key}=" if explode else f"%20"
157
+ query_param = f"{key}={self._serialize_value(data=data, explode=explode, separator=separator)}"
158
+ elif style == "pipeDelimited":
159
+ separator = f"&{key}=" if explode else "|"
160
+ query_param = f"{key}={self._serialize_value(data=data, explode=explode, separator=separator)}"
161
+ elif style == "deepObject":
162
+ query_param = "".join(
163
+ f"{key}[{k}]={quote(self._serialize_value(v))}&"
164
+ for k, v in data.items()
165
+ ).rstrip("&")
166
+
167
+ self.query.append(query_param)
168
+ return self
169
+
170
+ def serialize(self) -> Request:
171
+ """
172
+ Serializes the components and returns a Request object.
173
+
174
+ :return: The Request object containing the serialized components.
175
+ :rtype: Request
176
+ """
177
+ final_url = self._define_url()
178
+
179
+ if len(self.cookies) > 0:
180
+ self.headers["Cookie"] = ";".join(self.cookies)
181
+
182
+ return Request().set_url(final_url).set_headers(self.headers)
183
+
184
+ def _define_url(self) -> str:
185
+ """
186
+ Constructs the final URL by replacing path parameters and appending query parameters.
187
+
188
+ :return: The final URL.
189
+ :rtype: str
190
+ """
191
+ final_url = self.url
192
+
193
+ for key, value in self.path.items():
194
+ final_url = final_url.replace(f"{{{key}}}", value)
195
+
196
+ if len(self.query) > 0:
197
+ final_url += "?" + "&".join(self.query)
198
+
199
+ return final_url
200
+
201
+ def _serialize_value(
202
+ self,
203
+ data: Any,
204
+ separator: str = ",",
205
+ explode: bool = False,
206
+ quote_str_values: bool = True,
207
+ ) -> str:
208
+ """
209
+ Serializes a value based on the specified separator and explode flag.
210
+
211
+ :param Any data: The data to be serialized.
212
+ :param str separator: The separator used for serialization.
213
+ :param bool explode: Flag indicating whether to explode the data.
214
+ :return: The serialized value.
215
+ :rtype: str
216
+ """
217
+ if data is None:
218
+ return "null"
219
+
220
+ if isinstance(data, list):
221
+ return separator.join(
222
+ self._serialize_value(item, separator, explode) for item in data
223
+ )
224
+
225
+ if isinstance(data, dict):
226
+ if explode:
227
+ return separator.join(
228
+ [
229
+ f"{k}={self._serialize_value(v, separator, explode)}"
230
+ for k, v in data.items()
231
+ ]
232
+ )
233
+ else:
234
+ return separator.join(
235
+ [
236
+ self._serialize_value(item, separator, explode)
237
+ for sublist in data.items()
238
+ for item in sublist
239
+ ]
240
+ )
241
+
242
+ if isinstance(data, str) and quote_str_values:
243
+ return quote(data)
244
+ if isinstance(data, bool):
245
+ return str(data).lower()
246
+ if isinstance(data, (int, float)):
247
+ return str(data)
248
+
249
+ return data
@@ -0,0 +1,28 @@
1
+ from enum import Enum
2
+ from typing import Any
3
+ from ...models.base import BaseModel
4
+
5
+
6
+ def extract_original_data(data: Any) -> Any:
7
+ """
8
+ Extracts the original data from internal models and enums.
9
+
10
+ :param Any data: The data to be extracted.
11
+ :return: The extracted data.
12
+ :rtype: Any
13
+ """
14
+ if data is None:
15
+ return None
16
+
17
+ data_type = type(data)
18
+
19
+ if issubclass(data_type, BaseModel):
20
+ return data._map()
21
+
22
+ if issubclass(data_type, Enum):
23
+ return data.value
24
+
25
+ if issubclass(data_type, list):
26
+ return [extract_original_data(item) for item in data]
27
+
28
+ return data
celitech/sdk.py ADDED
@@ -0,0 +1,30 @@
1
+ from .services.destinations import DestinationsService
2
+ from .services.packages import PackagesService
3
+ from .services.purchases import PurchasesService
4
+ from .services.e_sim import ESimService
5
+ from .net.environment import Environment
6
+
7
+
8
+ class Celitech:
9
+ def __init__(self, base_url: str = Environment.DEFAULT.value):
10
+ """
11
+ Initializes Celitech the SDK class.
12
+ """
13
+ self.destinations = DestinationsService(base_url=base_url)
14
+ self.packages = PackagesService(base_url=base_url)
15
+ self.purchases = PurchasesService(base_url=base_url)
16
+ self.e_sim = ESimService(base_url=base_url)
17
+
18
+ def set_base_url(self, base_url):
19
+ """
20
+ Sets the base URL for the entire SDK.
21
+ """
22
+ self.destinations.set_base_url(base_url)
23
+ self.packages.set_base_url(base_url)
24
+ self.purchases.set_base_url(base_url)
25
+ self.e_sim.set_base_url(base_url)
26
+
27
+ return self
28
+
29
+
30
+ # c029837e0e474b76bc487506e8799df5e3335891efe4fb02bda7a1441840310c
File without changes
@@ -0,0 +1,29 @@
1
+ from .utils.validator import Validator
2
+ from .utils.base_service import BaseService
3
+ from ..net.transport.serializer import Serializer
4
+ from ..models.utils.cast_models import cast_models
5
+ from ..models.list_destinations_ok_response import ListDestinationsOkResponse
6
+
7
+
8
+ class DestinationsService(BaseService):
9
+
10
+ @cast_models
11
+ def list_destinations(self) -> ListDestinationsOkResponse:
12
+ """Name of the destinations
13
+
14
+ ...
15
+ :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
16
+ ...
17
+ :return: Successful Response
18
+ :rtype: ListDestinationsOkResponse
19
+ """
20
+
21
+ serialized_request = (
22
+ Serializer(f"{self.base_url}/destinations", self.get_default_headers())
23
+ .serialize()
24
+ .set_method("GET")
25
+ )
26
+
27
+ response = self.send_request(serialized_request)
28
+
29
+ return ListDestinationsOkResponse._unmap(response)
@@ -0,0 +1,121 @@
1
+ from .utils.validator import Validator
2
+ from .utils.base_service import BaseService
3
+ from ..net.transport.serializer import Serializer
4
+ from ..models.utils.cast_models import cast_models
5
+ from ..models.get_esim_ok_response import GetEsimOkResponse
6
+ from ..models.get_esim_mac_ok_response import GetEsimMacOkResponse
7
+ from ..models.get_esim_history_ok_response import GetEsimHistoryOkResponse
8
+ from ..models.get_esim_device_ok_response import GetEsimDeviceOkResponse
9
+
10
+
11
+ class ESimService(BaseService):
12
+
13
+ @cast_models
14
+ def get_esim(self, iccid: str) -> GetEsimOkResponse:
15
+ """Get status from eSIM
16
+
17
+ :param iccid: iccid
18
+ :type iccid: str
19
+ ...
20
+ :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
21
+ ...
22
+ :return: Successful Response
23
+ :rtype: GetEsimOkResponse
24
+ """
25
+
26
+ Validator(str).validate(iccid)
27
+
28
+ serialized_request = (
29
+ Serializer(f"{self.base_url}/esim", self.get_default_headers())
30
+ .add_query("iccid", iccid)
31
+ .serialize()
32
+ .set_method("GET")
33
+ )
34
+
35
+ response = self.send_request(serialized_request)
36
+
37
+ return GetEsimOkResponse._unmap(response)
38
+
39
+ @cast_models
40
+ def get_esim_device(self, iccid: str) -> GetEsimDeviceOkResponse:
41
+ """Get device info from an installed eSIM
42
+
43
+ :param iccid: iccid
44
+ :type iccid: str
45
+ ...
46
+ :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
47
+ ...
48
+ :return: Successful Response
49
+ :rtype: GetEsimDeviceOkResponse
50
+ """
51
+
52
+ Validator(str).validate(iccid)
53
+
54
+ serialized_request = (
55
+ Serializer(
56
+ f"{self.base_url}/esim/{{iccid}}/device", self.get_default_headers()
57
+ )
58
+ .add_path("iccid", iccid)
59
+ .serialize()
60
+ .set_method("GET")
61
+ )
62
+
63
+ response = self.send_request(serialized_request)
64
+
65
+ return GetEsimDeviceOkResponse._unmap(response)
66
+
67
+ @cast_models
68
+ def get_esim_history(self, iccid: str) -> GetEsimHistoryOkResponse:
69
+ """Get history from an eSIM
70
+
71
+ :param iccid: iccid
72
+ :type iccid: str
73
+ ...
74
+ :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
75
+ ...
76
+ :return: Successful Response
77
+ :rtype: GetEsimHistoryOkResponse
78
+ """
79
+
80
+ Validator(str).validate(iccid)
81
+
82
+ serialized_request = (
83
+ Serializer(
84
+ f"{self.base_url}/esim/{{iccid}}/history", self.get_default_headers()
85
+ )
86
+ .add_path("iccid", iccid)
87
+ .serialize()
88
+ .set_method("GET")
89
+ )
90
+
91
+ response = self.send_request(serialized_request)
92
+
93
+ return GetEsimHistoryOkResponse._unmap(response)
94
+
95
+ @cast_models
96
+ def get_esim_mac(self, iccid: str) -> GetEsimMacOkResponse:
97
+ """Get MAC from eSIM
98
+
99
+ :param iccid: iccid
100
+ :type iccid: str
101
+ ...
102
+ :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
103
+ ...
104
+ :return: Successful Response
105
+ :rtype: GetEsimMacOkResponse
106
+ """
107
+
108
+ Validator(str).validate(iccid)
109
+
110
+ serialized_request = (
111
+ Serializer(
112
+ f"{self.base_url}/esim/{{iccid}}/mac", self.get_default_headers()
113
+ )
114
+ .add_path("iccid", iccid)
115
+ .serialize()
116
+ .set_method("GET")
117
+ )
118
+
119
+ response = self.send_request(serialized_request)
120
+
121
+ return GetEsimMacOkResponse._unmap(response)
@@ -0,0 +1,72 @@
1
+ from .utils.validator import Validator
2
+ from .utils.base_service import BaseService
3
+ from ..net.transport.serializer import Serializer
4
+ from ..models.utils.cast_models import cast_models
5
+ from ..models.list_packages_ok_response import ListPackagesOkResponse
6
+
7
+
8
+ class PackagesService(BaseService):
9
+
10
+ @cast_models
11
+ def list_packages(
12
+ self,
13
+ destination: str = None,
14
+ start_date: str = None,
15
+ end_date: str = None,
16
+ after_cursor: str = None,
17
+ limit: float = None,
18
+ start_time: int = None,
19
+ end_time: int = None,
20
+ duration: float = None,
21
+ ) -> ListPackagesOkResponse:
22
+ """List of available packages
23
+
24
+ :param destination: destination, defaults to None
25
+ :type destination: str, optional
26
+ :param start_date: start_date, defaults to None
27
+ :type start_date: str, optional
28
+ :param end_date: end_date, defaults to None
29
+ :type end_date: str, optional
30
+ :param after_cursor: after_cursor, defaults to None
31
+ :type after_cursor: str, optional
32
+ :param limit: limit, defaults to None
33
+ :type limit: float, optional
34
+ :param start_time: start_time, defaults to None
35
+ :type start_time: int, optional
36
+ :param end_time: end_time, defaults to None
37
+ :type end_time: int, optional
38
+ :param duration: duration, defaults to None
39
+ :type duration: float, optional
40
+ ...
41
+ :raises RequestError: Raised when a request fails, with optional HTTP status code and details.
42
+ ...
43
+ :return: Successful Response
44
+ :rtype: ListPackagesOkResponse
45
+ """
46
+
47
+ Validator(str).is_optional().validate(destination)
48
+ Validator(str).is_optional().validate(start_date)
49
+ Validator(str).is_optional().validate(end_date)
50
+ Validator(str).is_optional().validate(after_cursor)
51
+ Validator(float).is_optional().validate(limit)
52
+ Validator(int).is_optional().validate(start_time)
53
+ Validator(int).is_optional().validate(end_time)
54
+ Validator(float).is_optional().validate(duration)
55
+
56
+ serialized_request = (
57
+ Serializer(f"{self.base_url}/packages", self.get_default_headers())
58
+ .add_query("destination", destination)
59
+ .add_query("startDate", start_date)
60
+ .add_query("endDate", end_date)
61
+ .add_query("afterCursor", after_cursor)
62
+ .add_query("limit", limit)
63
+ .add_query("startTime", start_time)
64
+ .add_query("endTime", end_time)
65
+ .add_query("duration", duration)
66
+ .serialize()
67
+ .set_method("GET")
68
+ )
69
+
70
+ response = self.send_request(serialized_request)
71
+
72
+ return ListPackagesOkResponse._unmap(response)