From 24e984ee142c5b1e7fefec7e669495a3c6f2d8da Mon Sep 17 00:00:00 2001 From: stainless-bot Date: Mon, 16 Sep 2024 22:36:09 +0000 Subject: [PATCH] chore: go live --- .github/workflows/publish-pypi.yml | 31 +++++++++ .github/workflows/release-doctor.yml | 21 ++++++ .release-please-manifest.json | 3 + .stats.yml | 2 +- CONTRIBUTING.md | 4 +- README.md | 47 +++++++------ bin/check-release-environment | 21 ++++++ pyproject.toml | 6 +- release-please-config.json | 66 +++++++++++++++++++ src/runwayml/_client.py | 12 ++-- src/runwayml/_version.py | 2 +- src/runwayml/resources/image_to_video.py | 22 +++---- src/runwayml/resources/tasks.py | 8 +-- .../types/image_to_video_create_params.py | 11 ++-- src/runwayml/types/task_retrieve_response.py | 3 +- tests/test_client.py | 36 ++++++++-- 16 files changed, 235 insertions(+), 60 deletions(-) create mode 100644 .github/workflows/publish-pypi.yml create mode 100644 .github/workflows/release-doctor.yml create mode 100644 .release-please-manifest.json create mode 100644 bin/check-release-environment create mode 100644 release-please-config.json diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml new file mode 100644 index 0000000..242fbd4 --- /dev/null +++ b/.github/workflows/publish-pypi.yml @@ -0,0 +1,31 @@ +# This workflow is triggered when a GitHub release is created. +# It can also be run manually to re-publish to PyPI in case it failed for some reason. +# You can run this workflow by navigating to https://www.github.com/runwayml/sdk-python/actions/workflows/publish-pypi.yml +name: Publish PyPI +on: + workflow_dispatch: + + release: + types: [published] + +jobs: + publish: + name: publish + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install Rye + run: | + curl -sSf https://rye.astral.sh/get | bash + echo "$HOME/.rye/shims" >> $GITHUB_PATH + env: + RYE_VERSION: '0.35.0' + RYE_INSTALL_OPTION: '--yes' + + - name: Publish to PyPI + run: | + bash ./bin/publish-pypi + env: + PYPI_TOKEN: ${{ secrets.RUNWAYML_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml new file mode 100644 index 0000000..d4a10a6 --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,21 @@ +name: Release Doctor +on: + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'runwayml/sdk-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') + + steps: + - uses: actions/checkout@v4 + + - name: Check release environment + run: | + bash ./bin/check-release-environment + env: + PYPI_TOKEN: ${{ secrets.RUNWAYML_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..c476280 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1-alpha.0" +} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 8ed588f..e8d3f3c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 3 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml%2Frunwayml-0f66f9e1d151b4f957cba43f88b83bdcae6fa931269b549aec14848624a610ee.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml%2Frunwayml-00c8db8bba8ad66c20debdbe1bb3e56123c3e9162f9310c49f1f5d748a40b96b.yml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0254983..4035f08 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,7 +59,7 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```bash -pip install git+ssh://git@github.com/stainless-sdks/runwayml-python.git +pip install git+ssh://git@github.com/runwayml/sdk-python.git ``` Alternatively, you can build from source and install the wheel file: @@ -117,7 +117,7 @@ the changes aren't made through the automated pipeline, you may want to make rel ### Publish with a GitHub workflow -You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/stainless-sdks/runwayml-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up. +You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/runwayml/sdk-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up. ### Publish manually diff --git a/README.md b/README.md index 2504e15..560a8db 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,13 @@ It is generated with [Stainless](https://www.stainlessapi.com/). ## Documentation -The REST API documentation can be found on [docs.runwayml.com](https://docs.runwayml.com). The full API of this library can be found in [api.md](api.md). +The REST API documentation can be found on [dev.runwayml.com](https://dev.runwayml.com). The full API of this library can be found in [api.md](api.md). ## Installation ```sh -# install from this staging repo -pip install git+ssh://git@github.com/stainless-sdks/runwayml-python.git +# install from the production repo +pip install git+ssh://git@github.com/runwayml/sdk-python.git ``` > [!NOTE] @@ -36,8 +36,9 @@ client = RunwayML( ) image_to_video = client.image_to_video.create( - model="REPLACE_ME", - prompt_image="REPLACE_ME", + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", ) print(image_to_video.id) ``` @@ -64,8 +65,9 @@ client = AsyncRunwayML( async def main() -> None: image_to_video = await client.image_to_video.create( - model="REPLACE_ME", - prompt_image="REPLACE_ME", + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", ) print(image_to_video.id) @@ -101,8 +103,9 @@ client = RunwayML() try: client.image_to_video.create( - model="REPLACE_ME", - prompt_image="REPLACE_ME", + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", ) except runwayml.APIConnectionError as e: print("The server could not be reached") @@ -147,8 +150,9 @@ client = RunwayML( # Or, configure per-request: client.with_options(max_retries=5).image_to_video.create( - model="REPLACE_ME", - prompt_image="REPLACE_ME", + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", ) ``` @@ -173,8 +177,9 @@ client = RunwayML( # Override per-request: client.with_options(timeout=5.0).image_to_video.create( - model="REPLACE_ME", - prompt_image="REPLACE_ME", + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", ) ``` @@ -215,8 +220,9 @@ from runwayml import RunwayML client = RunwayML() response = client.image_to_video.with_raw_response.create( - model="REPLACE_ME", - prompt_image="REPLACE_ME", + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", ) print(response.headers.get('X-My-Header')) @@ -224,9 +230,9 @@ image_to_video = response.parse() # get the object that `image_to_video.create( print(image_to_video.id) ``` -These methods return an [`APIResponse`](https://github.com/stainless-sdks/runwayml-python/tree/main/src/runwayml/_response.py) object. +These methods return an [`APIResponse`](https://github.com/runwayml/sdk-python/tree/main/src/runwayml/_response.py) object. -The async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/runwayml-python/tree/main/src/runwayml/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. +The async client returns an [`AsyncAPIResponse`](https://github.com/runwayml/sdk-python/tree/main/src/runwayml/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. #### `.with_streaming_response` @@ -236,8 +242,9 @@ To stream the response body, use `.with_streaming_response` instead, which requi ```python with client.image_to_video.with_streaming_response.create( - model="REPLACE_ME", - prompt_image="REPLACE_ME", + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", ) as response: print(response.headers.get("X-My-Header")) @@ -323,7 +330,7 @@ This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) con We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. -We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/runwayml-python/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/runwayml/sdk-python/issues) with questions, bugs, or suggestions. ### Determining the installed version diff --git a/bin/check-release-environment b/bin/check-release-environment new file mode 100644 index 0000000..8ddf41e --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +errors=() + +if [ -z "${PYPI_TOKEN}" ]; then + errors+=("The RUNWAYML_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") +fi + +lenErrors=${#errors[@]} + +if [[ lenErrors -gt 0 ]]; then + echo -e "Found the following errors in the release environment:\n" + + for error in "${errors[@]}"; do + echo -e "- $error\n" + done + + exit 1 +fi + +echo "The environment is ready to push releases!" diff --git a/pyproject.toml b/pyproject.toml index e0def5b..5ccced8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,8 +36,8 @@ classifiers = [ ] [project.urls] -Homepage = "https://github.com/stainless-sdks/runwayml-python" -Repository = "https://github.com/stainless-sdks/runwayml-python" +Homepage = "https://github.com/runwayml/sdk-python" +Repository = "https://github.com/runwayml/sdk-python" @@ -123,7 +123,7 @@ path = "README.md" [[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]] # replace relative links with absolute links pattern = '\[(.+?)\]\(((?!https?://)\S+?)\)' -replacement = '[\1](https://github.com/stainless-sdks/runwayml-python/tree/main/\g<2>)' +replacement = '[\1](https://github.com/runwayml/sdk-python/tree/main/\g<2>)' [tool.black] line-length = 120 diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..53d36ce --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,66 @@ +{ + "packages": { + ".": {} + }, + "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", + "include-v-in-tag": true, + "include-component-in-tag": false, + "versioning": "prerelease", + "prerelease": true, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": false, + "pull-request-header": "Automated Release PR", + "pull-request-title-pattern": "release: ${version}", + "changelog-sections": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "refactor", + "section": "Refactors" + }, + { + "type": "test", + "section": "Tests", + "hidden": true + }, + { + "type": "build", + "section": "Build System" + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": true + } + ], + "release-type": "python", + "extra-files": [ + "src/runwayml/_version.py" + ] +} \ No newline at end of file diff --git a/src/runwayml/_client.py b/src/runwayml/_client.py index 4c2423a..5d3f6a7 100644 --- a/src/runwayml/_client.py +++ b/src/runwayml/_client.py @@ -59,7 +59,7 @@ def __init__( self, *, api_key: str | None = None, - runway_version: str | None = "2023-09-06", + runway_version: str | None = "2024-09-13", base_url: str | httpx.URL | None = None, timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, @@ -92,13 +92,13 @@ def __init__( self.api_key = api_key if runway_version is None: - runway_version = "2023-09-06" + runway_version = "2024-09-13" self.runway_version = runway_version if base_url is None: base_url = os.environ.get("RUNWAYML_BASE_URL") if base_url is None: - base_url = f"https://playdoh.runwayml.com" + base_url = f"https://api.dev.runwayml.com" super().__init__( version=__version__, @@ -238,7 +238,7 @@ def __init__( self, *, api_key: str | None = None, - runway_version: str | None = "2023-09-06", + runway_version: str | None = "2024-09-13", base_url: str | httpx.URL | None = None, timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, @@ -271,13 +271,13 @@ def __init__( self.api_key = api_key if runway_version is None: - runway_version = "2023-09-06" + runway_version = "2024-09-13" self.runway_version = runway_version if base_url is None: base_url = os.environ.get("RUNWAYML_BASE_URL") if base_url is None: - base_url = f"https://playdoh.runwayml.com" + base_url = f"https://api.dev.runwayml.com" super().__init__( version=__version__, diff --git a/src/runwayml/_version.py b/src/runwayml/_version.py index ea497da..ac100a1 100644 --- a/src/runwayml/_version.py +++ b/src/runwayml/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "runwayml" -__version__ = "0.0.1-alpha.0" +__version__ = "0.0.1-alpha.0" # x-release-please-version diff --git a/src/runwayml/resources/image_to_video.py b/src/runwayml/resources/image_to_video.py index 11da28c..8548800 100644 --- a/src/runwayml/resources/image_to_video.py +++ b/src/runwayml/resources/image_to_video.py @@ -33,7 +33,7 @@ def with_raw_response(self) -> ImageToVideoResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/runwayml-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/runwayml/sdk-python#accessing-raw-response-data-eg-headers """ return ImageToVideoResourceWithRawResponse(self) @@ -42,7 +42,7 @@ def with_streaming_response(self) -> ImageToVideoResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/runwayml-python#with_streaming_response + For more information, see https://www.github.com/runwayml/sdk-python#with_streaming_response """ return ImageToVideoResourceWithStreamingResponse(self) @@ -67,11 +67,10 @@ def create( Args: model: The model variant to use. - prompt_image: A URL pointing to an image. See documentation on input URLs. + prompt_image: A HTTPS URL pointing to an image. Images must be JPEG, PNG, or WebP and are + limited to 16MB. Responses must include a valid `Content-Length` header. - prompt_text: A non-empty string up to 512 UTF-16 code points in length (that is, - `promptText.length === 512` in JavaScript). This should describe in detail what - should appear in the output. + prompt_text seed: If unspecified, a random number is chosen. Varying the seed integer is a way to get different results for the same other request parameters. Using the same seed @@ -114,7 +113,7 @@ def with_raw_response(self) -> AsyncImageToVideoResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/runwayml-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/runwayml/sdk-python#accessing-raw-response-data-eg-headers """ return AsyncImageToVideoResourceWithRawResponse(self) @@ -123,7 +122,7 @@ def with_streaming_response(self) -> AsyncImageToVideoResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/runwayml-python#with_streaming_response + For more information, see https://www.github.com/runwayml/sdk-python#with_streaming_response """ return AsyncImageToVideoResourceWithStreamingResponse(self) @@ -148,11 +147,10 @@ async def create( Args: model: The model variant to use. - prompt_image: A URL pointing to an image. See documentation on input URLs. + prompt_image: A HTTPS URL pointing to an image. Images must be JPEG, PNG, or WebP and are + limited to 16MB. Responses must include a valid `Content-Length` header. - prompt_text: A non-empty string up to 512 UTF-16 code points in length (that is, - `promptText.length === 512` in JavaScript). This should describe in detail what - should appear in the output. + prompt_text seed: If unspecified, a random number is chosen. Varying the seed integer is a way to get different results for the same other request parameters. Using the same seed diff --git a/src/runwayml/resources/tasks.py b/src/runwayml/resources/tasks.py index 45d5547..192eb72 100644 --- a/src/runwayml/resources/tasks.py +++ b/src/runwayml/resources/tasks.py @@ -26,7 +26,7 @@ def with_raw_response(self) -> TasksResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/runwayml-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/runwayml/sdk-python#accessing-raw-response-data-eg-headers """ return TasksResourceWithRawResponse(self) @@ -35,7 +35,7 @@ def with_streaming_response(self) -> TasksResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/runwayml-python#with_streaming_response + For more information, see https://www.github.com/runwayml/sdk-python#with_streaming_response """ return TasksResourceWithStreamingResponse(self) @@ -121,7 +121,7 @@ def with_raw_response(self) -> AsyncTasksResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/runwayml-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/runwayml/sdk-python#accessing-raw-response-data-eg-headers """ return AsyncTasksResourceWithRawResponse(self) @@ -130,7 +130,7 @@ def with_streaming_response(self) -> AsyncTasksResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/runwayml-python#with_streaming_response + For more information, see https://www.github.com/runwayml/sdk-python#with_streaming_response """ return AsyncTasksResourceWithStreamingResponse(self) diff --git a/src/runwayml/types/image_to_video_create_params.py b/src/runwayml/types/image_to_video_create_params.py index 1b964ef..b941b90 100644 --- a/src/runwayml/types/image_to_video_create_params.py +++ b/src/runwayml/types/image_to_video_create_params.py @@ -14,15 +14,14 @@ class ImageToVideoCreateParams(TypedDict, total=False): """The model variant to use.""" prompt_image: Required[Annotated[str, PropertyInfo(alias="promptImage")]] - """A URL pointing to an image. See documentation on input URLs.""" + """A HTTPS URL pointing to an image. - prompt_text: Annotated[str, PropertyInfo(alias="promptText")] - """ - A non-empty string up to 512 UTF-16 code points in length (that is, - `promptText.length === 512` in JavaScript). This should describe in detail what - should appear in the output. + Images must be JPEG, PNG, or WebP and are limited to 16MB. Responses must + include a valid `Content-Length` header. """ + prompt_text: Annotated[str, PropertyInfo(alias="promptText")] + seed: int """If unspecified, a random number is chosen. diff --git a/src/runwayml/types/task_retrieve_response.py b/src/runwayml/types/task_retrieve_response.py index e2398e0..69866b8 100644 --- a/src/runwayml/types/task_retrieve_response.py +++ b/src/runwayml/types/task_retrieve_response.py @@ -47,7 +47,8 @@ class TaskRetrieveResponse(BaseModel): """If the status is `SUCCEEDED`, this will contain an array of strings. Each string will be a URL that returns an output from the task. URLs expire - within 24-48 hours. + within 24-48 hours; fetch the task again to get fresh URLs. It is expected that + you download the assets at these URLs and store them in your own storage system. """ progress: Optional[float] = None diff --git a/tests/test_client.py b/tests/test_client.py index 9f62e31..a7f7d3e 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -711,7 +711,14 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> No with pytest.raises(APITimeoutError): self.client.post( "/v1/image_to_video", - body=cast(object, dict(model="REPLACE_ME", prompt_image="REPLACE_ME")), + body=cast( + object, + dict( + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", + ), + ), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -726,7 +733,14 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> Non with pytest.raises(APIStatusError): self.client.post( "/v1/image_to_video", - body=cast(object, dict(model="REPLACE_ME", prompt_image="REPLACE_ME")), + body=cast( + object, + dict( + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", + ), + ), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -1432,7 +1446,14 @@ async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) with pytest.raises(APITimeoutError): await self.client.post( "/v1/image_to_video", - body=cast(object, dict(model="REPLACE_ME", prompt_image="REPLACE_ME")), + body=cast( + object, + dict( + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", + ), + ), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -1447,7 +1468,14 @@ async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) with pytest.raises(APIStatusError): await self.client.post( "/v1/image_to_video", - body=cast(object, dict(model="REPLACE_ME", prompt_image="REPLACE_ME")), + body=cast( + object, + dict( + model="gen3a_turbo", + prompt_image="https://example.com/assets/bunny.jpg", + prompt_text="The bunny is eating a carrot", + ), + ), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, )