runwayml 3.4.0__tar.gz → 3.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.
- runwayml-3.6.0/.release-please-manifest.json +3 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/CHANGELOG.md +45 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/PKG-INFO +43 -3
- {runwayml-3.4.0 → runwayml-3.6.0}/README.md +39 -2
- runwayml-3.6.0/examples/generate_image.py +16 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/pyproject.toml +5 -2
- {runwayml-3.4.0 → runwayml-3.6.0}/requirements-dev.lock +31 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/requirements.lock +27 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/__init__.py +5 -1
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_base_client.py +38 -2
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_version.py +1 -1
- runwayml-3.6.0/src/runwayml/lib/polling.py +127 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/resources/image_to_video.py +20 -6
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/resources/tasks.py +17 -4
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/resources/text_to_image.py +10 -4
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/resources/video_upscale.py +10 -4
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/types/image_to_video_create_params.py +13 -2
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/api_resources/test_image_to_video.py +13 -9
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/api_resources/test_organization.py +3 -1
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/api_resources/test_tasks.py +3 -1
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/api_resources/test_text_to_image.py +3 -1
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/api_resources/test_video_upscale.py +3 -1
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/conftest.py +39 -6
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_client.py +72 -83
- runwayml-3.4.0/.release-please-manifest.json +0 -3
- {runwayml-3.4.0 → runwayml-3.6.0}/.gitignore +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/CONTRIBUTING.md +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/LICENSE +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/SECURITY.md +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/api.md +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/bin/check-release-environment +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/bin/publish-pypi +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/examples/.keep +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/mypy.ini +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/noxfile.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/release-please-config.json +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_client.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_compat.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_constants.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_exceptions.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_files.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_models.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_qs.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_resource.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_response.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_streaming.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_types.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_utils/__init__.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_utils/_logs.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_utils/_proxy.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_utils/_reflection.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_utils/_resources_proxy.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_utils/_streams.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_utils/_sync.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_utils/_transform.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_utils/_typing.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/_utils/_utils.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/lib/.keep +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/py.typed +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/resources/__init__.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/resources/organization.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/types/__init__.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/types/image_to_video_create_response.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/types/organization_retrieve_response.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/types/task_retrieve_response.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/types/text_to_image_create_params.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/types/text_to_image_create_response.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/types/video_upscale_create_params.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/src/runwayml/types/video_upscale_create_response.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/__init__.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/api_resources/__init__.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/sample_file.txt +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_deepcopy.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_extract_files.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_files.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_models.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_qs.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_required_args.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_response.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_streaming.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_transform.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_utils/test_proxy.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/test_utils/test_typing.py +0 -0
- {runwayml-3.4.0 → runwayml-3.6.0}/tests/utils.py +0 -0
@@ -1,5 +1,50 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 3.6.0 (2025-06-23)
|
4
|
+
|
5
|
+
Full Changelog: [v3.5.0...v3.6.0](https://github.com/runwayml/sdk-python/compare/v3.5.0...v3.6.0)
|
6
|
+
|
7
|
+
### Features
|
8
|
+
|
9
|
+
* **client:** add support for aiohttp ([7d5490c](https://github.com/runwayml/sdk-python/commit/7d5490ca015dd0ff55789889036cc1bd32a58c43))
|
10
|
+
|
11
|
+
|
12
|
+
### Bug Fixes
|
13
|
+
|
14
|
+
* **tests:** fix: tests which call HTTP endpoints directly with the example parameters ([33301dd](https://github.com/runwayml/sdk-python/commit/33301ddf84cc64581d715d6b8ce1eda48ff66ed5))
|
15
|
+
|
16
|
+
|
17
|
+
### Chores
|
18
|
+
|
19
|
+
* **readme:** update badges ([147dc95](https://github.com/runwayml/sdk-python/commit/147dc95f9ab390065ab96403a88ca5a87e59f597))
|
20
|
+
|
21
|
+
|
22
|
+
### Documentation
|
23
|
+
|
24
|
+
* **client:** fix httpx.Timeout documentation reference ([af9fecb](https://github.com/runwayml/sdk-python/commit/af9fecb38a4075fcc8f7687f2ef130ad8c813389))
|
25
|
+
|
26
|
+
## 3.5.0 (2025-06-17)
|
27
|
+
|
28
|
+
Full Changelog: [v3.4.0...v3.5.0](https://github.com/runwayml/sdk-python/compare/v3.4.0...v3.5.0)
|
29
|
+
|
30
|
+
### Features
|
31
|
+
|
32
|
+
* **api:** SDK updates, contentModeration for i2v ([1286e32](https://github.com/runwayml/sdk-python/commit/1286e3239f388143404c4b0a61816f5f6282fe1c))
|
33
|
+
* **api:** SDK updates, contentModeration for i2v ([8ff202e](https://github.com/runwayml/sdk-python/commit/8ff202ee39dc5856118bf1f3f5537e459a120967))
|
34
|
+
|
35
|
+
|
36
|
+
### Bug Fixes
|
37
|
+
|
38
|
+
* **client:** correctly parse binary response | stream ([fc9bedb](https://github.com/runwayml/sdk-python/commit/fc9bedb3cbb47849e83a5982ed92a694796e80c7))
|
39
|
+
|
40
|
+
|
41
|
+
### Chores
|
42
|
+
|
43
|
+
* **ci:** enable for pull requests ([4b439c9](https://github.com/runwayml/sdk-python/commit/4b439c99012918849be4fa64b1ab8d1802cee6e6))
|
44
|
+
* **internal:** update conftest.py ([0ff71fd](https://github.com/runwayml/sdk-python/commit/0ff71fd67a421dbff729e98418b6cd72ed0e57b3))
|
45
|
+
* **tests:** add tests for httpx client instantiation & proxies ([89e5fbe](https://github.com/runwayml/sdk-python/commit/89e5fbef9e8a64d050252f489b2d76e4c510c663))
|
46
|
+
* **tests:** run tests in parallel ([7edbcd1](https://github.com/runwayml/sdk-python/commit/7edbcd1db04ed139e026701fe24501199b4eaffd))
|
47
|
+
|
3
48
|
## 3.4.0 (2025-06-04)
|
4
49
|
|
5
50
|
Full Changelog: [v3.3.0...v3.4.0](https://github.com/runwayml/sdk-python/compare/v3.3.0...v3.4.0)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: runwayml
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.6.0
|
4
4
|
Summary: The official Python library for the runwayml API
|
5
5
|
Project-URL: Homepage, https://github.com/runwayml/sdk-python
|
6
6
|
Project-URL: Repository, https://github.com/runwayml/sdk-python
|
@@ -27,11 +27,14 @@ Requires-Dist: httpx<1,>=0.23.0
|
|
27
27
|
Requires-Dist: pydantic<3,>=1.9.0
|
28
28
|
Requires-Dist: sniffio
|
29
29
|
Requires-Dist: typing-extensions<5,>=4.10
|
30
|
+
Provides-Extra: aiohttp
|
31
|
+
Requires-Dist: aiohttp; extra == 'aiohttp'
|
32
|
+
Requires-Dist: httpx-aiohttp>=0.1.6; extra == 'aiohttp'
|
30
33
|
Description-Content-Type: text/markdown
|
31
34
|
|
32
35
|
# RunwayML Python API library
|
33
36
|
|
34
|
-
[](https://pypi.org/project/runwayml/)
|
37
|
+
[>)](https://pypi.org/project/runwayml/)
|
35
38
|
|
36
39
|
The RunwayML Python library provides convenient access to the RunwayML REST API from any Python 3.8+
|
37
40
|
application. The library includes type definitions for all request params and response fields,
|
@@ -105,6 +108,43 @@ asyncio.run(main())
|
|
105
108
|
|
106
109
|
Functionality between the synchronous and asynchronous clients is otherwise identical.
|
107
110
|
|
111
|
+
### With aiohttp
|
112
|
+
|
113
|
+
By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.
|
114
|
+
|
115
|
+
You can enable this by installing `aiohttp`:
|
116
|
+
|
117
|
+
```sh
|
118
|
+
# install from PyPI
|
119
|
+
pip install runwayml[aiohttp]
|
120
|
+
```
|
121
|
+
|
122
|
+
Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
|
123
|
+
|
124
|
+
```python
|
125
|
+
import os
|
126
|
+
import asyncio
|
127
|
+
from runwayml import DefaultAioHttpClient
|
128
|
+
from runwayml import AsyncRunwayML
|
129
|
+
|
130
|
+
|
131
|
+
async def main() -> None:
|
132
|
+
async with AsyncRunwayML(
|
133
|
+
api_key=os.environ.get("RUNWAYML_API_SECRET"), # This is the default and can be omitted
|
134
|
+
http_client=DefaultAioHttpClient(),
|
135
|
+
) as client:
|
136
|
+
image_to_video = await client.image_to_video.create(
|
137
|
+
model="gen4_turbo",
|
138
|
+
prompt_image="https://example.com/assets/bunny.jpg",
|
139
|
+
ratio="1280:720",
|
140
|
+
prompt_text="The bunny is eating a carrot",
|
141
|
+
)
|
142
|
+
print(image_to_video.id)
|
143
|
+
|
144
|
+
|
145
|
+
asyncio.run(main())
|
146
|
+
```
|
147
|
+
|
108
148
|
## Using types
|
109
149
|
|
110
150
|
Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
|
@@ -206,7 +246,7 @@ client.with_options(max_retries=5).image_to_video.create(
|
|
206
246
|
### Timeouts
|
207
247
|
|
208
248
|
By default requests time out after 1 minute. You can configure this with a `timeout` option,
|
209
|
-
which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object:
|
249
|
+
which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:
|
210
250
|
|
211
251
|
```python
|
212
252
|
from runwayml import RunwayML
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# RunwayML Python API library
|
2
2
|
|
3
|
-
[](https://pypi.org/project/runwayml/)
|
3
|
+
[>)](https://pypi.org/project/runwayml/)
|
4
4
|
|
5
5
|
The RunwayML Python library provides convenient access to the RunwayML REST API from any Python 3.8+
|
6
6
|
application. The library includes type definitions for all request params and response fields,
|
@@ -74,6 +74,43 @@ asyncio.run(main())
|
|
74
74
|
|
75
75
|
Functionality between the synchronous and asynchronous clients is otherwise identical.
|
76
76
|
|
77
|
+
### With aiohttp
|
78
|
+
|
79
|
+
By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.
|
80
|
+
|
81
|
+
You can enable this by installing `aiohttp`:
|
82
|
+
|
83
|
+
```sh
|
84
|
+
# install from PyPI
|
85
|
+
pip install runwayml[aiohttp]
|
86
|
+
```
|
87
|
+
|
88
|
+
Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
|
89
|
+
|
90
|
+
```python
|
91
|
+
import os
|
92
|
+
import asyncio
|
93
|
+
from runwayml import DefaultAioHttpClient
|
94
|
+
from runwayml import AsyncRunwayML
|
95
|
+
|
96
|
+
|
97
|
+
async def main() -> None:
|
98
|
+
async with AsyncRunwayML(
|
99
|
+
api_key=os.environ.get("RUNWAYML_API_SECRET"), # This is the default and can be omitted
|
100
|
+
http_client=DefaultAioHttpClient(),
|
101
|
+
) as client:
|
102
|
+
image_to_video = await client.image_to_video.create(
|
103
|
+
model="gen4_turbo",
|
104
|
+
prompt_image="https://example.com/assets/bunny.jpg",
|
105
|
+
ratio="1280:720",
|
106
|
+
prompt_text="The bunny is eating a carrot",
|
107
|
+
)
|
108
|
+
print(image_to_video.id)
|
109
|
+
|
110
|
+
|
111
|
+
asyncio.run(main())
|
112
|
+
```
|
113
|
+
|
77
114
|
## Using types
|
78
115
|
|
79
116
|
Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
|
@@ -175,7 +212,7 @@ client.with_options(max_retries=5).image_to_video.create(
|
|
175
212
|
### Timeouts
|
176
213
|
|
177
214
|
By default requests time out after 1 minute. You can configure this with a `timeout` option,
|
178
|
-
which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object:
|
215
|
+
which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:
|
179
216
|
|
180
217
|
```python
|
181
218
|
from runwayml import RunwayML
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from runwayml import RunwayML, TaskFailedError
|
2
|
+
|
3
|
+
client = RunwayML()
|
4
|
+
|
5
|
+
image_task = client.text_to_image.create(
|
6
|
+
model="gen4_image",
|
7
|
+
prompt_text="A beautiful sunset over a calm ocean",
|
8
|
+
ratio="1920:1080",
|
9
|
+
)
|
10
|
+
try:
|
11
|
+
output = image_task.wait_for_task_output()
|
12
|
+
except TaskFailedError as e:
|
13
|
+
print('The image failed to generate.')
|
14
|
+
print(e.task_details)
|
15
|
+
else:
|
16
|
+
print(output.output[0]) # type: ignore
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "runwayml"
|
3
|
-
version = "3.
|
3
|
+
version = "3.6.0"
|
4
4
|
description = "The official Python library for the runwayml API"
|
5
5
|
dynamic = ["readme"]
|
6
6
|
license = "Apache-2.0"
|
@@ -37,6 +37,8 @@ classifiers = [
|
|
37
37
|
Homepage = "https://github.com/runwayml/sdk-python"
|
38
38
|
Repository = "https://github.com/runwayml/sdk-python"
|
39
39
|
|
40
|
+
[project.optional-dependencies]
|
41
|
+
aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.6"]
|
40
42
|
|
41
43
|
[tool.rye]
|
42
44
|
managed = true
|
@@ -54,6 +56,7 @@ dev-dependencies = [
|
|
54
56
|
"importlib-metadata>=6.7.0",
|
55
57
|
"rich>=13.7.1",
|
56
58
|
"nest_asyncio==1.6.0",
|
59
|
+
"pytest-xdist>=3.6.1",
|
57
60
|
]
|
58
61
|
|
59
62
|
[tool.rye.scripts]
|
@@ -125,7 +128,7 @@ replacement = '[\1](https://github.com/runwayml/sdk-python/tree/main/\g<2>)'
|
|
125
128
|
|
126
129
|
[tool.pytest.ini_options]
|
127
130
|
testpaths = ["tests"]
|
128
|
-
addopts = "--tb=short"
|
131
|
+
addopts = "--tb=short -n auto"
|
129
132
|
xfail_strict = true
|
130
133
|
asyncio_mode = "auto"
|
131
134
|
asyncio_default_fixture_loop_scope = "session"
|
@@ -10,6 +10,13 @@
|
|
10
10
|
# universal: false
|
11
11
|
|
12
12
|
-e file:.
|
13
|
+
aiohappyeyeballs==2.6.1
|
14
|
+
# via aiohttp
|
15
|
+
aiohttp==3.12.8
|
16
|
+
# via httpx-aiohttp
|
17
|
+
# via runwayml
|
18
|
+
aiosignal==1.3.2
|
19
|
+
# via aiohttp
|
13
20
|
annotated-types==0.6.0
|
14
21
|
# via pydantic
|
15
22
|
anyio==4.4.0
|
@@ -17,6 +24,10 @@ anyio==4.4.0
|
|
17
24
|
# via runwayml
|
18
25
|
argcomplete==3.1.2
|
19
26
|
# via nox
|
27
|
+
async-timeout==5.0.1
|
28
|
+
# via aiohttp
|
29
|
+
attrs==25.3.0
|
30
|
+
# via aiohttp
|
20
31
|
certifi==2023.7.22
|
21
32
|
# via httpcore
|
22
33
|
# via httpx
|
@@ -30,18 +41,27 @@ distro==1.8.0
|
|
30
41
|
exceptiongroup==1.2.2
|
31
42
|
# via anyio
|
32
43
|
# via pytest
|
44
|
+
execnet==2.1.1
|
45
|
+
# via pytest-xdist
|
33
46
|
filelock==3.12.4
|
34
47
|
# via virtualenv
|
48
|
+
frozenlist==1.6.2
|
49
|
+
# via aiohttp
|
50
|
+
# via aiosignal
|
35
51
|
h11==0.14.0
|
36
52
|
# via httpcore
|
37
53
|
httpcore==1.0.2
|
38
54
|
# via httpx
|
39
55
|
httpx==0.28.1
|
56
|
+
# via httpx-aiohttp
|
40
57
|
# via respx
|
41
58
|
# via runwayml
|
59
|
+
httpx-aiohttp==0.1.6
|
60
|
+
# via runwayml
|
42
61
|
idna==3.4
|
43
62
|
# via anyio
|
44
63
|
# via httpx
|
64
|
+
# via yarl
|
45
65
|
importlib-metadata==7.0.0
|
46
66
|
iniconfig==2.0.0
|
47
67
|
# via pytest
|
@@ -49,6 +69,9 @@ markdown-it-py==3.0.0
|
|
49
69
|
# via rich
|
50
70
|
mdurl==0.1.2
|
51
71
|
# via markdown-it-py
|
72
|
+
multidict==6.4.4
|
73
|
+
# via aiohttp
|
74
|
+
# via yarl
|
52
75
|
mypy==1.14.1
|
53
76
|
mypy-extensions==1.0.0
|
54
77
|
# via mypy
|
@@ -63,6 +86,9 @@ platformdirs==3.11.0
|
|
63
86
|
# via virtualenv
|
64
87
|
pluggy==1.5.0
|
65
88
|
# via pytest
|
89
|
+
propcache==0.3.1
|
90
|
+
# via aiohttp
|
91
|
+
# via yarl
|
66
92
|
pydantic==2.10.3
|
67
93
|
# via runwayml
|
68
94
|
pydantic-core==2.27.1
|
@@ -72,7 +98,9 @@ pygments==2.18.0
|
|
72
98
|
pyright==1.1.399
|
73
99
|
pytest==8.3.3
|
74
100
|
# via pytest-asyncio
|
101
|
+
# via pytest-xdist
|
75
102
|
pytest-asyncio==0.24.0
|
103
|
+
pytest-xdist==3.7.0
|
76
104
|
python-dateutil==2.8.2
|
77
105
|
# via time-machine
|
78
106
|
pytz==2023.3.post1
|
@@ -93,6 +121,7 @@ tomli==2.0.2
|
|
93
121
|
# via pytest
|
94
122
|
typing-extensions==4.12.2
|
95
123
|
# via anyio
|
124
|
+
# via multidict
|
96
125
|
# via mypy
|
97
126
|
# via pydantic
|
98
127
|
# via pydantic-core
|
@@ -100,5 +129,7 @@ typing-extensions==4.12.2
|
|
100
129
|
# via runwayml
|
101
130
|
virtualenv==20.24.5
|
102
131
|
# via nox
|
132
|
+
yarl==1.20.0
|
133
|
+
# via aiohttp
|
103
134
|
zipp==3.17.0
|
104
135
|
# via importlib-metadata
|
@@ -10,11 +10,22 @@
|
|
10
10
|
# universal: false
|
11
11
|
|
12
12
|
-e file:.
|
13
|
+
aiohappyeyeballs==2.6.1
|
14
|
+
# via aiohttp
|
15
|
+
aiohttp==3.12.8
|
16
|
+
# via httpx-aiohttp
|
17
|
+
# via runwayml
|
18
|
+
aiosignal==1.3.2
|
19
|
+
# via aiohttp
|
13
20
|
annotated-types==0.6.0
|
14
21
|
# via pydantic
|
15
22
|
anyio==4.4.0
|
16
23
|
# via httpx
|
17
24
|
# via runwayml
|
25
|
+
async-timeout==5.0.1
|
26
|
+
# via aiohttp
|
27
|
+
attrs==25.3.0
|
28
|
+
# via aiohttp
|
18
29
|
certifi==2023.7.22
|
19
30
|
# via httpcore
|
20
31
|
# via httpx
|
@@ -22,15 +33,28 @@ distro==1.8.0
|
|
22
33
|
# via runwayml
|
23
34
|
exceptiongroup==1.2.2
|
24
35
|
# via anyio
|
36
|
+
frozenlist==1.6.2
|
37
|
+
# via aiohttp
|
38
|
+
# via aiosignal
|
25
39
|
h11==0.14.0
|
26
40
|
# via httpcore
|
27
41
|
httpcore==1.0.2
|
28
42
|
# via httpx
|
29
43
|
httpx==0.28.1
|
44
|
+
# via httpx-aiohttp
|
45
|
+
# via runwayml
|
46
|
+
httpx-aiohttp==0.1.6
|
30
47
|
# via runwayml
|
31
48
|
idna==3.4
|
32
49
|
# via anyio
|
33
50
|
# via httpx
|
51
|
+
# via yarl
|
52
|
+
multidict==6.4.4
|
53
|
+
# via aiohttp
|
54
|
+
# via yarl
|
55
|
+
propcache==0.3.1
|
56
|
+
# via aiohttp
|
57
|
+
# via yarl
|
34
58
|
pydantic==2.10.3
|
35
59
|
# via runwayml
|
36
60
|
pydantic-core==2.27.1
|
@@ -40,6 +64,9 @@ sniffio==1.3.0
|
|
40
64
|
# via runwayml
|
41
65
|
typing-extensions==4.12.2
|
42
66
|
# via anyio
|
67
|
+
# via multidict
|
43
68
|
# via pydantic
|
44
69
|
# via pydantic-core
|
45
70
|
# via runwayml
|
71
|
+
yarl==1.20.0
|
72
|
+
# via aiohttp
|
@@ -36,7 +36,8 @@ from ._exceptions import (
|
|
36
36
|
UnprocessableEntityError,
|
37
37
|
APIResponseValidationError,
|
38
38
|
)
|
39
|
-
from .
|
39
|
+
from .lib.polling import TaskFailedError, TaskTimeoutError
|
40
|
+
from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient
|
40
41
|
from ._utils._logs import setup_logging as _setup_logging
|
41
42
|
|
42
43
|
__all__ = [
|
@@ -78,6 +79,9 @@ __all__ = [
|
|
78
79
|
"DEFAULT_CONNECTION_LIMITS",
|
79
80
|
"DefaultHttpxClient",
|
80
81
|
"DefaultAsyncHttpxClient",
|
82
|
+
"DefaultAioHttpClient",
|
83
|
+
"TaskFailedError",
|
84
|
+
"TaskTimeoutError",
|
81
85
|
]
|
82
86
|
|
83
87
|
if not _t.TYPE_CHECKING:
|
@@ -1071,7 +1071,14 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
|
|
1071
1071
|
) -> ResponseT:
|
1072
1072
|
origin = get_origin(cast_to) or cast_to
|
1073
1073
|
|
1074
|
-
if
|
1074
|
+
if (
|
1075
|
+
inspect.isclass(origin)
|
1076
|
+
and issubclass(origin, BaseAPIResponse)
|
1077
|
+
# we only want to actually return the custom BaseAPIResponse class if we're
|
1078
|
+
# returning the raw response, or if we're not streaming SSE, as if we're streaming
|
1079
|
+
# SSE then `cast_to` doesn't actively reflect the type we need to parse into
|
1080
|
+
and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
|
1081
|
+
):
|
1075
1082
|
if not issubclass(origin, APIResponse):
|
1076
1083
|
raise TypeError(f"API Response types must subclass {APIResponse}; Received {origin}")
|
1077
1084
|
|
@@ -1282,6 +1289,24 @@ class _DefaultAsyncHttpxClient(httpx.AsyncClient):
|
|
1282
1289
|
super().__init__(**kwargs)
|
1283
1290
|
|
1284
1291
|
|
1292
|
+
try:
|
1293
|
+
import httpx_aiohttp
|
1294
|
+
except ImportError:
|
1295
|
+
|
1296
|
+
class _DefaultAioHttpClient(httpx.AsyncClient):
|
1297
|
+
def __init__(self, **_kwargs: Any) -> None:
|
1298
|
+
raise RuntimeError("To use the aiohttp client you must have installed the package with the `aiohttp` extra")
|
1299
|
+
else:
|
1300
|
+
|
1301
|
+
class _DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore
|
1302
|
+
def __init__(self, **kwargs: Any) -> None:
|
1303
|
+
kwargs.setdefault("timeout", DEFAULT_TIMEOUT)
|
1304
|
+
kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS)
|
1305
|
+
kwargs.setdefault("follow_redirects", True)
|
1306
|
+
|
1307
|
+
super().__init__(**kwargs)
|
1308
|
+
|
1309
|
+
|
1285
1310
|
if TYPE_CHECKING:
|
1286
1311
|
DefaultAsyncHttpxClient = httpx.AsyncClient
|
1287
1312
|
"""An alias to `httpx.AsyncClient` that provides the same defaults that this SDK
|
@@ -1290,8 +1315,12 @@ if TYPE_CHECKING:
|
|
1290
1315
|
This is useful because overriding the `http_client` with your own instance of
|
1291
1316
|
`httpx.AsyncClient` will result in httpx's defaults being used, not ours.
|
1292
1317
|
"""
|
1318
|
+
|
1319
|
+
DefaultAioHttpClient = httpx.AsyncClient
|
1320
|
+
"""An alias to `httpx.AsyncClient` that changes the default HTTP transport to `aiohttp`."""
|
1293
1321
|
else:
|
1294
1322
|
DefaultAsyncHttpxClient = _DefaultAsyncHttpxClient
|
1323
|
+
DefaultAioHttpClient = _DefaultAioHttpClient
|
1295
1324
|
|
1296
1325
|
|
1297
1326
|
class AsyncHttpxClientWrapper(DefaultAsyncHttpxClient):
|
@@ -1574,7 +1603,14 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
|
|
1574
1603
|
) -> ResponseT:
|
1575
1604
|
origin = get_origin(cast_to) or cast_to
|
1576
1605
|
|
1577
|
-
if
|
1606
|
+
if (
|
1607
|
+
inspect.isclass(origin)
|
1608
|
+
and issubclass(origin, BaseAPIResponse)
|
1609
|
+
# we only want to actually return the custom BaseAPIResponse class if we're
|
1610
|
+
# returning the raw response, or if we're not streaming SSE, as if we're streaming
|
1611
|
+
# SSE then `cast_to` doesn't actively reflect the type we need to parse into
|
1612
|
+
and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
|
1613
|
+
):
|
1578
1614
|
if not issubclass(origin, AsyncAPIResponse):
|
1579
1615
|
raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}")
|
1580
1616
|
|
@@ -0,0 +1,127 @@
|
|
1
|
+
import time
|
2
|
+
import random
|
3
|
+
from typing import TYPE_CHECKING, Type, Union, TypeVar, cast
|
4
|
+
from typing_extensions import ParamSpec
|
5
|
+
|
6
|
+
import anyio
|
7
|
+
|
8
|
+
from .._models import BaseModel
|
9
|
+
from ..types.task_retrieve_response import TaskRetrieveResponse
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from .._client import RunwayML, AsyncRunwayML
|
13
|
+
|
14
|
+
P = ParamSpec("P")
|
15
|
+
T = TypeVar("T")
|
16
|
+
|
17
|
+
POLL_TIME = 6
|
18
|
+
POLL_JITTER = 3
|
19
|
+
|
20
|
+
|
21
|
+
class AwaitableTaskResponseMixin:
|
22
|
+
def wait_for_task_output(self, timeout: Union[float, None] = 60 * 10) -> TaskRetrieveResponse: # type: ignore[empty-body]
|
23
|
+
"""
|
24
|
+
When called, this will block until the task is complete.
|
25
|
+
|
26
|
+
If the task fails or is cancelled, a `TaskFailedError` will be raised.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
timeout: The maximum amount of time to wait for the task to complete in seconds. If not
|
30
|
+
specified, the default timeout is 10 minutes. Will raise a `TaskTimeoutError` if the
|
31
|
+
task does not complete within the timeout.
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
The task details, equivalent to calling `client.tasks.retrieve(task_id)`.
|
35
|
+
"""
|
36
|
+
...
|
37
|
+
|
38
|
+
|
39
|
+
class NewTaskCreatedResponse(AwaitableTaskResponseMixin, BaseModel):
|
40
|
+
id: str
|
41
|
+
|
42
|
+
|
43
|
+
class AwaitableTaskRetrieveResponse(AwaitableTaskResponseMixin, TaskRetrieveResponse):
|
44
|
+
pass
|
45
|
+
|
46
|
+
|
47
|
+
class AsyncAwaitableTaskResponseMixin:
|
48
|
+
async def wait_for_task_output(self, timeout: Union[float, None] = 60 * 10) -> TaskRetrieveResponse: # type: ignore[empty-body]
|
49
|
+
"""
|
50
|
+
When called, this will wait until the task is complete.
|
51
|
+
|
52
|
+
If the task fails or is cancelled, a `TaskFailedError` will be raised.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
timeout: The maximum amount of time to wait for the task to complete in seconds. If not
|
56
|
+
specified, the default timeout is 10 minutes. Will raise a `TaskTimeoutError` if the
|
57
|
+
task does not complete within the timeout. Setting this to `None` will wait
|
58
|
+
indefinitely (disabling the timeout).
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
The task details, equivalent to awaiting `client.tasks.retrieve(task_id)`.
|
62
|
+
"""
|
63
|
+
...
|
64
|
+
|
65
|
+
|
66
|
+
class AsyncNewTaskCreatedResponse(AsyncAwaitableTaskResponseMixin, BaseModel):
|
67
|
+
id: str
|
68
|
+
|
69
|
+
|
70
|
+
class AsyncAwaitableTaskRetrieveResponse(AsyncAwaitableTaskResponseMixin, TaskRetrieveResponse):
|
71
|
+
pass
|
72
|
+
|
73
|
+
|
74
|
+
def create_waitable_resource(base_class: Type[T], client: "RunwayML") -> Type[NewTaskCreatedResponse]:
|
75
|
+
class WithClient(base_class): # type: ignore[valid-type,misc]
|
76
|
+
id: str
|
77
|
+
|
78
|
+
def wait_for_task_output(self, timeout: Union[float, None] = 60 * 10) -> TaskRetrieveResponse:
|
79
|
+
start_time = time.time()
|
80
|
+
while True:
|
81
|
+
time.sleep(POLL_TIME + random.random() * POLL_JITTER - POLL_JITTER / 2)
|
82
|
+
task_details = client.tasks.retrieve(self.id)
|
83
|
+
if task_details.status == "SUCCEEDED":
|
84
|
+
return task_details
|
85
|
+
if task_details.status == "FAILED":
|
86
|
+
raise TaskFailedError(task_details)
|
87
|
+
if timeout is not None and time.time() - start_time > timeout:
|
88
|
+
raise TaskTimeoutError(task_details)
|
89
|
+
|
90
|
+
WithClient.__name__ = base_class.__name__
|
91
|
+
WithClient.__qualname__ = base_class.__qualname__
|
92
|
+
|
93
|
+
return cast(Type[NewTaskCreatedResponse], WithClient)
|
94
|
+
|
95
|
+
|
96
|
+
def create_async_waitable_resource(base_class: Type[T], client: "AsyncRunwayML") -> Type[AsyncNewTaskCreatedResponse]:
|
97
|
+
class WithClient(base_class): # type: ignore[valid-type,misc]
|
98
|
+
id: str
|
99
|
+
|
100
|
+
async def wait_for_task_output(self, timeout: Union[float, None] = 60 * 10) -> TaskRetrieveResponse:
|
101
|
+
start_time = anyio.current_time()
|
102
|
+
while True:
|
103
|
+
await anyio.sleep(POLL_TIME + random.random() * POLL_JITTER - POLL_JITTER / 2)
|
104
|
+
task_details = await client.tasks.retrieve(self.id)
|
105
|
+
if task_details.status == "SUCCEEDED":
|
106
|
+
return task_details
|
107
|
+
if task_details.status == "FAILED" or task_details.status == "CANCELLED":
|
108
|
+
raise TaskFailedError(task_details)
|
109
|
+
if timeout is not None and anyio.current_time() - start_time > timeout:
|
110
|
+
raise TaskTimeoutError(task_details)
|
111
|
+
|
112
|
+
WithClient.__name__ = base_class.__name__
|
113
|
+
WithClient.__qualname__ = base_class.__qualname__
|
114
|
+
|
115
|
+
return cast(Type[AsyncNewTaskCreatedResponse], WithClient)
|
116
|
+
|
117
|
+
|
118
|
+
class TaskFailedError(Exception):
|
119
|
+
def __init__(self, task_details: TaskRetrieveResponse):
|
120
|
+
self.task_details = task_details
|
121
|
+
super().__init__(f"Task failed")
|
122
|
+
|
123
|
+
|
124
|
+
class TaskTimeoutError(Exception):
|
125
|
+
def __init__(self, task_details: TaskRetrieveResponse):
|
126
|
+
self.task_details = task_details
|
127
|
+
super().__init__(f"Task timed out")
|