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.
- latitudesh_python_sdk/__init__.py +18 -0
- latitudesh_python_sdk/_hooks/__init__.py +5 -0
- latitudesh_python_sdk/_hooks/registration.py +13 -0
- latitudesh_python_sdk/_hooks/sdkhooks.py +76 -0
- latitudesh_python_sdk/_hooks/types.py +113 -0
- latitudesh_python_sdk/_version.py +17 -0
- latitudesh_python_sdk/apikeys.py +703 -0
- latitudesh_python_sdk/basesdk.py +374 -0
- latitudesh_python_sdk/billing.py +197 -0
- latitudesh_python_sdk/events_sdk.py +298 -0
- latitudesh_python_sdk/firewalls_sdk.py +1786 -0
- latitudesh_python_sdk/httpclient.py +125 -0
- latitudesh_python_sdk/ipaddresses_sdk.py +470 -0
- latitudesh_python_sdk/models/__init__.py +3581 -0
- latitudesh_python_sdk/models/api_key.py +81 -0
- latitudesh_python_sdk/models/apierror.py +40 -0
- latitudesh_python_sdk/models/assign_server_virtual_networkop.py +43 -0
- latitudesh_python_sdk/models/bandwidth_packages.py +67 -0
- latitudesh_python_sdk/models/bandwidth_plan_data.py +72 -0
- latitudesh_python_sdk/models/bandwidth_plans.py +26 -0
- latitudesh_python_sdk/models/billing_usage.py +249 -0
- latitudesh_python_sdk/models/container_plan_data.py +163 -0
- latitudesh_python_sdk/models/create_api_key.py +40 -0
- latitudesh_python_sdk/models/create_firewall_assignmentop.py +61 -0
- latitudesh_python_sdk/models/create_firewallop.py +73 -0
- latitudesh_python_sdk/models/create_ipmi_sessionop.py +16 -0
- latitudesh_python_sdk/models/create_projectop.py +79 -0
- latitudesh_python_sdk/models/create_server_actionop.py +69 -0
- latitudesh_python_sdk/models/create_server_out_of_bandop.py +61 -0
- latitudesh_python_sdk/models/create_server_reinstallop.py +140 -0
- latitudesh_python_sdk/models/create_serverop.py +173 -0
- latitudesh_python_sdk/models/create_tagop.py +50 -0
- latitudesh_python_sdk/models/create_virtual_machine_actionop.py +63 -0
- latitudesh_python_sdk/models/create_virtual_networkop.py +72 -0
- latitudesh_python_sdk/models/custom_tag.py +26 -0
- latitudesh_python_sdk/models/custom_tag_data.py +54 -0
- latitudesh_python_sdk/models/custom_tags.py +26 -0
- latitudesh_python_sdk/models/delete_api_keyop.py +16 -0
- latitudesh_python_sdk/models/delete_firewall_assignmentop.py +25 -0
- latitudesh_python_sdk/models/delete_firewallop.py +18 -0
- latitudesh_python_sdk/models/delete_project_ssh_keyop.py +23 -0
- latitudesh_python_sdk/models/delete_project_user_dataop.py +23 -0
- latitudesh_python_sdk/models/delete_projectop.py +18 -0
- latitudesh_python_sdk/models/delete_ssh_keyop.py +16 -0
- latitudesh_python_sdk/models/delete_storage_filesystemsop.py +16 -0
- latitudesh_python_sdk/models/delete_storage_volumesop.py +16 -0
- latitudesh_python_sdk/models/delete_user_dataop.py +16 -0
- latitudesh_python_sdk/models/delete_virtual_networks_assignmentsop.py +16 -0
- latitudesh_python_sdk/models/delete_vpn_sessionop.py +16 -0
- latitudesh_python_sdk/models/deploy_config.py +62 -0
- latitudesh_python_sdk/models/destroy_serverop.py +31 -0
- latitudesh_python_sdk/models/destroy_tagop.py +16 -0
- latitudesh_python_sdk/models/destroy_team_memberop.py +18 -0
- latitudesh_python_sdk/models/destroy_virtual_machineop.py +16 -0
- latitudesh_python_sdk/models/destroy_virtual_networkop.py +18 -0
- latitudesh_python_sdk/models/event_data.py +98 -0
- latitudesh_python_sdk/models/events.py +26 -0
- latitudesh_python_sdk/models/filesystem_data.py +57 -0
- latitudesh_python_sdk/models/firewall.py +26 -0
- latitudesh_python_sdk/models/firewall_assignment_data.py +50 -0
- latitudesh_python_sdk/models/firewall_assignments.py +29 -0
- latitudesh_python_sdk/models/firewall_data.py +75 -0
- latitudesh_python_sdk/models/firewall_server.py +36 -0
- latitudesh_python_sdk/models/firewalls.py +26 -0
- latitudesh_python_sdk/models/get_all_firewall_assignmentsop.py +51 -0
- latitudesh_python_sdk/models/get_bandwidth_plansop.py +62 -0
- latitudesh_python_sdk/models/get_billing_usageop.py +46 -0
- latitudesh_python_sdk/models/get_containers_planop.py +18 -0
- latitudesh_python_sdk/models/get_eventsop.py +126 -0
- latitudesh_python_sdk/models/get_firewall_assignmentsop.py +53 -0
- latitudesh_python_sdk/models/get_firewallop.py +18 -0
- latitudesh_python_sdk/models/get_ipop.py +33 -0
- latitudesh_python_sdk/models/get_ipsop.py +120 -0
- latitudesh_python_sdk/models/get_planop.py +16 -0
- latitudesh_python_sdk/models/get_plans_operating_systemop.py +54 -0
- latitudesh_python_sdk/models/get_plansop.py +125 -0
- latitudesh_python_sdk/models/get_project_ssh_keyop.py +37 -0
- latitudesh_python_sdk/models/get_project_ssh_keysop.py +33 -0
- latitudesh_python_sdk/models/get_project_user_dataop.py +38 -0
- latitudesh_python_sdk/models/get_project_users_dataop.py +46 -0
- latitudesh_python_sdk/models/get_projectsop.py +105 -0
- latitudesh_python_sdk/models/get_regionop.py +18 -0
- latitudesh_python_sdk/models/get_regionsop.py +42 -0
- latitudesh_python_sdk/models/get_role_idop.py +16 -0
- latitudesh_python_sdk/models/get_rolesop.py +54 -0
- latitudesh_python_sdk/models/get_server_deploy_configop.py +18 -0
- latitudesh_python_sdk/models/get_server_out_of_bandop.py +18 -0
- latitudesh_python_sdk/models/get_serverop.py +33 -0
- latitudesh_python_sdk/models/get_serversop.py +185 -0
- latitudesh_python_sdk/models/get_ssh_keyop.py +30 -0
- latitudesh_python_sdk/models/get_ssh_keysop.py +31 -0
- latitudesh_python_sdk/models/get_storage_filesystemsop.py +22 -0
- latitudesh_python_sdk/models/get_storage_volumeop.py +32 -0
- latitudesh_python_sdk/models/get_storage_volumesop.py +35 -0
- latitudesh_python_sdk/models/get_team_membersop.py +42 -0
- latitudesh_python_sdk/models/get_traffic_consumptionop.py +49 -0
- latitudesh_python_sdk/models/get_traffic_quotaop.py +20 -0
- latitudesh_python_sdk/models/get_user_dataop.py +31 -0
- latitudesh_python_sdk/models/get_user_profileop.py +19 -0
- latitudesh_python_sdk/models/get_users_dataop.py +44 -0
- latitudesh_python_sdk/models/get_virtual_networkop.py +32 -0
- latitudesh_python_sdk/models/get_virtual_networks_assignmentsop.py +72 -0
- latitudesh_python_sdk/models/get_virtual_networksop.py +69 -0
- latitudesh_python_sdk/models/get_vpn_sessionsop.py +70 -0
- latitudesh_python_sdk/models/index_virtual_machineop.py +31 -0
- latitudesh_python_sdk/models/ip_address.py +122 -0
- latitudesh_python_sdk/models/ip_addresses.py +15 -0
- latitudesh_python_sdk/models/ipmi_session.py +53 -0
- latitudesh_python_sdk/models/latitudesherror.py +30 -0
- latitudesh_python_sdk/models/list_firewallsop.py +49 -0
- latitudesh_python_sdk/models/membership.py +63 -0
- latitudesh_python_sdk/models/no_response_error.py +17 -0
- latitudesh_python_sdk/models/operating_system_data.py +65 -0
- latitudesh_python_sdk/models/operating_systems.py +26 -0
- latitudesh_python_sdk/models/out_of_band_connection.py +88 -0
- latitudesh_python_sdk/models/patch_current_teamop.py +91 -0
- latitudesh_python_sdk/models/patch_storage_filesystemsop.py +79 -0
- latitudesh_python_sdk/models/patch_user_dataop.py +69 -0
- latitudesh_python_sdk/models/patch_user_profileop.py +88 -0
- latitudesh_python_sdk/models/plan.py +15 -0
- latitudesh_python_sdk/models/plan_data.py +210 -0
- latitudesh_python_sdk/models/post_api_keyop.py +19 -0
- latitudesh_python_sdk/models/post_project_ssh_keyop.py +81 -0
- latitudesh_python_sdk/models/post_project_user_dataop.py +68 -0
- latitudesh_python_sdk/models/post_ssh_keyop.py +63 -0
- latitudesh_python_sdk/models/post_storage_filesystemsop.py +63 -0
- latitudesh_python_sdk/models/post_storage_volumes_mountop.py +62 -0
- latitudesh_python_sdk/models/post_storage_volumesop.py +63 -0
- latitudesh_python_sdk/models/post_team_membersop.py +54 -0
- latitudesh_python_sdk/models/post_teamop.py +67 -0
- latitudesh_python_sdk/models/post_user_dataop.py +50 -0
- latitudesh_python_sdk/models/post_vpn_sessionop.py +63 -0
- latitudesh_python_sdk/models/project.py +131 -0
- latitudesh_python_sdk/models/project_include.py +75 -0
- latitudesh_python_sdk/models/projects.py +15 -0
- latitudesh_python_sdk/models/put_project_ssh_keyop.py +87 -0
- latitudesh_python_sdk/models/put_project_user_dataop.py +76 -0
- latitudesh_python_sdk/models/put_ssh_keyop.py +80 -0
- latitudesh_python_sdk/models/put_vpn_sessionop.py +16 -0
- latitudesh_python_sdk/models/region.py +50 -0
- latitudesh_python_sdk/models/region_resource_data.py +37 -0
- latitudesh_python_sdk/models/regions.py +50 -0
- latitudesh_python_sdk/models/responsevalidationerror.py +27 -0
- latitudesh_python_sdk/models/role.py +26 -0
- latitudesh_python_sdk/models/role_data.py +35 -0
- latitudesh_python_sdk/models/security.py +25 -0
- latitudesh_python_sdk/models/server.py +26 -0
- latitudesh_python_sdk/models/server_action.py +52 -0
- latitudesh_python_sdk/models/server_data.py +280 -0
- latitudesh_python_sdk/models/server_exit_rescue_modeop.py +16 -0
- latitudesh_python_sdk/models/server_lockop.py +16 -0
- latitudesh_python_sdk/models/server_region_resource_data.py +40 -0
- latitudesh_python_sdk/models/server_rescue.py +22 -0
- latitudesh_python_sdk/models/server_schedule_deletion.py +44 -0
- latitudesh_python_sdk/models/server_schedule_deletionop.py +16 -0
- latitudesh_python_sdk/models/server_start_rescue_modeop.py +16 -0
- latitudesh_python_sdk/models/server_unlockop.py +16 -0
- latitudesh_python_sdk/models/server_unschedule_deletionop.py +16 -0
- latitudesh_python_sdk/models/servers.py +26 -0
- latitudesh_python_sdk/models/show_virtual_machineop.py +16 -0
- latitudesh_python_sdk/models/ssh_key_data.py +55 -0
- latitudesh_python_sdk/models/ssh_keys.py +26 -0
- latitudesh_python_sdk/models/storage_plan_data.py +47 -0
- latitudesh_python_sdk/models/storage_plans.py +26 -0
- latitudesh_python_sdk/models/team.py +74 -0
- latitudesh_python_sdk/models/team_include.py +43 -0
- latitudesh_python_sdk/models/team_members.py +51 -0
- latitudesh_python_sdk/models/teams.py +26 -0
- latitudesh_python_sdk/models/traffic.py +133 -0
- latitudesh_python_sdk/models/traffic_quota.py +106 -0
- latitudesh_python_sdk/models/update_api_key.py +48 -0
- latitudesh_python_sdk/models/update_api_keyop.py +41 -0
- latitudesh_python_sdk/models/update_firewallop.py +89 -0
- latitudesh_python_sdk/models/update_plans_bandwidthop.py +50 -0
- latitudesh_python_sdk/models/update_projectop.py +95 -0
- latitudesh_python_sdk/models/update_server_deploy_configop.py +122 -0
- latitudesh_python_sdk/models/update_serverop.py +85 -0
- latitudesh_python_sdk/models/update_tagop.py +74 -0
- latitudesh_python_sdk/models/update_virtual_networkop.py +67 -0
- latitudesh_python_sdk/models/user.py +59 -0
- latitudesh_python_sdk/models/user_data.py +26 -0
- latitudesh_python_sdk/models/user_data_properties.py +46 -0
- latitudesh_python_sdk/models/user_include.py +52 -0
- latitudesh_python_sdk/models/user_team.py +61 -0
- latitudesh_python_sdk/models/user_teams.py +26 -0
- latitudesh_python_sdk/models/user_update.py +37 -0
- latitudesh_python_sdk/models/virtual_machine.py +29 -0
- latitudesh_python_sdk/models/virtual_machine_attributes.py +115 -0
- latitudesh_python_sdk/models/virtual_machine_payload.py +47 -0
- latitudesh_python_sdk/models/virtual_machine_plans.py +181 -0
- latitudesh_python_sdk/models/virtual_network.py +26 -0
- latitudesh_python_sdk/models/virtual_network_assignment.py +29 -0
- latitudesh_python_sdk/models/virtual_network_assignment_data.py +65 -0
- latitudesh_python_sdk/models/virtual_network_assignments.py +29 -0
- latitudesh_python_sdk/models/virtual_network_data.py +114 -0
- latitudesh_python_sdk/models/virtual_networks.py +26 -0
- latitudesh_python_sdk/models/volume_data.py +111 -0
- latitudesh_python_sdk/models/vpn_session_data_with_password.py +77 -0
- latitudesh_python_sdk/models/vpn_session_with_password.py +18 -0
- latitudesh_python_sdk/operatingsystems_sdk.py +238 -0
- latitudesh_python_sdk/plans.py +1304 -0
- latitudesh_python_sdk/privatenetworks.py +1612 -0
- latitudesh_python_sdk/projects_sdk.py +830 -0
- latitudesh_python_sdk/py.typed +1 -0
- latitudesh_python_sdk/regions_sdk.py +398 -0
- latitudesh_python_sdk/roles.py +398 -0
- latitudesh_python_sdk/sdk.py +264 -0
- latitudesh_python_sdk/sdkconfiguration.py +50 -0
- latitudesh_python_sdk/servers_sdk.py +3414 -0
- latitudesh_python_sdk/sshkeys_sdk.py +1882 -0
- latitudesh_python_sdk/storage.py +1651 -0
- latitudesh_python_sdk/tags.py +715 -0
- latitudesh_python_sdk/teams_sdk.py +527 -0
- latitudesh_python_sdk/teamsmembers.py +576 -0
- latitudesh_python_sdk/traffic_sdk.py +357 -0
- latitudesh_python_sdk/types/__init__.py +21 -0
- latitudesh_python_sdk/types/basemodel.py +39 -0
- latitudesh_python_sdk/userdata_sdk.py +1888 -0
- latitudesh_python_sdk/userprofile.py +531 -0
- latitudesh_python_sdk/utils/__init__.py +200 -0
- latitudesh_python_sdk/utils/annotations.py +79 -0
- latitudesh_python_sdk/utils/datetimes.py +23 -0
- latitudesh_python_sdk/utils/enums.py +74 -0
- latitudesh_python_sdk/utils/eventstreaming.py +248 -0
- latitudesh_python_sdk/utils/forms.py +234 -0
- latitudesh_python_sdk/utils/headers.py +136 -0
- latitudesh_python_sdk/utils/logger.py +27 -0
- latitudesh_python_sdk/utils/metadata.py +118 -0
- latitudesh_python_sdk/utils/queryparams.py +217 -0
- latitudesh_python_sdk/utils/requestbodies.py +66 -0
- latitudesh_python_sdk/utils/retries.py +281 -0
- latitudesh_python_sdk/utils/security.py +192 -0
- latitudesh_python_sdk/utils/serializers.py +249 -0
- latitudesh_python_sdk/utils/unmarshal_json_response.py +38 -0
- latitudesh_python_sdk/utils/url.py +155 -0
- latitudesh_python_sdk/utils/values.py +137 -0
- latitudesh_python_sdk/virtualmachines.py +941 -0
- latitudesh_python_sdk/vpnsessions.py +715 -0
- latitudesh_python_sdk-2.3.0.dist-info/METADATA +787 -0
- latitudesh_python_sdk-2.3.0.dist-info/RECORD +242 -0
- latitudesh_python_sdk-2.3.0.dist-info/WHEEL +4 -0
- 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
|