runwayml 3.5.0__tar.gz → 3.6.1__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.1/.release-please-manifest.json +3 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/CHANGELOG.md +31 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/PKG-INFO +43 -3
- {runwayml-3.5.0 → runwayml-3.6.1}/README.md +39 -2
- {runwayml-3.5.0 → runwayml-3.6.1}/pyproject.toml +3 -1
- {runwayml-3.5.0 → runwayml-3.6.1}/requirements-dev.lock +27 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/requirements.lock +27 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/__init__.py +2 -1
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_base_client.py +22 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_version.py +1 -1
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/api_resources/test_image_to_video.py +3 -1
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/api_resources/test_organization.py +3 -1
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/api_resources/test_tasks.py +3 -1
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/api_resources/test_text_to_image.py +3 -1
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/api_resources/test_video_upscale.py +3 -1
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/conftest.py +37 -6
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_client.py +22 -77
- runwayml-3.5.0/.release-please-manifest.json +0 -3
- {runwayml-3.5.0 → runwayml-3.6.1}/.gitignore +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/CONTRIBUTING.md +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/LICENSE +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/SECURITY.md +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/api.md +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/bin/check-release-environment +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/bin/publish-pypi +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/examples/.keep +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/examples/generate_image.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/mypy.ini +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/noxfile.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/release-please-config.json +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_client.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_compat.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_constants.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_exceptions.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_files.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_models.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_qs.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_resource.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_response.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_streaming.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_types.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_utils/__init__.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_utils/_logs.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_utils/_proxy.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_utils/_reflection.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_utils/_resources_proxy.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_utils/_streams.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_utils/_sync.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_utils/_transform.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_utils/_typing.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/_utils/_utils.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/lib/.keep +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/lib/polling.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/py.typed +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/resources/__init__.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/resources/image_to_video.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/resources/organization.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/resources/tasks.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/resources/text_to_image.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/resources/video_upscale.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/types/__init__.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/types/image_to_video_create_params.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/types/image_to_video_create_response.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/types/organization_retrieve_response.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/types/task_retrieve_response.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/types/text_to_image_create_params.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/types/text_to_image_create_response.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/types/video_upscale_create_params.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/src/runwayml/types/video_upscale_create_response.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/__init__.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/api_resources/__init__.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/sample_file.txt +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_deepcopy.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_extract_files.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_files.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_models.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_qs.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_required_args.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_response.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_streaming.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_transform.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_utils/test_proxy.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/test_utils/test_typing.py +0 -0
- {runwayml-3.5.0 → runwayml-3.6.1}/tests/utils.py +0 -0
@@ -1,5 +1,36 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 3.6.1 (2025-06-24)
|
4
|
+
|
5
|
+
Full Changelog: [v3.6.0...v3.6.1](https://github.com/runwayml/sdk-python/compare/v3.6.0...v3.6.1)
|
6
|
+
|
7
|
+
### Chores
|
8
|
+
|
9
|
+
* **tests:** skip some failing tests on the latest python versions ([732236d](https://github.com/runwayml/sdk-python/commit/732236d2ced9511c21179e9850bafcaf0b0a4edf))
|
10
|
+
|
11
|
+
## 3.6.0 (2025-06-23)
|
12
|
+
|
13
|
+
Full Changelog: [v3.5.0...v3.6.0](https://github.com/runwayml/sdk-python/compare/v3.5.0...v3.6.0)
|
14
|
+
|
15
|
+
### Features
|
16
|
+
|
17
|
+
* **client:** add support for aiohttp ([7d5490c](https://github.com/runwayml/sdk-python/commit/7d5490ca015dd0ff55789889036cc1bd32a58c43))
|
18
|
+
|
19
|
+
|
20
|
+
### Bug Fixes
|
21
|
+
|
22
|
+
* **tests:** fix: tests which call HTTP endpoints directly with the example parameters ([33301dd](https://github.com/runwayml/sdk-python/commit/33301ddf84cc64581d715d6b8ce1eda48ff66ed5))
|
23
|
+
|
24
|
+
|
25
|
+
### Chores
|
26
|
+
|
27
|
+
* **readme:** update badges ([147dc95](https://github.com/runwayml/sdk-python/commit/147dc95f9ab390065ab96403a88ca5a87e59f597))
|
28
|
+
|
29
|
+
|
30
|
+
### Documentation
|
31
|
+
|
32
|
+
* **client:** fix httpx.Timeout documentation reference ([af9fecb](https://github.com/runwayml/sdk-python/commit/af9fecb38a4075fcc8f7687f2ef130ad8c813389))
|
33
|
+
|
3
34
|
## 3.5.0 (2025-06-17)
|
4
35
|
|
5
36
|
Full Changelog: [v3.4.0...v3.5.0](https://github.com/runwayml/sdk-python/compare/v3.4.0...v3.5.0)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: runwayml
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.6.1
|
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
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "runwayml"
|
3
|
-
version = "3.
|
3
|
+
version = "3.6.1"
|
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
|
@@ -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
|
@@ -34,16 +45,23 @@ execnet==2.1.1
|
|
34
45
|
# via pytest-xdist
|
35
46
|
filelock==3.12.4
|
36
47
|
# via virtualenv
|
48
|
+
frozenlist==1.6.2
|
49
|
+
# via aiohttp
|
50
|
+
# via aiosignal
|
37
51
|
h11==0.14.0
|
38
52
|
# via httpcore
|
39
53
|
httpcore==1.0.2
|
40
54
|
# via httpx
|
41
55
|
httpx==0.28.1
|
56
|
+
# via httpx-aiohttp
|
42
57
|
# via respx
|
43
58
|
# via runwayml
|
59
|
+
httpx-aiohttp==0.1.6
|
60
|
+
# via runwayml
|
44
61
|
idna==3.4
|
45
62
|
# via anyio
|
46
63
|
# via httpx
|
64
|
+
# via yarl
|
47
65
|
importlib-metadata==7.0.0
|
48
66
|
iniconfig==2.0.0
|
49
67
|
# via pytest
|
@@ -51,6 +69,9 @@ markdown-it-py==3.0.0
|
|
51
69
|
# via rich
|
52
70
|
mdurl==0.1.2
|
53
71
|
# via markdown-it-py
|
72
|
+
multidict==6.4.4
|
73
|
+
# via aiohttp
|
74
|
+
# via yarl
|
54
75
|
mypy==1.14.1
|
55
76
|
mypy-extensions==1.0.0
|
56
77
|
# via mypy
|
@@ -65,6 +86,9 @@ platformdirs==3.11.0
|
|
65
86
|
# via virtualenv
|
66
87
|
pluggy==1.5.0
|
67
88
|
# via pytest
|
89
|
+
propcache==0.3.1
|
90
|
+
# via aiohttp
|
91
|
+
# via yarl
|
68
92
|
pydantic==2.10.3
|
69
93
|
# via runwayml
|
70
94
|
pydantic-core==2.27.1
|
@@ -97,6 +121,7 @@ tomli==2.0.2
|
|
97
121
|
# via pytest
|
98
122
|
typing-extensions==4.12.2
|
99
123
|
# via anyio
|
124
|
+
# via multidict
|
100
125
|
# via mypy
|
101
126
|
# via pydantic
|
102
127
|
# via pydantic-core
|
@@ -104,5 +129,7 @@ typing-extensions==4.12.2
|
|
104
129
|
# via runwayml
|
105
130
|
virtualenv==20.24.5
|
106
131
|
# via nox
|
132
|
+
yarl==1.20.0
|
133
|
+
# via aiohttp
|
107
134
|
zipp==3.17.0
|
108
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
|
@@ -37,7 +37,7 @@ from ._exceptions import (
|
|
37
37
|
APIResponseValidationError,
|
38
38
|
)
|
39
39
|
from .lib.polling import TaskFailedError, TaskTimeoutError
|
40
|
-
from ._base_client import DefaultHttpxClient, DefaultAsyncHttpxClient
|
40
|
+
from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient
|
41
41
|
from ._utils._logs import setup_logging as _setup_logging
|
42
42
|
|
43
43
|
__all__ = [
|
@@ -79,6 +79,7 @@ __all__ = [
|
|
79
79
|
"DEFAULT_CONNECTION_LIMITS",
|
80
80
|
"DefaultHttpxClient",
|
81
81
|
"DefaultAsyncHttpxClient",
|
82
|
+
"DefaultAioHttpClient",
|
82
83
|
"TaskFailedError",
|
83
84
|
"TaskTimeoutError",
|
84
85
|
]
|
@@ -1289,6 +1289,24 @@ class _DefaultAsyncHttpxClient(httpx.AsyncClient):
|
|
1289
1289
|
super().__init__(**kwargs)
|
1290
1290
|
|
1291
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
|
+
|
1292
1310
|
if TYPE_CHECKING:
|
1293
1311
|
DefaultAsyncHttpxClient = httpx.AsyncClient
|
1294
1312
|
"""An alias to `httpx.AsyncClient` that provides the same defaults that this SDK
|
@@ -1297,8 +1315,12 @@ if TYPE_CHECKING:
|
|
1297
1315
|
This is useful because overriding the `http_client` with your own instance of
|
1298
1316
|
`httpx.AsyncClient` will result in httpx's defaults being used, not ours.
|
1299
1317
|
"""
|
1318
|
+
|
1319
|
+
DefaultAioHttpClient = httpx.AsyncClient
|
1320
|
+
"""An alias to `httpx.AsyncClient` that changes the default HTTP transport to `aiohttp`."""
|
1300
1321
|
else:
|
1301
1322
|
DefaultAsyncHttpxClient = _DefaultAsyncHttpxClient
|
1323
|
+
DefaultAioHttpClient = _DefaultAioHttpClient
|
1302
1324
|
|
1303
1325
|
|
1304
1326
|
class AsyncHttpxClientWrapper(DefaultAsyncHttpxClient):
|
@@ -69,7 +69,9 @@ class TestImageToVideo:
|
|
69
69
|
|
70
70
|
|
71
71
|
class TestAsyncImageToVideo:
|
72
|
-
parametrize = pytest.mark.parametrize(
|
72
|
+
parametrize = pytest.mark.parametrize(
|
73
|
+
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
|
74
|
+
)
|
73
75
|
|
74
76
|
@parametrize
|
75
77
|
async def test_method_create(self, async_client: AsyncRunwayML) -> None:
|
@@ -44,7 +44,9 @@ class TestOrganization:
|
|
44
44
|
|
45
45
|
|
46
46
|
class TestAsyncOrganization:
|
47
|
-
parametrize = pytest.mark.parametrize(
|
47
|
+
parametrize = pytest.mark.parametrize(
|
48
|
+
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
|
49
|
+
)
|
48
50
|
|
49
51
|
@parametrize
|
50
52
|
async def test_method_retrieve(self, async_client: AsyncRunwayML) -> None:
|
@@ -95,7 +95,9 @@ class TestTasks:
|
|
95
95
|
|
96
96
|
|
97
97
|
class TestAsyncTasks:
|
98
|
-
parametrize = pytest.mark.parametrize(
|
98
|
+
parametrize = pytest.mark.parametrize(
|
99
|
+
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
|
100
|
+
)
|
99
101
|
|
100
102
|
@parametrize
|
101
103
|
async def test_method_retrieve(self, async_client: AsyncRunwayML) -> None:
|
@@ -73,7 +73,9 @@ class TestTextToImage:
|
|
73
73
|
|
74
74
|
|
75
75
|
class TestAsyncTextToImage:
|
76
|
-
parametrize = pytest.mark.parametrize(
|
76
|
+
parametrize = pytest.mark.parametrize(
|
77
|
+
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
|
78
|
+
)
|
77
79
|
|
78
80
|
@parametrize
|
79
81
|
async def test_method_create(self, async_client: AsyncRunwayML) -> None:
|
@@ -53,7 +53,9 @@ class TestVideoUpscale:
|
|
53
53
|
|
54
54
|
|
55
55
|
class TestAsyncVideoUpscale:
|
56
|
-
parametrize = pytest.mark.parametrize(
|
56
|
+
parametrize = pytest.mark.parametrize(
|
57
|
+
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
|
58
|
+
)
|
57
59
|
|
58
60
|
@parametrize
|
59
61
|
async def test_method_create(self, async_client: AsyncRunwayML) -> None:
|
@@ -6,10 +6,12 @@ import os
|
|
6
6
|
import logging
|
7
7
|
from typing import TYPE_CHECKING, Iterator, AsyncIterator
|
8
8
|
|
9
|
+
import httpx
|
9
10
|
import pytest
|
10
11
|
from pytest_asyncio import is_async_test
|
11
12
|
|
12
|
-
from runwayml import RunwayML, AsyncRunwayML
|
13
|
+
from runwayml import RunwayML, AsyncRunwayML, DefaultAioHttpClient
|
14
|
+
from runwayml._utils import is_dict
|
13
15
|
|
14
16
|
if TYPE_CHECKING:
|
15
17
|
from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage]
|
@@ -27,6 +29,19 @@ def pytest_collection_modifyitems(items: list[pytest.Function]) -> None:
|
|
27
29
|
for async_test in pytest_asyncio_tests:
|
28
30
|
async_test.add_marker(session_scope_marker, append=False)
|
29
31
|
|
32
|
+
# We skip tests that use both the aiohttp client and respx_mock as respx_mock
|
33
|
+
# doesn't support custom transports.
|
34
|
+
for item in items:
|
35
|
+
if "async_client" not in item.fixturenames or "respx_mock" not in item.fixturenames:
|
36
|
+
continue
|
37
|
+
|
38
|
+
if not hasattr(item, "callspec"):
|
39
|
+
continue
|
40
|
+
|
41
|
+
async_client_param = item.callspec.params.get("async_client")
|
42
|
+
if is_dict(async_client_param) and async_client_param.get("http_client") == "aiohttp":
|
43
|
+
item.add_marker(pytest.mark.skip(reason="aiohttp client is not compatible with respx_mock"))
|
44
|
+
|
30
45
|
|
31
46
|
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
|
32
47
|
|
@@ -45,9 +60,25 @@ def client(request: FixtureRequest) -> Iterator[RunwayML]:
|
|
45
60
|
|
46
61
|
@pytest.fixture(scope="session")
|
47
62
|
async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncRunwayML]:
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
63
|
+
param = getattr(request, "param", True)
|
64
|
+
|
65
|
+
# defaults
|
66
|
+
strict = True
|
67
|
+
http_client: None | httpx.AsyncClient = None
|
68
|
+
|
69
|
+
if isinstance(param, bool):
|
70
|
+
strict = param
|
71
|
+
elif is_dict(param):
|
72
|
+
strict = param.get("strict", True)
|
73
|
+
assert isinstance(strict, bool)
|
74
|
+
|
75
|
+
http_client_type = param.get("http_client", "httpx")
|
76
|
+
if http_client_type == "aiohttp":
|
77
|
+
http_client = DefaultAioHttpClient()
|
78
|
+
else:
|
79
|
+
raise TypeError(f"Unexpected fixture parameter type {type(param)}, expected bool or dict")
|
80
|
+
|
81
|
+
async with AsyncRunwayML(
|
82
|
+
base_url=base_url, api_key=api_key, _strict_response_validation=strict, http_client=http_client
|
83
|
+
) as client:
|
53
84
|
yield client
|
@@ -23,9 +23,7 @@ from pydantic import ValidationError
|
|
23
23
|
|
24
24
|
from runwayml import RunwayML, AsyncRunwayML, APIResponseValidationError
|
25
25
|
from runwayml._types import Omit
|
26
|
-
from runwayml._utils import maybe_transform
|
27
26
|
from runwayml._models import BaseModel, FinalRequestOptions
|
28
|
-
from runwayml._constants import RAW_RESPONSE_HEADER
|
29
27
|
from runwayml._exceptions import RunwayMLError, APIStatusError, APITimeoutError, APIResponseValidationError
|
30
28
|
from runwayml._base_client import (
|
31
29
|
DEFAULT_TIMEOUT,
|
@@ -35,7 +33,6 @@ from runwayml._base_client import (
|
|
35
33
|
DefaultAsyncHttpxClient,
|
36
34
|
make_request_options,
|
37
35
|
)
|
38
|
-
from runwayml.types.image_to_video_create_params import ImageToVideoCreateParams
|
39
36
|
|
40
37
|
from .utils import update_env
|
41
38
|
|
@@ -194,6 +191,7 @@ class TestRunwayML:
|
|
194
191
|
copy_param = copy_signature.parameters.get(name)
|
195
192
|
assert copy_param is not None, f"copy() signature is missing the {name} param"
|
196
193
|
|
194
|
+
@pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12")
|
197
195
|
def test_copy_build_request(self) -> None:
|
198
196
|
options = FinalRequestOptions(method="get", url="/foo")
|
199
197
|
|
@@ -715,54 +713,25 @@ class TestRunwayML:
|
|
715
713
|
|
716
714
|
@mock.patch("runwayml._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
|
717
715
|
@pytest.mark.respx(base_url=base_url)
|
718
|
-
def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None:
|
716
|
+
def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: RunwayML) -> None:
|
719
717
|
respx_mock.post("/v1/image_to_video").mock(side_effect=httpx.TimeoutException("Test timeout error"))
|
720
718
|
|
721
719
|
with pytest.raises(APITimeoutError):
|
722
|
-
|
723
|
-
"
|
724
|
-
|
725
|
-
object,
|
726
|
-
maybe_transform(
|
727
|
-
dict(
|
728
|
-
model="gen4_turbo",
|
729
|
-
prompt_image="https://example.com/assets/bunny.jpg",
|
730
|
-
ratio="1280:720",
|
731
|
-
prompt_text="The bunny is eating a carrot",
|
732
|
-
),
|
733
|
-
ImageToVideoCreateParams,
|
734
|
-
),
|
735
|
-
),
|
736
|
-
cast_to=httpx.Response,
|
737
|
-
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
|
738
|
-
)
|
720
|
+
client.image_to_video.with_streaming_response.create(
|
721
|
+
model="gen3a_turbo", prompt_image="https://example.com", ratio="1280:720"
|
722
|
+
).__enter__()
|
739
723
|
|
740
724
|
assert _get_open_connections(self.client) == 0
|
741
725
|
|
742
726
|
@mock.patch("runwayml._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
|
743
727
|
@pytest.mark.respx(base_url=base_url)
|
744
|
-
def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None:
|
728
|
+
def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: RunwayML) -> None:
|
745
729
|
respx_mock.post("/v1/image_to_video").mock(return_value=httpx.Response(500))
|
746
730
|
|
747
731
|
with pytest.raises(APIStatusError):
|
748
|
-
|
749
|
-
"
|
750
|
-
|
751
|
-
object,
|
752
|
-
maybe_transform(
|
753
|
-
dict(
|
754
|
-
model="gen4_turbo",
|
755
|
-
prompt_image="https://example.com/assets/bunny.jpg",
|
756
|
-
ratio="1280:720",
|
757
|
-
prompt_text="The bunny is eating a carrot",
|
758
|
-
),
|
759
|
-
ImageToVideoCreateParams,
|
760
|
-
),
|
761
|
-
),
|
762
|
-
cast_to=httpx.Response,
|
763
|
-
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
|
764
|
-
)
|
765
|
-
|
732
|
+
client.image_to_video.with_streaming_response.create(
|
733
|
+
model="gen3a_turbo", prompt_image="https://example.com", ratio="1280:720"
|
734
|
+
).__enter__()
|
766
735
|
assert _get_open_connections(self.client) == 0
|
767
736
|
|
768
737
|
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
|
@@ -1039,6 +1008,7 @@ class TestAsyncRunwayML:
|
|
1039
1008
|
copy_param = copy_signature.parameters.get(name)
|
1040
1009
|
assert copy_param is not None, f"copy() signature is missing the {name} param"
|
1041
1010
|
|
1011
|
+
@pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12")
|
1042
1012
|
def test_copy_build_request(self) -> None:
|
1043
1013
|
options = FinalRequestOptions(method="get", url="/foo")
|
1044
1014
|
|
@@ -1574,54 +1544,29 @@ class TestAsyncRunwayML:
|
|
1574
1544
|
|
1575
1545
|
@mock.patch("runwayml._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
|
1576
1546
|
@pytest.mark.respx(base_url=base_url)
|
1577
|
-
async def test_retrying_timeout_errors_doesnt_leak(
|
1547
|
+
async def test_retrying_timeout_errors_doesnt_leak(
|
1548
|
+
self, respx_mock: MockRouter, async_client: AsyncRunwayML
|
1549
|
+
) -> None:
|
1578
1550
|
respx_mock.post("/v1/image_to_video").mock(side_effect=httpx.TimeoutException("Test timeout error"))
|
1579
1551
|
|
1580
1552
|
with pytest.raises(APITimeoutError):
|
1581
|
-
await
|
1582
|
-
"
|
1583
|
-
|
1584
|
-
object,
|
1585
|
-
maybe_transform(
|
1586
|
-
dict(
|
1587
|
-
model="gen4_turbo",
|
1588
|
-
prompt_image="https://example.com/assets/bunny.jpg",
|
1589
|
-
ratio="1280:720",
|
1590
|
-
prompt_text="The bunny is eating a carrot",
|
1591
|
-
),
|
1592
|
-
ImageToVideoCreateParams,
|
1593
|
-
),
|
1594
|
-
),
|
1595
|
-
cast_to=httpx.Response,
|
1596
|
-
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
|
1597
|
-
)
|
1553
|
+
await async_client.image_to_video.with_streaming_response.create(
|
1554
|
+
model="gen3a_turbo", prompt_image="https://example.com", ratio="1280:720"
|
1555
|
+
).__aenter__()
|
1598
1556
|
|
1599
1557
|
assert _get_open_connections(self.client) == 0
|
1600
1558
|
|
1601
1559
|
@mock.patch("runwayml._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
|
1602
1560
|
@pytest.mark.respx(base_url=base_url)
|
1603
|
-
async def test_retrying_status_errors_doesnt_leak(
|
1561
|
+
async def test_retrying_status_errors_doesnt_leak(
|
1562
|
+
self, respx_mock: MockRouter, async_client: AsyncRunwayML
|
1563
|
+
) -> None:
|
1604
1564
|
respx_mock.post("/v1/image_to_video").mock(return_value=httpx.Response(500))
|
1605
1565
|
|
1606
1566
|
with pytest.raises(APIStatusError):
|
1607
|
-
await
|
1608
|
-
"
|
1609
|
-
|
1610
|
-
object,
|
1611
|
-
maybe_transform(
|
1612
|
-
dict(
|
1613
|
-
model="gen4_turbo",
|
1614
|
-
prompt_image="https://example.com/assets/bunny.jpg",
|
1615
|
-
ratio="1280:720",
|
1616
|
-
prompt_text="The bunny is eating a carrot",
|
1617
|
-
),
|
1618
|
-
ImageToVideoCreateParams,
|
1619
|
-
),
|
1620
|
-
),
|
1621
|
-
cast_to=httpx.Response,
|
1622
|
-
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
|
1623
|
-
)
|
1624
|
-
|
1567
|
+
await async_client.image_to_video.with_streaming_response.create(
|
1568
|
+
model="gen3a_turbo", prompt_image="https://example.com", ratio="1280:720"
|
1569
|
+
).__aenter__()
|
1625
1570
|
assert _get_open_connections(self.client) == 0
|
1626
1571
|
|
1627
1572
|
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|