latitudesh-python-sdk 2.3.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 (242) hide show
  1. latitudesh_python_sdk/__init__.py +18 -0
  2. latitudesh_python_sdk/_hooks/__init__.py +5 -0
  3. latitudesh_python_sdk/_hooks/registration.py +13 -0
  4. latitudesh_python_sdk/_hooks/sdkhooks.py +76 -0
  5. latitudesh_python_sdk/_hooks/types.py +113 -0
  6. latitudesh_python_sdk/_version.py +17 -0
  7. latitudesh_python_sdk/apikeys.py +703 -0
  8. latitudesh_python_sdk/basesdk.py +374 -0
  9. latitudesh_python_sdk/billing.py +197 -0
  10. latitudesh_python_sdk/events_sdk.py +298 -0
  11. latitudesh_python_sdk/firewalls_sdk.py +1786 -0
  12. latitudesh_python_sdk/httpclient.py +125 -0
  13. latitudesh_python_sdk/ipaddresses_sdk.py +470 -0
  14. latitudesh_python_sdk/models/__init__.py +3581 -0
  15. latitudesh_python_sdk/models/api_key.py +81 -0
  16. latitudesh_python_sdk/models/apierror.py +40 -0
  17. latitudesh_python_sdk/models/assign_server_virtual_networkop.py +43 -0
  18. latitudesh_python_sdk/models/bandwidth_packages.py +67 -0
  19. latitudesh_python_sdk/models/bandwidth_plan_data.py +72 -0
  20. latitudesh_python_sdk/models/bandwidth_plans.py +26 -0
  21. latitudesh_python_sdk/models/billing_usage.py +249 -0
  22. latitudesh_python_sdk/models/container_plan_data.py +163 -0
  23. latitudesh_python_sdk/models/create_api_key.py +40 -0
  24. latitudesh_python_sdk/models/create_firewall_assignmentop.py +61 -0
  25. latitudesh_python_sdk/models/create_firewallop.py +73 -0
  26. latitudesh_python_sdk/models/create_ipmi_sessionop.py +16 -0
  27. latitudesh_python_sdk/models/create_projectop.py +79 -0
  28. latitudesh_python_sdk/models/create_server_actionop.py +69 -0
  29. latitudesh_python_sdk/models/create_server_out_of_bandop.py +61 -0
  30. latitudesh_python_sdk/models/create_server_reinstallop.py +140 -0
  31. latitudesh_python_sdk/models/create_serverop.py +173 -0
  32. latitudesh_python_sdk/models/create_tagop.py +50 -0
  33. latitudesh_python_sdk/models/create_virtual_machine_actionop.py +63 -0
  34. latitudesh_python_sdk/models/create_virtual_networkop.py +72 -0
  35. latitudesh_python_sdk/models/custom_tag.py +26 -0
  36. latitudesh_python_sdk/models/custom_tag_data.py +54 -0
  37. latitudesh_python_sdk/models/custom_tags.py +26 -0
  38. latitudesh_python_sdk/models/delete_api_keyop.py +16 -0
  39. latitudesh_python_sdk/models/delete_firewall_assignmentop.py +25 -0
  40. latitudesh_python_sdk/models/delete_firewallop.py +18 -0
  41. latitudesh_python_sdk/models/delete_project_ssh_keyop.py +23 -0
  42. latitudesh_python_sdk/models/delete_project_user_dataop.py +23 -0
  43. latitudesh_python_sdk/models/delete_projectop.py +18 -0
  44. latitudesh_python_sdk/models/delete_ssh_keyop.py +16 -0
  45. latitudesh_python_sdk/models/delete_storage_filesystemsop.py +16 -0
  46. latitudesh_python_sdk/models/delete_storage_volumesop.py +16 -0
  47. latitudesh_python_sdk/models/delete_user_dataop.py +16 -0
  48. latitudesh_python_sdk/models/delete_virtual_networks_assignmentsop.py +16 -0
  49. latitudesh_python_sdk/models/delete_vpn_sessionop.py +16 -0
  50. latitudesh_python_sdk/models/deploy_config.py +62 -0
  51. latitudesh_python_sdk/models/destroy_serverop.py +31 -0
  52. latitudesh_python_sdk/models/destroy_tagop.py +16 -0
  53. latitudesh_python_sdk/models/destroy_team_memberop.py +18 -0
  54. latitudesh_python_sdk/models/destroy_virtual_machineop.py +16 -0
  55. latitudesh_python_sdk/models/destroy_virtual_networkop.py +18 -0
  56. latitudesh_python_sdk/models/event_data.py +98 -0
  57. latitudesh_python_sdk/models/events.py +26 -0
  58. latitudesh_python_sdk/models/filesystem_data.py +57 -0
  59. latitudesh_python_sdk/models/firewall.py +26 -0
  60. latitudesh_python_sdk/models/firewall_assignment_data.py +50 -0
  61. latitudesh_python_sdk/models/firewall_assignments.py +29 -0
  62. latitudesh_python_sdk/models/firewall_data.py +75 -0
  63. latitudesh_python_sdk/models/firewall_server.py +36 -0
  64. latitudesh_python_sdk/models/firewalls.py +26 -0
  65. latitudesh_python_sdk/models/get_all_firewall_assignmentsop.py +51 -0
  66. latitudesh_python_sdk/models/get_bandwidth_plansop.py +62 -0
  67. latitudesh_python_sdk/models/get_billing_usageop.py +46 -0
  68. latitudesh_python_sdk/models/get_containers_planop.py +18 -0
  69. latitudesh_python_sdk/models/get_eventsop.py +126 -0
  70. latitudesh_python_sdk/models/get_firewall_assignmentsop.py +53 -0
  71. latitudesh_python_sdk/models/get_firewallop.py +18 -0
  72. latitudesh_python_sdk/models/get_ipop.py +33 -0
  73. latitudesh_python_sdk/models/get_ipsop.py +120 -0
  74. latitudesh_python_sdk/models/get_planop.py +16 -0
  75. latitudesh_python_sdk/models/get_plans_operating_systemop.py +54 -0
  76. latitudesh_python_sdk/models/get_plansop.py +125 -0
  77. latitudesh_python_sdk/models/get_project_ssh_keyop.py +37 -0
  78. latitudesh_python_sdk/models/get_project_ssh_keysop.py +33 -0
  79. latitudesh_python_sdk/models/get_project_user_dataop.py +38 -0
  80. latitudesh_python_sdk/models/get_project_users_dataop.py +46 -0
  81. latitudesh_python_sdk/models/get_projectsop.py +105 -0
  82. latitudesh_python_sdk/models/get_regionop.py +18 -0
  83. latitudesh_python_sdk/models/get_regionsop.py +42 -0
  84. latitudesh_python_sdk/models/get_role_idop.py +16 -0
  85. latitudesh_python_sdk/models/get_rolesop.py +54 -0
  86. latitudesh_python_sdk/models/get_server_deploy_configop.py +18 -0
  87. latitudesh_python_sdk/models/get_server_out_of_bandop.py +18 -0
  88. latitudesh_python_sdk/models/get_serverop.py +33 -0
  89. latitudesh_python_sdk/models/get_serversop.py +185 -0
  90. latitudesh_python_sdk/models/get_ssh_keyop.py +30 -0
  91. latitudesh_python_sdk/models/get_ssh_keysop.py +31 -0
  92. latitudesh_python_sdk/models/get_storage_filesystemsop.py +22 -0
  93. latitudesh_python_sdk/models/get_storage_volumeop.py +32 -0
  94. latitudesh_python_sdk/models/get_storage_volumesop.py +35 -0
  95. latitudesh_python_sdk/models/get_team_membersop.py +42 -0
  96. latitudesh_python_sdk/models/get_traffic_consumptionop.py +49 -0
  97. latitudesh_python_sdk/models/get_traffic_quotaop.py +20 -0
  98. latitudesh_python_sdk/models/get_user_dataop.py +31 -0
  99. latitudesh_python_sdk/models/get_user_profileop.py +19 -0
  100. latitudesh_python_sdk/models/get_users_dataop.py +44 -0
  101. latitudesh_python_sdk/models/get_virtual_networkop.py +32 -0
  102. latitudesh_python_sdk/models/get_virtual_networks_assignmentsop.py +72 -0
  103. latitudesh_python_sdk/models/get_virtual_networksop.py +69 -0
  104. latitudesh_python_sdk/models/get_vpn_sessionsop.py +70 -0
  105. latitudesh_python_sdk/models/index_virtual_machineop.py +31 -0
  106. latitudesh_python_sdk/models/ip_address.py +122 -0
  107. latitudesh_python_sdk/models/ip_addresses.py +15 -0
  108. latitudesh_python_sdk/models/ipmi_session.py +53 -0
  109. latitudesh_python_sdk/models/latitudesherror.py +30 -0
  110. latitudesh_python_sdk/models/list_firewallsop.py +49 -0
  111. latitudesh_python_sdk/models/membership.py +63 -0
  112. latitudesh_python_sdk/models/no_response_error.py +17 -0
  113. latitudesh_python_sdk/models/operating_system_data.py +65 -0
  114. latitudesh_python_sdk/models/operating_systems.py +26 -0
  115. latitudesh_python_sdk/models/out_of_band_connection.py +88 -0
  116. latitudesh_python_sdk/models/patch_current_teamop.py +91 -0
  117. latitudesh_python_sdk/models/patch_storage_filesystemsop.py +79 -0
  118. latitudesh_python_sdk/models/patch_user_dataop.py +69 -0
  119. latitudesh_python_sdk/models/patch_user_profileop.py +88 -0
  120. latitudesh_python_sdk/models/plan.py +15 -0
  121. latitudesh_python_sdk/models/plan_data.py +210 -0
  122. latitudesh_python_sdk/models/post_api_keyop.py +19 -0
  123. latitudesh_python_sdk/models/post_project_ssh_keyop.py +81 -0
  124. latitudesh_python_sdk/models/post_project_user_dataop.py +68 -0
  125. latitudesh_python_sdk/models/post_ssh_keyop.py +63 -0
  126. latitudesh_python_sdk/models/post_storage_filesystemsop.py +63 -0
  127. latitudesh_python_sdk/models/post_storage_volumes_mountop.py +62 -0
  128. latitudesh_python_sdk/models/post_storage_volumesop.py +63 -0
  129. latitudesh_python_sdk/models/post_team_membersop.py +54 -0
  130. latitudesh_python_sdk/models/post_teamop.py +67 -0
  131. latitudesh_python_sdk/models/post_user_dataop.py +50 -0
  132. latitudesh_python_sdk/models/post_vpn_sessionop.py +63 -0
  133. latitudesh_python_sdk/models/project.py +131 -0
  134. latitudesh_python_sdk/models/project_include.py +75 -0
  135. latitudesh_python_sdk/models/projects.py +15 -0
  136. latitudesh_python_sdk/models/put_project_ssh_keyop.py +87 -0
  137. latitudesh_python_sdk/models/put_project_user_dataop.py +76 -0
  138. latitudesh_python_sdk/models/put_ssh_keyop.py +80 -0
  139. latitudesh_python_sdk/models/put_vpn_sessionop.py +16 -0
  140. latitudesh_python_sdk/models/region.py +50 -0
  141. latitudesh_python_sdk/models/region_resource_data.py +37 -0
  142. latitudesh_python_sdk/models/regions.py +50 -0
  143. latitudesh_python_sdk/models/responsevalidationerror.py +27 -0
  144. latitudesh_python_sdk/models/role.py +26 -0
  145. latitudesh_python_sdk/models/role_data.py +35 -0
  146. latitudesh_python_sdk/models/security.py +25 -0
  147. latitudesh_python_sdk/models/server.py +26 -0
  148. latitudesh_python_sdk/models/server_action.py +52 -0
  149. latitudesh_python_sdk/models/server_data.py +280 -0
  150. latitudesh_python_sdk/models/server_exit_rescue_modeop.py +16 -0
  151. latitudesh_python_sdk/models/server_lockop.py +16 -0
  152. latitudesh_python_sdk/models/server_region_resource_data.py +40 -0
  153. latitudesh_python_sdk/models/server_rescue.py +22 -0
  154. latitudesh_python_sdk/models/server_schedule_deletion.py +44 -0
  155. latitudesh_python_sdk/models/server_schedule_deletionop.py +16 -0
  156. latitudesh_python_sdk/models/server_start_rescue_modeop.py +16 -0
  157. latitudesh_python_sdk/models/server_unlockop.py +16 -0
  158. latitudesh_python_sdk/models/server_unschedule_deletionop.py +16 -0
  159. latitudesh_python_sdk/models/servers.py +26 -0
  160. latitudesh_python_sdk/models/show_virtual_machineop.py +16 -0
  161. latitudesh_python_sdk/models/ssh_key_data.py +55 -0
  162. latitudesh_python_sdk/models/ssh_keys.py +26 -0
  163. latitudesh_python_sdk/models/storage_plan_data.py +47 -0
  164. latitudesh_python_sdk/models/storage_plans.py +26 -0
  165. latitudesh_python_sdk/models/team.py +74 -0
  166. latitudesh_python_sdk/models/team_include.py +43 -0
  167. latitudesh_python_sdk/models/team_members.py +51 -0
  168. latitudesh_python_sdk/models/teams.py +26 -0
  169. latitudesh_python_sdk/models/traffic.py +133 -0
  170. latitudesh_python_sdk/models/traffic_quota.py +106 -0
  171. latitudesh_python_sdk/models/update_api_key.py +48 -0
  172. latitudesh_python_sdk/models/update_api_keyop.py +41 -0
  173. latitudesh_python_sdk/models/update_firewallop.py +89 -0
  174. latitudesh_python_sdk/models/update_plans_bandwidthop.py +50 -0
  175. latitudesh_python_sdk/models/update_projectop.py +95 -0
  176. latitudesh_python_sdk/models/update_server_deploy_configop.py +122 -0
  177. latitudesh_python_sdk/models/update_serverop.py +85 -0
  178. latitudesh_python_sdk/models/update_tagop.py +74 -0
  179. latitudesh_python_sdk/models/update_virtual_networkop.py +67 -0
  180. latitudesh_python_sdk/models/user.py +59 -0
  181. latitudesh_python_sdk/models/user_data.py +26 -0
  182. latitudesh_python_sdk/models/user_data_properties.py +46 -0
  183. latitudesh_python_sdk/models/user_include.py +52 -0
  184. latitudesh_python_sdk/models/user_team.py +61 -0
  185. latitudesh_python_sdk/models/user_teams.py +26 -0
  186. latitudesh_python_sdk/models/user_update.py +37 -0
  187. latitudesh_python_sdk/models/virtual_machine.py +29 -0
  188. latitudesh_python_sdk/models/virtual_machine_attributes.py +115 -0
  189. latitudesh_python_sdk/models/virtual_machine_payload.py +47 -0
  190. latitudesh_python_sdk/models/virtual_machine_plans.py +181 -0
  191. latitudesh_python_sdk/models/virtual_network.py +26 -0
  192. latitudesh_python_sdk/models/virtual_network_assignment.py +29 -0
  193. latitudesh_python_sdk/models/virtual_network_assignment_data.py +65 -0
  194. latitudesh_python_sdk/models/virtual_network_assignments.py +29 -0
  195. latitudesh_python_sdk/models/virtual_network_data.py +114 -0
  196. latitudesh_python_sdk/models/virtual_networks.py +26 -0
  197. latitudesh_python_sdk/models/volume_data.py +111 -0
  198. latitudesh_python_sdk/models/vpn_session_data_with_password.py +77 -0
  199. latitudesh_python_sdk/models/vpn_session_with_password.py +18 -0
  200. latitudesh_python_sdk/operatingsystems_sdk.py +238 -0
  201. latitudesh_python_sdk/plans.py +1304 -0
  202. latitudesh_python_sdk/privatenetworks.py +1612 -0
  203. latitudesh_python_sdk/projects_sdk.py +830 -0
  204. latitudesh_python_sdk/py.typed +1 -0
  205. latitudesh_python_sdk/regions_sdk.py +398 -0
  206. latitudesh_python_sdk/roles.py +398 -0
  207. latitudesh_python_sdk/sdk.py +264 -0
  208. latitudesh_python_sdk/sdkconfiguration.py +50 -0
  209. latitudesh_python_sdk/servers_sdk.py +3414 -0
  210. latitudesh_python_sdk/sshkeys_sdk.py +1882 -0
  211. latitudesh_python_sdk/storage.py +1651 -0
  212. latitudesh_python_sdk/tags.py +715 -0
  213. latitudesh_python_sdk/teams_sdk.py +527 -0
  214. latitudesh_python_sdk/teamsmembers.py +576 -0
  215. latitudesh_python_sdk/traffic_sdk.py +357 -0
  216. latitudesh_python_sdk/types/__init__.py +21 -0
  217. latitudesh_python_sdk/types/basemodel.py +39 -0
  218. latitudesh_python_sdk/userdata_sdk.py +1888 -0
  219. latitudesh_python_sdk/userprofile.py +531 -0
  220. latitudesh_python_sdk/utils/__init__.py +200 -0
  221. latitudesh_python_sdk/utils/annotations.py +79 -0
  222. latitudesh_python_sdk/utils/datetimes.py +23 -0
  223. latitudesh_python_sdk/utils/enums.py +74 -0
  224. latitudesh_python_sdk/utils/eventstreaming.py +248 -0
  225. latitudesh_python_sdk/utils/forms.py +234 -0
  226. latitudesh_python_sdk/utils/headers.py +136 -0
  227. latitudesh_python_sdk/utils/logger.py +27 -0
  228. latitudesh_python_sdk/utils/metadata.py +118 -0
  229. latitudesh_python_sdk/utils/queryparams.py +217 -0
  230. latitudesh_python_sdk/utils/requestbodies.py +66 -0
  231. latitudesh_python_sdk/utils/retries.py +281 -0
  232. latitudesh_python_sdk/utils/security.py +192 -0
  233. latitudesh_python_sdk/utils/serializers.py +249 -0
  234. latitudesh_python_sdk/utils/unmarshal_json_response.py +38 -0
  235. latitudesh_python_sdk/utils/url.py +155 -0
  236. latitudesh_python_sdk/utils/values.py +137 -0
  237. latitudesh_python_sdk/virtualmachines.py +941 -0
  238. latitudesh_python_sdk/vpnsessions.py +715 -0
  239. latitudesh_python_sdk-2.3.0.dist-info/METADATA +787 -0
  240. latitudesh_python_sdk-2.3.0.dist-info/RECORD +242 -0
  241. latitudesh_python_sdk-2.3.0.dist-info/WHEEL +4 -0
  242. latitudesh_python_sdk-2.3.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,217 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from typing import (
4
+ Any,
5
+ Dict,
6
+ get_type_hints,
7
+ List,
8
+ Optional,
9
+ )
10
+
11
+ from pydantic import BaseModel
12
+ from pydantic.fields import FieldInfo
13
+
14
+ from .metadata import (
15
+ QueryParamMetadata,
16
+ find_field_metadata,
17
+ )
18
+ from .values import (
19
+ _get_serialized_params,
20
+ _is_set,
21
+ _populate_from_globals,
22
+ _val_to_string,
23
+ )
24
+ from .forms import _populate_form
25
+
26
+
27
+ def get_query_params(
28
+ query_params: Any,
29
+ gbls: Optional[Any] = None,
30
+ allow_empty_value: Optional[List[str]] = None,
31
+ ) -> Dict[str, List[str]]:
32
+ params: Dict[str, List[str]] = {}
33
+
34
+ globals_already_populated = _populate_query_params(query_params, gbls, params, [], allow_empty_value)
35
+ if _is_set(gbls):
36
+ _populate_query_params(gbls, None, params, globals_already_populated, allow_empty_value)
37
+
38
+ return params
39
+
40
+
41
+ def _populate_query_params(
42
+ query_params: Any,
43
+ gbls: Any,
44
+ query_param_values: Dict[str, List[str]],
45
+ skip_fields: List[str],
46
+ allow_empty_value: Optional[List[str]] = None,
47
+ ) -> List[str]:
48
+ globals_already_populated: List[str] = []
49
+
50
+ if not isinstance(query_params, BaseModel):
51
+ return globals_already_populated
52
+
53
+ param_fields: Dict[str, FieldInfo] = query_params.__class__.model_fields
54
+ param_field_types = get_type_hints(query_params.__class__)
55
+ for name in param_fields:
56
+ if name in skip_fields:
57
+ continue
58
+
59
+ field = param_fields[name]
60
+
61
+ metadata = find_field_metadata(field, QueryParamMetadata)
62
+ if not metadata:
63
+ continue
64
+
65
+ value = getattr(query_params, name) if _is_set(query_params) else None
66
+
67
+ value, global_found = _populate_from_globals(
68
+ name, value, QueryParamMetadata, gbls
69
+ )
70
+ if global_found:
71
+ globals_already_populated.append(name)
72
+
73
+ f_name = field.alias if field.alias is not None else name
74
+
75
+ allow_empty_set = set(allow_empty_value or [])
76
+ should_include_empty = f_name in allow_empty_set and (
77
+ value is None or value == [] or value == ""
78
+ )
79
+
80
+ if should_include_empty:
81
+ query_param_values[f_name] = [""]
82
+ continue
83
+
84
+ serialization = metadata.serialization
85
+ if serialization is not None:
86
+ serialized_parms = _get_serialized_params(
87
+ metadata, f_name, value, param_field_types[name]
88
+ )
89
+ for key, value in serialized_parms.items():
90
+ if key in query_param_values:
91
+ query_param_values[key].extend(value)
92
+ else:
93
+ query_param_values[key] = [value]
94
+ else:
95
+ style = metadata.style
96
+ if style == "deepObject":
97
+ _populate_deep_object_query_params(f_name, value, query_param_values)
98
+ elif style == "form":
99
+ _populate_delimited_query_params(
100
+ metadata, f_name, value, ",", query_param_values
101
+ )
102
+ elif style == "pipeDelimited":
103
+ _populate_delimited_query_params(
104
+ metadata, f_name, value, "|", query_param_values
105
+ )
106
+ else:
107
+ raise NotImplementedError(
108
+ f"query param style {style} not yet supported"
109
+ )
110
+
111
+ return globals_already_populated
112
+
113
+
114
+ def _populate_deep_object_query_params(
115
+ field_name: str,
116
+ obj: Any,
117
+ params: Dict[str, List[str]],
118
+ ):
119
+ if not _is_set(obj):
120
+ return
121
+
122
+ if isinstance(obj, BaseModel):
123
+ _populate_deep_object_query_params_basemodel(field_name, obj, params)
124
+ elif isinstance(obj, Dict):
125
+ _populate_deep_object_query_params_dict(field_name, obj, params)
126
+
127
+
128
+ def _populate_deep_object_query_params_basemodel(
129
+ prior_params_key: str,
130
+ obj: Any,
131
+ params: Dict[str, List[str]],
132
+ ):
133
+ if not _is_set(obj) or not isinstance(obj, BaseModel):
134
+ return
135
+
136
+ obj_fields: Dict[str, FieldInfo] = obj.__class__.model_fields
137
+ for name in obj_fields:
138
+ obj_field = obj_fields[name]
139
+
140
+ f_name = obj_field.alias if obj_field.alias is not None else name
141
+
142
+ params_key = f"{prior_params_key}[{f_name}]"
143
+
144
+ obj_param_metadata = find_field_metadata(obj_field, QueryParamMetadata)
145
+ if not _is_set(obj_param_metadata):
146
+ continue
147
+
148
+ obj_val = getattr(obj, name)
149
+ if not _is_set(obj_val):
150
+ continue
151
+
152
+ if isinstance(obj_val, BaseModel):
153
+ _populate_deep_object_query_params_basemodel(params_key, obj_val, params)
154
+ elif isinstance(obj_val, Dict):
155
+ _populate_deep_object_query_params_dict(params_key, obj_val, params)
156
+ elif isinstance(obj_val, List):
157
+ _populate_deep_object_query_params_list(params_key, obj_val, params)
158
+ else:
159
+ params[params_key] = [_val_to_string(obj_val)]
160
+
161
+
162
+ def _populate_deep_object_query_params_dict(
163
+ prior_params_key: str,
164
+ value: Dict,
165
+ params: Dict[str, List[str]],
166
+ ):
167
+ if not _is_set(value):
168
+ return
169
+
170
+ for key, val in value.items():
171
+ if not _is_set(val):
172
+ continue
173
+
174
+ params_key = f"{prior_params_key}[{key}]"
175
+
176
+ if isinstance(val, BaseModel):
177
+ _populate_deep_object_query_params_basemodel(params_key, val, params)
178
+ elif isinstance(val, Dict):
179
+ _populate_deep_object_query_params_dict(params_key, val, params)
180
+ elif isinstance(val, List):
181
+ _populate_deep_object_query_params_list(params_key, val, params)
182
+ else:
183
+ params[params_key] = [_val_to_string(val)]
184
+
185
+
186
+ def _populate_deep_object_query_params_list(
187
+ params_key: str,
188
+ value: List,
189
+ params: Dict[str, List[str]],
190
+ ):
191
+ if not _is_set(value):
192
+ return
193
+
194
+ for val in value:
195
+ if not _is_set(val):
196
+ continue
197
+
198
+ if params.get(params_key) is None:
199
+ params[params_key] = []
200
+
201
+ params[params_key].append(_val_to_string(val))
202
+
203
+
204
+ def _populate_delimited_query_params(
205
+ metadata: QueryParamMetadata,
206
+ field_name: str,
207
+ obj: Any,
208
+ delimiter: str,
209
+ query_param_values: Dict[str, List[str]],
210
+ ):
211
+ _populate_form(
212
+ field_name,
213
+ metadata.explode,
214
+ obj,
215
+ delimiter,
216
+ query_param_values,
217
+ )
@@ -0,0 +1,66 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ import io
4
+ from dataclasses import dataclass
5
+ import re
6
+ from typing import (
7
+ Any,
8
+ Optional,
9
+ )
10
+
11
+ from .forms import serialize_form_data, serialize_multipart_form
12
+
13
+ from .serializers import marshal_json
14
+
15
+ SERIALIZATION_METHOD_TO_CONTENT_TYPE = {
16
+ "json": "application/json",
17
+ "form": "application/x-www-form-urlencoded",
18
+ "multipart": "multipart/form-data",
19
+ "raw": "application/octet-stream",
20
+ "string": "text/plain",
21
+ }
22
+
23
+
24
+ @dataclass
25
+ class SerializedRequestBody:
26
+ media_type: Optional[str] = None
27
+ content: Optional[Any] = None
28
+ data: Optional[Any] = None
29
+ files: Optional[Any] = None
30
+
31
+
32
+ def serialize_request_body(
33
+ request_body: Any,
34
+ nullable: bool,
35
+ optional: bool,
36
+ serialization_method: str,
37
+ request_body_type,
38
+ ) -> Optional[SerializedRequestBody]:
39
+ if request_body is None:
40
+ if not nullable and optional:
41
+ return None
42
+
43
+ media_type = SERIALIZATION_METHOD_TO_CONTENT_TYPE[serialization_method]
44
+
45
+ serialized_request_body = SerializedRequestBody(media_type)
46
+
47
+ if re.match(r"(application|text)\/.*?\+*json.*", media_type) is not None:
48
+ serialized_request_body.content = marshal_json(request_body, request_body_type)
49
+ elif re.match(r"multipart\/.*", media_type) is not None:
50
+ (
51
+ serialized_request_body.media_type,
52
+ serialized_request_body.data,
53
+ serialized_request_body.files,
54
+ ) = serialize_multipart_form(media_type, request_body)
55
+ elif re.match(r"application\/x-www-form-urlencoded.*", media_type) is not None:
56
+ serialized_request_body.data = serialize_form_data(request_body)
57
+ elif isinstance(request_body, (bytes, bytearray, io.BytesIO, io.BufferedReader)):
58
+ serialized_request_body.content = request_body
59
+ elif isinstance(request_body, str):
60
+ serialized_request_body.content = request_body
61
+ else:
62
+ raise TypeError(
63
+ f"invalid request body type {type(request_body)} for mediaType {media_type}"
64
+ )
65
+
66
+ return serialized_request_body
@@ -0,0 +1,281 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ import asyncio
4
+ import random
5
+ import time
6
+ from datetime import datetime
7
+ from email.utils import parsedate_to_datetime
8
+ from typing import List, Optional
9
+
10
+ import httpx
11
+
12
+
13
+ class BackoffStrategy:
14
+ initial_interval: int
15
+ max_interval: int
16
+ exponent: float
17
+ max_elapsed_time: int
18
+
19
+ def __init__(
20
+ self,
21
+ initial_interval: int,
22
+ max_interval: int,
23
+ exponent: float,
24
+ max_elapsed_time: int,
25
+ ):
26
+ self.initial_interval = initial_interval
27
+ self.max_interval = max_interval
28
+ self.exponent = exponent
29
+ self.max_elapsed_time = max_elapsed_time
30
+
31
+
32
+ class RetryConfig:
33
+ strategy: str
34
+ backoff: BackoffStrategy
35
+ retry_connection_errors: bool
36
+
37
+ def __init__(
38
+ self, strategy: str, backoff: BackoffStrategy, retry_connection_errors: bool
39
+ ):
40
+ self.strategy = strategy
41
+ self.backoff = backoff
42
+ self.retry_connection_errors = retry_connection_errors
43
+
44
+
45
+ class Retries:
46
+ config: RetryConfig
47
+ status_codes: List[str]
48
+
49
+ def __init__(self, config: RetryConfig, status_codes: List[str]):
50
+ self.config = config
51
+ self.status_codes = status_codes
52
+
53
+
54
+ class TemporaryError(Exception):
55
+ response: httpx.Response
56
+ retry_after: Optional[int]
57
+
58
+ def __init__(self, response: httpx.Response):
59
+ self.response = response
60
+ self.retry_after = _parse_retry_after_header(response)
61
+
62
+
63
+ class PermanentError(Exception):
64
+ inner: Exception
65
+
66
+ def __init__(self, inner: Exception):
67
+ self.inner = inner
68
+
69
+
70
+ def _parse_retry_after_header(response: httpx.Response) -> Optional[int]:
71
+ """Parse Retry-After header from response.
72
+
73
+ Returns:
74
+ Retry interval in milliseconds, or None if header is missing or invalid.
75
+ """
76
+ retry_after_header = response.headers.get("retry-after")
77
+ if not retry_after_header:
78
+ return None
79
+
80
+ try:
81
+ seconds = float(retry_after_header)
82
+ return round(seconds * 1000)
83
+ except ValueError:
84
+ pass
85
+
86
+ try:
87
+ retry_date = parsedate_to_datetime(retry_after_header)
88
+ delta = (retry_date - datetime.now(retry_date.tzinfo)).total_seconds()
89
+ return round(max(0, delta) * 1000)
90
+ except (ValueError, TypeError):
91
+ pass
92
+
93
+ return None
94
+
95
+
96
+ def _get_sleep_interval(
97
+ exception: Exception,
98
+ initial_interval: int,
99
+ max_interval: int,
100
+ exponent: float,
101
+ retries: int,
102
+ ) -> float:
103
+ """Get sleep interval for retry with exponential backoff.
104
+
105
+ Args:
106
+ exception: The exception that triggered the retry.
107
+ initial_interval: Initial retry interval in milliseconds.
108
+ max_interval: Maximum retry interval in milliseconds.
109
+ exponent: Base for exponential backoff calculation.
110
+ retries: Current retry attempt count.
111
+
112
+ Returns:
113
+ Sleep interval in seconds.
114
+ """
115
+ if (
116
+ isinstance(exception, TemporaryError)
117
+ and exception.retry_after is not None
118
+ and exception.retry_after > 0
119
+ ):
120
+ return exception.retry_after / 1000
121
+
122
+ sleep = (initial_interval / 1000) * exponent**retries + random.uniform(0, 1)
123
+ return min(sleep, max_interval / 1000)
124
+
125
+
126
+ def retry(func, retries: Retries):
127
+ if retries.config.strategy == "backoff":
128
+
129
+ def do_request() -> httpx.Response:
130
+ res: httpx.Response
131
+ try:
132
+ res = func()
133
+
134
+ for code in retries.status_codes:
135
+ if "X" in code.upper():
136
+ code_range = int(code[0])
137
+
138
+ status_major = res.status_code / 100
139
+
140
+ if code_range <= status_major < code_range + 1:
141
+ raise TemporaryError(res)
142
+ else:
143
+ parsed_code = int(code)
144
+
145
+ if res.status_code == parsed_code:
146
+ raise TemporaryError(res)
147
+ except httpx.ConnectError as exception:
148
+ if retries.config.retry_connection_errors:
149
+ raise
150
+
151
+ raise PermanentError(exception) from exception
152
+ except httpx.TimeoutException as exception:
153
+ if retries.config.retry_connection_errors:
154
+ raise
155
+
156
+ raise PermanentError(exception) from exception
157
+ except TemporaryError:
158
+ raise
159
+ except Exception as exception:
160
+ raise PermanentError(exception) from exception
161
+
162
+ return res
163
+
164
+ return retry_with_backoff(
165
+ do_request,
166
+ retries.config.backoff.initial_interval,
167
+ retries.config.backoff.max_interval,
168
+ retries.config.backoff.exponent,
169
+ retries.config.backoff.max_elapsed_time,
170
+ )
171
+
172
+ return func()
173
+
174
+
175
+ async def retry_async(func, retries: Retries):
176
+ if retries.config.strategy == "backoff":
177
+
178
+ async def do_request() -> httpx.Response:
179
+ res: httpx.Response
180
+ try:
181
+ res = await func()
182
+
183
+ for code in retries.status_codes:
184
+ if "X" in code.upper():
185
+ code_range = int(code[0])
186
+
187
+ status_major = res.status_code / 100
188
+
189
+ if code_range <= status_major < code_range + 1:
190
+ raise TemporaryError(res)
191
+ else:
192
+ parsed_code = int(code)
193
+
194
+ if res.status_code == parsed_code:
195
+ raise TemporaryError(res)
196
+ except httpx.ConnectError as exception:
197
+ if retries.config.retry_connection_errors:
198
+ raise
199
+
200
+ raise PermanentError(exception) from exception
201
+ except httpx.TimeoutException as exception:
202
+ if retries.config.retry_connection_errors:
203
+ raise
204
+
205
+ raise PermanentError(exception) from exception
206
+ except TemporaryError:
207
+ raise
208
+ except Exception as exception:
209
+ raise PermanentError(exception) from exception
210
+
211
+ return res
212
+
213
+ return await retry_with_backoff_async(
214
+ do_request,
215
+ retries.config.backoff.initial_interval,
216
+ retries.config.backoff.max_interval,
217
+ retries.config.backoff.exponent,
218
+ retries.config.backoff.max_elapsed_time,
219
+ )
220
+
221
+ return await func()
222
+
223
+
224
+ def retry_with_backoff(
225
+ func,
226
+ initial_interval=500,
227
+ max_interval=60000,
228
+ exponent=1.5,
229
+ max_elapsed_time=3600000,
230
+ ):
231
+ start = round(time.time() * 1000)
232
+ retries = 0
233
+
234
+ while True:
235
+ try:
236
+ return func()
237
+ except PermanentError as exception:
238
+ raise exception.inner
239
+ except Exception as exception: # pylint: disable=broad-exception-caught
240
+ now = round(time.time() * 1000)
241
+ if now - start > max_elapsed_time:
242
+ if isinstance(exception, TemporaryError):
243
+ return exception.response
244
+
245
+ raise
246
+
247
+ sleep = _get_sleep_interval(
248
+ exception, initial_interval, max_interval, exponent, retries
249
+ )
250
+ time.sleep(sleep)
251
+ retries += 1
252
+
253
+
254
+ async def retry_with_backoff_async(
255
+ func,
256
+ initial_interval=500,
257
+ max_interval=60000,
258
+ exponent=1.5,
259
+ max_elapsed_time=3600000,
260
+ ):
261
+ start = round(time.time() * 1000)
262
+ retries = 0
263
+
264
+ while True:
265
+ try:
266
+ return await func()
267
+ except PermanentError as exception:
268
+ raise exception.inner
269
+ except Exception as exception: # pylint: disable=broad-exception-caught
270
+ now = round(time.time() * 1000)
271
+ if now - start > max_elapsed_time:
272
+ if isinstance(exception, TemporaryError):
273
+ return exception.response
274
+
275
+ raise
276
+
277
+ sleep = _get_sleep_interval(
278
+ exception, initial_interval, max_interval, exponent, retries
279
+ )
280
+ await asyncio.sleep(sleep)
281
+ retries += 1