spitch 1.4.0__tar.gz → 1.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of spitch might be problematic. Click here for more details.
- spitch-1.6.0/.release-please-manifest.json +3 -0
- {spitch-1.4.0 → spitch-1.6.0}/CHANGELOG.md +26 -0
- {spitch-1.4.0 → spitch-1.6.0}/PKG-INFO +23 -9
- {spitch-1.4.0 → spitch-1.6.0}/README.md +22 -8
- {spitch-1.4.0 → spitch-1.6.0}/examples/example.py +2 -1
- {spitch-1.4.0 → spitch-1.6.0}/pyproject.toml +1 -1
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_base_client.py +8 -1
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_version.py +1 -1
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/resources/speech.py +2 -2
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/types/speech_generate_params.py +1 -1
- {spitch-1.4.0 → spitch-1.6.0}/tests/api_resources/test_speech.py +4 -26
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_client.py +30 -28
- spitch-1.4.0/.release-please-manifest.json +0 -3
- {spitch-1.4.0 → spitch-1.6.0}/.gitignore +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/CONTRIBUTING.md +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/LICENSE +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/SECURITY.md +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/api.md +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/bin/check-release-environment +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/bin/publish-pypi +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/examples/.keep +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/mypy.ini +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/noxfile.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/release-please-config.json +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/requirements-dev.lock +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/requirements.lock +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/__init__.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_client.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_compat.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_constants.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_exceptions.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_files.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_models.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_qs.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_resource.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_response.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_streaming.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_types.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_utils/__init__.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_utils/_logs.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_utils/_proxy.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_utils/_reflection.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_utils/_streams.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_utils/_sync.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_utils/_transform.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_utils/_typing.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/_utils/_utils.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/lib/.keep +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/py.typed +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/resources/__init__.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/resources/text.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/types/__init__.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/types/speech_transcibe_params.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/src/spitch/types/text_tone_mark_params.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/__init__.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/api_resources/__init__.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/api_resources/test_text.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/conftest.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/sample_file.txt +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_deepcopy.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_extract_files.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_files.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_models.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_qs.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_required_args.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_response.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_streaming.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_transform.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_utils/test_proxy.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/test_utils/test_typing.py +0 -0
- {spitch-1.4.0 → spitch-1.6.0}/tests/utils.py +0 -0
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.6.0 (2024-10-07)
|
|
4
|
+
|
|
5
|
+
Full Changelog: [v1.5.0...v1.6.0](https://github.com/spi-tch/spitch-python/compare/v1.5.0...v1.6.0)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* **api:** update via SDK Studio ([#29](https://github.com/spi-tch/spitch-python/issues/29)) ([1dae398](https://github.com/spi-tch/spitch-python/commit/1dae398c9f7ba96bc45d59f4faa2934b2cad59e4))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* **client:** avoid OverflowError with very large retry counts ([#30](https://github.com/spi-tch/spitch-python/issues/30)) ([1e63664](https://github.com/spi-tch/spitch-python/commit/1e63664f64fa1f38f2294df8e06bd60a17885d2f))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Chores
|
|
18
|
+
|
|
19
|
+
* add repr to PageInfo class ([#32](https://github.com/spi-tch/spitch-python/issues/32)) ([ea3c95d](https://github.com/spi-tch/spitch-python/commit/ea3c95d2ce4a9fdd1e558931f8a92904a9394321))
|
|
20
|
+
|
|
21
|
+
## 1.5.0 (2024-10-07)
|
|
22
|
+
|
|
23
|
+
Full Changelog: [v1.4.0...v1.5.0](https://github.com/spi-tch/spitch-python/compare/v1.4.0...v1.5.0)
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* **api:** update via SDK Studio ([#26](https://github.com/spi-tch/spitch-python/issues/26)) ([1fb1268](https://github.com/spi-tch/spitch-python/commit/1fb12681c9bbdadd7dd4cb41f06ee03d38be235f))
|
|
28
|
+
|
|
3
29
|
## 1.4.0 (2024-10-07)
|
|
4
30
|
|
|
5
31
|
Full Changelog: [v1.3.0...v1.4.0](https://github.com/spi-tch/spitch-python/compare/v1.3.0...v1.4.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: spitch
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.0
|
|
4
4
|
Summary: The official Python library for the spitch API
|
|
5
5
|
Project-URL: Homepage, https://github.com/spi-tch/spitch-python
|
|
6
6
|
Project-URL: Repository, https://github.com/spi-tch/spitch-python
|
|
@@ -66,8 +66,10 @@ client = Spitch(
|
|
|
66
66
|
api_key=os.environ.get("SPITCH_API_KEY"),
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
-
response = client.speech.
|
|
69
|
+
response = client.speech.generate(
|
|
70
70
|
language="yo",
|
|
71
|
+
text="text",
|
|
72
|
+
voice="sade",
|
|
71
73
|
)
|
|
72
74
|
```
|
|
73
75
|
|
|
@@ -92,8 +94,10 @@ client = AsyncSpitch(
|
|
|
92
94
|
|
|
93
95
|
|
|
94
96
|
async def main() -> None:
|
|
95
|
-
response = await client.speech.
|
|
97
|
+
response = await client.speech.generate(
|
|
96
98
|
language="yo",
|
|
99
|
+
text="text",
|
|
100
|
+
voice="sade",
|
|
97
101
|
)
|
|
98
102
|
|
|
99
103
|
|
|
@@ -127,8 +131,10 @@ from spitch import Spitch
|
|
|
127
131
|
client = Spitch()
|
|
128
132
|
|
|
129
133
|
try:
|
|
130
|
-
client.speech.
|
|
134
|
+
client.speech.generate(
|
|
131
135
|
language="yo",
|
|
136
|
+
text="text",
|
|
137
|
+
voice="sade",
|
|
132
138
|
)
|
|
133
139
|
except spitch.APIConnectionError as e:
|
|
134
140
|
print("The server could not be reached")
|
|
@@ -172,8 +178,10 @@ client = Spitch(
|
|
|
172
178
|
)
|
|
173
179
|
|
|
174
180
|
# Or, configure per-request:
|
|
175
|
-
client.with_options(max_retries=5).speech.
|
|
181
|
+
client.with_options(max_retries=5).speech.generate(
|
|
176
182
|
language="yo",
|
|
183
|
+
text="text",
|
|
184
|
+
voice="sade",
|
|
177
185
|
)
|
|
178
186
|
```
|
|
179
187
|
|
|
@@ -197,8 +205,10 @@ client = Spitch(
|
|
|
197
205
|
)
|
|
198
206
|
|
|
199
207
|
# Override per-request:
|
|
200
|
-
client.with_options(timeout=5.0).speech.
|
|
208
|
+
client.with_options(timeout=5.0).speech.generate(
|
|
201
209
|
language="yo",
|
|
210
|
+
text="text",
|
|
211
|
+
voice="sade",
|
|
202
212
|
)
|
|
203
213
|
```
|
|
204
214
|
|
|
@@ -238,12 +248,14 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
|
|
|
238
248
|
from spitch import Spitch
|
|
239
249
|
|
|
240
250
|
client = Spitch()
|
|
241
|
-
response = client.speech.with_raw_response.
|
|
251
|
+
response = client.speech.with_raw_response.generate(
|
|
242
252
|
language="yo",
|
|
253
|
+
text="text",
|
|
254
|
+
voice="sade",
|
|
243
255
|
)
|
|
244
256
|
print(response.headers.get('X-My-Header'))
|
|
245
257
|
|
|
246
|
-
speech = response.parse() # get the object that `speech.
|
|
258
|
+
speech = response.parse() # get the object that `speech.generate()` would have returned
|
|
247
259
|
print(speech)
|
|
248
260
|
```
|
|
249
261
|
|
|
@@ -258,8 +270,10 @@ The above interface eagerly reads the full response body when you make the reque
|
|
|
258
270
|
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
|
|
259
271
|
|
|
260
272
|
```python
|
|
261
|
-
with client.speech.with_streaming_response.
|
|
273
|
+
with client.speech.with_streaming_response.generate(
|
|
262
274
|
language="yo",
|
|
275
|
+
text="text",
|
|
276
|
+
voice="sade",
|
|
263
277
|
) as response:
|
|
264
278
|
print(response.headers.get("X-My-Header"))
|
|
265
279
|
|
|
@@ -32,8 +32,10 @@ client = Spitch(
|
|
|
32
32
|
api_key=os.environ.get("SPITCH_API_KEY"),
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
-
response = client.speech.
|
|
35
|
+
response = client.speech.generate(
|
|
36
36
|
language="yo",
|
|
37
|
+
text="text",
|
|
38
|
+
voice="sade",
|
|
37
39
|
)
|
|
38
40
|
```
|
|
39
41
|
|
|
@@ -58,8 +60,10 @@ client = AsyncSpitch(
|
|
|
58
60
|
|
|
59
61
|
|
|
60
62
|
async def main() -> None:
|
|
61
|
-
response = await client.speech.
|
|
63
|
+
response = await client.speech.generate(
|
|
62
64
|
language="yo",
|
|
65
|
+
text="text",
|
|
66
|
+
voice="sade",
|
|
63
67
|
)
|
|
64
68
|
|
|
65
69
|
|
|
@@ -93,8 +97,10 @@ from spitch import Spitch
|
|
|
93
97
|
client = Spitch()
|
|
94
98
|
|
|
95
99
|
try:
|
|
96
|
-
client.speech.
|
|
100
|
+
client.speech.generate(
|
|
97
101
|
language="yo",
|
|
102
|
+
text="text",
|
|
103
|
+
voice="sade",
|
|
98
104
|
)
|
|
99
105
|
except spitch.APIConnectionError as e:
|
|
100
106
|
print("The server could not be reached")
|
|
@@ -138,8 +144,10 @@ client = Spitch(
|
|
|
138
144
|
)
|
|
139
145
|
|
|
140
146
|
# Or, configure per-request:
|
|
141
|
-
client.with_options(max_retries=5).speech.
|
|
147
|
+
client.with_options(max_retries=5).speech.generate(
|
|
142
148
|
language="yo",
|
|
149
|
+
text="text",
|
|
150
|
+
voice="sade",
|
|
143
151
|
)
|
|
144
152
|
```
|
|
145
153
|
|
|
@@ -163,8 +171,10 @@ client = Spitch(
|
|
|
163
171
|
)
|
|
164
172
|
|
|
165
173
|
# Override per-request:
|
|
166
|
-
client.with_options(timeout=5.0).speech.
|
|
174
|
+
client.with_options(timeout=5.0).speech.generate(
|
|
167
175
|
language="yo",
|
|
176
|
+
text="text",
|
|
177
|
+
voice="sade",
|
|
168
178
|
)
|
|
169
179
|
```
|
|
170
180
|
|
|
@@ -204,12 +214,14 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
|
|
|
204
214
|
from spitch import Spitch
|
|
205
215
|
|
|
206
216
|
client = Spitch()
|
|
207
|
-
response = client.speech.with_raw_response.
|
|
217
|
+
response = client.speech.with_raw_response.generate(
|
|
208
218
|
language="yo",
|
|
219
|
+
text="text",
|
|
220
|
+
voice="sade",
|
|
209
221
|
)
|
|
210
222
|
print(response.headers.get('X-My-Header'))
|
|
211
223
|
|
|
212
|
-
speech = response.parse() # get the object that `speech.
|
|
224
|
+
speech = response.parse() # get the object that `speech.generate()` would have returned
|
|
213
225
|
print(speech)
|
|
214
226
|
```
|
|
215
227
|
|
|
@@ -224,8 +236,10 @@ The above interface eagerly reads the full response body when you make the reque
|
|
|
224
236
|
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
|
|
225
237
|
|
|
226
238
|
```python
|
|
227
|
-
with client.speech.with_streaming_response.
|
|
239
|
+
with client.speech.with_streaming_response.generate(
|
|
228
240
|
language="yo",
|
|
241
|
+
text="text",
|
|
242
|
+
voice="sade",
|
|
229
243
|
) as response:
|
|
230
244
|
print(response.headers.get("X-My-Header"))
|
|
231
245
|
|
|
@@ -13,7 +13,8 @@ def main() -> None:
|
|
|
13
13
|
start_time = time.time()
|
|
14
14
|
with client.speech.with_streaming_response.generate(
|
|
15
15
|
language="yo",
|
|
16
|
-
text="Bawo ni ololufe?"
|
|
16
|
+
text="Bawo ni ololufe?",
|
|
17
|
+
voice="funmi"
|
|
17
18
|
) as speech:
|
|
18
19
|
print(f"Time to first byte: {int((time.time() - start_time) * 1000)}ms")
|
|
19
20
|
speech.stream_to_file(speech_file_path)
|
|
@@ -143,6 +143,12 @@ class PageInfo:
|
|
|
143
143
|
self.url = url
|
|
144
144
|
self.params = params
|
|
145
145
|
|
|
146
|
+
@override
|
|
147
|
+
def __repr__(self) -> str:
|
|
148
|
+
if self.url:
|
|
149
|
+
return f"{self.__class__.__name__}(url={self.url})"
|
|
150
|
+
return f"{self.__class__.__name__}(params={self.params})"
|
|
151
|
+
|
|
146
152
|
|
|
147
153
|
class BasePage(GenericModel, Generic[_T]):
|
|
148
154
|
"""
|
|
@@ -689,7 +695,8 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
|
|
|
689
695
|
if retry_after is not None and 0 < retry_after <= 60:
|
|
690
696
|
return retry_after
|
|
691
697
|
|
|
692
|
-
|
|
698
|
+
# Also cap retry count to 1000 to avoid any potential overflows with `pow`
|
|
699
|
+
nb_retries = min(max_retries - remaining_retries, 1000)
|
|
693
700
|
|
|
694
701
|
# Apply exponential backoff, but not more than the max.
|
|
695
702
|
sleep_seconds = min(INITIAL_RETRY_DELAY * pow(2.0, nb_retries), MAX_RETRY_DELAY)
|
|
@@ -61,7 +61,7 @@ class SpeechResource(SyncAPIResource):
|
|
|
61
61
|
*,
|
|
62
62
|
language: Literal["yo", "en", "ha", "ig"],
|
|
63
63
|
text: str,
|
|
64
|
-
voice: Literal["sade", "segun", "femi", "funmi"]
|
|
64
|
+
voice: Literal["sade", "segun", "femi", "funmi"],
|
|
65
65
|
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
|
|
66
66
|
# The extra values given here take precedence over values defined on the client or passed to this method.
|
|
67
67
|
extra_headers: Headers | None = None,
|
|
@@ -171,7 +171,7 @@ class AsyncSpeechResource(AsyncAPIResource):
|
|
|
171
171
|
*,
|
|
172
172
|
language: Literal["yo", "en", "ha", "ig"],
|
|
173
173
|
text: str,
|
|
174
|
-
voice: Literal["sade", "segun", "femi", "funmi"]
|
|
174
|
+
voice: Literal["sade", "segun", "femi", "funmi"],
|
|
175
175
|
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
|
|
176
176
|
# The extra values given here take precedence over values defined on the client or passed to this method.
|
|
177
177
|
extra_headers: Headers | None = None,
|
|
@@ -27,19 +27,6 @@ class TestSpeech:
|
|
|
27
27
|
@parametrize
|
|
28
28
|
@pytest.mark.respx(base_url=base_url)
|
|
29
29
|
def test_method_generate(self, client: Spitch, respx_mock: MockRouter) -> None:
|
|
30
|
-
respx_mock.post("/v1/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
|
|
31
|
-
speech = client.speech.generate(
|
|
32
|
-
language="yo",
|
|
33
|
-
text="text",
|
|
34
|
-
)
|
|
35
|
-
assert speech.is_closed
|
|
36
|
-
assert speech.json() == {"foo": "bar"}
|
|
37
|
-
assert cast(Any, speech.is_closed) is True
|
|
38
|
-
assert isinstance(speech, BinaryAPIResponse)
|
|
39
|
-
|
|
40
|
-
@parametrize
|
|
41
|
-
@pytest.mark.respx(base_url=base_url)
|
|
42
|
-
def test_method_generate_with_all_params(self, client: Spitch, respx_mock: MockRouter) -> None:
|
|
43
30
|
respx_mock.post("/v1/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
|
|
44
31
|
speech = client.speech.generate(
|
|
45
32
|
language="yo",
|
|
@@ -59,6 +46,7 @@ class TestSpeech:
|
|
|
59
46
|
speech = client.speech.with_raw_response.generate(
|
|
60
47
|
language="yo",
|
|
61
48
|
text="text",
|
|
49
|
+
voice="sade",
|
|
62
50
|
)
|
|
63
51
|
|
|
64
52
|
assert speech.is_closed is True
|
|
@@ -73,6 +61,7 @@ class TestSpeech:
|
|
|
73
61
|
with client.speech.with_streaming_response.generate(
|
|
74
62
|
language="yo",
|
|
75
63
|
text="text",
|
|
64
|
+
voice="sade",
|
|
76
65
|
) as speech:
|
|
77
66
|
assert not speech.is_closed
|
|
78
67
|
assert speech.http_request.headers.get("X-Stainless-Lang") == "python"
|
|
@@ -130,19 +119,6 @@ class TestAsyncSpeech:
|
|
|
130
119
|
@parametrize
|
|
131
120
|
@pytest.mark.respx(base_url=base_url)
|
|
132
121
|
async def test_method_generate(self, async_client: AsyncSpitch, respx_mock: MockRouter) -> None:
|
|
133
|
-
respx_mock.post("/v1/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
|
|
134
|
-
speech = await async_client.speech.generate(
|
|
135
|
-
language="yo",
|
|
136
|
-
text="text",
|
|
137
|
-
)
|
|
138
|
-
assert speech.is_closed
|
|
139
|
-
assert await speech.json() == {"foo": "bar"}
|
|
140
|
-
assert cast(Any, speech.is_closed) is True
|
|
141
|
-
assert isinstance(speech, AsyncBinaryAPIResponse)
|
|
142
|
-
|
|
143
|
-
@parametrize
|
|
144
|
-
@pytest.mark.respx(base_url=base_url)
|
|
145
|
-
async def test_method_generate_with_all_params(self, async_client: AsyncSpitch, respx_mock: MockRouter) -> None:
|
|
146
122
|
respx_mock.post("/v1/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
|
|
147
123
|
speech = await async_client.speech.generate(
|
|
148
124
|
language="yo",
|
|
@@ -162,6 +138,7 @@ class TestAsyncSpeech:
|
|
|
162
138
|
speech = await async_client.speech.with_raw_response.generate(
|
|
163
139
|
language="yo",
|
|
164
140
|
text="text",
|
|
141
|
+
voice="sade",
|
|
165
142
|
)
|
|
166
143
|
|
|
167
144
|
assert speech.is_closed is True
|
|
@@ -176,6 +153,7 @@ class TestAsyncSpeech:
|
|
|
176
153
|
async with async_client.speech.with_streaming_response.generate(
|
|
177
154
|
language="yo",
|
|
178
155
|
text="text",
|
|
156
|
+
voice="sade",
|
|
179
157
|
) as speech:
|
|
180
158
|
assert not speech.is_closed
|
|
181
159
|
assert speech.http_request.headers.get("X-Stainless-Lang") == "python"
|
|
@@ -685,6 +685,7 @@ class TestSpitch:
|
|
|
685
685
|
[3, "", 0.5],
|
|
686
686
|
[2, "", 0.5 * 2.0],
|
|
687
687
|
[1, "", 0.5 * 4.0],
|
|
688
|
+
[-1100, "", 7.8], # test large number potentially overflowing
|
|
688
689
|
],
|
|
689
690
|
)
|
|
690
691
|
@mock.patch("time.time", mock.MagicMock(return_value=1696004797))
|
|
@@ -699,12 +700,12 @@ class TestSpitch:
|
|
|
699
700
|
@mock.patch("spitch._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
|
|
700
701
|
@pytest.mark.respx(base_url=base_url)
|
|
701
702
|
def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None:
|
|
702
|
-
respx_mock.post("/v1/
|
|
703
|
+
respx_mock.post("/v1/speech").mock(side_effect=httpx.TimeoutException("Test timeout error"))
|
|
703
704
|
|
|
704
705
|
with pytest.raises(APITimeoutError):
|
|
705
706
|
self.client.post(
|
|
706
|
-
"/v1/
|
|
707
|
-
body=cast(object, dict(language="yo")),
|
|
707
|
+
"/v1/speech",
|
|
708
|
+
body=cast(object, dict(language="yo", text="text", voice="sade")),
|
|
708
709
|
cast_to=httpx.Response,
|
|
709
710
|
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
|
|
710
711
|
)
|
|
@@ -714,12 +715,12 @@ class TestSpitch:
|
|
|
714
715
|
@mock.patch("spitch._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
|
|
715
716
|
@pytest.mark.respx(base_url=base_url)
|
|
716
717
|
def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None:
|
|
717
|
-
respx_mock.post("/v1/
|
|
718
|
+
respx_mock.post("/v1/speech").mock(return_value=httpx.Response(500))
|
|
718
719
|
|
|
719
720
|
with pytest.raises(APIStatusError):
|
|
720
721
|
self.client.post(
|
|
721
|
-
"/v1/
|
|
722
|
-
body=cast(object, dict(language="yo")),
|
|
722
|
+
"/v1/speech",
|
|
723
|
+
body=cast(object, dict(language="yo", text="text", voice="sade")),
|
|
723
724
|
cast_to=httpx.Response,
|
|
724
725
|
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
|
|
725
726
|
)
|
|
@@ -741,9 +742,9 @@ class TestSpitch:
|
|
|
741
742
|
return httpx.Response(500)
|
|
742
743
|
return httpx.Response(200)
|
|
743
744
|
|
|
744
|
-
respx_mock.post("/v1/
|
|
745
|
+
respx_mock.post("/v1/speech").mock(side_effect=retry_handler)
|
|
745
746
|
|
|
746
|
-
response = client.speech.with_raw_response.
|
|
747
|
+
response = client.speech.with_raw_response.generate(language="yo", text="text", voice="sade")
|
|
747
748
|
|
|
748
749
|
assert response.retries_taken == failures_before_success
|
|
749
750
|
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
|
|
@@ -765,10 +766,10 @@ class TestSpitch:
|
|
|
765
766
|
return httpx.Response(500)
|
|
766
767
|
return httpx.Response(200)
|
|
767
768
|
|
|
768
|
-
respx_mock.post("/v1/
|
|
769
|
+
respx_mock.post("/v1/speech").mock(side_effect=retry_handler)
|
|
769
770
|
|
|
770
|
-
response = client.speech.with_raw_response.
|
|
771
|
-
language="yo", extra_headers={"x-stainless-retry-count": Omit()}
|
|
771
|
+
response = client.speech.with_raw_response.generate(
|
|
772
|
+
language="yo", text="text", voice="sade", extra_headers={"x-stainless-retry-count": Omit()}
|
|
772
773
|
)
|
|
773
774
|
|
|
774
775
|
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
|
|
@@ -790,10 +791,10 @@ class TestSpitch:
|
|
|
790
791
|
return httpx.Response(500)
|
|
791
792
|
return httpx.Response(200)
|
|
792
793
|
|
|
793
|
-
respx_mock.post("/v1/
|
|
794
|
+
respx_mock.post("/v1/speech").mock(side_effect=retry_handler)
|
|
794
795
|
|
|
795
|
-
response = client.speech.with_raw_response.
|
|
796
|
-
language="yo", extra_headers={"x-stainless-retry-count": "42"}
|
|
796
|
+
response = client.speech.with_raw_response.generate(
|
|
797
|
+
language="yo", text="text", voice="sade", extra_headers={"x-stainless-retry-count": "42"}
|
|
797
798
|
)
|
|
798
799
|
|
|
799
800
|
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
|
|
@@ -1454,6 +1455,7 @@ class TestAsyncSpitch:
|
|
|
1454
1455
|
[3, "", 0.5],
|
|
1455
1456
|
[2, "", 0.5 * 2.0],
|
|
1456
1457
|
[1, "", 0.5 * 4.0],
|
|
1458
|
+
[-1100, "", 7.8], # test large number potentially overflowing
|
|
1457
1459
|
],
|
|
1458
1460
|
)
|
|
1459
1461
|
@mock.patch("time.time", mock.MagicMock(return_value=1696004797))
|
|
@@ -1469,12 +1471,12 @@ class TestAsyncSpitch:
|
|
|
1469
1471
|
@mock.patch("spitch._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
|
|
1470
1472
|
@pytest.mark.respx(base_url=base_url)
|
|
1471
1473
|
async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None:
|
|
1472
|
-
respx_mock.post("/v1/
|
|
1474
|
+
respx_mock.post("/v1/speech").mock(side_effect=httpx.TimeoutException("Test timeout error"))
|
|
1473
1475
|
|
|
1474
1476
|
with pytest.raises(APITimeoutError):
|
|
1475
1477
|
await self.client.post(
|
|
1476
|
-
"/v1/
|
|
1477
|
-
body=cast(object, dict(language="yo")),
|
|
1478
|
+
"/v1/speech",
|
|
1479
|
+
body=cast(object, dict(language="yo", text="text", voice="sade")),
|
|
1478
1480
|
cast_to=httpx.Response,
|
|
1479
1481
|
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
|
|
1480
1482
|
)
|
|
@@ -1484,12 +1486,12 @@ class TestAsyncSpitch:
|
|
|
1484
1486
|
@mock.patch("spitch._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
|
|
1485
1487
|
@pytest.mark.respx(base_url=base_url)
|
|
1486
1488
|
async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None:
|
|
1487
|
-
respx_mock.post("/v1/
|
|
1489
|
+
respx_mock.post("/v1/speech").mock(return_value=httpx.Response(500))
|
|
1488
1490
|
|
|
1489
1491
|
with pytest.raises(APIStatusError):
|
|
1490
1492
|
await self.client.post(
|
|
1491
|
-
"/v1/
|
|
1492
|
-
body=cast(object, dict(language="yo")),
|
|
1493
|
+
"/v1/speech",
|
|
1494
|
+
body=cast(object, dict(language="yo", text="text", voice="sade")),
|
|
1493
1495
|
cast_to=httpx.Response,
|
|
1494
1496
|
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
|
|
1495
1497
|
)
|
|
@@ -1514,9 +1516,9 @@ class TestAsyncSpitch:
|
|
|
1514
1516
|
return httpx.Response(500)
|
|
1515
1517
|
return httpx.Response(200)
|
|
1516
1518
|
|
|
1517
|
-
respx_mock.post("/v1/
|
|
1519
|
+
respx_mock.post("/v1/speech").mock(side_effect=retry_handler)
|
|
1518
1520
|
|
|
1519
|
-
response = await client.speech.with_raw_response.
|
|
1521
|
+
response = await client.speech.with_raw_response.generate(language="yo", text="text", voice="sade")
|
|
1520
1522
|
|
|
1521
1523
|
assert response.retries_taken == failures_before_success
|
|
1522
1524
|
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
|
|
@@ -1539,10 +1541,10 @@ class TestAsyncSpitch:
|
|
|
1539
1541
|
return httpx.Response(500)
|
|
1540
1542
|
return httpx.Response(200)
|
|
1541
1543
|
|
|
1542
|
-
respx_mock.post("/v1/
|
|
1544
|
+
respx_mock.post("/v1/speech").mock(side_effect=retry_handler)
|
|
1543
1545
|
|
|
1544
|
-
response = await client.speech.with_raw_response.
|
|
1545
|
-
language="yo", extra_headers={"x-stainless-retry-count": Omit()}
|
|
1546
|
+
response = await client.speech.with_raw_response.generate(
|
|
1547
|
+
language="yo", text="text", voice="sade", extra_headers={"x-stainless-retry-count": Omit()}
|
|
1546
1548
|
)
|
|
1547
1549
|
|
|
1548
1550
|
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
|
|
@@ -1565,10 +1567,10 @@ class TestAsyncSpitch:
|
|
|
1565
1567
|
return httpx.Response(500)
|
|
1566
1568
|
return httpx.Response(200)
|
|
1567
1569
|
|
|
1568
|
-
respx_mock.post("/v1/
|
|
1570
|
+
respx_mock.post("/v1/speech").mock(side_effect=retry_handler)
|
|
1569
1571
|
|
|
1570
|
-
response = await client.speech.with_raw_response.
|
|
1571
|
-
language="yo", extra_headers={"x-stainless-retry-count": "42"}
|
|
1572
|
+
response = await client.speech.with_raw_response.generate(
|
|
1573
|
+
language="yo", text="text", voice="sade", extra_headers={"x-stainless-retry-count": "42"}
|
|
1572
1574
|
)
|
|
1573
1575
|
|
|
1574
1576
|
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|