Skip to content

Commit 58d3920

Browse files
committed
ci: regenerated with OpenAPI Doc 0.1.0, Speakeay CLI 0.18.0
1 parent 0cd9b2d commit 58d3920

File tree

6 files changed

+133
-12
lines changed

6 files changed

+133
-12
lines changed

gen.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
management:
22
openapi-checksum: 8e8183d84cace76310a3208e63cd7855
33
openapi-version: 0.1.0
4-
speakeasy-version: 0.17.4
4+
speakeasy-version: 0.18.0
55
python:
66
author: Speakeasy
77
description: Speakeasy API Client SDK for Python
88
packagename: speakeasy-client-sdk-python
9-
version: 0.9.1
9+
version: 0.10.0
1010
telemetryenabled: null

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
setuptools.setup(
1010
name="speakeasy-client-sdk-python",
11-
version="0.9.1",
11+
version="0.10.0",
1212
author="Speakeasy",
1313
description="Speakeasy API Client SDK for Python",
1414
long_description=long_description,

src/sdk/sdk.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ class SDK:
3333
_security: shared.Security
3434
_server_url: str = SERVERS[SERVER_PROD]
3535
_language: str = "python"
36-
_sdk_version: str = "0.9.1"
37-
_gen_version: str = "0.17.4"
36+
_sdk_version: str = "0.10.0"
37+
_gen_version: str = "0.18.0"
3838

3939
def __init__(self) -> None:
4040
self._client = requests.Session()

src/sdk/utils/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
from .utils import *
1+
from .retries import *
2+
from .utils import *

src/sdk/utils/retries.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import random
2+
import time
3+
4+
import requests
5+
6+
7+
class BackoffStrategy:
8+
initial_interval: int
9+
max_interval: int
10+
exponent: float
11+
max_elapsed_time: int
12+
13+
def __init__(self, initial_interval: int, max_interval: int, exponent: float, max_elapsed_time: int):
14+
self.initial_interval = initial_interval
15+
self.max_interval = max_interval
16+
self.exponent = exponent
17+
self.max_elapsed_time = max_elapsed_time
18+
19+
20+
class RetryConfig:
21+
strategy: str
22+
backoff: BackoffStrategy
23+
retry_connection_errors: bool
24+
25+
def __init__(self, strategy: str, retry_connection_errors: bool):
26+
self.strategy = strategy
27+
self.retry_connection_errors = retry_connection_errors
28+
29+
30+
class Retries:
31+
config: RetryConfig
32+
status_codes: list[str]
33+
34+
def __init__(self, config: RetryConfig, status_codes: list[str]):
35+
self.config = config
36+
self.status_codes = status_codes
37+
38+
39+
class TemporaryError(Exception):
40+
response: requests.Response
41+
42+
def __init__(self, response: requests.Response):
43+
self.response = response
44+
45+
46+
class PermanentError(Exception):
47+
inner: Exception
48+
49+
def __init__(self, inner: Exception):
50+
self.inner = inner
51+
52+
53+
def retry(fn, retries: Retries):
54+
if retries.config.strategy == 'backoff':
55+
def do_request():
56+
res: requests.Response
57+
try:
58+
res = fn()
59+
60+
for code in retries.status_codes:
61+
if "X" in code.upper():
62+
codeRange = int(code[0])
63+
64+
s = res.status_code / 100
65+
66+
if s >= codeRange and s < codeRange + 1:
67+
raise TemporaryError(res)
68+
else:
69+
parsed_code = int(code)
70+
71+
if res.status_code == parsed_code:
72+
raise TemporaryError(res)
73+
except requests.exceptions.ConnectionError as e:
74+
if not retries.config.config.retry_connection_errors:
75+
raise
76+
else:
77+
raise PermanentError(e)
78+
except requests.exceptions.Timeout as e:
79+
if not retries.config.config.retry_connection_errors:
80+
raise
81+
else:
82+
raise PermanentError(e)
83+
except TemporaryError:
84+
raise
85+
except Exception as e:
86+
raise PermanentError(e)
87+
88+
return res
89+
90+
return retry_with_backoff(do_request, retries.config.backoff.initial_interval, retries.config.backoff.max_interval, retries.config.backoff.exponent, retries.config.backoff.max_elapsed_time)
91+
else:
92+
fn()
93+
94+
95+
def retry_with_backoff(fn, initial_interval=500, max_interval=60000, exponent=1.5, max_elapsed_time=3600000):
96+
start = round(time.time()*1000)
97+
x = 0
98+
99+
while True:
100+
try:
101+
return fn()
102+
except PermanentError as e:
103+
raise e.inner
104+
except Exception as e:
105+
now = round(time.time()*1000)
106+
if now - start > max_elapsed_time:
107+
if isinstance(e, TemporaryError):
108+
return e.response
109+
else:
110+
raise
111+
sleep = ((initial_interval/1000) *
112+
exponent**x + random.uniform(0, 1))
113+
if sleep > max_interval/1000:
114+
sleep = max_interval/1000
115+
time.sleep(sleep)
116+
x += 1

src/sdk/utils/utils.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import re
55
from dataclasses import Field, dataclass, fields, is_dataclass, make_dataclass
66
from datetime import date, datetime
7-
from typing import Callable, Tuple, Union, get_args, get_origin, Optional
7+
from typing import Callable, Optional, Tuple, Union, get_args, get_origin
88
from xmlrpc.client import boolean
99

1010
import requests
@@ -368,7 +368,8 @@ def serialize_json(request: dataclass) -> str:
368368

369369

370370
def dict_to_dataclass(orig: dict[str, any], dataclass_type: str):
371-
cast_type = str(dataclass_type).replace("typing.Optional[", "").replace("]", "")
371+
cast_type = str(dataclass_type).replace(
372+
"typing.Optional[", "").replace("]", "")
372373
cast_module = cast_type.split(".")[:-1]
373374
module = None
374375
for m in cast_module:
@@ -439,7 +440,8 @@ def serialize_multipart_form(media_type: str, request: dataclass) -> Tuple[str,
439440
content = bytes()
440441

441442
for file_field in file_fields:
442-
file_metadata = file_field.metadata.get('multipart_form')
443+
file_metadata = file_field.metadata.get(
444+
'multipart_form')
443445
if file_metadata is None:
444446
continue
445447
if file_metadata.get("content") is True:
@@ -458,7 +460,8 @@ def serialize_multipart_form(media_type: str, request: dataclass) -> Tuple[str,
458460
form.append(to_append)
459461
else:
460462
val = getattr(field_value, field_value_f.name)
461-
field_name = field_metadata.get("field_name", field_value_f.name)
463+
field_name = field_metadata.get(
464+
"field_name", field_value_f.name)
462465
if isinstance(val, list):
463466
for value in val:
464467
form.append([field_name + "[]", [None, value]])
@@ -477,7 +480,7 @@ def _get_form_field_name(obj_field: Field) -> str:
477480

478481

479482
def serialize_dict(original: dict, explode: bool, field_name, existing: Optional[dict[str, list[str]]]) -> dict[
480-
str, list[str]]:
483+
str, list[str]]:
481484
if existing is None:
482485
existing = []
483486

@@ -521,7 +524,8 @@ def serialize_form(data: dataclass, meta_string: str) -> dict[str, any]:
521524
if "style" not in metadata or ("json" in metadata and metadata["json"] is True):
522525
if f_name not in form:
523526
form[f_name] = []
524-
form[f_name].append(json.dumps(getattr(field_value, f_name)))
527+
form[f_name].append(json.dumps(
528+
getattr(field_value, f_name)))
525529
else:
526530
if "style" in metadata and metadata["style"] == "form":
527531
form = form | serialize_form(value, "form")

0 commit comments

Comments
 (0)