runwayml 3.3.0__tar.gz → 3.5.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.
Files changed (84) hide show
  1. runwayml-3.5.0/.release-please-manifest.json +3 -0
  2. {runwayml-3.3.0 → runwayml-3.5.0}/CHANGELOG.md +30 -0
  3. {runwayml-3.3.0 → runwayml-3.5.0}/PKG-INFO +1 -1
  4. {runwayml-3.3.0 → runwayml-3.5.0}/api.md +12 -0
  5. runwayml-3.5.0/examples/generate_image.py +16 -0
  6. {runwayml-3.3.0 → runwayml-3.5.0}/pyproject.toml +3 -2
  7. {runwayml-3.3.0 → runwayml-3.5.0}/requirements-dev.lock +4 -0
  8. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/__init__.py +3 -0
  9. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_base_client.py +16 -2
  10. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_client.py +9 -1
  11. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_version.py +1 -1
  12. runwayml-3.5.0/src/runwayml/lib/polling.py +127 -0
  13. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/resources/__init__.py +14 -0
  14. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/resources/image_to_video.py +20 -6
  15. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/resources/tasks.py +17 -4
  16. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/resources/text_to_image.py +10 -4
  17. runwayml-3.5.0/src/runwayml/resources/video_upscale.py +201 -0
  18. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/types/__init__.py +2 -0
  19. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/types/image_to_video_create_params.py +13 -2
  20. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/types/organization_retrieve_response.py +21 -0
  21. runwayml-3.5.0/src/runwayml/types/video_upscale_create_params.py +22 -0
  22. runwayml-3.5.0/src/runwayml/types/video_upscale_create_response.py +10 -0
  23. {runwayml-3.3.0 → runwayml-3.5.0}/tests/api_resources/test_image_to_video.py +10 -8
  24. runwayml-3.5.0/tests/api_resources/test_video_upscale.py +90 -0
  25. {runwayml-3.3.0 → runwayml-3.5.0}/tests/conftest.py +2 -0
  26. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_client.py +52 -6
  27. runwayml-3.3.0/.release-please-manifest.json +0 -3
  28. {runwayml-3.3.0 → runwayml-3.5.0}/.gitignore +0 -0
  29. {runwayml-3.3.0 → runwayml-3.5.0}/CONTRIBUTING.md +0 -0
  30. {runwayml-3.3.0 → runwayml-3.5.0}/LICENSE +0 -0
  31. {runwayml-3.3.0 → runwayml-3.5.0}/README.md +0 -0
  32. {runwayml-3.3.0 → runwayml-3.5.0}/SECURITY.md +0 -0
  33. {runwayml-3.3.0 → runwayml-3.5.0}/bin/check-release-environment +0 -0
  34. {runwayml-3.3.0 → runwayml-3.5.0}/bin/publish-pypi +0 -0
  35. {runwayml-3.3.0 → runwayml-3.5.0}/examples/.keep +0 -0
  36. {runwayml-3.3.0 → runwayml-3.5.0}/mypy.ini +0 -0
  37. {runwayml-3.3.0 → runwayml-3.5.0}/noxfile.py +0 -0
  38. {runwayml-3.3.0 → runwayml-3.5.0}/release-please-config.json +0 -0
  39. {runwayml-3.3.0 → runwayml-3.5.0}/requirements.lock +0 -0
  40. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_compat.py +0 -0
  41. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_constants.py +0 -0
  42. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_exceptions.py +0 -0
  43. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_files.py +0 -0
  44. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_models.py +0 -0
  45. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_qs.py +0 -0
  46. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_resource.py +0 -0
  47. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_response.py +0 -0
  48. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_streaming.py +0 -0
  49. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_types.py +0 -0
  50. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_utils/__init__.py +0 -0
  51. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_utils/_logs.py +0 -0
  52. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_utils/_proxy.py +0 -0
  53. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_utils/_reflection.py +0 -0
  54. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_utils/_resources_proxy.py +0 -0
  55. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_utils/_streams.py +0 -0
  56. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_utils/_sync.py +0 -0
  57. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_utils/_transform.py +0 -0
  58. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_utils/_typing.py +0 -0
  59. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/_utils/_utils.py +0 -0
  60. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/lib/.keep +0 -0
  61. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/py.typed +0 -0
  62. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/resources/organization.py +0 -0
  63. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/types/image_to_video_create_response.py +0 -0
  64. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/types/task_retrieve_response.py +0 -0
  65. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/types/text_to_image_create_params.py +0 -0
  66. {runwayml-3.3.0 → runwayml-3.5.0}/src/runwayml/types/text_to_image_create_response.py +0 -0
  67. {runwayml-3.3.0 → runwayml-3.5.0}/tests/__init__.py +0 -0
  68. {runwayml-3.3.0 → runwayml-3.5.0}/tests/api_resources/__init__.py +0 -0
  69. {runwayml-3.3.0 → runwayml-3.5.0}/tests/api_resources/test_organization.py +0 -0
  70. {runwayml-3.3.0 → runwayml-3.5.0}/tests/api_resources/test_tasks.py +0 -0
  71. {runwayml-3.3.0 → runwayml-3.5.0}/tests/api_resources/test_text_to_image.py +0 -0
  72. {runwayml-3.3.0 → runwayml-3.5.0}/tests/sample_file.txt +0 -0
  73. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_deepcopy.py +0 -0
  74. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_extract_files.py +0 -0
  75. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_files.py +0 -0
  76. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_models.py +0 -0
  77. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_qs.py +0 -0
  78. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_required_args.py +0 -0
  79. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_response.py +0 -0
  80. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_streaming.py +0 -0
  81. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_transform.py +0 -0
  82. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_utils/test_proxy.py +0 -0
  83. {runwayml-3.3.0 → runwayml-3.5.0}/tests/test_utils/test_typing.py +0 -0
  84. {runwayml-3.3.0 → runwayml-3.5.0}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "3.5.0"
3
+ }
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.5.0 (2025-06-17)
4
+
5
+ Full Changelog: [v3.4.0...v3.5.0](https://github.com/runwayml/sdk-python/compare/v3.4.0...v3.5.0)
6
+
7
+ ### Features
8
+
9
+ * **api:** SDK updates, contentModeration for i2v ([1286e32](https://github.com/runwayml/sdk-python/commit/1286e3239f388143404c4b0a61816f5f6282fe1c))
10
+ * **api:** SDK updates, contentModeration for i2v ([8ff202e](https://github.com/runwayml/sdk-python/commit/8ff202ee39dc5856118bf1f3f5537e459a120967))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **client:** correctly parse binary response | stream ([fc9bedb](https://github.com/runwayml/sdk-python/commit/fc9bedb3cbb47849e83a5982ed92a694796e80c7))
16
+
17
+
18
+ ### Chores
19
+
20
+ * **ci:** enable for pull requests ([4b439c9](https://github.com/runwayml/sdk-python/commit/4b439c99012918849be4fa64b1ab8d1802cee6e6))
21
+ * **internal:** update conftest.py ([0ff71fd](https://github.com/runwayml/sdk-python/commit/0ff71fd67a421dbff729e98418b6cd72ed0e57b3))
22
+ * **tests:** add tests for httpx client instantiation & proxies ([89e5fbe](https://github.com/runwayml/sdk-python/commit/89e5fbef9e8a64d050252f489b2d76e4c510c663))
23
+ * **tests:** run tests in parallel ([7edbcd1](https://github.com/runwayml/sdk-python/commit/7edbcd1db04ed139e026701fe24501199b4eaffd))
24
+
25
+ ## 3.4.0 (2025-06-04)
26
+
27
+ Full Changelog: [v3.3.0...v3.4.0](https://github.com/runwayml/sdk-python/compare/v3.3.0...v3.4.0)
28
+
29
+ ### Features
30
+
31
+ * **api:** Add video upscale endpoint ([aac6a70](https://github.com/runwayml/sdk-python/commit/aac6a707ca2925034fa141ceac8a9515958a77c1))
32
+
3
33
  ## 3.3.0 (2025-06-04)
4
34
 
5
35
  Full Changelog: [v3.2.0...v3.3.0](https://github.com/runwayml/sdk-python/compare/v3.2.0...v3.3.0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: runwayml
3
- Version: 3.3.0
3
+ Version: 3.5.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
@@ -35,6 +35,18 @@ Methods:
35
35
 
36
36
  - <code title="post /v1/text_to_image">client.text_to_image.<a href="./src/runwayml/resources/text_to_image.py">create</a>(\*\*<a href="src/runwayml/types/text_to_image_create_params.py">params</a>) -> <a href="./src/runwayml/types/text_to_image_create_response.py">TextToImageCreateResponse</a></code>
37
37
 
38
+ # VideoUpscale
39
+
40
+ Types:
41
+
42
+ ```python
43
+ from runwayml.types import VideoUpscaleCreateResponse
44
+ ```
45
+
46
+ Methods:
47
+
48
+ - <code title="post /v1/video_upscale">client.video_upscale.<a href="./src/runwayml/resources/video_upscale.py">create</a>(\*\*<a href="src/runwayml/types/video_upscale_create_params.py">params</a>) -> <a href="./src/runwayml/types/video_upscale_create_response.py">VideoUpscaleCreateResponse</a></code>
49
+
38
50
  # Organization
39
51
 
40
52
  Types:
@@ -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.0"
3
+ version = "3.5.0"
4
4
  description = "The official Python library for the runwayml API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
@@ -54,6 +54,7 @@ dev-dependencies = [
54
54
  "importlib-metadata>=6.7.0",
55
55
  "rich>=13.7.1",
56
56
  "nest_asyncio==1.6.0",
57
+ "pytest-xdist>=3.6.1",
57
58
  ]
58
59
 
59
60
  [tool.rye.scripts]
@@ -125,7 +126,7 @@ replacement = '[\1](https://github.com/runwayml/sdk-python/tree/main/\g<2>)'
125
126
 
126
127
  [tool.pytest.ini_options]
127
128
  testpaths = ["tests"]
128
- addopts = "--tb=short"
129
+ addopts = "--tb=short -n auto"
129
130
  xfail_strict = true
130
131
  asyncio_mode = "auto"
131
132
  asyncio_default_fixture_loop_scope = "session"
@@ -30,6 +30,8 @@ distro==1.8.0
30
30
  exceptiongroup==1.2.2
31
31
  # via anyio
32
32
  # via pytest
33
+ execnet==2.1.1
34
+ # via pytest-xdist
33
35
  filelock==3.12.4
34
36
  # via virtualenv
35
37
  h11==0.14.0
@@ -72,7 +74,9 @@ pygments==2.18.0
72
74
  pyright==1.1.399
73
75
  pytest==8.3.3
74
76
  # via pytest-asyncio
77
+ # via pytest-xdist
75
78
  pytest-asyncio==0.24.0
79
+ pytest-xdist==3.7.0
76
80
  python-dateutil==2.8.2
77
81
  # via time-machine
78
82
  pytz==2023.3.post1
@@ -36,6 +36,7 @@ from ._exceptions import (
36
36
  UnprocessableEntityError,
37
37
  APIResponseValidationError,
38
38
  )
39
+ from .lib.polling import TaskFailedError, TaskTimeoutError
39
40
  from ._base_client import DefaultHttpxClient, DefaultAsyncHttpxClient
40
41
  from ._utils._logs import setup_logging as _setup_logging
41
42
 
@@ -78,6 +79,8 @@ __all__ = [
78
79
  "DEFAULT_CONNECTION_LIMITS",
79
80
  "DefaultHttpxClient",
80
81
  "DefaultAsyncHttpxClient",
82
+ "TaskFailedError",
83
+ "TaskTimeoutError",
81
84
  ]
82
85
 
83
86
  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 inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
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
 
@@ -1574,7 +1581,14 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1574
1581
  ) -> ResponseT:
1575
1582
  origin = get_origin(cast_to) or cast_to
1576
1583
 
1577
- if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
1584
+ if (
1585
+ inspect.isclass(origin)
1586
+ and issubclass(origin, BaseAPIResponse)
1587
+ # we only want to actually return the custom BaseAPIResponse class if we're
1588
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
1589
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
1590
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
1591
+ ):
1578
1592
  if not issubclass(origin, AsyncAPIResponse):
1579
1593
  raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}")
1580
1594
 
@@ -21,7 +21,7 @@ from ._types import (
21
21
  )
22
22
  from ._utils import is_given, get_async_library
23
23
  from ._version import __version__
24
- from .resources import tasks, organization, text_to_image, image_to_video
24
+ from .resources import tasks, organization, text_to_image, video_upscale, image_to_video
25
25
  from ._streaming import Stream as Stream, AsyncStream as AsyncStream
26
26
  from ._exceptions import RunwayMLError, APIStatusError
27
27
  from ._base_client import (
@@ -46,6 +46,7 @@ class RunwayML(SyncAPIClient):
46
46
  tasks: tasks.TasksResource
47
47
  image_to_video: image_to_video.ImageToVideoResource
48
48
  text_to_image: text_to_image.TextToImageResource
49
+ video_upscale: video_upscale.VideoUpscaleResource
49
50
  organization: organization.OrganizationResource
50
51
  with_raw_response: RunwayMLWithRawResponse
51
52
  with_streaming_response: RunwayMLWithStreamedResponse
@@ -113,6 +114,7 @@ class RunwayML(SyncAPIClient):
113
114
  self.tasks = tasks.TasksResource(self)
114
115
  self.image_to_video = image_to_video.ImageToVideoResource(self)
115
116
  self.text_to_image = text_to_image.TextToImageResource(self)
117
+ self.video_upscale = video_upscale.VideoUpscaleResource(self)
116
118
  self.organization = organization.OrganizationResource(self)
117
119
  self.with_raw_response = RunwayMLWithRawResponse(self)
118
120
  self.with_streaming_response = RunwayMLWithStreamedResponse(self)
@@ -229,6 +231,7 @@ class AsyncRunwayML(AsyncAPIClient):
229
231
  tasks: tasks.AsyncTasksResource
230
232
  image_to_video: image_to_video.AsyncImageToVideoResource
231
233
  text_to_image: text_to_image.AsyncTextToImageResource
234
+ video_upscale: video_upscale.AsyncVideoUpscaleResource
232
235
  organization: organization.AsyncOrganizationResource
233
236
  with_raw_response: AsyncRunwayMLWithRawResponse
234
237
  with_streaming_response: AsyncRunwayMLWithStreamedResponse
@@ -296,6 +299,7 @@ class AsyncRunwayML(AsyncAPIClient):
296
299
  self.tasks = tasks.AsyncTasksResource(self)
297
300
  self.image_to_video = image_to_video.AsyncImageToVideoResource(self)
298
301
  self.text_to_image = text_to_image.AsyncTextToImageResource(self)
302
+ self.video_upscale = video_upscale.AsyncVideoUpscaleResource(self)
299
303
  self.organization = organization.AsyncOrganizationResource(self)
300
304
  self.with_raw_response = AsyncRunwayMLWithRawResponse(self)
301
305
  self.with_streaming_response = AsyncRunwayMLWithStreamedResponse(self)
@@ -413,6 +417,7 @@ class RunwayMLWithRawResponse:
413
417
  self.tasks = tasks.TasksResourceWithRawResponse(client.tasks)
414
418
  self.image_to_video = image_to_video.ImageToVideoResourceWithRawResponse(client.image_to_video)
415
419
  self.text_to_image = text_to_image.TextToImageResourceWithRawResponse(client.text_to_image)
420
+ self.video_upscale = video_upscale.VideoUpscaleResourceWithRawResponse(client.video_upscale)
416
421
  self.organization = organization.OrganizationResourceWithRawResponse(client.organization)
417
422
 
418
423
 
@@ -421,6 +426,7 @@ class AsyncRunwayMLWithRawResponse:
421
426
  self.tasks = tasks.AsyncTasksResourceWithRawResponse(client.tasks)
422
427
  self.image_to_video = image_to_video.AsyncImageToVideoResourceWithRawResponse(client.image_to_video)
423
428
  self.text_to_image = text_to_image.AsyncTextToImageResourceWithRawResponse(client.text_to_image)
429
+ self.video_upscale = video_upscale.AsyncVideoUpscaleResourceWithRawResponse(client.video_upscale)
424
430
  self.organization = organization.AsyncOrganizationResourceWithRawResponse(client.organization)
425
431
 
426
432
 
@@ -429,6 +435,7 @@ class RunwayMLWithStreamedResponse:
429
435
  self.tasks = tasks.TasksResourceWithStreamingResponse(client.tasks)
430
436
  self.image_to_video = image_to_video.ImageToVideoResourceWithStreamingResponse(client.image_to_video)
431
437
  self.text_to_image = text_to_image.TextToImageResourceWithStreamingResponse(client.text_to_image)
438
+ self.video_upscale = video_upscale.VideoUpscaleResourceWithStreamingResponse(client.video_upscale)
432
439
  self.organization = organization.OrganizationResourceWithStreamingResponse(client.organization)
433
440
 
434
441
 
@@ -437,6 +444,7 @@ class AsyncRunwayMLWithStreamedResponse:
437
444
  self.tasks = tasks.AsyncTasksResourceWithStreamingResponse(client.tasks)
438
445
  self.image_to_video = image_to_video.AsyncImageToVideoResourceWithStreamingResponse(client.image_to_video)
439
446
  self.text_to_image = text_to_image.AsyncTextToImageResourceWithStreamingResponse(client.text_to_image)
447
+ self.video_upscale = video_upscale.AsyncVideoUpscaleResourceWithStreamingResponse(client.video_upscale)
440
448
  self.organization = organization.AsyncOrganizationResourceWithStreamingResponse(client.organization)
441
449
 
442
450
 
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "runwayml"
4
- __version__ = "3.3.0" # x-release-please-version
4
+ __version__ = "3.5.0" # x-release-please-version
@@ -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")
@@ -24,6 +24,14 @@ from .text_to_image import (
24
24
  TextToImageResourceWithStreamingResponse,
25
25
  AsyncTextToImageResourceWithStreamingResponse,
26
26
  )
27
+ from .video_upscale import (
28
+ VideoUpscaleResource,
29
+ AsyncVideoUpscaleResource,
30
+ VideoUpscaleResourceWithRawResponse,
31
+ AsyncVideoUpscaleResourceWithRawResponse,
32
+ VideoUpscaleResourceWithStreamingResponse,
33
+ AsyncVideoUpscaleResourceWithStreamingResponse,
34
+ )
27
35
  from .image_to_video import (
28
36
  ImageToVideoResource,
29
37
  AsyncImageToVideoResource,
@@ -52,6 +60,12 @@ __all__ = [
52
60
  "AsyncTextToImageResourceWithRawResponse",
53
61
  "TextToImageResourceWithStreamingResponse",
54
62
  "AsyncTextToImageResourceWithStreamingResponse",
63
+ "VideoUpscaleResource",
64
+ "AsyncVideoUpscaleResource",
65
+ "VideoUpscaleResourceWithRawResponse",
66
+ "AsyncVideoUpscaleResourceWithRawResponse",
67
+ "VideoUpscaleResourceWithStreamingResponse",
68
+ "AsyncVideoUpscaleResourceWithStreamingResponse",
55
69
  "OrganizationResource",
56
70
  "AsyncOrganizationResource",
57
71
  "OrganizationResourceWithRawResponse",
@@ -18,6 +18,12 @@ from .._response import (
18
18
  async_to_raw_response_wrapper,
19
19
  async_to_streamed_response_wrapper,
20
20
  )
21
+ from ..lib.polling import (
22
+ NewTaskCreatedResponse,
23
+ AsyncNewTaskCreatedResponse,
24
+ create_waitable_resource,
25
+ create_async_waitable_resource,
26
+ )
21
27
  from .._base_client import make_request_options
22
28
  from ..types.image_to_video_create_response import ImageToVideoCreateResponse
23
29
 
@@ -47,9 +53,10 @@ class ImageToVideoResource(SyncAPIResource):
47
53
  def create(
48
54
  self,
49
55
  *,
50
- model: Literal["gen4_turbo", "gen3a_turbo"],
56
+ model: Literal["gen3a_turbo", "gen4_turbo"],
51
57
  prompt_image: Union[str, Iterable[image_to_video_create_params.PromptImagePromptImage]],
52
58
  ratio: Literal["1280:720", "720:1280", "1104:832", "832:1104", "960:960", "1584:672", "1280:768", "768:1280"],
59
+ content_moderation: image_to_video_create_params.ContentModeration | NotGiven = NOT_GIVEN,
53
60
  duration: Literal[5, 10] | NotGiven = NOT_GIVEN,
54
61
  prompt_text: str | NotGiven = NOT_GIVEN,
55
62
  seed: int | NotGiven = NOT_GIVEN,
@@ -59,7 +66,7 @@ class ImageToVideoResource(SyncAPIResource):
59
66
  extra_query: Query | None = None,
60
67
  extra_body: Body | None = None,
61
68
  timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
62
- ) -> ImageToVideoCreateResponse:
69
+ ) -> NewTaskCreatedResponse:
63
70
  """
64
71
  This endpoint will start a new task to generate a video from an image prompt.
65
72
 
@@ -86,6 +93,8 @@ class ImageToVideoResource(SyncAPIResource):
86
93
  - `1280:768`
87
94
  - `768:1280`
88
95
 
96
+ content_moderation: Settings that affect the behavior of the content moderation system.
97
+
89
98
  duration: The number of seconds of duration for the output video.
90
99
 
91
100
  prompt_text: A non-empty string up to 1000 characters (measured in UTF-16 code units). This
@@ -110,6 +119,7 @@ class ImageToVideoResource(SyncAPIResource):
110
119
  "model": model,
111
120
  "prompt_image": prompt_image,
112
121
  "ratio": ratio,
122
+ "content_moderation": content_moderation,
113
123
  "duration": duration,
114
124
  "prompt_text": prompt_text,
115
125
  "seed": seed,
@@ -119,7 +129,7 @@ class ImageToVideoResource(SyncAPIResource):
119
129
  options=make_request_options(
120
130
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
121
131
  ),
122
- cast_to=ImageToVideoCreateResponse,
132
+ cast_to=create_waitable_resource(ImageToVideoCreateResponse, self._client),
123
133
  )
124
134
 
125
135
 
@@ -146,9 +156,10 @@ class AsyncImageToVideoResource(AsyncAPIResource):
146
156
  async def create(
147
157
  self,
148
158
  *,
149
- model: Literal["gen4_turbo", "gen3a_turbo"],
159
+ model: Literal["gen3a_turbo", "gen4_turbo"],
150
160
  prompt_image: Union[str, Iterable[image_to_video_create_params.PromptImagePromptImage]],
151
161
  ratio: Literal["1280:720", "720:1280", "1104:832", "832:1104", "960:960", "1584:672", "1280:768", "768:1280"],
162
+ content_moderation: image_to_video_create_params.ContentModeration | NotGiven = NOT_GIVEN,
152
163
  duration: Literal[5, 10] | NotGiven = NOT_GIVEN,
153
164
  prompt_text: str | NotGiven = NOT_GIVEN,
154
165
  seed: int | NotGiven = NOT_GIVEN,
@@ -158,7 +169,7 @@ class AsyncImageToVideoResource(AsyncAPIResource):
158
169
  extra_query: Query | None = None,
159
170
  extra_body: Body | None = None,
160
171
  timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
161
- ) -> ImageToVideoCreateResponse:
172
+ ) -> AsyncNewTaskCreatedResponse:
162
173
  """
163
174
  This endpoint will start a new task to generate a video from an image prompt.
164
175
 
@@ -185,6 +196,8 @@ class AsyncImageToVideoResource(AsyncAPIResource):
185
196
  - `1280:768`
186
197
  - `768:1280`
187
198
 
199
+ content_moderation: Settings that affect the behavior of the content moderation system.
200
+
188
201
  duration: The number of seconds of duration for the output video.
189
202
 
190
203
  prompt_text: A non-empty string up to 1000 characters (measured in UTF-16 code units). This
@@ -209,6 +222,7 @@ class AsyncImageToVideoResource(AsyncAPIResource):
209
222
  "model": model,
210
223
  "prompt_image": prompt_image,
211
224
  "ratio": ratio,
225
+ "content_moderation": content_moderation,
212
226
  "duration": duration,
213
227
  "prompt_text": prompt_text,
214
228
  "seed": seed,
@@ -218,7 +232,7 @@ class AsyncImageToVideoResource(AsyncAPIResource):
218
232
  options=make_request_options(
219
233
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
220
234
  ),
221
- cast_to=ImageToVideoCreateResponse,
235
+ cast_to=create_async_waitable_resource(ImageToVideoCreateResponse, self._client),
222
236
  )
223
237
 
224
238
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from typing import cast
6
+
5
7
  import httpx
6
8
 
7
9
  from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven
@@ -13,6 +15,12 @@ from .._response import (
13
15
  async_to_raw_response_wrapper,
14
16
  async_to_streamed_response_wrapper,
15
17
  )
18
+ from ..lib.polling import (
19
+ AwaitableTaskRetrieveResponse,
20
+ AsyncAwaitableTaskRetrieveResponse,
21
+ create_waitable_resource,
22
+ create_async_waitable_resource,
23
+ )
16
24
  from .._base_client import make_request_options
17
25
  from ..types.task_retrieve_response import TaskRetrieveResponse
18
26
 
@@ -49,7 +57,7 @@ class TasksResource(SyncAPIResource):
49
57
  extra_query: Query | None = None,
50
58
  extra_body: Body | None = None,
51
59
  timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
52
- ) -> TaskRetrieveResponse:
60
+ ) -> AwaitableTaskRetrieveResponse:
53
61
  """Return details about a task.
54
62
 
55
63
  Consumers of this API should not expect updates
@@ -71,7 +79,9 @@ class TasksResource(SyncAPIResource):
71
79
  options=make_request_options(
72
80
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
73
81
  ),
74
- cast_to=TaskRetrieveResponse,
82
+ cast_to=cast(
83
+ type[AwaitableTaskRetrieveResponse], create_waitable_resource(TaskRetrieveResponse, self._client)
84
+ ),
75
85
  )
76
86
 
77
87
  def delete(
@@ -144,7 +154,7 @@ class AsyncTasksResource(AsyncAPIResource):
144
154
  extra_query: Query | None = None,
145
155
  extra_body: Body | None = None,
146
156
  timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
147
- ) -> TaskRetrieveResponse:
157
+ ) -> AsyncAwaitableTaskRetrieveResponse:
148
158
  """Return details about a task.
149
159
 
150
160
  Consumers of this API should not expect updates
@@ -166,7 +176,10 @@ class AsyncTasksResource(AsyncAPIResource):
166
176
  options=make_request_options(
167
177
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
168
178
  ),
169
- cast_to=TaskRetrieveResponse,
179
+ cast_to=cast(
180
+ type[AsyncAwaitableTaskRetrieveResponse],
181
+ create_async_waitable_resource(TaskRetrieveResponse, self._client),
182
+ ),
170
183
  )
171
184
 
172
185
  async def delete(
@@ -18,6 +18,12 @@ from .._response import (
18
18
  async_to_raw_response_wrapper,
19
19
  async_to_streamed_response_wrapper,
20
20
  )
21
+ from ..lib.polling import (
22
+ NewTaskCreatedResponse,
23
+ AsyncNewTaskCreatedResponse,
24
+ create_waitable_resource,
25
+ create_async_waitable_resource,
26
+ )
21
27
  from .._base_client import make_request_options
22
28
  from ..types.text_to_image_create_response import TextToImageCreateResponse
23
29
 
@@ -76,7 +82,7 @@ class TextToImageResource(SyncAPIResource):
76
82
  extra_query: Query | None = None,
77
83
  extra_body: Body | None = None,
78
84
  timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
79
- ) -> TextToImageCreateResponse:
85
+ ) -> NewTaskCreatedResponse:
80
86
  """
81
87
  This endpoint will start a new task to generate images from text.
82
88
 
@@ -121,7 +127,7 @@ class TextToImageResource(SyncAPIResource):
121
127
  options=make_request_options(
122
128
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
123
129
  ),
124
- cast_to=TextToImageCreateResponse,
130
+ cast_to=create_waitable_resource(TextToImageCreateResponse, self._client),
125
131
  )
126
132
 
127
133
 
@@ -177,7 +183,7 @@ class AsyncTextToImageResource(AsyncAPIResource):
177
183
  extra_query: Query | None = None,
178
184
  extra_body: Body | None = None,
179
185
  timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
180
- ) -> TextToImageCreateResponse:
186
+ ) -> AsyncNewTaskCreatedResponse:
181
187
  """
182
188
  This endpoint will start a new task to generate images from text.
183
189
 
@@ -222,7 +228,7 @@ class AsyncTextToImageResource(AsyncAPIResource):
222
228
  options=make_request_options(
223
229
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
224
230
  ),
225
- cast_to=TextToImageCreateResponse,
231
+ cast_to=create_async_waitable_resource(TextToImageCreateResponse, self._client),
226
232
  )
227
233
 
228
234