From fa1217ede9f79e634f1d8041f1d4dd2f7cb6148f Mon Sep 17 00:00:00 2001 From: "stainless-sdks[bot]" <167585319+stainless-sdks[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 12:13:53 +0000 Subject: [PATCH 001/177] Initial commit --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..4bab7f0 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# imagekit-python \ No newline at end of file From 68cfc834f51a6717ccfc4983f74b2359acee42e2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 12:14:11 +0000 Subject: [PATCH 002/177] feat: enable python --- .devcontainer/Dockerfile | 9 + .devcontainer/devcontainer.json | 43 + .github/workflows/ci.yml | 96 + .gitignore | 15 + .python-version | 1 + .stats.yml | 4 + .vscode/settings.json | 3 + Brewfile | 2 + CONTRIBUTING.md | 128 + LICENSE | 201 ++ README.md | 419 ++- SECURITY.md | 27 + api.md | 154 ++ bin/publish-pypi | 6 + examples/.keep | 4 + mypy.ini | 50 + noxfile.py | 9 + pyproject.toml | 211 ++ requirements-dev.lock | 135 + requirements.lock | 72 + scripts/bootstrap | 19 + scripts/format | 8 + scripts/lint | 11 + scripts/mock | 41 + scripts/test | 61 + scripts/utils/ruffen-docs.py | 167 ++ scripts/utils/upload-artifact.sh | 27 + src/imagekit/__init__.py | 100 + src/imagekit/_base_client.py | 1995 +++++++++++++++ src/imagekit/_client.py | 500 ++++ src/imagekit/_compat.py | 219 ++ src/imagekit/_constants.py | 14 + src/imagekit/_exceptions.py | 108 + src/imagekit/_files.py | 123 + src/imagekit/_models.py | 829 ++++++ src/imagekit/_qs.py | 150 ++ src/imagekit/_resource.py | 43 + src/imagekit/_response.py | 830 ++++++ src/imagekit/_streaming.py | 333 +++ src/imagekit/_types.py | 219 ++ src/imagekit/_utils/__init__.py | 57 + src/imagekit/_utils/_logs.py | 25 + src/imagekit/_utils/_proxy.py | 65 + src/imagekit/_utils/_reflection.py | 42 + src/imagekit/_utils/_resources_proxy.py | 24 + src/imagekit/_utils/_streams.py | 12 + src/imagekit/_utils/_sync.py | 86 + src/imagekit/_utils/_transform.py | 447 ++++ src/imagekit/_utils/_typing.py | 151 ++ src/imagekit/_utils/_utils.py | 422 +++ src/imagekit/_version.py | 4 + src/imagekit/lib/.keep | 4 + src/imagekit/py.typed | 0 src/imagekit/resources/__init__.py | 75 + src/imagekit/resources/accounts.py | 206 ++ src/imagekit/resources/bulk_jobs.py | 397 +++ .../resources/custom_metadata_fields.py | 509 ++++ src/imagekit/resources/files/__init__.py | 89 + src/imagekit/resources/files/batch.py | 181 ++ src/imagekit/resources/files/details.py | 447 ++++ src/imagekit/resources/files/files.py | 2258 +++++++++++++++++ src/imagekit/resources/files/metadata.py | 264 ++ src/imagekit/resources/files/purge.py | 252 ++ src/imagekit/resources/files/versions.py | 425 ++++ src/imagekit/resources/folder.py | 292 +++ src/imagekit/types/__init__.py | 39 + .../types/account_get_usage_params.py | 27 + .../types/account_get_usage_response.py | 26 + .../types/bulk_job_copy_folder_params.py | 27 + .../types/bulk_job_copy_folder_response.py | 17 + .../types/bulk_job_move_folder_params.py | 20 + .../types/bulk_job_move_folder_response.py | 17 + .../bulk_job_retrieve_status_response.py | 20 + .../custom_metadata_field_create_params.py | 82 + .../custom_metadata_field_create_response.py | 73 + .../custom_metadata_field_list_params.py | 17 + .../custom_metadata_field_list_response.py | 80 + .../custom_metadata_field_update_params.py | 80 + .../custom_metadata_field_update_response.py | 73 + src/imagekit/types/file_add_tags_params.py | 18 + src/imagekit/types/file_add_tags_response.py | 14 + src/imagekit/types/file_copy_params.py | 24 + src/imagekit/types/file_list_params.py | 81 + src/imagekit/types/file_list_response.py | 117 + src/imagekit/types/file_move_params.py | 17 + .../types/file_remove_ai_tags_params.py | 18 + .../types/file_remove_ai_tags_response.py | 14 + src/imagekit/types/file_remove_tags_params.py | 18 + .../types/file_remove_tags_response.py | 14 + src/imagekit/types/file_rename_params.py | 42 + src/imagekit/types/file_rename_response.py | 17 + src/imagekit/types/file_upload_v1_params.py | 211 ++ src/imagekit/types/file_upload_v1_response.py | 715 ++++++ src/imagekit/types/file_upload_v2_params.py | 179 ++ src/imagekit/types/file_upload_v2_response.py | 715 ++++++ src/imagekit/types/files/__init__.py | 18 + .../types/files/batch_delete_params.py | 15 + .../types/files/batch_delete_response.py | 14 + .../types/files/detail_retrieve_response.py | 113 + .../types/files/detail_update_params.py | 139 + .../types/files/detail_update_response.py | 128 + .../types/files/metadata_from_url_params.py | 15 + .../types/files/metadata_from_url_response.py | 181 ++ .../types/files/metadata_retrieve_response.py | 181 ++ .../types/files/purge_execute_params.py | 12 + .../types/files/purge_execute_response.py | 17 + .../types/files/purge_status_response.py | 13 + .../types/files/version_list_response.py | 122 + .../types/files/version_restore_response.py | 113 + .../types/files/version_retrieve_response.py | 113 + src/imagekit/types/folder_create_params.py | 30 + src/imagekit/types/folder_delete_params.py | 14 + tests/__init__.py | 1 + tests/api_resources/__init__.py | 1 + tests/api_resources/files/__init__.py | 1 + tests/api_resources/files/test_batch.py | 92 + tests/api_resources/files/test_details.py | 348 +++ tests/api_resources/files/test_metadata.py | 176 ++ tests/api_resources/files/test_purge.py | 176 ++ tests/api_resources/files/test_versions.py | 420 +++ tests/api_resources/test_accounts.py | 99 + tests/api_resources/test_bulk_jobs.py | 280 ++ .../test_custom_metadata_fields.py | 422 +++ tests/api_resources/test_files.py | 942 +++++++ tests/api_resources/test_folder.py | 165 ++ tests/conftest.py | 91 + tests/sample_file.txt | 1 + tests/test_client.py | 1919 ++++++++++++++ tests/test_deepcopy.py | 58 + tests/test_extract_files.py | 64 + tests/test_files.py | 51 + tests/test_models.py | 963 +++++++ tests/test_qs.py | 78 + tests/test_required_args.py | 111 + tests/test_response.py | 277 ++ tests/test_streaming.py | 248 ++ tests/test_transform.py | 453 ++++ tests/test_utils/test_proxy.py | 34 + tests/test_utils/test_typing.py | 73 + tests/utils.py | 159 ++ 140 files changed, 25872 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .python-version create mode 100644 .stats.yml create mode 100644 .vscode/settings.json create mode 100644 Brewfile create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 SECURITY.md create mode 100644 api.md create mode 100644 bin/publish-pypi create mode 100644 examples/.keep create mode 100644 mypy.ini create mode 100644 noxfile.py create mode 100644 pyproject.toml create mode 100644 requirements-dev.lock create mode 100644 requirements.lock create mode 100755 scripts/bootstrap create mode 100755 scripts/format create mode 100755 scripts/lint create mode 100755 scripts/mock create mode 100755 scripts/test create mode 100644 scripts/utils/ruffen-docs.py create mode 100755 scripts/utils/upload-artifact.sh create mode 100644 src/imagekit/__init__.py create mode 100644 src/imagekit/_base_client.py create mode 100644 src/imagekit/_client.py create mode 100644 src/imagekit/_compat.py create mode 100644 src/imagekit/_constants.py create mode 100644 src/imagekit/_exceptions.py create mode 100644 src/imagekit/_files.py create mode 100644 src/imagekit/_models.py create mode 100644 src/imagekit/_qs.py create mode 100644 src/imagekit/_resource.py create mode 100644 src/imagekit/_response.py create mode 100644 src/imagekit/_streaming.py create mode 100644 src/imagekit/_types.py create mode 100644 src/imagekit/_utils/__init__.py create mode 100644 src/imagekit/_utils/_logs.py create mode 100644 src/imagekit/_utils/_proxy.py create mode 100644 src/imagekit/_utils/_reflection.py create mode 100644 src/imagekit/_utils/_resources_proxy.py create mode 100644 src/imagekit/_utils/_streams.py create mode 100644 src/imagekit/_utils/_sync.py create mode 100644 src/imagekit/_utils/_transform.py create mode 100644 src/imagekit/_utils/_typing.py create mode 100644 src/imagekit/_utils/_utils.py create mode 100644 src/imagekit/_version.py create mode 100644 src/imagekit/lib/.keep create mode 100644 src/imagekit/py.typed create mode 100644 src/imagekit/resources/__init__.py create mode 100644 src/imagekit/resources/accounts.py create mode 100644 src/imagekit/resources/bulk_jobs.py create mode 100644 src/imagekit/resources/custom_metadata_fields.py create mode 100644 src/imagekit/resources/files/__init__.py create mode 100644 src/imagekit/resources/files/batch.py create mode 100644 src/imagekit/resources/files/details.py create mode 100644 src/imagekit/resources/files/files.py create mode 100644 src/imagekit/resources/files/metadata.py create mode 100644 src/imagekit/resources/files/purge.py create mode 100644 src/imagekit/resources/files/versions.py create mode 100644 src/imagekit/resources/folder.py create mode 100644 src/imagekit/types/__init__.py create mode 100644 src/imagekit/types/account_get_usage_params.py create mode 100644 src/imagekit/types/account_get_usage_response.py create mode 100644 src/imagekit/types/bulk_job_copy_folder_params.py create mode 100644 src/imagekit/types/bulk_job_copy_folder_response.py create mode 100644 src/imagekit/types/bulk_job_move_folder_params.py create mode 100644 src/imagekit/types/bulk_job_move_folder_response.py create mode 100644 src/imagekit/types/bulk_job_retrieve_status_response.py create mode 100644 src/imagekit/types/custom_metadata_field_create_params.py create mode 100644 src/imagekit/types/custom_metadata_field_create_response.py create mode 100644 src/imagekit/types/custom_metadata_field_list_params.py create mode 100644 src/imagekit/types/custom_metadata_field_list_response.py create mode 100644 src/imagekit/types/custom_metadata_field_update_params.py create mode 100644 src/imagekit/types/custom_metadata_field_update_response.py create mode 100644 src/imagekit/types/file_add_tags_params.py create mode 100644 src/imagekit/types/file_add_tags_response.py create mode 100644 src/imagekit/types/file_copy_params.py create mode 100644 src/imagekit/types/file_list_params.py create mode 100644 src/imagekit/types/file_list_response.py create mode 100644 src/imagekit/types/file_move_params.py create mode 100644 src/imagekit/types/file_remove_ai_tags_params.py create mode 100644 src/imagekit/types/file_remove_ai_tags_response.py create mode 100644 src/imagekit/types/file_remove_tags_params.py create mode 100644 src/imagekit/types/file_remove_tags_response.py create mode 100644 src/imagekit/types/file_rename_params.py create mode 100644 src/imagekit/types/file_rename_response.py create mode 100644 src/imagekit/types/file_upload_v1_params.py create mode 100644 src/imagekit/types/file_upload_v1_response.py create mode 100644 src/imagekit/types/file_upload_v2_params.py create mode 100644 src/imagekit/types/file_upload_v2_response.py create mode 100644 src/imagekit/types/files/__init__.py create mode 100644 src/imagekit/types/files/batch_delete_params.py create mode 100644 src/imagekit/types/files/batch_delete_response.py create mode 100644 src/imagekit/types/files/detail_retrieve_response.py create mode 100644 src/imagekit/types/files/detail_update_params.py create mode 100644 src/imagekit/types/files/detail_update_response.py create mode 100644 src/imagekit/types/files/metadata_from_url_params.py create mode 100644 src/imagekit/types/files/metadata_from_url_response.py create mode 100644 src/imagekit/types/files/metadata_retrieve_response.py create mode 100644 src/imagekit/types/files/purge_execute_params.py create mode 100644 src/imagekit/types/files/purge_execute_response.py create mode 100644 src/imagekit/types/files/purge_status_response.py create mode 100644 src/imagekit/types/files/version_list_response.py create mode 100644 src/imagekit/types/files/version_restore_response.py create mode 100644 src/imagekit/types/files/version_retrieve_response.py create mode 100644 src/imagekit/types/folder_create_params.py create mode 100644 src/imagekit/types/folder_delete_params.py create mode 100644 tests/__init__.py create mode 100644 tests/api_resources/__init__.py create mode 100644 tests/api_resources/files/__init__.py create mode 100644 tests/api_resources/files/test_batch.py create mode 100644 tests/api_resources/files/test_details.py create mode 100644 tests/api_resources/files/test_metadata.py create mode 100644 tests/api_resources/files/test_purge.py create mode 100644 tests/api_resources/files/test_versions.py create mode 100644 tests/api_resources/test_accounts.py create mode 100644 tests/api_resources/test_bulk_jobs.py create mode 100644 tests/api_resources/test_custom_metadata_fields.py create mode 100644 tests/api_resources/test_files.py create mode 100644 tests/api_resources/test_folder.py create mode 100644 tests/conftest.py create mode 100644 tests/sample_file.txt create mode 100644 tests/test_client.py create mode 100644 tests/test_deepcopy.py create mode 100644 tests/test_extract_files.py create mode 100644 tests/test_files.py create mode 100644 tests/test_models.py create mode 100644 tests/test_qs.py create mode 100644 tests/test_required_args.py create mode 100644 tests/test_response.py create mode 100644 tests/test_streaming.py create mode 100644 tests/test_transform.py create mode 100644 tests/test_utils/test_proxy.py create mode 100644 tests/test_utils/test_typing.py create mode 100644 tests/utils.py diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..ff261ba --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,9 @@ +ARG VARIANT="3.9" +FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} + +USER vscode + +RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.44.0" RYE_INSTALL_OPTION="--yes" bash +ENV PATH=/home/vscode/.rye/shims:$PATH + +RUN echo "[[ -d .venv ]] && source .venv/bin/activate || export PATH=\$PATH" >> /home/vscode/.bashrc diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..c17fdc1 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,43 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/debian +{ + "name": "Debian", + "build": { + "dockerfile": "Dockerfile", + "context": ".." + }, + + "postStartCommand": "rye sync --all-features", + + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python" + ], + "settings": { + "terminal.integrated.shell.linux": "/bin/bash", + "python.pythonPath": ".venv/bin/python", + "python.defaultInterpreterPath": ".venv/bin/python", + "python.typeChecking": "basic", + "terminal.integrated.env.linux": { + "PATH": "/home/vscode/.rye/shims:${env:PATH}" + } + } + } + }, + "features": { + "ghcr.io/devcontainers/features/node:1": {} + } + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..fc0291c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,96 @@ +name: CI +on: + push: + branches-ignore: + - 'generated' + - 'codegen/**' + - 'integrated/**' + - 'stl-preview-head/**' + - 'stl-preview-base/**' + pull_request: + branches-ignore: + - 'stl-preview-head/**' + - 'stl-preview-base/**' + +jobs: + lint: + timeout-minutes: 10 + name: lint + runs-on: ${{ github.repository == 'stainless-sdks/imagekit-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + 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.44.0' + RYE_INSTALL_OPTION: '--yes' + + - name: Install dependencies + run: rye sync --all-features + + - name: Run lints + run: ./scripts/lint + + build: + if: github.repository == 'stainless-sdks/imagekit-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork) + timeout-minutes: 10 + name: build + permissions: + contents: read + id-token: write + runs-on: depot-ubuntu-24.04 + 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.44.0' + RYE_INSTALL_OPTION: '--yes' + + - name: Install dependencies + run: rye sync --all-features + + - name: Run build + run: rye build + + - name: Get GitHub OIDC Token + id: github-oidc + uses: actions/github-script@v6 + with: + script: core.setOutput('github_token', await core.getIDToken()); + + - name: Upload tarball + env: + URL: https://pkg.stainless.com/s + AUTH: ${{ steps.github-oidc.outputs.github_token }} + SHA: ${{ github.sha }} + run: ./scripts/utils/upload-artifact.sh + + test: + timeout-minutes: 10 + name: test + runs-on: ${{ github.repository == 'stainless-sdks/imagekit-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + 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.44.0' + RYE_INSTALL_OPTION: '--yes' + + - name: Bootstrap + run: ./scripts/bootstrap + + - name: Run tests + run: ./scripts/test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..95ceb18 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +.prism.log +_dev + +__pycache__ +.mypy_cache + +dist + +.venv +.idea + +.env +.envrc +codegen.log +Brewfile.lock.json diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..43077b2 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.9.18 diff --git a/.stats.yml b/.stats.yml new file mode 100644 index 0000000..3f0734c --- /dev/null +++ b/.stats.yml @@ -0,0 +1,4 @@ +configured_endpoints: 31 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0ffd73f83f6d2c3ad75d943fab8f4511847a7b1f8db10fb26a08f075ec814cc9.yml +openapi_spec_hash: afa5d5b601dc01949e9b9acff127ae0d +config_hash: 0076af6656b570a0e67dfbae986295d3 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5b01030 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.analysis.importFormat": "relative", +} diff --git a/Brewfile b/Brewfile new file mode 100644 index 0000000..492ca37 --- /dev/null +++ b/Brewfile @@ -0,0 +1,2 @@ +brew "rye" + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..a133f19 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,128 @@ +## Setting up the environment + +### With Rye + +We use [Rye](https://rye.astral.sh/) to manage dependencies because it will automatically provision a Python environment with the expected Python version. To set it up, run: + +```sh +$ ./scripts/bootstrap +``` + +Or [install Rye manually](https://rye.astral.sh/guide/installation/) and run: + +```sh +$ rye sync --all-features +``` + +You can then run scripts using `rye run python script.py` or by activating the virtual environment: + +```sh +# Activate the virtual environment - https://docs.python.org/3/library/venv.html#how-venvs-work +$ source .venv/bin/activate + +# now you can omit the `rye run` prefix +$ python script.py +``` + +### Without Rye + +Alternatively if you don't want to install `Rye`, you can stick with the standard `pip` setup by ensuring you have the Python version specified in `.python-version`, create a virtual environment however you desire and then install dependencies using this command: + +```sh +$ pip install -r requirements-dev.lock +``` + +## Modifying/Adding code + +Most of the SDK is generated code. Modifications to code will be persisted between generations, but may +result in merge conflicts between manual patches and changes from the generator. The generator will never +modify the contents of the `src/imagekit/lib/` and `examples/` directories. + +## Adding and running examples + +All files in the `examples/` directory are not modified by the generator and can be freely edited or added to. + +```py +# add an example to examples/.py + +#!/usr/bin/env -S rye run python +… +``` + +```sh +$ chmod +x examples/.py +# run the example against your api +$ ./examples/.py +``` + +## Using the repository from source + +If you’d like to use the repository from source, you can either install from git or link to a cloned repository: + +To install via git: + +```sh +$ pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git +``` + +Alternatively, you can build from source and install the wheel file: + +Building this package will create two files in the `dist/` directory, a `.tar.gz` containing the source files and a `.whl` that can be used to install the package efficiently. + +To create a distributable version of the library, all you have to do is run this command: + +```sh +$ rye build +# or +$ python -m build +``` + +Then to install: + +```sh +$ pip install ./path-to-wheel-file.whl +``` + +## Running tests + +Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. + +```sh +# you will need npm installed +$ npx prism mock path/to/your/openapi.yml +``` + +```sh +$ ./scripts/test +``` + +## Linting and formatting + +This repository uses [ruff](https://github.com/astral-sh/ruff) and +[black](https://github.com/psf/black) to format the code in the repository. + +To lint: + +```sh +$ ./scripts/lint +``` + +To format and fix all ruff issues automatically: + +```sh +$ ./scripts/format +``` + +## Publishing and releases + +Changes made to this repository via the automated release PR pipeline should publish to PyPI automatically. If +the changes aren't made through the automated pipeline, you may want to make releases manually. + +### Publish with a GitHub workflow + +You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/stainless-sdks/imagekit-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up. + +### Publish manually + +If you need to manually release a package, you can run the `bin/publish-pypi` script with a `PYPI_TOKEN` set on +the environment. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e7a4d16 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2025 Image Kit + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 4bab7f0..204ede0 100644 --- a/README.md +++ b/README.md @@ -1 +1,418 @@ -# imagekit-python \ No newline at end of file +# Image Kit Python API library + + +[![PyPI version](https://img.shields.io/pypi/v/imagekit.svg?label=pypi%20(stable))](https://pypi.org/project/imagekit/) + +The Image Kit Python library provides convenient access to the Image Kit REST API from any Python 3.8+ +application. The library includes type definitions for all request params and response fields, +and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx). + +It is generated with [Stainless](https://www.stainless.com/). + +## Documentation + +The REST API documentation can be found on [imagekit.io](https://imagekit.io). 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/imagekit-python.git +``` + +> [!NOTE] +> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install imagekit` + +## Usage + +The full API of this library can be found in [api.md](api.md). + +```python +import os +from imagekit import ImageKit + +client = ImageKit( + private_api_key=os.environ.get( + "IMAGEKIT_PRIVATE_API_KEY" + ), # This is the default and can be omitted + password=os.environ.get("ORG_MY_PASSWORD_TOKEN"), # This is the default and can be omitted +) + +response = client.files.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", +) +print(response.video_codec) +``` + +While you can provide a `private_api_key` keyword argument, +we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/) +to add `IMAGEKIT_PRIVATE_API_KEY="My Private API Key"` to your `.env` file +so that your Private API Key is not stored in source control. + +## Async usage + +Simply import `AsyncImageKit` instead of `ImageKit` and use `await` with each API call: + +```python +import os +import asyncio +from imagekit import AsyncImageKit + +client = AsyncImageKit( + private_api_key=os.environ.get( + "IMAGEKIT_PRIVATE_API_KEY" + ), # This is the default and can be omitted + password=os.environ.get("ORG_MY_PASSWORD_TOKEN"), # This is the default and can be omitted +) + + +async def main() -> None: + response = await client.files.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) + print(response.video_codec) + + +asyncio.run(main()) +``` + +Functionality between the synchronous and asynchronous clients is otherwise identical. + +### With aiohttp + +By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend. + +You can enable this by installing `aiohttp`: + +```sh +# install from this staging repo +pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/stainless-sdks/imagekit-python.git' +``` + +Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: + +```python +import asyncio +from imagekit import DefaultAioHttpClient +from imagekit import AsyncImageKit + + +async def main() -> None: + async with AsyncImageKit( + private_api_key="My Private API Key", + password="My Password", + http_client=DefaultAioHttpClient(), + ) as client: + response = await client.files.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) + print(response.video_codec) + + +asyncio.run(main()) +``` + +## Using types + +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: + +- Serializing back into JSON, `model.to_json()` +- Converting to a dictionary, `model.to_dict()` + +Typed requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`. + +## Nested params + +Nested parameters are dictionaries, typed using `TypedDict`, for example: + +```python +from imagekit import ImageKit + +client = ImageKit() + +custom_metadata_field = client.custom_metadata_fields.create( + label="price", + name="price", + schema={ + "type": "Number", + "max_value": 3000, + "min_value": 1000, + }, +) +print(custom_metadata_field.schema) +``` + +## Handling errors + +When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `imagekit.APIConnectionError` is raised. + +When the API returns a non-success status code (that is, 4xx or 5xx +response), a subclass of `imagekit.APIStatusError` is raised, containing `status_code` and `response` properties. + +All errors inherit from `imagekit.APIError`. + +```python +import imagekit +from imagekit import ImageKit + +client = ImageKit() + +try: + client.files.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) +except imagekit.APIConnectionError as e: + print("The server could not be reached") + print(e.__cause__) # an underlying Exception, likely raised within httpx. +except imagekit.RateLimitError as e: + print("A 429 status code was received; we should back off a bit.") +except imagekit.APIStatusError as e: + print("Another non-200-range status code was received") + print(e.status_code) + print(e.response) +``` + +Error codes are as follows: + +| Status Code | Error Type | +| ----------- | -------------------------- | +| 400 | `BadRequestError` | +| 401 | `AuthenticationError` | +| 403 | `PermissionDeniedError` | +| 404 | `NotFoundError` | +| 422 | `UnprocessableEntityError` | +| 429 | `RateLimitError` | +| >=500 | `InternalServerError` | +| N/A | `APIConnectionError` | + +### Retries + +Certain errors are automatically retried 2 times by default, with a short exponential backoff. +Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, +429 Rate Limit, and >=500 Internal errors are all retried by default. + +You can use the `max_retries` option to configure or disable retry settings: + +```python +from imagekit import ImageKit + +# Configure the default for all requests: +client = ImageKit( + # default is 2 + max_retries=0, +) + +# Or, configure per-request: +client.with_options(max_retries=5).files.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", +) +``` + +### Timeouts + +By default requests time out after 1 minute. You can configure this with a `timeout` option, +which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object: + +```python +from imagekit import ImageKit + +# Configure the default for all requests: +client = ImageKit( + # 20 seconds (default is 1 minute) + timeout=20.0, +) + +# More granular control: +client = ImageKit( + timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0), +) + +# Override per-request: +client.with_options(timeout=5.0).files.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", +) +``` + +On timeout, an `APITimeoutError` is thrown. + +Note that requests that time out are [retried twice by default](#retries). + +## Advanced + +### Logging + +We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module. + +You can enable logging by setting the environment variable `IMAGE_KIT_LOG` to `info`. + +```shell +$ export IMAGE_KIT_LOG=info +``` + +Or to `debug` for more verbose logging. + +### How to tell whether `None` means `null` or missing + +In an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`: + +```py +if response.my_field is None: + if 'my_field' not in response.model_fields_set: + print('Got json like {}, without a "my_field" key present at all.') + else: + print('Got json like {"my_field": null}.') +``` + +### Accessing raw response data (e.g. headers) + +The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g., + +```py +from imagekit import ImageKit + +client = ImageKit() +response = client.files.with_raw_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", +) +print(response.headers.get('X-My-Header')) + +file = response.parse() # get the object that `files.upload_v1()` would have returned +print(file.video_codec) +``` + +These methods return an [`APIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekit/_response.py) object. + +The async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekit/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. + +#### `.with_streaming_response` + +The above interface eagerly reads the full response body when you make the request, which may not always be what you want. + +To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods. + +```python +with client.files.with_streaming_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", +) as response: + print(response.headers.get("X-My-Header")) + + for line in response.iter_lines(): + print(line) +``` + +The context manager is required so that the response will reliably be closed. + +### Making custom/undocumented requests + +This library is typed for convenient access to the documented API. + +If you need to access undocumented endpoints, params, or response properties, the library can still be used. + +#### Undocumented endpoints + +To make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other +http verbs. Options on the client will be respected (such as retries) when making this request. + +```py +import httpx + +response = client.post( + "/foo", + cast_to=httpx.Response, + body={"my_param": True}, +) + +print(response.headers.get("x-foo")) +``` + +#### Undocumented request params + +If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request +options. + +#### Undocumented response properties + +To access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You +can also get all the extra fields on the Pydantic model as a dict with +[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra). + +### Configuring the HTTP client + +You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including: + +- Support for [proxies](https://www.python-httpx.org/advanced/proxies/) +- Custom [transports](https://www.python-httpx.org/advanced/transports/) +- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality + +```python +import httpx +from imagekit import ImageKit, DefaultHttpxClient + +client = ImageKit( + # Or use the `IMAGE_KIT_BASE_URL` env var + base_url="http://my.test.server.example.com:8083", + http_client=DefaultHttpxClient( + proxy="http://my.test.proxy.example.com", + transport=httpx.HTTPTransport(local_address="0.0.0.0"), + ), +) +``` + +You can also customize the client on a per-request basis by using `with_options()`: + +```python +client.with_options(http_client=DefaultHttpxClient(...)) +``` + +### Managing HTTP resources + +By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting. + +```py +from imagekit import ImageKit + +with ImageKit() as client: + # make requests here + ... + +# HTTP client is now closed +``` + +## Versioning + +This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: + +1. Changes that only affect static types, without breaking runtime behavior. +2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_ +3. Changes that we do not expect to impact the vast majority of users in practice. + +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/imagekit-python/issues) with questions, bugs, or suggestions. + +### Determining the installed version + +If you've upgraded to the latest version but aren't seeing any new features you were expecting then your python environment is likely still using an older version. + +You can determine the version that is being used at runtime with: + +```py +import imagekit +print(imagekit.__version__) +``` + +## Requirements + +Python 3.8 or higher. + +## Contributing + +See [the contributing documentation](./CONTRIBUTING.md). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..8e64327 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,27 @@ +# Security Policy + +## Reporting Security Issues + +This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. + +To report a security issue, please contact the Stainless team at security@stainless.com. + +## Responsible Disclosure + +We appreciate the efforts of security researchers and individuals who help us maintain the security of +SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible +disclosure practices by allowing us a reasonable amount of time to investigate and address the issue +before making any information public. + +## Reporting Non-SDK Related Security Issues + +If you encounter security issues that are not directly related to SDKs but pertain to the services +or products provided by Image Kit, please follow the respective company's security reporting guidelines. + +### Image Kit Terms and Policies + +Please contact developer@imagekit.io for any questions or concerns regarding the security of our services. + +--- + +Thank you for helping us keep the SDKs and systems they interact with secure. diff --git a/api.md b/api.md new file mode 100644 index 0000000..8e75811 --- /dev/null +++ b/api.md @@ -0,0 +1,154 @@ +# CustomMetadataFields + +Types: + +```python +from imagekit.types import ( + CustomMetadataFieldCreateResponse, + CustomMetadataFieldUpdateResponse, + CustomMetadataFieldListResponse, +) +``` + +Methods: + +- client.custom_metadata_fields.create(\*\*params) -> CustomMetadataFieldCreateResponse +- client.custom_metadata_fields.update(id, \*\*params) -> CustomMetadataFieldUpdateResponse +- client.custom_metadata_fields.list(\*\*params) -> CustomMetadataFieldListResponse +- client.custom_metadata_fields.delete(id) -> object + +# Files + +Types: + +```python +from imagekit.types import ( + FileListResponse, + FileAddTagsResponse, + FileRemoveAITagsResponse, + FileRemoveTagsResponse, + FileRenameResponse, + FileUploadV1Response, + FileUploadV2Response, +) +``` + +Methods: + +- client.files.list(\*\*params) -> FileListResponse +- client.files.delete(file_id) -> None +- client.files.add_tags(\*\*params) -> FileAddTagsResponse +- client.files.copy(\*\*params) -> object +- client.files.move(\*\*params) -> object +- client.files.remove_ai_tags(\*\*params) -> FileRemoveAITagsResponse +- client.files.remove_tags(\*\*params) -> FileRemoveTagsResponse +- client.files.rename(\*\*params) -> FileRenameResponse +- client.files.upload_v1(\*\*params) -> FileUploadV1Response +- client.files.upload_v2(\*\*params) -> FileUploadV2Response + +## Details + +Types: + +```python +from imagekit.types.files import DetailRetrieveResponse, DetailUpdateResponse +``` + +Methods: + +- client.files.details.retrieve(file_id) -> DetailRetrieveResponse +- client.files.details.update(file_id, \*\*params) -> DetailUpdateResponse + +## Batch + +Types: + +```python +from imagekit.types.files import BatchDeleteResponse +``` + +Methods: + +- client.files.batch.delete(\*\*params) -> BatchDeleteResponse + +## Versions + +Types: + +```python +from imagekit.types.files import ( + VersionRetrieveResponse, + VersionListResponse, + VersionRestoreResponse, +) +``` + +Methods: + +- client.files.versions.retrieve(version_id, \*, file_id) -> VersionRetrieveResponse +- client.files.versions.list(file_id) -> VersionListResponse +- client.files.versions.delete(version_id, \*, file_id) -> object +- client.files.versions.restore(version_id, \*, file_id) -> VersionRestoreResponse + +## Purge + +Types: + +```python +from imagekit.types.files import PurgeExecuteResponse, PurgeStatusResponse +``` + +Methods: + +- client.files.purge.execute(\*\*params) -> PurgeExecuteResponse +- client.files.purge.status(request_id) -> PurgeStatusResponse + +## Metadata + +Types: + +```python +from imagekit.types.files import MetadataRetrieveResponse, MetadataFromURLResponse +``` + +Methods: + +- client.files.metadata.retrieve(file_id) -> MetadataRetrieveResponse +- client.files.metadata.from_url(\*\*params) -> MetadataFromURLResponse + +# Folder + +Methods: + +- client.folder.create(\*\*params) -> object +- client.folder.delete(\*\*params) -> object + +# BulkJobs + +Types: + +```python +from imagekit.types import ( + BulkJobCopyFolderResponse, + BulkJobMoveFolderResponse, + BulkJobRetrieveStatusResponse, +) +``` + +Methods: + +- client.bulk_jobs.copy_folder(\*\*params) -> BulkJobCopyFolderResponse +- client.bulk_jobs.move_folder(\*\*params) -> BulkJobMoveFolderResponse +- client.bulk_jobs.retrieve_status(job_id) -> BulkJobRetrieveStatusResponse + +# Accounts + +Types: + +```python +from imagekit.types import AccountGetUsageResponse +``` + +Methods: + +- client.accounts.get_usage(\*\*params) -> AccountGetUsageResponse diff --git a/bin/publish-pypi b/bin/publish-pypi new file mode 100644 index 0000000..826054e --- /dev/null +++ b/bin/publish-pypi @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -eux +mkdir -p dist +rye build --clean +rye publish --yes --token=$PYPI_TOKEN diff --git a/examples/.keep b/examples/.keep new file mode 100644 index 0000000..d8c73e9 --- /dev/null +++ b/examples/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store example files demonstrating usage of this SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..b2e3de8 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,50 @@ +[mypy] +pretty = True +show_error_codes = True + +# Exclude _files.py because mypy isn't smart enough to apply +# the correct type narrowing and as this is an internal module +# it's fine to just use Pyright. +# +# We also exclude our `tests` as mypy doesn't always infer +# types correctly and Pyright will still catch any type errors. +exclude = ^(src/imagekit/_files\.py|_dev/.*\.py|tests/.*)$ + +strict_equality = True +implicit_reexport = True +check_untyped_defs = True +no_implicit_optional = True + +warn_return_any = True +warn_unreachable = True +warn_unused_configs = True + +# Turn these options off as it could cause conflicts +# with the Pyright options. +warn_unused_ignores = False +warn_redundant_casts = False + +disallow_any_generics = True +disallow_untyped_defs = True +disallow_untyped_calls = True +disallow_subclassing_any = True +disallow_incomplete_defs = True +disallow_untyped_decorators = True +cache_fine_grained = True + +# By default, mypy reports an error if you assign a value to the result +# of a function call that doesn't return anything. We do this in our test +# cases: +# ``` +# result = ... +# assert result is None +# ``` +# Changing this codegen to make mypy happy would increase complexity +# and would not be worth it. +disable_error_code = func-returns-value,overload-cannot-match + +# https://github.com/python/mypy/issues/12162 +[mypy.overrides] +module = "black.files.*" +ignore_errors = true +ignore_missing_imports = true diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 0000000..53bca7f --- /dev/null +++ b/noxfile.py @@ -0,0 +1,9 @@ +import nox + + +@nox.session(reuse_venv=True, name="test-pydantic-v1") +def test_pydantic_v1(session: nox.Session) -> None: + session.install("-r", "requirements-dev.lock") + session.install("pydantic<2") + + session.run("pytest", "--showlocals", "--ignore=tests/functional", *session.posargs) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..68e2646 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,211 @@ +[project] +name = "imagekit" +version = "0.0.1" +description = "The official Python library for the ImageKit API" +dynamic = ["readme"] +license = "Apache-2.0" +authors = [ +{ name = "Image Kit", email = "developer@imagekit.io" }, +] +dependencies = [ + "httpx>=0.23.0, <1", + "pydantic>=1.9.0, <3", + "typing-extensions>=4.10, <5", + "anyio>=3.5.0, <5", + "distro>=1.7.0, <2", + "sniffio", +] +requires-python = ">= 3.8" +classifiers = [ + "Typing :: Typed", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Operating System :: OS Independent", + "Operating System :: POSIX", + "Operating System :: MacOS", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Topic :: Software Development :: Libraries :: Python Modules", + "License :: OSI Approved :: Apache Software License" +] + +[project.urls] +Homepage = "https://github.com/stainless-sdks/imagekit-python" +Repository = "https://github.com/stainless-sdks/imagekit-python" + +[project.optional-dependencies] +aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] + +[tool.rye] +managed = true +# version pins are in requirements-dev.lock +dev-dependencies = [ + "pyright==1.1.399", + "mypy", + "respx", + "pytest", + "pytest-asyncio", + "ruff", + "time-machine", + "nox", + "dirty-equals>=0.6.0", + "importlib-metadata>=6.7.0", + "rich>=13.7.1", + "nest_asyncio==1.6.0", + "pytest-xdist>=3.6.1", +] + +[tool.rye.scripts] +format = { chain = [ + "format:ruff", + "format:docs", + "fix:ruff", + # run formatting again to fix any inconsistencies when imports are stripped + "format:ruff", +]} +"format:docs" = "python scripts/utils/ruffen-docs.py README.md api.md" +"format:ruff" = "ruff format" + +"lint" = { chain = [ + "check:ruff", + "typecheck", + "check:importable", +]} +"check:ruff" = "ruff check ." +"fix:ruff" = "ruff check --fix ." + +"check:importable" = "python -c 'import imagekit'" + +typecheck = { chain = [ + "typecheck:pyright", + "typecheck:mypy" +]} +"typecheck:pyright" = "pyright" +"typecheck:verify-types" = "pyright --verifytypes imagekit --ignoreexternal" +"typecheck:mypy" = "mypy ." + +[build-system] +requires = ["hatchling==1.26.3", "hatch-fancy-pypi-readme"] +build-backend = "hatchling.build" + +[tool.hatch.build] +include = [ + "src/*" +] + +[tool.hatch.build.targets.wheel] +packages = ["src/imagekit"] + +[tool.hatch.build.targets.sdist] +# Basically everything except hidden files/directories (such as .github, .devcontainers, .python-version, etc) +include = [ + "/*.toml", + "/*.json", + "/*.lock", + "/*.md", + "/mypy.ini", + "/noxfile.py", + "bin/*", + "examples/*", + "src/*", + "tests/*", +] + +[tool.hatch.metadata.hooks.fancy-pypi-readme] +content-type = "text/markdown" + +[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] +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/imagekit-python/tree/main/\g<2>)' + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = "--tb=short -n auto" +xfail_strict = true +asyncio_mode = "auto" +asyncio_default_fixture_loop_scope = "session" +filterwarnings = [ + "error" +] + +[tool.pyright] +# this enables practically every flag given by pyright. +# there are a couple of flags that are still disabled by +# default in strict mode as they are experimental and niche. +typeCheckingMode = "strict" +pythonVersion = "3.8" + +exclude = [ + "_dev", + ".venv", + ".nox", +] + +reportImplicitOverride = true +reportOverlappingOverload = false + +reportImportCycles = false +reportPrivateUsage = false + +[tool.ruff] +line-length = 120 +output-format = "grouped" +target-version = "py38" + +[tool.ruff.format] +docstring-code-format = true + +[tool.ruff.lint] +select = [ + # isort + "I", + # bugbear rules + "B", + # remove unused imports + "F401", + # bare except statements + "E722", + # unused arguments + "ARG", + # print statements + "T201", + "T203", + # misuse of typing.TYPE_CHECKING + "TC004", + # import rules + "TID251", +] +ignore = [ + # mutable defaults + "B006", +] +unfixable = [ + # disable auto fix for print statements + "T201", + "T203", +] + +[tool.ruff.lint.flake8-tidy-imports.banned-api] +"functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead" + +[tool.ruff.lint.isort] +length-sort = true +length-sort-straight = true +combine-as-imports = true +extra-standard-library = ["typing_extensions"] +known-first-party = ["imagekit", "tests"] + +[tool.ruff.lint.per-file-ignores] +"bin/**.py" = ["T201", "T203"] +"scripts/**.py" = ["T201", "T203"] +"tests/**.py" = ["T201", "T203"] +"examples/**.py" = ["T201", "T203"] diff --git a/requirements-dev.lock b/requirements-dev.lock new file mode 100644 index 0000000..2d04bf1 --- /dev/null +++ b/requirements-dev.lock @@ -0,0 +1,135 @@ +# generated by rye +# use `rye lock` or `rye sync` to update this lockfile +# +# last locked with the following flags: +# pre: false +# features: [] +# all-features: true +# with-sources: false +# generate-hashes: false +# universal: false + +-e file:. +aiohappyeyeballs==2.6.1 + # via aiohttp +aiohttp==3.12.8 + # via httpx-aiohttp + # via imagekit +aiosignal==1.3.2 + # via aiohttp +annotated-types==0.6.0 + # via pydantic +anyio==4.4.0 + # via httpx + # via imagekit +argcomplete==3.1.2 + # via nox +async-timeout==5.0.1 + # via aiohttp +attrs==25.3.0 + # via aiohttp +certifi==2023.7.22 + # via httpcore + # via httpx +colorlog==6.7.0 + # via nox +dirty-equals==0.6.0 +distlib==0.3.7 + # via virtualenv +distro==1.8.0 + # via imagekit +exceptiongroup==1.2.2 + # via anyio + # via pytest +execnet==2.1.1 + # via pytest-xdist +filelock==3.12.4 + # via virtualenv +frozenlist==1.6.2 + # via aiohttp + # via aiosignal +h11==0.16.0 + # via httpcore +httpcore==1.0.9 + # via httpx +httpx==0.28.1 + # via httpx-aiohttp + # via imagekit + # via respx +httpx-aiohttp==0.1.8 + # via imagekit +idna==3.4 + # via anyio + # via httpx + # via yarl +importlib-metadata==7.0.0 +iniconfig==2.0.0 + # via pytest +markdown-it-py==3.0.0 + # via rich +mdurl==0.1.2 + # via markdown-it-py +multidict==6.4.4 + # via aiohttp + # via yarl +mypy==1.14.1 +mypy-extensions==1.0.0 + # via mypy +nest-asyncio==1.6.0 +nodeenv==1.8.0 + # via pyright +nox==2023.4.22 +packaging==23.2 + # via nox + # via pytest +platformdirs==3.11.0 + # via virtualenv +pluggy==1.5.0 + # via pytest +propcache==0.3.1 + # via aiohttp + # via yarl +pydantic==2.10.3 + # via imagekit +pydantic-core==2.27.1 + # via pydantic +pygments==2.18.0 + # via rich +pyright==1.1.399 +pytest==8.3.3 + # via pytest-asyncio + # via pytest-xdist +pytest-asyncio==0.24.0 +pytest-xdist==3.7.0 +python-dateutil==2.8.2 + # via time-machine +pytz==2023.3.post1 + # via dirty-equals +respx==0.22.0 +rich==13.7.1 +ruff==0.9.4 +setuptools==68.2.2 + # via nodeenv +six==1.16.0 + # via python-dateutil +sniffio==1.3.0 + # via anyio + # via imagekit +time-machine==2.9.0 +tomli==2.0.2 + # via mypy + # via pytest +typing-extensions==4.12.2 + # via anyio + # via imagekit + # via multidict + # via mypy + # via pydantic + # via pydantic-core + # via pyright +virtualenv==20.24.5 + # via nox +yarl==1.20.0 + # via aiohttp +zipp==3.17.0 + # via importlib-metadata diff --git a/requirements.lock b/requirements.lock new file mode 100644 index 0000000..85ed03b --- /dev/null +++ b/requirements.lock @@ -0,0 +1,72 @@ +# generated by rye +# use `rye lock` or `rye sync` to update this lockfile +# +# last locked with the following flags: +# pre: false +# features: [] +# all-features: true +# with-sources: false +# generate-hashes: false +# universal: false + +-e file:. +aiohappyeyeballs==2.6.1 + # via aiohttp +aiohttp==3.12.8 + # via httpx-aiohttp + # via imagekit +aiosignal==1.3.2 + # via aiohttp +annotated-types==0.6.0 + # via pydantic +anyio==4.4.0 + # via httpx + # via imagekit +async-timeout==5.0.1 + # via aiohttp +attrs==25.3.0 + # via aiohttp +certifi==2023.7.22 + # via httpcore + # via httpx +distro==1.8.0 + # via imagekit +exceptiongroup==1.2.2 + # via anyio +frozenlist==1.6.2 + # via aiohttp + # via aiosignal +h11==0.16.0 + # via httpcore +httpcore==1.0.9 + # via httpx +httpx==0.28.1 + # via httpx-aiohttp + # via imagekit +httpx-aiohttp==0.1.8 + # via imagekit +idna==3.4 + # via anyio + # via httpx + # via yarl +multidict==6.4.4 + # via aiohttp + # via yarl +propcache==0.3.1 + # via aiohttp + # via yarl +pydantic==2.10.3 + # via imagekit +pydantic-core==2.27.1 + # via pydantic +sniffio==1.3.0 + # via anyio + # via imagekit +typing-extensions==4.12.2 + # via anyio + # via imagekit + # via multidict + # via pydantic + # via pydantic-core +yarl==1.20.0 + # via aiohttp diff --git a/scripts/bootstrap b/scripts/bootstrap new file mode 100755 index 0000000..e84fe62 --- /dev/null +++ b/scripts/bootstrap @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if ! command -v rye >/dev/null 2>&1 && [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then + brew bundle check >/dev/null 2>&1 || { + echo "==> Installing Homebrew dependencies…" + brew bundle + } +fi + +echo "==> Installing Python dependencies…" + +# experimental uv support makes installations significantly faster +rye config --set-bool behavior.use-uv=true + +rye sync --all-features diff --git a/scripts/format b/scripts/format new file mode 100755 index 0000000..667ec2d --- /dev/null +++ b/scripts/format @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Running formatters" +rye run format diff --git a/scripts/lint b/scripts/lint new file mode 100755 index 0000000..3a31c2a --- /dev/null +++ b/scripts/lint @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Running lints" +rye run lint + +echo "==> Making sure it imports" +rye run python -c 'import imagekit' diff --git a/scripts/mock b/scripts/mock new file mode 100755 index 0000000..0b28f6e --- /dev/null +++ b/scripts/mock @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if [[ -n "$1" && "$1" != '--'* ]]; then + URL="$1" + shift +else + URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" +fi + +# Check if the URL is empty +if [ -z "$URL" ]; then + echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" + exit 1 +fi + +echo "==> Starting mock server with URL ${URL}" + +# Run prism mock on the given spec +if [ "$1" == "--daemon" ]; then + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & + + # Wait for server to come online + echo -n "Waiting for server" + while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + echo -n "." + sleep 0.1 + done + + if grep -q "✖ fatal" ".prism.log"; then + cat .prism.log + exit 1 + fi + + echo +else + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" +fi diff --git a/scripts/test b/scripts/test new file mode 100755 index 0000000..dbeda2d --- /dev/null +++ b/scripts/test @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +NC='\033[0m' # No Color + +function prism_is_running() { + curl --silent "http://localhost:4010" >/dev/null 2>&1 +} + +kill_server_on_port() { + pids=$(lsof -t -i tcp:"$1" || echo "") + if [ "$pids" != "" ]; then + kill "$pids" + echo "Stopped $pids." + fi +} + +function is_overriding_api_base_url() { + [ -n "$TEST_API_BASE_URL" ] +} + +if ! is_overriding_api_base_url && ! prism_is_running ; then + # When we exit this script, make sure to kill the background mock server process + trap 'kill_server_on_port 4010' EXIT + + # Start the dev server + ./scripts/mock --daemon +fi + +if is_overriding_api_base_url ; then + echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" + echo +elif ! prism_is_running ; then + echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" + echo -e "running against your OpenAPI spec." + echo + echo -e "To run the server, pass in the path or url of your OpenAPI" + echo -e "spec to the prism command:" + echo + echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" + echo + + exit 1 +else + echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo +fi + +export DEFER_PYDANTIC_BUILD=false + +echo "==> Running tests" +rye run pytest "$@" + +echo "==> Running Pydantic v1 tests" +rye run nox -s test-pydantic-v1 -- "$@" diff --git a/scripts/utils/ruffen-docs.py b/scripts/utils/ruffen-docs.py new file mode 100644 index 0000000..0cf2bd2 --- /dev/null +++ b/scripts/utils/ruffen-docs.py @@ -0,0 +1,167 @@ +# fork of https://github.com/asottile/blacken-docs adapted for ruff +from __future__ import annotations + +import re +import sys +import argparse +import textwrap +import contextlib +import subprocess +from typing import Match, Optional, Sequence, Generator, NamedTuple, cast + +MD_RE = re.compile( + r"(?P^(?P *)```\s*python\n)" r"(?P.*?)" r"(?P^(?P=indent)```\s*$)", + re.DOTALL | re.MULTILINE, +) +MD_PYCON_RE = re.compile( + r"(?P^(?P *)```\s*pycon\n)" r"(?P.*?)" r"(?P^(?P=indent)```.*$)", + re.DOTALL | re.MULTILINE, +) +PYCON_PREFIX = ">>> " +PYCON_CONTINUATION_PREFIX = "..." +PYCON_CONTINUATION_RE = re.compile( + rf"^{re.escape(PYCON_CONTINUATION_PREFIX)}( |$)", +) +DEFAULT_LINE_LENGTH = 100 + + +class CodeBlockError(NamedTuple): + offset: int + exc: Exception + + +def format_str( + src: str, +) -> tuple[str, Sequence[CodeBlockError]]: + errors: list[CodeBlockError] = [] + + @contextlib.contextmanager + def _collect_error(match: Match[str]) -> Generator[None, None, None]: + try: + yield + except Exception as e: + errors.append(CodeBlockError(match.start(), e)) + + def _md_match(match: Match[str]) -> str: + code = textwrap.dedent(match["code"]) + with _collect_error(match): + code = format_code_block(code) + code = textwrap.indent(code, match["indent"]) + return f"{match['before']}{code}{match['after']}" + + def _pycon_match(match: Match[str]) -> str: + code = "" + fragment = cast(Optional[str], None) + + def finish_fragment() -> None: + nonlocal code + nonlocal fragment + + if fragment is not None: + with _collect_error(match): + fragment = format_code_block(fragment) + fragment_lines = fragment.splitlines() + code += f"{PYCON_PREFIX}{fragment_lines[0]}\n" + for line in fragment_lines[1:]: + # Skip blank lines to handle Black adding a blank above + # functions within blocks. A blank line would end the REPL + # continuation prompt. + # + # >>> if True: + # ... def f(): + # ... pass + # ... + if line: + code += f"{PYCON_CONTINUATION_PREFIX} {line}\n" + if fragment_lines[-1].startswith(" "): + code += f"{PYCON_CONTINUATION_PREFIX}\n" + fragment = None + + indentation = None + for line in match["code"].splitlines(): + orig_line, line = line, line.lstrip() + if indentation is None and line: + indentation = len(orig_line) - len(line) + continuation_match = PYCON_CONTINUATION_RE.match(line) + if continuation_match and fragment is not None: + fragment += line[continuation_match.end() :] + "\n" + else: + finish_fragment() + if line.startswith(PYCON_PREFIX): + fragment = line[len(PYCON_PREFIX) :] + "\n" + else: + code += orig_line[indentation:] + "\n" + finish_fragment() + return code + + def _md_pycon_match(match: Match[str]) -> str: + code = _pycon_match(match) + code = textwrap.indent(code, match["indent"]) + return f"{match['before']}{code}{match['after']}" + + src = MD_RE.sub(_md_match, src) + src = MD_PYCON_RE.sub(_md_pycon_match, src) + return src, errors + + +def format_code_block(code: str) -> str: + return subprocess.check_output( + [ + sys.executable, + "-m", + "ruff", + "format", + "--stdin-filename=script.py", + f"--line-length={DEFAULT_LINE_LENGTH}", + ], + encoding="utf-8", + input=code, + ) + + +def format_file( + filename: str, + skip_errors: bool, +) -> int: + with open(filename, encoding="UTF-8") as f: + contents = f.read() + new_contents, errors = format_str(contents) + for error in errors: + lineno = contents[: error.offset].count("\n") + 1 + print(f"{filename}:{lineno}: code block parse error {error.exc}") + if errors and not skip_errors: + return 1 + if contents != new_contents: + print(f"{filename}: Rewriting...") + with open(filename, "w", encoding="UTF-8") as f: + f.write(new_contents) + return 0 + else: + return 0 + + +def main(argv: Sequence[str] | None = None) -> int: + parser = argparse.ArgumentParser() + parser.add_argument( + "-l", + "--line-length", + type=int, + default=DEFAULT_LINE_LENGTH, + ) + parser.add_argument( + "-S", + "--skip-string-normalization", + action="store_true", + ) + parser.add_argument("-E", "--skip-errors", action="store_true") + parser.add_argument("filenames", nargs="*") + args = parser.parse_args(argv) + + retv = 0 + for filename in args.filenames: + retv |= format_file(filename, skip_errors=args.skip_errors) + return retv + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh new file mode 100755 index 0000000..ace7ffb --- /dev/null +++ b/scripts/utils/upload-artifact.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -exuo pipefail + +FILENAME=$(basename dist/*.whl) + +RESPONSE=$(curl -X POST "$URL?filename=$FILENAME" \ + -H "Authorization: Bearer $AUTH" \ + -H "Content-Type: application/json") + +SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') + +if [[ "$SIGNED_URL" == "null" ]]; then + echo -e "\033[31mFailed to get signed URL.\033[0m" + exit 1 +fi + +UPLOAD_RESPONSE=$(curl -v -X PUT \ + -H "Content-Type: binary/octet-stream" \ + --data-binary "@dist/$FILENAME" "$SIGNED_URL" 2>&1) + +if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then + echo -e "\033[32mUploaded build to Stainless storage.\033[0m" + echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/imagekit-python/$SHA/$FILENAME'\033[0m" +else + echo -e "\033[31mFailed to upload artifact.\033[0m" + exit 1 +fi diff --git a/src/imagekit/__init__.py b/src/imagekit/__init__.py new file mode 100644 index 0000000..07a48e8 --- /dev/null +++ b/src/imagekit/__init__.py @@ -0,0 +1,100 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import typing as _t + +from . import types +from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes +from ._utils import file_from_path +from ._client import ( + Client, + Stream, + Timeout, + ImageKit, + Transport, + AsyncClient, + AsyncStream, + AsyncImageKit, + RequestOptions, +) +from ._models import BaseModel +from ._version import __title__, __version__ +from ._response import APIResponse as APIResponse, AsyncAPIResponse as AsyncAPIResponse +from ._constants import DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES, DEFAULT_CONNECTION_LIMITS +from ._exceptions import ( + APIError, + ConflictError, + ImageKitError, + NotFoundError, + APIStatusError, + RateLimitError, + APITimeoutError, + BadRequestError, + APIConnectionError, + AuthenticationError, + InternalServerError, + PermissionDeniedError, + UnprocessableEntityError, + APIResponseValidationError, +) +from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient +from ._utils._logs import setup_logging as _setup_logging + +__all__ = [ + "types", + "__version__", + "__title__", + "NoneType", + "Transport", + "ProxiesTypes", + "NotGiven", + "NOT_GIVEN", + "Omit", + "ImageKitError", + "APIError", + "APIStatusError", + "APITimeoutError", + "APIConnectionError", + "APIResponseValidationError", + "BadRequestError", + "AuthenticationError", + "PermissionDeniedError", + "NotFoundError", + "ConflictError", + "UnprocessableEntityError", + "RateLimitError", + "InternalServerError", + "Timeout", + "RequestOptions", + "Client", + "AsyncClient", + "Stream", + "AsyncStream", + "ImageKit", + "AsyncImageKit", + "file_from_path", + "BaseModel", + "DEFAULT_TIMEOUT", + "DEFAULT_MAX_RETRIES", + "DEFAULT_CONNECTION_LIMITS", + "DefaultHttpxClient", + "DefaultAsyncHttpxClient", + "DefaultAioHttpClient", +] + +if not _t.TYPE_CHECKING: + from ._utils._resources_proxy import resources as resources + +_setup_logging() + +# Update the __module__ attribute for exported symbols so that +# error messages point to this module instead of the module +# it was originally defined in, e.g. +# imagekit._exceptions.NotFoundError -> imagekit.NotFoundError +__locals = locals() +for __name in __all__: + if not __name.startswith("__"): + try: + __locals[__name].__module__ = "imagekit" + except (TypeError, AttributeError): + # Some of our exported symbols are builtins which we can't set attributes for. + pass diff --git a/src/imagekit/_base_client.py b/src/imagekit/_base_client.py new file mode 100644 index 0000000..9dcf022 --- /dev/null +++ b/src/imagekit/_base_client.py @@ -0,0 +1,1995 @@ +from __future__ import annotations + +import sys +import json +import time +import uuid +import email +import asyncio +import inspect +import logging +import platform +import email.utils +from types import TracebackType +from random import random +from typing import ( + TYPE_CHECKING, + Any, + Dict, + Type, + Union, + Generic, + Mapping, + TypeVar, + Iterable, + Iterator, + Optional, + Generator, + AsyncIterator, + cast, + overload, +) +from typing_extensions import Literal, override, get_origin + +import anyio +import httpx +import distro +import pydantic +from httpx import URL +from pydantic import PrivateAttr + +from . import _exceptions +from ._qs import Querystring +from ._files import to_httpx_files, async_to_httpx_files +from ._types import ( + NOT_GIVEN, + Body, + Omit, + Query, + Headers, + Timeout, + NotGiven, + ResponseT, + AnyMapping, + PostParser, + RequestFiles, + HttpxSendArgs, + RequestOptions, + HttpxRequestFiles, + ModelBuilderProtocol, +) +from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping +from ._compat import PYDANTIC_V2, model_copy, model_dump +from ._models import GenericModel, FinalRequestOptions, validate_type, construct_type +from ._response import ( + APIResponse, + BaseAPIResponse, + AsyncAPIResponse, + extract_response_type, +) +from ._constants import ( + DEFAULT_TIMEOUT, + MAX_RETRY_DELAY, + DEFAULT_MAX_RETRIES, + INITIAL_RETRY_DELAY, + RAW_RESPONSE_HEADER, + OVERRIDE_CAST_TO_HEADER, + DEFAULT_CONNECTION_LIMITS, +) +from ._streaming import Stream, SSEDecoder, AsyncStream, SSEBytesDecoder +from ._exceptions import ( + APIStatusError, + APITimeoutError, + APIConnectionError, + APIResponseValidationError, +) + +log: logging.Logger = logging.getLogger(__name__) + +# TODO: make base page type vars covariant +SyncPageT = TypeVar("SyncPageT", bound="BaseSyncPage[Any]") +AsyncPageT = TypeVar("AsyncPageT", bound="BaseAsyncPage[Any]") + + +_T = TypeVar("_T") +_T_co = TypeVar("_T_co", covariant=True) + +_StreamT = TypeVar("_StreamT", bound=Stream[Any]) +_AsyncStreamT = TypeVar("_AsyncStreamT", bound=AsyncStream[Any]) + +if TYPE_CHECKING: + from httpx._config import ( + DEFAULT_TIMEOUT_CONFIG, # pyright: ignore[reportPrivateImportUsage] + ) + + HTTPX_DEFAULT_TIMEOUT = DEFAULT_TIMEOUT_CONFIG +else: + try: + from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT + except ImportError: + # taken from https://github.com/encode/httpx/blob/3ba5fe0d7ac70222590e759c31442b1cab263791/httpx/_config.py#L366 + HTTPX_DEFAULT_TIMEOUT = Timeout(5.0) + + +class PageInfo: + """Stores the necessary information to build the request to retrieve the next page. + + Either `url` or `params` must be set. + """ + + url: URL | NotGiven + params: Query | NotGiven + json: Body | NotGiven + + @overload + def __init__( + self, + *, + url: URL, + ) -> None: ... + + @overload + def __init__( + self, + *, + params: Query, + ) -> None: ... + + @overload + def __init__( + self, + *, + json: Body, + ) -> None: ... + + def __init__( + self, + *, + url: URL | NotGiven = NOT_GIVEN, + json: Body | NotGiven = NOT_GIVEN, + params: Query | NotGiven = NOT_GIVEN, + ) -> None: + self.url = url + self.json = json + self.params = params + + @override + def __repr__(self) -> str: + if self.url: + return f"{self.__class__.__name__}(url={self.url})" + if self.json: + return f"{self.__class__.__name__}(json={self.json})" + return f"{self.__class__.__name__}(params={self.params})" + + +class BasePage(GenericModel, Generic[_T]): + """ + Defines the core interface for pagination. + + Type Args: + ModelT: The pydantic model that represents an item in the response. + + Methods: + has_next_page(): Check if there is another page available + next_page_info(): Get the necessary information to make a request for the next page + """ + + _options: FinalRequestOptions = PrivateAttr() + _model: Type[_T] = PrivateAttr() + + def has_next_page(self) -> bool: + items = self._get_page_items() + if not items: + return False + return self.next_page_info() is not None + + def next_page_info(self) -> Optional[PageInfo]: ... + + def _get_page_items(self) -> Iterable[_T]: # type: ignore[empty-body] + ... + + def _params_from_url(self, url: URL) -> httpx.QueryParams: + # TODO: do we have to preprocess params here? + return httpx.QueryParams(cast(Any, self._options.params)).merge(url.params) + + def _info_to_options(self, info: PageInfo) -> FinalRequestOptions: + options = model_copy(self._options) + options._strip_raw_response_header() + + if not isinstance(info.params, NotGiven): + options.params = {**options.params, **info.params} + return options + + if not isinstance(info.url, NotGiven): + params = self._params_from_url(info.url) + url = info.url.copy_with(params=params) + options.params = dict(url.params) + options.url = str(url) + return options + + if not isinstance(info.json, NotGiven): + if not is_mapping(info.json): + raise TypeError("Pagination is only supported with mappings") + + if not options.json_data: + options.json_data = {**info.json} + else: + if not is_mapping(options.json_data): + raise TypeError("Pagination is only supported with mappings") + + options.json_data = {**options.json_data, **info.json} + return options + + raise ValueError("Unexpected PageInfo state") + + +class BaseSyncPage(BasePage[_T], Generic[_T]): + _client: SyncAPIClient = pydantic.PrivateAttr() + + def _set_private_attributes( + self, + client: SyncAPIClient, + model: Type[_T], + options: FinalRequestOptions, + ) -> None: + if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None: + self.__pydantic_private__ = {} + + self._model = model + self._client = client + self._options = options + + # Pydantic uses a custom `__iter__` method to support casting BaseModels + # to dictionaries. e.g. dict(model). + # As we want to support `for item in page`, this is inherently incompatible + # with the default pydantic behaviour. It is not possible to support both + # use cases at once. Fortunately, this is not a big deal as all other pydantic + # methods should continue to work as expected as there is an alternative method + # to cast a model to a dictionary, model.dict(), which is used internally + # by pydantic. + def __iter__(self) -> Iterator[_T]: # type: ignore + for page in self.iter_pages(): + for item in page._get_page_items(): + yield item + + def iter_pages(self: SyncPageT) -> Iterator[SyncPageT]: + page = self + while True: + yield page + if page.has_next_page(): + page = page.get_next_page() + else: + return + + def get_next_page(self: SyncPageT) -> SyncPageT: + info = self.next_page_info() + if not info: + raise RuntimeError( + "No next page expected; please check `.has_next_page()` before calling `.get_next_page()`." + ) + + options = self._info_to_options(info) + return self._client._request_api_list(self._model, page=self.__class__, options=options) + + +class AsyncPaginator(Generic[_T, AsyncPageT]): + def __init__( + self, + client: AsyncAPIClient, + options: FinalRequestOptions, + page_cls: Type[AsyncPageT], + model: Type[_T], + ) -> None: + self._model = model + self._client = client + self._options = options + self._page_cls = page_cls + + def __await__(self) -> Generator[Any, None, AsyncPageT]: + return self._get_page().__await__() + + async def _get_page(self) -> AsyncPageT: + def _parser(resp: AsyncPageT) -> AsyncPageT: + resp._set_private_attributes( + model=self._model, + options=self._options, + client=self._client, + ) + return resp + + self._options.post_parser = _parser + + return await self._client.request(self._page_cls, self._options) + + async def __aiter__(self) -> AsyncIterator[_T]: + # https://github.com/microsoft/pyright/issues/3464 + page = cast( + AsyncPageT, + await self, # type: ignore + ) + async for item in page: + yield item + + +class BaseAsyncPage(BasePage[_T], Generic[_T]): + _client: AsyncAPIClient = pydantic.PrivateAttr() + + def _set_private_attributes( + self, + model: Type[_T], + client: AsyncAPIClient, + options: FinalRequestOptions, + ) -> None: + if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None: + self.__pydantic_private__ = {} + + self._model = model + self._client = client + self._options = options + + async def __aiter__(self) -> AsyncIterator[_T]: + async for page in self.iter_pages(): + for item in page._get_page_items(): + yield item + + async def iter_pages(self: AsyncPageT) -> AsyncIterator[AsyncPageT]: + page = self + while True: + yield page + if page.has_next_page(): + page = await page.get_next_page() + else: + return + + async def get_next_page(self: AsyncPageT) -> AsyncPageT: + info = self.next_page_info() + if not info: + raise RuntimeError( + "No next page expected; please check `.has_next_page()` before calling `.get_next_page()`." + ) + + options = self._info_to_options(info) + return await self._client._request_api_list(self._model, page=self.__class__, options=options) + + +_HttpxClientT = TypeVar("_HttpxClientT", bound=Union[httpx.Client, httpx.AsyncClient]) +_DefaultStreamT = TypeVar("_DefaultStreamT", bound=Union[Stream[Any], AsyncStream[Any]]) + + +class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]): + _client: _HttpxClientT + _version: str + _base_url: URL + max_retries: int + timeout: Union[float, Timeout, None] + _strict_response_validation: bool + _idempotency_header: str | None + _default_stream_cls: type[_DefaultStreamT] | None = None + + def __init__( + self, + *, + version: str, + base_url: str | URL, + _strict_response_validation: bool, + max_retries: int = DEFAULT_MAX_RETRIES, + timeout: float | Timeout | None = DEFAULT_TIMEOUT, + custom_headers: Mapping[str, str] | None = None, + custom_query: Mapping[str, object] | None = None, + ) -> None: + self._version = version + self._base_url = self._enforce_trailing_slash(URL(base_url)) + self.max_retries = max_retries + self.timeout = timeout + self._custom_headers = custom_headers or {} + self._custom_query = custom_query or {} + self._strict_response_validation = _strict_response_validation + self._idempotency_header = None + self._platform: Platform | None = None + + if max_retries is None: # pyright: ignore[reportUnnecessaryComparison] + raise TypeError( + "max_retries cannot be None. If you want to disable retries, pass `0`; if you want unlimited retries, pass `math.inf` or a very high number; if you want the default behavior, pass `imagekit.DEFAULT_MAX_RETRIES`" + ) + + def _enforce_trailing_slash(self, url: URL) -> URL: + if url.raw_path.endswith(b"/"): + return url + return url.copy_with(raw_path=url.raw_path + b"/") + + def _make_status_error_from_response( + self, + response: httpx.Response, + ) -> APIStatusError: + if response.is_closed and not response.is_stream_consumed: + # We can't read the response body as it has been closed + # before it was read. This can happen if an event hook + # raises a status error. + body = None + err_msg = f"Error code: {response.status_code}" + else: + err_text = response.text.strip() + body = err_text + + try: + body = json.loads(err_text) + err_msg = f"Error code: {response.status_code} - {body}" + except Exception: + err_msg = err_text or f"Error code: {response.status_code}" + + return self._make_status_error(err_msg, body=body, response=response) + + def _make_status_error( + self, + err_msg: str, + *, + body: object, + response: httpx.Response, + ) -> _exceptions.APIStatusError: + raise NotImplementedError() + + def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0) -> httpx.Headers: + custom_headers = options.headers or {} + headers_dict = _merge_mappings(self.default_headers, custom_headers) + self._validate_headers(headers_dict, custom_headers) + + # headers are case-insensitive while dictionaries are not. + headers = httpx.Headers(headers_dict) + + idempotency_header = self._idempotency_header + if idempotency_header and options.idempotency_key and idempotency_header not in headers: + headers[idempotency_header] = options.idempotency_key + + # Don't set these headers if they were already set or removed by the caller. We check + # `custom_headers`, which can contain `Omit()`, instead of `headers` to account for the removal case. + lower_custom_headers = [header.lower() for header in custom_headers] + if "x-stainless-retry-count" not in lower_custom_headers: + headers["x-stainless-retry-count"] = str(retries_taken) + if "x-stainless-read-timeout" not in lower_custom_headers: + timeout = self.timeout if isinstance(options.timeout, NotGiven) else options.timeout + if isinstance(timeout, Timeout): + timeout = timeout.read + if timeout is not None: + headers["x-stainless-read-timeout"] = str(timeout) + + return headers + + def _prepare_url(self, url: str) -> URL: + """ + Merge a URL argument together with any 'base_url' on the client, + to create the URL used for the outgoing request. + """ + # Copied from httpx's `_merge_url` method. + merge_url = URL(url) + if merge_url.is_relative_url: + merge_raw_path = self.base_url.raw_path + merge_url.raw_path.lstrip(b"/") + return self.base_url.copy_with(raw_path=merge_raw_path) + + return merge_url + + def _make_sse_decoder(self) -> SSEDecoder | SSEBytesDecoder: + return SSEDecoder() + + def _build_request( + self, + options: FinalRequestOptions, + *, + retries_taken: int = 0, + ) -> httpx.Request: + if log.isEnabledFor(logging.DEBUG): + log.debug("Request options: %s", model_dump(options, exclude_unset=True)) + + kwargs: dict[str, Any] = {} + + json_data = options.json_data + if options.extra_json is not None: + if json_data is None: + json_data = cast(Body, options.extra_json) + elif is_mapping(json_data): + json_data = _merge_mappings(json_data, options.extra_json) + else: + raise RuntimeError(f"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`") + + headers = self._build_headers(options, retries_taken=retries_taken) + params = _merge_mappings(self.default_query, options.params) + content_type = headers.get("Content-Type") + files = options.files + + # If the given Content-Type header is multipart/form-data then it + # has to be removed so that httpx can generate the header with + # additional information for us as it has to be in this form + # for the server to be able to correctly parse the request: + # multipart/form-data; boundary=---abc-- + if content_type is not None and content_type.startswith("multipart/form-data"): + if "boundary" not in content_type: + # only remove the header if the boundary hasn't been explicitly set + # as the caller doesn't want httpx to come up with their own boundary + headers.pop("Content-Type") + + # As we are now sending multipart/form-data instead of application/json + # we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/#multipart-file-encoding + if json_data: + if not is_dict(json_data): + raise TypeError( + f"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead." + ) + kwargs["data"] = self._serialize_multipartform(json_data) + + # httpx determines whether or not to send a "multipart/form-data" + # request based on the truthiness of the "files" argument. + # This gets around that issue by generating a dict value that + # evaluates to true. + # + # https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186 + if not files: + files = cast(HttpxRequestFiles, ForceMultipartDict()) + + prepared_url = self._prepare_url(options.url) + if "_" in prepared_url.host: + # work around https://github.com/encode/httpx/discussions/2880 + kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")} + + is_body_allowed = options.method.lower() != "get" + + if is_body_allowed: + if isinstance(json_data, bytes): + kwargs["content"] = json_data + else: + kwargs["json"] = json_data if is_given(json_data) else None + kwargs["files"] = files + else: + headers.pop("Content-Type", None) + kwargs.pop("data", None) + + # TODO: report this error to httpx + return self._client.build_request( # pyright: ignore[reportUnknownMemberType] + headers=headers, + timeout=self.timeout if isinstance(options.timeout, NotGiven) else options.timeout, + method=options.method, + url=prepared_url, + # the `Query` type that we use is incompatible with qs' + # `Params` type as it needs to be typed as `Mapping[str, object]` + # so that passing a `TypedDict` doesn't cause an error. + # https://github.com/microsoft/pyright/issues/3526#event-6715453066 + params=self.qs.stringify(cast(Mapping[str, Any], params)) if params else None, + **kwargs, + ) + + def _serialize_multipartform(self, data: Mapping[object, object]) -> dict[str, object]: + items = self.qs.stringify_items( + # TODO: type ignore is required as stringify_items is well typed but we can't be + # well typed without heavy validation. + data, # type: ignore + array_format="brackets", + ) + serialized: dict[str, object] = {} + for key, value in items: + existing = serialized.get(key) + + if not existing: + serialized[key] = value + continue + + # If a value has already been set for this key then that + # means we're sending data like `array[]=[1, 2, 3]` and we + # need to tell httpx that we want to send multiple values with + # the same key which is done by using a list or a tuple. + # + # Note: 2d arrays should never result in the same key at both + # levels so it's safe to assume that if the value is a list, + # it was because we changed it to be a list. + if is_list(existing): + existing.append(value) + else: + serialized[key] = [existing, value] + + return serialized + + def _maybe_override_cast_to(self, cast_to: type[ResponseT], options: FinalRequestOptions) -> type[ResponseT]: + if not is_given(options.headers): + return cast_to + + # make a copy of the headers so we don't mutate user-input + headers = dict(options.headers) + + # we internally support defining a temporary header to override the + # default `cast_to` type for use with `.with_raw_response` and `.with_streaming_response` + # see _response.py for implementation details + override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, NOT_GIVEN) + if is_given(override_cast_to): + options.headers = headers + return cast(Type[ResponseT], override_cast_to) + + return cast_to + + def _should_stream_response_body(self, request: httpx.Request) -> bool: + return request.headers.get(RAW_RESPONSE_HEADER) == "stream" # type: ignore[no-any-return] + + def _process_response_data( + self, + *, + data: object, + cast_to: type[ResponseT], + response: httpx.Response, + ) -> ResponseT: + if data is None: + return cast(ResponseT, None) + + if cast_to is object: + return cast(ResponseT, data) + + try: + if inspect.isclass(cast_to) and issubclass(cast_to, ModelBuilderProtocol): + return cast(ResponseT, cast_to.build(response=response, data=data)) + + if self._strict_response_validation: + return cast(ResponseT, validate_type(type_=cast_to, value=data)) + + return cast(ResponseT, construct_type(type_=cast_to, value=data)) + except pydantic.ValidationError as err: + raise APIResponseValidationError(response=response, body=data) from err + + @property + def qs(self) -> Querystring: + return Querystring() + + @property + def custom_auth(self) -> httpx.Auth | None: + return None + + @property + def auth_headers(self) -> dict[str, str]: + return {} + + @property + def default_headers(self) -> dict[str, str | Omit]: + return { + "Accept": "application/json", + "Content-Type": "application/json", + "User-Agent": self.user_agent, + **self.platform_headers(), + **self.auth_headers, + **self._custom_headers, + } + + @property + def default_query(self) -> dict[str, object]: + return { + **self._custom_query, + } + + def _validate_headers( + self, + headers: Headers, # noqa: ARG002 + custom_headers: Headers, # noqa: ARG002 + ) -> None: + """Validate the given default headers and custom headers. + + Does nothing by default. + """ + return + + @property + def user_agent(self) -> str: + return f"{self.__class__.__name__}/Python {self._version}" + + @property + def base_url(self) -> URL: + return self._base_url + + @base_url.setter + def base_url(self, url: URL | str) -> None: + self._base_url = self._enforce_trailing_slash(url if isinstance(url, URL) else URL(url)) + + def platform_headers(self) -> Dict[str, str]: + # the actual implementation is in a separate `lru_cache` decorated + # function because adding `lru_cache` to methods will leak memory + # https://github.com/python/cpython/issues/88476 + return platform_headers(self._version, platform=self._platform) + + def _parse_retry_after_header(self, response_headers: Optional[httpx.Headers] = None) -> float | None: + """Returns a float of the number of seconds (not milliseconds) to wait after retrying, or None if unspecified. + + About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + See also https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After#syntax + """ + if response_headers is None: + return None + + # First, try the non-standard `retry-after-ms` header for milliseconds, + # which is more precise than integer-seconds `retry-after` + try: + retry_ms_header = response_headers.get("retry-after-ms", None) + return float(retry_ms_header) / 1000 + except (TypeError, ValueError): + pass + + # Next, try parsing `retry-after` header as seconds (allowing nonstandard floats). + retry_header = response_headers.get("retry-after") + try: + # note: the spec indicates that this should only ever be an integer + # but if someone sends a float there's no reason for us to not respect it + return float(retry_header) + except (TypeError, ValueError): + pass + + # Last, try parsing `retry-after` as a date. + retry_date_tuple = email.utils.parsedate_tz(retry_header) + if retry_date_tuple is None: + return None + + retry_date = email.utils.mktime_tz(retry_date_tuple) + return float(retry_date - time.time()) + + def _calculate_retry_timeout( + self, + remaining_retries: int, + options: FinalRequestOptions, + response_headers: Optional[httpx.Headers] = None, + ) -> float: + max_retries = options.get_max_retries(self.max_retries) + + # If the API asks us to wait a certain amount of time (and it's a reasonable amount), just do what it says. + retry_after = self._parse_retry_after_header(response_headers) + if retry_after is not None and 0 < retry_after <= 60: + return retry_after + + # Also cap retry count to 1000 to avoid any potential overflows with `pow` + nb_retries = min(max_retries - remaining_retries, 1000) + + # Apply exponential backoff, but not more than the max. + sleep_seconds = min(INITIAL_RETRY_DELAY * pow(2.0, nb_retries), MAX_RETRY_DELAY) + + # Apply some jitter, plus-or-minus half a second. + jitter = 1 - 0.25 * random() + timeout = sleep_seconds * jitter + return timeout if timeout >= 0 else 0 + + def _should_retry(self, response: httpx.Response) -> bool: + # Note: this is not a standard header + should_retry_header = response.headers.get("x-should-retry") + + # If the server explicitly says whether or not to retry, obey. + if should_retry_header == "true": + log.debug("Retrying as header `x-should-retry` is set to `true`") + return True + if should_retry_header == "false": + log.debug("Not retrying as header `x-should-retry` is set to `false`") + return False + + # Retry on request timeouts. + if response.status_code == 408: + log.debug("Retrying due to status code %i", response.status_code) + return True + + # Retry on lock timeouts. + if response.status_code == 409: + log.debug("Retrying due to status code %i", response.status_code) + return True + + # Retry on rate limits. + if response.status_code == 429: + log.debug("Retrying due to status code %i", response.status_code) + return True + + # Retry internal errors. + if response.status_code >= 500: + log.debug("Retrying due to status code %i", response.status_code) + return True + + log.debug("Not retrying") + return False + + def _idempotency_key(self) -> str: + return f"stainless-python-retry-{uuid.uuid4()}" + + +class _DefaultHttpxClient(httpx.Client): + def __init__(self, **kwargs: Any) -> None: + kwargs.setdefault("timeout", DEFAULT_TIMEOUT) + kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS) + kwargs.setdefault("follow_redirects", True) + super().__init__(**kwargs) + + +if TYPE_CHECKING: + DefaultHttpxClient = httpx.Client + """An alias to `httpx.Client` that provides the same defaults that this SDK + uses internally. + + This is useful because overriding the `http_client` with your own instance of + `httpx.Client` will result in httpx's defaults being used, not ours. + """ +else: + DefaultHttpxClient = _DefaultHttpxClient + + +class SyncHttpxClientWrapper(DefaultHttpxClient): + def __del__(self) -> None: + if self.is_closed: + return + + try: + self.close() + except Exception: + pass + + +class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]): + _client: httpx.Client + _default_stream_cls: type[Stream[Any]] | None = None + + def __init__( + self, + *, + version: str, + base_url: str | URL, + max_retries: int = DEFAULT_MAX_RETRIES, + timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + http_client: httpx.Client | None = None, + custom_headers: Mapping[str, str] | None = None, + custom_query: Mapping[str, object] | None = None, + _strict_response_validation: bool, + ) -> None: + if not is_given(timeout): + # if the user passed in a custom http client with a non-default + # timeout set then we use that timeout. + # + # note: there is an edge case here where the user passes in a client + # where they've explicitly set the timeout to match the default timeout + # as this check is structural, meaning that we'll think they didn't + # pass in a timeout and will ignore it + if http_client and http_client.timeout != HTTPX_DEFAULT_TIMEOUT: + timeout = http_client.timeout + else: + timeout = DEFAULT_TIMEOUT + + if http_client is not None and not isinstance(http_client, httpx.Client): # pyright: ignore[reportUnnecessaryIsInstance] + raise TypeError( + f"Invalid `http_client` argument; Expected an instance of `httpx.Client` but got {type(http_client)}" + ) + + super().__init__( + version=version, + # cast to a valid type because mypy doesn't understand our type narrowing + timeout=cast(Timeout, timeout), + base_url=base_url, + max_retries=max_retries, + custom_query=custom_query, + custom_headers=custom_headers, + _strict_response_validation=_strict_response_validation, + ) + self._client = http_client or SyncHttpxClientWrapper( + base_url=base_url, + # cast to a valid type because mypy doesn't understand our type narrowing + timeout=cast(Timeout, timeout), + ) + + def is_closed(self) -> bool: + return self._client.is_closed + + def close(self) -> None: + """Close the underlying HTTPX client. + + The client will *not* be usable after this. + """ + # If an error is thrown while constructing a client, self._client + # may not be present + if hasattr(self, "_client"): + self._client.close() + + def __enter__(self: _T) -> _T: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.close() + + def _prepare_options( + self, + options: FinalRequestOptions, # noqa: ARG002 + ) -> FinalRequestOptions: + """Hook for mutating the given options""" + return options + + def _prepare_request( + self, + request: httpx.Request, # noqa: ARG002 + ) -> None: + """This method is used as a callback for mutating the `Request` object + after it has been constructed. + This is useful for cases where you want to add certain headers based off of + the request properties, e.g. `url`, `method` etc. + """ + return None + + @overload + def request( + self, + cast_to: Type[ResponseT], + options: FinalRequestOptions, + *, + stream: Literal[True], + stream_cls: Type[_StreamT], + ) -> _StreamT: ... + + @overload + def request( + self, + cast_to: Type[ResponseT], + options: FinalRequestOptions, + *, + stream: Literal[False] = False, + ) -> ResponseT: ... + + @overload + def request( + self, + cast_to: Type[ResponseT], + options: FinalRequestOptions, + *, + stream: bool = False, + stream_cls: Type[_StreamT] | None = None, + ) -> ResponseT | _StreamT: ... + + def request( + self, + cast_to: Type[ResponseT], + options: FinalRequestOptions, + *, + stream: bool = False, + stream_cls: type[_StreamT] | None = None, + ) -> ResponseT | _StreamT: + cast_to = self._maybe_override_cast_to(cast_to, options) + + # create a copy of the options we were given so that if the + # options are mutated later & we then retry, the retries are + # given the original options + input_options = model_copy(options) + if input_options.idempotency_key is None and input_options.method.lower() != "get": + # ensure the idempotency key is reused between requests + input_options.idempotency_key = self._idempotency_key() + + response: httpx.Response | None = None + max_retries = input_options.get_max_retries(self.max_retries) + + retries_taken = 0 + for retries_taken in range(max_retries + 1): + options = model_copy(input_options) + options = self._prepare_options(options) + + remaining_retries = max_retries - retries_taken + request = self._build_request(options, retries_taken=retries_taken) + self._prepare_request(request) + + kwargs: HttpxSendArgs = {} + if self.custom_auth is not None: + kwargs["auth"] = self.custom_auth + + if options.follow_redirects is not None: + kwargs["follow_redirects"] = options.follow_redirects + + log.debug("Sending HTTP Request: %s %s", request.method, request.url) + + response = None + try: + response = self._client.send( + request, + stream=stream or self._should_stream_response_body(request=request), + **kwargs, + ) + except httpx.TimeoutException as err: + log.debug("Encountered httpx.TimeoutException", exc_info=True) + + if remaining_retries > 0: + self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=None, + ) + continue + + log.debug("Raising timeout error") + raise APITimeoutError(request=request) from err + except Exception as err: + log.debug("Encountered Exception", exc_info=True) + + if remaining_retries > 0: + self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=None, + ) + continue + + log.debug("Raising connection error") + raise APIConnectionError(request=request) from err + + log.debug( + 'HTTP Response: %s %s "%i %s" %s', + request.method, + request.url, + response.status_code, + response.reason_phrase, + response.headers, + ) + + try: + response.raise_for_status() + except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code + log.debug("Encountered httpx.HTTPStatusError", exc_info=True) + + if remaining_retries > 0 and self._should_retry(err.response): + err.response.close() + self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=response, + ) + continue + + # If the response is streamed then we need to explicitly read the response + # to completion before attempting to access the response text. + if not err.response.is_closed: + err.response.read() + + log.debug("Re-raising status error") + raise self._make_status_error_from_response(err.response) from None + + break + + assert response is not None, "could not resolve response (should never happen)" + return self._process_response( + cast_to=cast_to, + options=options, + response=response, + stream=stream, + stream_cls=stream_cls, + retries_taken=retries_taken, + ) + + def _sleep_for_retry( + self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None + ) -> None: + remaining_retries = max_retries - retries_taken + if remaining_retries == 1: + log.debug("1 retry left") + else: + log.debug("%i retries left", remaining_retries) + + timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None) + log.info("Retrying request to %s in %f seconds", options.url, timeout) + + time.sleep(timeout) + + def _process_response( + self, + *, + cast_to: Type[ResponseT], + options: FinalRequestOptions, + response: httpx.Response, + stream: bool, + stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, + retries_taken: int = 0, + ) -> ResponseT: + origin = get_origin(cast_to) or cast_to + + if ( + inspect.isclass(origin) + and issubclass(origin, BaseAPIResponse) + # we only want to actually return the custom BaseAPIResponse class if we're + # returning the raw response, or if we're not streaming SSE, as if we're streaming + # SSE then `cast_to` doesn't actively reflect the type we need to parse into + and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER))) + ): + if not issubclass(origin, APIResponse): + raise TypeError(f"API Response types must subclass {APIResponse}; Received {origin}") + + response_cls = cast("type[BaseAPIResponse[Any]]", cast_to) + return cast( + ResponseT, + response_cls( + raw=response, + client=self, + cast_to=extract_response_type(response_cls), + stream=stream, + stream_cls=stream_cls, + options=options, + retries_taken=retries_taken, + ), + ) + + if cast_to == httpx.Response: + return cast(ResponseT, response) + + api_response = APIResponse( + raw=response, + client=self, + cast_to=cast("type[ResponseT]", cast_to), # pyright: ignore[reportUnnecessaryCast] + stream=stream, + stream_cls=stream_cls, + options=options, + retries_taken=retries_taken, + ) + if bool(response.request.headers.get(RAW_RESPONSE_HEADER)): + return cast(ResponseT, api_response) + + return api_response.parse() + + def _request_api_list( + self, + model: Type[object], + page: Type[SyncPageT], + options: FinalRequestOptions, + ) -> SyncPageT: + def _parser(resp: SyncPageT) -> SyncPageT: + resp._set_private_attributes( + client=self, + model=model, + options=options, + ) + return resp + + options.post_parser = _parser + + return self.request(page, options, stream=False) + + @overload + def get( + self, + path: str, + *, + cast_to: Type[ResponseT], + options: RequestOptions = {}, + stream: Literal[False] = False, + ) -> ResponseT: ... + + @overload + def get( + self, + path: str, + *, + cast_to: Type[ResponseT], + options: RequestOptions = {}, + stream: Literal[True], + stream_cls: type[_StreamT], + ) -> _StreamT: ... + + @overload + def get( + self, + path: str, + *, + cast_to: Type[ResponseT], + options: RequestOptions = {}, + stream: bool, + stream_cls: type[_StreamT] | None = None, + ) -> ResponseT | _StreamT: ... + + def get( + self, + path: str, + *, + cast_to: Type[ResponseT], + options: RequestOptions = {}, + stream: bool = False, + stream_cls: type[_StreamT] | None = None, + ) -> ResponseT | _StreamT: + opts = FinalRequestOptions.construct(method="get", url=path, **options) + # cast is required because mypy complains about returning Any even though + # it understands the type variables + return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) + + @overload + def post( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + options: RequestOptions = {}, + files: RequestFiles | None = None, + stream: Literal[False] = False, + ) -> ResponseT: ... + + @overload + def post( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + options: RequestOptions = {}, + files: RequestFiles | None = None, + stream: Literal[True], + stream_cls: type[_StreamT], + ) -> _StreamT: ... + + @overload + def post( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + options: RequestOptions = {}, + files: RequestFiles | None = None, + stream: bool, + stream_cls: type[_StreamT] | None = None, + ) -> ResponseT | _StreamT: ... + + def post( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + options: RequestOptions = {}, + files: RequestFiles | None = None, + stream: bool = False, + stream_cls: type[_StreamT] | None = None, + ) -> ResponseT | _StreamT: + opts = FinalRequestOptions.construct( + method="post", url=path, json_data=body, files=to_httpx_files(files), **options + ) + return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) + + def patch( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + options: RequestOptions = {}, + ) -> ResponseT: + opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options) + return self.request(cast_to, opts) + + def put( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + files: RequestFiles | None = None, + options: RequestOptions = {}, + ) -> ResponseT: + opts = FinalRequestOptions.construct( + method="put", url=path, json_data=body, files=to_httpx_files(files), **options + ) + return self.request(cast_to, opts) + + def delete( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + options: RequestOptions = {}, + ) -> ResponseT: + opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options) + return self.request(cast_to, opts) + + def get_api_list( + self, + path: str, + *, + model: Type[object], + page: Type[SyncPageT], + body: Body | None = None, + options: RequestOptions = {}, + method: str = "get", + ) -> SyncPageT: + opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options) + return self._request_api_list(model, page, opts) + + +class _DefaultAsyncHttpxClient(httpx.AsyncClient): + def __init__(self, **kwargs: Any) -> None: + kwargs.setdefault("timeout", DEFAULT_TIMEOUT) + kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS) + kwargs.setdefault("follow_redirects", True) + super().__init__(**kwargs) + + +try: + import httpx_aiohttp +except ImportError: + + class _DefaultAioHttpClient(httpx.AsyncClient): + def __init__(self, **_kwargs: Any) -> None: + raise RuntimeError("To use the aiohttp client you must have installed the package with the `aiohttp` extra") +else: + + class _DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore + def __init__(self, **kwargs: Any) -> None: + kwargs.setdefault("timeout", DEFAULT_TIMEOUT) + kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS) + kwargs.setdefault("follow_redirects", True) + + super().__init__(**kwargs) + + +if TYPE_CHECKING: + DefaultAsyncHttpxClient = httpx.AsyncClient + """An alias to `httpx.AsyncClient` that provides the same defaults that this SDK + uses internally. + + This is useful because overriding the `http_client` with your own instance of + `httpx.AsyncClient` will result in httpx's defaults being used, not ours. + """ + + DefaultAioHttpClient = httpx.AsyncClient + """An alias to `httpx.AsyncClient` that changes the default HTTP transport to `aiohttp`.""" +else: + DefaultAsyncHttpxClient = _DefaultAsyncHttpxClient + DefaultAioHttpClient = _DefaultAioHttpClient + + +class AsyncHttpxClientWrapper(DefaultAsyncHttpxClient): + def __del__(self) -> None: + if self.is_closed: + return + + try: + # TODO(someday): support non asyncio runtimes here + asyncio.get_running_loop().create_task(self.aclose()) + except Exception: + pass + + +class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]): + _client: httpx.AsyncClient + _default_stream_cls: type[AsyncStream[Any]] | None = None + + def __init__( + self, + *, + version: str, + base_url: str | URL, + _strict_response_validation: bool, + max_retries: int = DEFAULT_MAX_RETRIES, + timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + http_client: httpx.AsyncClient | None = None, + custom_headers: Mapping[str, str] | None = None, + custom_query: Mapping[str, object] | None = None, + ) -> None: + if not is_given(timeout): + # if the user passed in a custom http client with a non-default + # timeout set then we use that timeout. + # + # note: there is an edge case here where the user passes in a client + # where they've explicitly set the timeout to match the default timeout + # as this check is structural, meaning that we'll think they didn't + # pass in a timeout and will ignore it + if http_client and http_client.timeout != HTTPX_DEFAULT_TIMEOUT: + timeout = http_client.timeout + else: + timeout = DEFAULT_TIMEOUT + + if http_client is not None and not isinstance(http_client, httpx.AsyncClient): # pyright: ignore[reportUnnecessaryIsInstance] + raise TypeError( + f"Invalid `http_client` argument; Expected an instance of `httpx.AsyncClient` but got {type(http_client)}" + ) + + super().__init__( + version=version, + base_url=base_url, + # cast to a valid type because mypy doesn't understand our type narrowing + timeout=cast(Timeout, timeout), + max_retries=max_retries, + custom_query=custom_query, + custom_headers=custom_headers, + _strict_response_validation=_strict_response_validation, + ) + self._client = http_client or AsyncHttpxClientWrapper( + base_url=base_url, + # cast to a valid type because mypy doesn't understand our type narrowing + timeout=cast(Timeout, timeout), + ) + + def is_closed(self) -> bool: + return self._client.is_closed + + async def close(self) -> None: + """Close the underlying HTTPX client. + + The client will *not* be usable after this. + """ + await self._client.aclose() + + async def __aenter__(self: _T) -> _T: + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + await self.close() + + async def _prepare_options( + self, + options: FinalRequestOptions, # noqa: ARG002 + ) -> FinalRequestOptions: + """Hook for mutating the given options""" + return options + + async def _prepare_request( + self, + request: httpx.Request, # noqa: ARG002 + ) -> None: + """This method is used as a callback for mutating the `Request` object + after it has been constructed. + This is useful for cases where you want to add certain headers based off of + the request properties, e.g. `url`, `method` etc. + """ + return None + + @overload + async def request( + self, + cast_to: Type[ResponseT], + options: FinalRequestOptions, + *, + stream: Literal[False] = False, + ) -> ResponseT: ... + + @overload + async def request( + self, + cast_to: Type[ResponseT], + options: FinalRequestOptions, + *, + stream: Literal[True], + stream_cls: type[_AsyncStreamT], + ) -> _AsyncStreamT: ... + + @overload + async def request( + self, + cast_to: Type[ResponseT], + options: FinalRequestOptions, + *, + stream: bool, + stream_cls: type[_AsyncStreamT] | None = None, + ) -> ResponseT | _AsyncStreamT: ... + + async def request( + self, + cast_to: Type[ResponseT], + options: FinalRequestOptions, + *, + stream: bool = False, + stream_cls: type[_AsyncStreamT] | None = None, + ) -> ResponseT | _AsyncStreamT: + if self._platform is None: + # `get_platform` can make blocking IO calls so we + # execute it earlier while we are in an async context + self._platform = await asyncify(get_platform)() + + cast_to = self._maybe_override_cast_to(cast_to, options) + + # create a copy of the options we were given so that if the + # options are mutated later & we then retry, the retries are + # given the original options + input_options = model_copy(options) + if input_options.idempotency_key is None and input_options.method.lower() != "get": + # ensure the idempotency key is reused between requests + input_options.idempotency_key = self._idempotency_key() + + response: httpx.Response | None = None + max_retries = input_options.get_max_retries(self.max_retries) + + retries_taken = 0 + for retries_taken in range(max_retries + 1): + options = model_copy(input_options) + options = await self._prepare_options(options) + + remaining_retries = max_retries - retries_taken + request = self._build_request(options, retries_taken=retries_taken) + await self._prepare_request(request) + + kwargs: HttpxSendArgs = {} + if self.custom_auth is not None: + kwargs["auth"] = self.custom_auth + + if options.follow_redirects is not None: + kwargs["follow_redirects"] = options.follow_redirects + + log.debug("Sending HTTP Request: %s %s", request.method, request.url) + + response = None + try: + response = await self._client.send( + request, + stream=stream or self._should_stream_response_body(request=request), + **kwargs, + ) + except httpx.TimeoutException as err: + log.debug("Encountered httpx.TimeoutException", exc_info=True) + + if remaining_retries > 0: + await self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=None, + ) + continue + + log.debug("Raising timeout error") + raise APITimeoutError(request=request) from err + except Exception as err: + log.debug("Encountered Exception", exc_info=True) + + if remaining_retries > 0: + await self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=None, + ) + continue + + log.debug("Raising connection error") + raise APIConnectionError(request=request) from err + + log.debug( + 'HTTP Response: %s %s "%i %s" %s', + request.method, + request.url, + response.status_code, + response.reason_phrase, + response.headers, + ) + + try: + response.raise_for_status() + except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code + log.debug("Encountered httpx.HTTPStatusError", exc_info=True) + + if remaining_retries > 0 and self._should_retry(err.response): + await err.response.aclose() + await self._sleep_for_retry( + retries_taken=retries_taken, + max_retries=max_retries, + options=input_options, + response=response, + ) + continue + + # If the response is streamed then we need to explicitly read the response + # to completion before attempting to access the response text. + if not err.response.is_closed: + await err.response.aread() + + log.debug("Re-raising status error") + raise self._make_status_error_from_response(err.response) from None + + break + + assert response is not None, "could not resolve response (should never happen)" + return await self._process_response( + cast_to=cast_to, + options=options, + response=response, + stream=stream, + stream_cls=stream_cls, + retries_taken=retries_taken, + ) + + async def _sleep_for_retry( + self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None + ) -> None: + remaining_retries = max_retries - retries_taken + if remaining_retries == 1: + log.debug("1 retry left") + else: + log.debug("%i retries left", remaining_retries) + + timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None) + log.info("Retrying request to %s in %f seconds", options.url, timeout) + + await anyio.sleep(timeout) + + async def _process_response( + self, + *, + cast_to: Type[ResponseT], + options: FinalRequestOptions, + response: httpx.Response, + stream: bool, + stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, + retries_taken: int = 0, + ) -> ResponseT: + origin = get_origin(cast_to) or cast_to + + if ( + inspect.isclass(origin) + and issubclass(origin, BaseAPIResponse) + # we only want to actually return the custom BaseAPIResponse class if we're + # returning the raw response, or if we're not streaming SSE, as if we're streaming + # SSE then `cast_to` doesn't actively reflect the type we need to parse into + and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER))) + ): + if not issubclass(origin, AsyncAPIResponse): + raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}") + + response_cls = cast("type[BaseAPIResponse[Any]]", cast_to) + return cast( + "ResponseT", + response_cls( + raw=response, + client=self, + cast_to=extract_response_type(response_cls), + stream=stream, + stream_cls=stream_cls, + options=options, + retries_taken=retries_taken, + ), + ) + + if cast_to == httpx.Response: + return cast(ResponseT, response) + + api_response = AsyncAPIResponse( + raw=response, + client=self, + cast_to=cast("type[ResponseT]", cast_to), # pyright: ignore[reportUnnecessaryCast] + stream=stream, + stream_cls=stream_cls, + options=options, + retries_taken=retries_taken, + ) + if bool(response.request.headers.get(RAW_RESPONSE_HEADER)): + return cast(ResponseT, api_response) + + return await api_response.parse() + + def _request_api_list( + self, + model: Type[_T], + page: Type[AsyncPageT], + options: FinalRequestOptions, + ) -> AsyncPaginator[_T, AsyncPageT]: + return AsyncPaginator(client=self, options=options, page_cls=page, model=model) + + @overload + async def get( + self, + path: str, + *, + cast_to: Type[ResponseT], + options: RequestOptions = {}, + stream: Literal[False] = False, + ) -> ResponseT: ... + + @overload + async def get( + self, + path: str, + *, + cast_to: Type[ResponseT], + options: RequestOptions = {}, + stream: Literal[True], + stream_cls: type[_AsyncStreamT], + ) -> _AsyncStreamT: ... + + @overload + async def get( + self, + path: str, + *, + cast_to: Type[ResponseT], + options: RequestOptions = {}, + stream: bool, + stream_cls: type[_AsyncStreamT] | None = None, + ) -> ResponseT | _AsyncStreamT: ... + + async def get( + self, + path: str, + *, + cast_to: Type[ResponseT], + options: RequestOptions = {}, + stream: bool = False, + stream_cls: type[_AsyncStreamT] | None = None, + ) -> ResponseT | _AsyncStreamT: + opts = FinalRequestOptions.construct(method="get", url=path, **options) + return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls) + + @overload + async def post( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + files: RequestFiles | None = None, + options: RequestOptions = {}, + stream: Literal[False] = False, + ) -> ResponseT: ... + + @overload + async def post( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + files: RequestFiles | None = None, + options: RequestOptions = {}, + stream: Literal[True], + stream_cls: type[_AsyncStreamT], + ) -> _AsyncStreamT: ... + + @overload + async def post( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + files: RequestFiles | None = None, + options: RequestOptions = {}, + stream: bool, + stream_cls: type[_AsyncStreamT] | None = None, + ) -> ResponseT | _AsyncStreamT: ... + + async def post( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + files: RequestFiles | None = None, + options: RequestOptions = {}, + stream: bool = False, + stream_cls: type[_AsyncStreamT] | None = None, + ) -> ResponseT | _AsyncStreamT: + opts = FinalRequestOptions.construct( + method="post", url=path, json_data=body, files=await async_to_httpx_files(files), **options + ) + return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls) + + async def patch( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + options: RequestOptions = {}, + ) -> ResponseT: + opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options) + return await self.request(cast_to, opts) + + async def put( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + files: RequestFiles | None = None, + options: RequestOptions = {}, + ) -> ResponseT: + opts = FinalRequestOptions.construct( + method="put", url=path, json_data=body, files=await async_to_httpx_files(files), **options + ) + return await self.request(cast_to, opts) + + async def delete( + self, + path: str, + *, + cast_to: Type[ResponseT], + body: Body | None = None, + options: RequestOptions = {}, + ) -> ResponseT: + opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options) + return await self.request(cast_to, opts) + + def get_api_list( + self, + path: str, + *, + model: Type[_T], + page: Type[AsyncPageT], + body: Body | None = None, + options: RequestOptions = {}, + method: str = "get", + ) -> AsyncPaginator[_T, AsyncPageT]: + opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options) + return self._request_api_list(model, page, opts) + + +def make_request_options( + *, + query: Query | None = None, + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + idempotency_key: str | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + post_parser: PostParser | NotGiven = NOT_GIVEN, +) -> RequestOptions: + """Create a dict of type RequestOptions without keys of NotGiven values.""" + options: RequestOptions = {} + if extra_headers is not None: + options["headers"] = extra_headers + + if extra_body is not None: + options["extra_json"] = cast(AnyMapping, extra_body) + + if query is not None: + options["params"] = query + + if extra_query is not None: + options["params"] = {**options.get("params", {}), **extra_query} + + if not isinstance(timeout, NotGiven): + options["timeout"] = timeout + + if idempotency_key is not None: + options["idempotency_key"] = idempotency_key + + if is_given(post_parser): + # internal + options["post_parser"] = post_parser # type: ignore + + return options + + +class ForceMultipartDict(Dict[str, None]): + def __bool__(self) -> bool: + return True + + +class OtherPlatform: + def __init__(self, name: str) -> None: + self.name = name + + @override + def __str__(self) -> str: + return f"Other:{self.name}" + + +Platform = Union[ + OtherPlatform, + Literal[ + "MacOS", + "Linux", + "Windows", + "FreeBSD", + "OpenBSD", + "iOS", + "Android", + "Unknown", + ], +] + + +def get_platform() -> Platform: + try: + system = platform.system().lower() + platform_name = platform.platform().lower() + except Exception: + return "Unknown" + + if "iphone" in platform_name or "ipad" in platform_name: + # Tested using Python3IDE on an iPhone 11 and Pythonista on an iPad 7 + # system is Darwin and platform_name is a string like: + # - Darwin-21.6.0-iPhone12,1-64bit + # - Darwin-21.6.0-iPad7,11-64bit + return "iOS" + + if system == "darwin": + return "MacOS" + + if system == "windows": + return "Windows" + + if "android" in platform_name: + # Tested using Pydroid 3 + # system is Linux and platform_name is a string like 'Linux-5.10.81-android12-9-00001-geba40aecb3b7-ab8534902-aarch64-with-libc' + return "Android" + + if system == "linux": + # https://distro.readthedocs.io/en/latest/#distro.id + distro_id = distro.id() + if distro_id == "freebsd": + return "FreeBSD" + + if distro_id == "openbsd": + return "OpenBSD" + + return "Linux" + + if platform_name: + return OtherPlatform(platform_name) + + return "Unknown" + + +@lru_cache(maxsize=None) +def platform_headers(version: str, *, platform: Platform | None) -> Dict[str, str]: + return { + "X-Stainless-Lang": "python", + "X-Stainless-Package-Version": version, + "X-Stainless-OS": str(platform or get_platform()), + "X-Stainless-Arch": str(get_architecture()), + "X-Stainless-Runtime": get_python_runtime(), + "X-Stainless-Runtime-Version": get_python_version(), + } + + +class OtherArch: + def __init__(self, name: str) -> None: + self.name = name + + @override + def __str__(self) -> str: + return f"other:{self.name}" + + +Arch = Union[OtherArch, Literal["x32", "x64", "arm", "arm64", "unknown"]] + + +def get_python_runtime() -> str: + try: + return platform.python_implementation() + except Exception: + return "unknown" + + +def get_python_version() -> str: + try: + return platform.python_version() + except Exception: + return "unknown" + + +def get_architecture() -> Arch: + try: + machine = platform.machine().lower() + except Exception: + return "unknown" + + if machine in ("arm64", "aarch64"): + return "arm64" + + # TODO: untested + if machine == "arm": + return "arm" + + if machine == "x86_64": + return "x64" + + # TODO: untested + if sys.maxsize <= 2**32: + return "x32" + + if machine: + return OtherArch(machine) + + return "unknown" + + +def _merge_mappings( + obj1: Mapping[_T_co, Union[_T, Omit]], + obj2: Mapping[_T_co, Union[_T, Omit]], +) -> Dict[_T_co, _T]: + """Merge two mappings of the same type, removing any values that are instances of `Omit`. + + In cases with duplicate keys the second mapping takes precedence. + """ + merged = {**obj1, **obj2} + return {key: value for key, value in merged.items() if not isinstance(value, Omit)} diff --git a/src/imagekit/_client.py b/src/imagekit/_client.py new file mode 100644 index 0000000..6c5a255 --- /dev/null +++ b/src/imagekit/_client.py @@ -0,0 +1,500 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +import base64 +from typing import Any, Union, Mapping +from typing_extensions import Self, override + +import httpx + +from . import _exceptions +from ._qs import Querystring +from ._types import ( + NOT_GIVEN, + Omit, + Headers, + Timeout, + NotGiven, + Transport, + ProxiesTypes, + RequestOptions, +) +from ._utils import is_given, get_async_library +from ._version import __version__ +from .resources import folder, accounts, bulk_jobs, custom_metadata_fields +from ._streaming import Stream as Stream, AsyncStream as AsyncStream +from ._exceptions import ImageKitError, APIStatusError +from ._base_client import ( + DEFAULT_MAX_RETRIES, + SyncAPIClient, + AsyncAPIClient, +) +from .resources.files import files + +__all__ = [ + "Timeout", + "Transport", + "ProxiesTypes", + "RequestOptions", + "ImageKit", + "AsyncImageKit", + "Client", + "AsyncClient", +] + + +class ImageKit(SyncAPIClient): + custom_metadata_fields: custom_metadata_fields.CustomMetadataFieldsResource + files: files.FilesResource + folder: folder.FolderResource + bulk_jobs: bulk_jobs.BulkJobsResource + accounts: accounts.AccountsResource + with_raw_response: ImageKitWithRawResponse + with_streaming_response: ImageKitWithStreamedResponse + + # client options + private_api_key: str + password: str | None + + def __init__( + self, + *, + private_api_key: str | None = None, + password: str | None = None, + base_url: str | httpx.URL | None = None, + timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, + max_retries: int = DEFAULT_MAX_RETRIES, + default_headers: Mapping[str, str] | None = None, + default_query: Mapping[str, object] | None = None, + # Configure a custom httpx client. + # We provide a `DefaultHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. + # See the [httpx documentation](https://www.python-httpx.org/api/#client) for more details. + http_client: httpx.Client | None = None, + # Enable or disable schema validation for data returned by the API. + # When enabled an error APIResponseValidationError is raised + # if the API responds with invalid data for the expected schema. + # + # This parameter may be removed or changed in the future. + # If you rely on this feature, please open a GitHub issue + # outlining your use-case to help us decide if it should be + # part of our public interface in the future. + _strict_response_validation: bool = False, + ) -> None: + """Construct a new synchronous ImageKit client instance. + + This automatically infers the following arguments from their corresponding environment variables if they are not provided: + - `private_api_key` from `IMAGEKIT_PRIVATE_API_KEY` + - `password` from `ORG_MY_PASSWORD_TOKEN` + """ + if private_api_key is None: + private_api_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") + if private_api_key is None: + raise ImageKitError( + "The private_api_key client option must be set either by passing private_api_key to the client or by setting the IMAGEKIT_PRIVATE_API_KEY environment variable" + ) + self.private_api_key = private_api_key + + if password is None: + password = os.environ.get("ORG_MY_PASSWORD_TOKEN") or "does_not_matter" + self.password = password + + if base_url is None: + base_url = os.environ.get("IMAGE_KIT_BASE_URL") + self._base_url_overridden = base_url is not None + if base_url is None: + base_url = f"https://api.imagekit.io" + + super().__init__( + version=__version__, + base_url=base_url, + max_retries=max_retries, + timeout=timeout, + http_client=http_client, + custom_headers=default_headers, + custom_query=default_query, + _strict_response_validation=_strict_response_validation, + ) + + self.custom_metadata_fields = custom_metadata_fields.CustomMetadataFieldsResource(self) + self.files = files.FilesResource(self) + self.folder = folder.FolderResource(self) + self.bulk_jobs = bulk_jobs.BulkJobsResource(self) + self.accounts = accounts.AccountsResource(self) + self.with_raw_response = ImageKitWithRawResponse(self) + self.with_streaming_response = ImageKitWithStreamedResponse(self) + + @property + @override + def qs(self) -> Querystring: + return Querystring(array_format="comma") + + @property + @override + def auth_headers(self) -> dict[str, str]: + if self.password is None: + return {} + credentials = f"{self.private_api_key}:{self.password}".encode("ascii") + header = f"Basic {base64.b64encode(credentials).decode('ascii')}" + return {"Authorization": header} + + @property + @override + def default_headers(self) -> dict[str, str | Omit]: + return { + **super().default_headers, + "X-Stainless-Async": "false", + **self._custom_headers, + } + + @override + def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None: + if self.private_api_key and self.password and headers.get("Authorization"): + return + if isinstance(custom_headers.get("Authorization"), Omit): + return + + raise TypeError( + '"Could not resolve authentication method. Expected the private_api_key or password to be set. Or for the `Authorization` headers to be explicitly omitted"' + ) + + def copy( + self, + *, + private_api_key: str | None = None, + password: str | None = None, + base_url: str | httpx.URL | None = None, + timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + http_client: httpx.Client | None = None, + max_retries: int | NotGiven = NOT_GIVEN, + default_headers: Mapping[str, str] | None = None, + set_default_headers: Mapping[str, str] | None = None, + default_query: Mapping[str, object] | None = None, + set_default_query: Mapping[str, object] | None = None, + _extra_kwargs: Mapping[str, Any] = {}, + ) -> Self: + """ + Create a new client instance re-using the same options given to the current client with optional overriding. + """ + if default_headers is not None and set_default_headers is not None: + raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") + + if default_query is not None and set_default_query is not None: + raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive") + + headers = self._custom_headers + if default_headers is not None: + headers = {**headers, **default_headers} + elif set_default_headers is not None: + headers = set_default_headers + + params = self._custom_query + if default_query is not None: + params = {**params, **default_query} + elif set_default_query is not None: + params = set_default_query + + http_client = http_client or self._client + client = self.__class__( + private_api_key=private_api_key or self.private_api_key, + password=password or self.password, + base_url=base_url or self.base_url, + timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, + http_client=http_client, + max_retries=max_retries if is_given(max_retries) else self.max_retries, + default_headers=headers, + default_query=params, + **_extra_kwargs, + ) + client._base_url_overridden = self._base_url_overridden or base_url is not None + return client + + # Alias for `copy` for nicer inline usage, e.g. + # client.with_options(timeout=10).foo.create(...) + with_options = copy + + @override + def _make_status_error( + self, + err_msg: str, + *, + body: object, + response: httpx.Response, + ) -> APIStatusError: + if response.status_code == 400: + return _exceptions.BadRequestError(err_msg, response=response, body=body) + + if response.status_code == 401: + return _exceptions.AuthenticationError(err_msg, response=response, body=body) + + if response.status_code == 403: + return _exceptions.PermissionDeniedError(err_msg, response=response, body=body) + + if response.status_code == 404: + return _exceptions.NotFoundError(err_msg, response=response, body=body) + + if response.status_code == 409: + return _exceptions.ConflictError(err_msg, response=response, body=body) + + if response.status_code == 422: + return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body) + + if response.status_code == 429: + return _exceptions.RateLimitError(err_msg, response=response, body=body) + + if response.status_code >= 500: + return _exceptions.InternalServerError(err_msg, response=response, body=body) + return APIStatusError(err_msg, response=response, body=body) + + +class AsyncImageKit(AsyncAPIClient): + custom_metadata_fields: custom_metadata_fields.AsyncCustomMetadataFieldsResource + files: files.AsyncFilesResource + folder: folder.AsyncFolderResource + bulk_jobs: bulk_jobs.AsyncBulkJobsResource + accounts: accounts.AsyncAccountsResource + with_raw_response: AsyncImageKitWithRawResponse + with_streaming_response: AsyncImageKitWithStreamedResponse + + # client options + private_api_key: str + password: str | None + + def __init__( + self, + *, + private_api_key: str | None = None, + password: str | None = None, + base_url: str | httpx.URL | None = None, + timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, + max_retries: int = DEFAULT_MAX_RETRIES, + default_headers: Mapping[str, str] | None = None, + default_query: Mapping[str, object] | None = None, + # Configure a custom httpx client. + # We provide a `DefaultAsyncHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`. + # See the [httpx documentation](https://www.python-httpx.org/api/#asyncclient) for more details. + http_client: httpx.AsyncClient | None = None, + # Enable or disable schema validation for data returned by the API. + # When enabled an error APIResponseValidationError is raised + # if the API responds with invalid data for the expected schema. + # + # This parameter may be removed or changed in the future. + # If you rely on this feature, please open a GitHub issue + # outlining your use-case to help us decide if it should be + # part of our public interface in the future. + _strict_response_validation: bool = False, + ) -> None: + """Construct a new async AsyncImageKit client instance. + + This automatically infers the following arguments from their corresponding environment variables if they are not provided: + - `private_api_key` from `IMAGEKIT_PRIVATE_API_KEY` + - `password` from `ORG_MY_PASSWORD_TOKEN` + """ + if private_api_key is None: + private_api_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") + if private_api_key is None: + raise ImageKitError( + "The private_api_key client option must be set either by passing private_api_key to the client or by setting the IMAGEKIT_PRIVATE_API_KEY environment variable" + ) + self.private_api_key = private_api_key + + if password is None: + password = os.environ.get("ORG_MY_PASSWORD_TOKEN") or "does_not_matter" + self.password = password + + if base_url is None: + base_url = os.environ.get("IMAGE_KIT_BASE_URL") + self._base_url_overridden = base_url is not None + if base_url is None: + base_url = f"https://api.imagekit.io" + + super().__init__( + version=__version__, + base_url=base_url, + max_retries=max_retries, + timeout=timeout, + http_client=http_client, + custom_headers=default_headers, + custom_query=default_query, + _strict_response_validation=_strict_response_validation, + ) + + self.custom_metadata_fields = custom_metadata_fields.AsyncCustomMetadataFieldsResource(self) + self.files = files.AsyncFilesResource(self) + self.folder = folder.AsyncFolderResource(self) + self.bulk_jobs = bulk_jobs.AsyncBulkJobsResource(self) + self.accounts = accounts.AsyncAccountsResource(self) + self.with_raw_response = AsyncImageKitWithRawResponse(self) + self.with_streaming_response = AsyncImageKitWithStreamedResponse(self) + + @property + @override + def qs(self) -> Querystring: + return Querystring(array_format="comma") + + @property + @override + def auth_headers(self) -> dict[str, str]: + if self.password is None: + return {} + credentials = f"{self.private_api_key}:{self.password}".encode("ascii") + header = f"Basic {base64.b64encode(credentials).decode('ascii')}" + return {"Authorization": header} + + @property + @override + def default_headers(self) -> dict[str, str | Omit]: + return { + **super().default_headers, + "X-Stainless-Async": f"async:{get_async_library()}", + **self._custom_headers, + } + + @override + def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None: + if self.private_api_key and self.password and headers.get("Authorization"): + return + if isinstance(custom_headers.get("Authorization"), Omit): + return + + raise TypeError( + '"Could not resolve authentication method. Expected the private_api_key or password to be set. Or for the `Authorization` headers to be explicitly omitted"' + ) + + def copy( + self, + *, + private_api_key: str | None = None, + password: str | None = None, + base_url: str | httpx.URL | None = None, + timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + http_client: httpx.AsyncClient | None = None, + max_retries: int | NotGiven = NOT_GIVEN, + default_headers: Mapping[str, str] | None = None, + set_default_headers: Mapping[str, str] | None = None, + default_query: Mapping[str, object] | None = None, + set_default_query: Mapping[str, object] | None = None, + _extra_kwargs: Mapping[str, Any] = {}, + ) -> Self: + """ + Create a new client instance re-using the same options given to the current client with optional overriding. + """ + if default_headers is not None and set_default_headers is not None: + raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") + + if default_query is not None and set_default_query is not None: + raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive") + + headers = self._custom_headers + if default_headers is not None: + headers = {**headers, **default_headers} + elif set_default_headers is not None: + headers = set_default_headers + + params = self._custom_query + if default_query is not None: + params = {**params, **default_query} + elif set_default_query is not None: + params = set_default_query + + http_client = http_client or self._client + client = self.__class__( + private_api_key=private_api_key or self.private_api_key, + password=password or self.password, + base_url=base_url or self.base_url, + timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, + http_client=http_client, + max_retries=max_retries if is_given(max_retries) else self.max_retries, + default_headers=headers, + default_query=params, + **_extra_kwargs, + ) + client._base_url_overridden = self._base_url_overridden or base_url is not None + return client + + # Alias for `copy` for nicer inline usage, e.g. + # client.with_options(timeout=10).foo.create(...) + with_options = copy + + @override + def _make_status_error( + self, + err_msg: str, + *, + body: object, + response: httpx.Response, + ) -> APIStatusError: + if response.status_code == 400: + return _exceptions.BadRequestError(err_msg, response=response, body=body) + + if response.status_code == 401: + return _exceptions.AuthenticationError(err_msg, response=response, body=body) + + if response.status_code == 403: + return _exceptions.PermissionDeniedError(err_msg, response=response, body=body) + + if response.status_code == 404: + return _exceptions.NotFoundError(err_msg, response=response, body=body) + + if response.status_code == 409: + return _exceptions.ConflictError(err_msg, response=response, body=body) + + if response.status_code == 422: + return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body) + + if response.status_code == 429: + return _exceptions.RateLimitError(err_msg, response=response, body=body) + + if response.status_code >= 500: + return _exceptions.InternalServerError(err_msg, response=response, body=body) + return APIStatusError(err_msg, response=response, body=body) + + +class ImageKitWithRawResponse: + def __init__(self, client: ImageKit) -> None: + self.custom_metadata_fields = custom_metadata_fields.CustomMetadataFieldsResourceWithRawResponse( + client.custom_metadata_fields + ) + self.files = files.FilesResourceWithRawResponse(client.files) + self.folder = folder.FolderResourceWithRawResponse(client.folder) + self.bulk_jobs = bulk_jobs.BulkJobsResourceWithRawResponse(client.bulk_jobs) + self.accounts = accounts.AccountsResourceWithRawResponse(client.accounts) + + +class AsyncImageKitWithRawResponse: + def __init__(self, client: AsyncImageKit) -> None: + self.custom_metadata_fields = custom_metadata_fields.AsyncCustomMetadataFieldsResourceWithRawResponse( + client.custom_metadata_fields + ) + self.files = files.AsyncFilesResourceWithRawResponse(client.files) + self.folder = folder.AsyncFolderResourceWithRawResponse(client.folder) + self.bulk_jobs = bulk_jobs.AsyncBulkJobsResourceWithRawResponse(client.bulk_jobs) + self.accounts = accounts.AsyncAccountsResourceWithRawResponse(client.accounts) + + +class ImageKitWithStreamedResponse: + def __init__(self, client: ImageKit) -> None: + self.custom_metadata_fields = custom_metadata_fields.CustomMetadataFieldsResourceWithStreamingResponse( + client.custom_metadata_fields + ) + self.files = files.FilesResourceWithStreamingResponse(client.files) + self.folder = folder.FolderResourceWithStreamingResponse(client.folder) + self.bulk_jobs = bulk_jobs.BulkJobsResourceWithStreamingResponse(client.bulk_jobs) + self.accounts = accounts.AccountsResourceWithStreamingResponse(client.accounts) + + +class AsyncImageKitWithStreamedResponse: + def __init__(self, client: AsyncImageKit) -> None: + self.custom_metadata_fields = custom_metadata_fields.AsyncCustomMetadataFieldsResourceWithStreamingResponse( + client.custom_metadata_fields + ) + self.files = files.AsyncFilesResourceWithStreamingResponse(client.files) + self.folder = folder.AsyncFolderResourceWithStreamingResponse(client.folder) + self.bulk_jobs = bulk_jobs.AsyncBulkJobsResourceWithStreamingResponse(client.bulk_jobs) + self.accounts = accounts.AsyncAccountsResourceWithStreamingResponse(client.accounts) + + +Client = ImageKit + +AsyncClient = AsyncImageKit diff --git a/src/imagekit/_compat.py b/src/imagekit/_compat.py new file mode 100644 index 0000000..92d9ee6 --- /dev/null +++ b/src/imagekit/_compat.py @@ -0,0 +1,219 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Union, Generic, TypeVar, Callable, cast, overload +from datetime import date, datetime +from typing_extensions import Self, Literal + +import pydantic +from pydantic.fields import FieldInfo + +from ._types import IncEx, StrBytesIntFloat + +_T = TypeVar("_T") +_ModelT = TypeVar("_ModelT", bound=pydantic.BaseModel) + +# --------------- Pydantic v2 compatibility --------------- + +# Pyright incorrectly reports some of our functions as overriding a method when they don't +# pyright: reportIncompatibleMethodOverride=false + +PYDANTIC_V2 = pydantic.VERSION.startswith("2.") + +# v1 re-exports +if TYPE_CHECKING: + + def parse_date(value: date | StrBytesIntFloat) -> date: # noqa: ARG001 + ... + + def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime: # noqa: ARG001 + ... + + def get_args(t: type[Any]) -> tuple[Any, ...]: # noqa: ARG001 + ... + + def is_union(tp: type[Any] | None) -> bool: # noqa: ARG001 + ... + + def get_origin(t: type[Any]) -> type[Any] | None: # noqa: ARG001 + ... + + def is_literal_type(type_: type[Any]) -> bool: # noqa: ARG001 + ... + + def is_typeddict(type_: type[Any]) -> bool: # noqa: ARG001 + ... + +else: + if PYDANTIC_V2: + from pydantic.v1.typing import ( + get_args as get_args, + is_union as is_union, + get_origin as get_origin, + is_typeddict as is_typeddict, + is_literal_type as is_literal_type, + ) + from pydantic.v1.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime + else: + from pydantic.typing import ( + get_args as get_args, + is_union as is_union, + get_origin as get_origin, + is_typeddict as is_typeddict, + is_literal_type as is_literal_type, + ) + from pydantic.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime + + +# refactored config +if TYPE_CHECKING: + from pydantic import ConfigDict as ConfigDict +else: + if PYDANTIC_V2: + from pydantic import ConfigDict + else: + # TODO: provide an error message here? + ConfigDict = None + + +# renamed methods / properties +def parse_obj(model: type[_ModelT], value: object) -> _ModelT: + if PYDANTIC_V2: + return model.model_validate(value) + else: + return cast(_ModelT, model.parse_obj(value)) # pyright: ignore[reportDeprecated, reportUnnecessaryCast] + + +def field_is_required(field: FieldInfo) -> bool: + if PYDANTIC_V2: + return field.is_required() + return field.required # type: ignore + + +def field_get_default(field: FieldInfo) -> Any: + value = field.get_default() + if PYDANTIC_V2: + from pydantic_core import PydanticUndefined + + if value == PydanticUndefined: + return None + return value + return value + + +def field_outer_type(field: FieldInfo) -> Any: + if PYDANTIC_V2: + return field.annotation + return field.outer_type_ # type: ignore + + +def get_model_config(model: type[pydantic.BaseModel]) -> Any: + if PYDANTIC_V2: + return model.model_config + return model.__config__ # type: ignore + + +def get_model_fields(model: type[pydantic.BaseModel]) -> dict[str, FieldInfo]: + if PYDANTIC_V2: + return model.model_fields + return model.__fields__ # type: ignore + + +def model_copy(model: _ModelT, *, deep: bool = False) -> _ModelT: + if PYDANTIC_V2: + return model.model_copy(deep=deep) + return model.copy(deep=deep) # type: ignore + + +def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str: + if PYDANTIC_V2: + return model.model_dump_json(indent=indent) + return model.json(indent=indent) # type: ignore + + +def model_dump( + model: pydantic.BaseModel, + *, + exclude: IncEx | None = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + warnings: bool = True, + mode: Literal["json", "python"] = "python", +) -> dict[str, Any]: + if PYDANTIC_V2 or hasattr(model, "model_dump"): + return model.model_dump( + mode=mode, + exclude=exclude, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + # warnings are not supported in Pydantic v1 + warnings=warnings if PYDANTIC_V2 else True, + ) + return cast( + "dict[str, Any]", + model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast] + exclude=exclude, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + ), + ) + + +def model_parse(model: type[_ModelT], data: Any) -> _ModelT: + if PYDANTIC_V2: + return model.model_validate(data) + return model.parse_obj(data) # pyright: ignore[reportDeprecated] + + +# generic models +if TYPE_CHECKING: + + class GenericModel(pydantic.BaseModel): ... + +else: + if PYDANTIC_V2: + # there no longer needs to be a distinction in v2 but + # we still have to create our own subclass to avoid + # inconsistent MRO ordering errors + class GenericModel(pydantic.BaseModel): ... + + else: + import pydantic.generics + + class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): ... + + +# cached properties +if TYPE_CHECKING: + cached_property = property + + # we define a separate type (copied from typeshed) + # that represents that `cached_property` is `set`able + # at runtime, which differs from `@property`. + # + # this is a separate type as editors likely special case + # `@property` and we don't want to cause issues just to have + # more helpful internal types. + + class typed_cached_property(Generic[_T]): + func: Callable[[Any], _T] + attrname: str | None + + def __init__(self, func: Callable[[Any], _T]) -> None: ... + + @overload + def __get__(self, instance: None, owner: type[Any] | None = None) -> Self: ... + + @overload + def __get__(self, instance: object, owner: type[Any] | None = None) -> _T: ... + + def __get__(self, instance: object, owner: type[Any] | None = None) -> _T | Self: + raise NotImplementedError() + + def __set_name__(self, owner: type[Any], name: str) -> None: ... + + # __set__ is not defined at runtime, but @cached_property is designed to be settable + def __set__(self, instance: object, value: _T) -> None: ... +else: + from functools import cached_property as cached_property + + typed_cached_property = cached_property diff --git a/src/imagekit/_constants.py b/src/imagekit/_constants.py new file mode 100644 index 0000000..6ddf2c7 --- /dev/null +++ b/src/imagekit/_constants.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import httpx + +RAW_RESPONSE_HEADER = "X-Stainless-Raw-Response" +OVERRIDE_CAST_TO_HEADER = "____stainless_override_cast_to" + +# default timeout is 1 minute +DEFAULT_TIMEOUT = httpx.Timeout(timeout=60, connect=5.0) +DEFAULT_MAX_RETRIES = 2 +DEFAULT_CONNECTION_LIMITS = httpx.Limits(max_connections=100, max_keepalive_connections=20) + +INITIAL_RETRY_DELAY = 0.5 +MAX_RETRY_DELAY = 8.0 diff --git a/src/imagekit/_exceptions.py b/src/imagekit/_exceptions.py new file mode 100644 index 0000000..990ca06 --- /dev/null +++ b/src/imagekit/_exceptions.py @@ -0,0 +1,108 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +import httpx + +__all__ = [ + "BadRequestError", + "AuthenticationError", + "PermissionDeniedError", + "NotFoundError", + "ConflictError", + "UnprocessableEntityError", + "RateLimitError", + "InternalServerError", +] + + +class ImageKitError(Exception): + pass + + +class APIError(ImageKitError): + message: str + request: httpx.Request + + body: object | None + """The API response body. + + If the API responded with a valid JSON structure then this property will be the + decoded result. + + If it isn't a valid JSON structure then this will be the raw response. + + If there was no response associated with this error then it will be `None`. + """ + + def __init__(self, message: str, request: httpx.Request, *, body: object | None) -> None: # noqa: ARG002 + super().__init__(message) + self.request = request + self.message = message + self.body = body + + +class APIResponseValidationError(APIError): + response: httpx.Response + status_code: int + + def __init__(self, response: httpx.Response, body: object | None, *, message: str | None = None) -> None: + super().__init__(message or "Data returned by API invalid for expected schema.", response.request, body=body) + self.response = response + self.status_code = response.status_code + + +class APIStatusError(APIError): + """Raised when an API response has a status code of 4xx or 5xx.""" + + response: httpx.Response + status_code: int + + def __init__(self, message: str, *, response: httpx.Response, body: object | None) -> None: + super().__init__(message, response.request, body=body) + self.response = response + self.status_code = response.status_code + + +class APIConnectionError(APIError): + def __init__(self, *, message: str = "Connection error.", request: httpx.Request) -> None: + super().__init__(message, request, body=None) + + +class APITimeoutError(APIConnectionError): + def __init__(self, request: httpx.Request) -> None: + super().__init__(message="Request timed out.", request=request) + + +class BadRequestError(APIStatusError): + status_code: Literal[400] = 400 # pyright: ignore[reportIncompatibleVariableOverride] + + +class AuthenticationError(APIStatusError): + status_code: Literal[401] = 401 # pyright: ignore[reportIncompatibleVariableOverride] + + +class PermissionDeniedError(APIStatusError): + status_code: Literal[403] = 403 # pyright: ignore[reportIncompatibleVariableOverride] + + +class NotFoundError(APIStatusError): + status_code: Literal[404] = 404 # pyright: ignore[reportIncompatibleVariableOverride] + + +class ConflictError(APIStatusError): + status_code: Literal[409] = 409 # pyright: ignore[reportIncompatibleVariableOverride] + + +class UnprocessableEntityError(APIStatusError): + status_code: Literal[422] = 422 # pyright: ignore[reportIncompatibleVariableOverride] + + +class RateLimitError(APIStatusError): + status_code: Literal[429] = 429 # pyright: ignore[reportIncompatibleVariableOverride] + + +class InternalServerError(APIStatusError): + pass diff --git a/src/imagekit/_files.py b/src/imagekit/_files.py new file mode 100644 index 0000000..cc14c14 --- /dev/null +++ b/src/imagekit/_files.py @@ -0,0 +1,123 @@ +from __future__ import annotations + +import io +import os +import pathlib +from typing import overload +from typing_extensions import TypeGuard + +import anyio + +from ._types import ( + FileTypes, + FileContent, + RequestFiles, + HttpxFileTypes, + Base64FileInput, + HttpxFileContent, + HttpxRequestFiles, +) +from ._utils import is_tuple_t, is_mapping_t, is_sequence_t + + +def is_base64_file_input(obj: object) -> TypeGuard[Base64FileInput]: + return isinstance(obj, io.IOBase) or isinstance(obj, os.PathLike) + + +def is_file_content(obj: object) -> TypeGuard[FileContent]: + return ( + isinstance(obj, bytes) or isinstance(obj, tuple) or isinstance(obj, io.IOBase) or isinstance(obj, os.PathLike) + ) + + +def assert_is_file_content(obj: object, *, key: str | None = None) -> None: + if not is_file_content(obj): + prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" + raise RuntimeError( + f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead." + ) from None + + +@overload +def to_httpx_files(files: None) -> None: ... + + +@overload +def to_httpx_files(files: RequestFiles) -> HttpxRequestFiles: ... + + +def to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles | None: + if files is None: + return None + + if is_mapping_t(files): + files = {key: _transform_file(file) for key, file in files.items()} + elif is_sequence_t(files): + files = [(key, _transform_file(file)) for key, file in files] + else: + raise TypeError(f"Unexpected file type input {type(files)}, expected mapping or sequence") + + return files + + +def _transform_file(file: FileTypes) -> HttpxFileTypes: + if is_file_content(file): + if isinstance(file, os.PathLike): + path = pathlib.Path(file) + return (path.name, path.read_bytes()) + + return file + + if is_tuple_t(file): + return (file[0], read_file_content(file[1]), *file[2:]) + + raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple") + + +def read_file_content(file: FileContent) -> HttpxFileContent: + if isinstance(file, os.PathLike): + return pathlib.Path(file).read_bytes() + return file + + +@overload +async def async_to_httpx_files(files: None) -> None: ... + + +@overload +async def async_to_httpx_files(files: RequestFiles) -> HttpxRequestFiles: ... + + +async def async_to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles | None: + if files is None: + return None + + if is_mapping_t(files): + files = {key: await _async_transform_file(file) for key, file in files.items()} + elif is_sequence_t(files): + files = [(key, await _async_transform_file(file)) for key, file in files] + else: + raise TypeError("Unexpected file type input {type(files)}, expected mapping or sequence") + + return files + + +async def _async_transform_file(file: FileTypes) -> HttpxFileTypes: + if is_file_content(file): + if isinstance(file, os.PathLike): + path = anyio.Path(file) + return (path.name, await path.read_bytes()) + + return file + + if is_tuple_t(file): + return (file[0], await async_read_file_content(file[1]), *file[2:]) + + raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple") + + +async def async_read_file_content(file: FileContent) -> HttpxFileContent: + if isinstance(file, os.PathLike): + return await anyio.Path(file).read_bytes() + + return file diff --git a/src/imagekit/_models.py b/src/imagekit/_models.py new file mode 100644 index 0000000..b8387ce --- /dev/null +++ b/src/imagekit/_models.py @@ -0,0 +1,829 @@ +from __future__ import annotations + +import os +import inspect +from typing import TYPE_CHECKING, Any, Type, Union, Generic, TypeVar, Callable, Optional, cast +from datetime import date, datetime +from typing_extensions import ( + List, + Unpack, + Literal, + ClassVar, + Protocol, + Required, + ParamSpec, + TypedDict, + TypeGuard, + final, + override, + runtime_checkable, +) + +import pydantic +from pydantic.fields import FieldInfo + +from ._types import ( + Body, + IncEx, + Query, + ModelT, + Headers, + Timeout, + NotGiven, + AnyMapping, + HttpxRequestFiles, +) +from ._utils import ( + PropertyInfo, + is_list, + is_given, + json_safe, + lru_cache, + is_mapping, + parse_date, + coerce_boolean, + parse_datetime, + strip_not_given, + extract_type_arg, + is_annotated_type, + is_type_alias_type, + strip_annotated_type, +) +from ._compat import ( + PYDANTIC_V2, + ConfigDict, + GenericModel as BaseGenericModel, + get_args, + is_union, + parse_obj, + get_origin, + is_literal_type, + get_model_config, + get_model_fields, + field_get_default, +) +from ._constants import RAW_RESPONSE_HEADER + +if TYPE_CHECKING: + from pydantic_core.core_schema import ModelField, ModelSchema, LiteralSchema, ModelFieldsSchema + +__all__ = ["BaseModel", "GenericModel"] + +_T = TypeVar("_T") +_BaseModelT = TypeVar("_BaseModelT", bound="BaseModel") + +P = ParamSpec("P") + + +@runtime_checkable +class _ConfigProtocol(Protocol): + allow_population_by_field_name: bool + + +class BaseModel(pydantic.BaseModel): + if PYDANTIC_V2: + model_config: ClassVar[ConfigDict] = ConfigDict( + extra="allow", defer_build=coerce_boolean(os.environ.get("DEFER_PYDANTIC_BUILD", "true")) + ) + else: + + @property + @override + def model_fields_set(self) -> set[str]: + # a forwards-compat shim for pydantic v2 + return self.__fields_set__ # type: ignore + + class Config(pydantic.BaseConfig): # pyright: ignore[reportDeprecated] + extra: Any = pydantic.Extra.allow # type: ignore + + def to_dict( + self, + *, + mode: Literal["json", "python"] = "python", + use_api_names: bool = True, + exclude_unset: bool = True, + exclude_defaults: bool = False, + exclude_none: bool = False, + warnings: bool = True, + ) -> dict[str, object]: + """Recursively generate a dictionary representation of the model, optionally specifying which fields to include or exclude. + + By default, fields that were not set by the API will not be included, + and keys will match the API response, *not* the property names from the model. + + For example, if the API responds with `"fooBar": true` but we've defined a `foo_bar: bool` property, + the output will use the `"fooBar"` key (unless `use_api_names=False` is passed). + + Args: + mode: + If mode is 'json', the dictionary will only contain JSON serializable types. e.g. `datetime` will be turned into a string, `"2024-3-22T18:11:19.117000Z"`. + If mode is 'python', the dictionary may contain any Python objects. e.g. `datetime(2024, 3, 22)` + + use_api_names: Whether to use the key that the API responded with or the property name. Defaults to `True`. + exclude_unset: Whether to exclude fields that have not been explicitly set. + exclude_defaults: Whether to exclude fields that are set to their default value from the output. + exclude_none: Whether to exclude fields that have a value of `None` from the output. + warnings: Whether to log warnings when invalid fields are encountered. This is only supported in Pydantic v2. + """ + return self.model_dump( + mode=mode, + by_alias=use_api_names, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + warnings=warnings, + ) + + def to_json( + self, + *, + indent: int | None = 2, + use_api_names: bool = True, + exclude_unset: bool = True, + exclude_defaults: bool = False, + exclude_none: bool = False, + warnings: bool = True, + ) -> str: + """Generates a JSON string representing this model as it would be received from or sent to the API (but with indentation). + + By default, fields that were not set by the API will not be included, + and keys will match the API response, *not* the property names from the model. + + For example, if the API responds with `"fooBar": true` but we've defined a `foo_bar: bool` property, + the output will use the `"fooBar"` key (unless `use_api_names=False` is passed). + + Args: + indent: Indentation to use in the JSON output. If `None` is passed, the output will be compact. Defaults to `2` + use_api_names: Whether to use the key that the API responded with or the property name. Defaults to `True`. + exclude_unset: Whether to exclude fields that have not been explicitly set. + exclude_defaults: Whether to exclude fields that have the default value. + exclude_none: Whether to exclude fields that have a value of `None`. + warnings: Whether to show any warnings that occurred during serialization. This is only supported in Pydantic v2. + """ + return self.model_dump_json( + indent=indent, + by_alias=use_api_names, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + warnings=warnings, + ) + + @override + def __str__(self) -> str: + # mypy complains about an invalid self arg + return f"{self.__repr_name__()}({self.__repr_str__(', ')})" # type: ignore[misc] + + # Override the 'construct' method in a way that supports recursive parsing without validation. + # Based on https://github.com/samuelcolvin/pydantic/issues/1168#issuecomment-817742836. + @classmethod + @override + def construct( # pyright: ignore[reportIncompatibleMethodOverride] + __cls: Type[ModelT], + _fields_set: set[str] | None = None, + **values: object, + ) -> ModelT: + m = __cls.__new__(__cls) + fields_values: dict[str, object] = {} + + config = get_model_config(__cls) + populate_by_name = ( + config.allow_population_by_field_name + if isinstance(config, _ConfigProtocol) + else config.get("populate_by_name") + ) + + if _fields_set is None: + _fields_set = set() + + model_fields = get_model_fields(__cls) + for name, field in model_fields.items(): + key = field.alias + if key is None or (key not in values and populate_by_name): + key = name + + if key in values: + fields_values[name] = _construct_field(value=values[key], field=field, key=key) + _fields_set.add(name) + else: + fields_values[name] = field_get_default(field) + + extra_field_type = _get_extra_fields_type(__cls) + + _extra = {} + for key, value in values.items(): + if key not in model_fields: + parsed = construct_type(value=value, type_=extra_field_type) if extra_field_type is not None else value + + if PYDANTIC_V2: + _extra[key] = parsed + else: + _fields_set.add(key) + fields_values[key] = parsed + + object.__setattr__(m, "__dict__", fields_values) + + if PYDANTIC_V2: + # these properties are copied from Pydantic's `model_construct()` method + object.__setattr__(m, "__pydantic_private__", None) + object.__setattr__(m, "__pydantic_extra__", _extra) + object.__setattr__(m, "__pydantic_fields_set__", _fields_set) + else: + # init_private_attributes() does not exist in v2 + m._init_private_attributes() # type: ignore + + # copied from Pydantic v1's `construct()` method + object.__setattr__(m, "__fields_set__", _fields_set) + + return m + + if not TYPE_CHECKING: + # type checkers incorrectly complain about this assignment + # because the type signatures are technically different + # although not in practice + model_construct = construct + + if not PYDANTIC_V2: + # we define aliases for some of the new pydantic v2 methods so + # that we can just document these methods without having to specify + # a specific pydantic version as some users may not know which + # pydantic version they are currently using + + @override + def model_dump( + self, + *, + mode: Literal["json", "python"] | str = "python", + include: IncEx | None = None, + exclude: IncEx | None = None, + by_alias: bool = False, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + round_trip: bool = False, + warnings: bool | Literal["none", "warn", "error"] = True, + context: dict[str, Any] | None = None, + serialize_as_any: bool = False, + ) -> dict[str, Any]: + """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump + + Generate a dictionary representation of the model, optionally specifying which fields to include or exclude. + + Args: + mode: The mode in which `to_python` should run. + If mode is 'json', the dictionary will only contain JSON serializable types. + If mode is 'python', the dictionary may contain any Python objects. + include: A list of fields to include in the output. + exclude: A list of fields to exclude from the output. + by_alias: Whether to use the field's alias in the dictionary key if defined. + exclude_unset: Whether to exclude fields that are unset or None from the output. + exclude_defaults: Whether to exclude fields that are set to their default value from the output. + exclude_none: Whether to exclude fields that have a value of `None` from the output. + round_trip: Whether to enable serialization and deserialization round-trip support. + warnings: Whether to log warnings when invalid fields are encountered. + + Returns: + A dictionary representation of the model. + """ + if mode not in {"json", "python"}: + raise ValueError("mode must be either 'json' or 'python'") + if round_trip != False: + raise ValueError("round_trip is only supported in Pydantic v2") + if warnings != True: + raise ValueError("warnings is only supported in Pydantic v2") + if context is not None: + raise ValueError("context is only supported in Pydantic v2") + if serialize_as_any != False: + raise ValueError("serialize_as_any is only supported in Pydantic v2") + dumped = super().dict( # pyright: ignore[reportDeprecated] + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + + return cast(dict[str, Any], json_safe(dumped)) if mode == "json" else dumped + + @override + def model_dump_json( + self, + *, + indent: int | None = None, + include: IncEx | None = None, + exclude: IncEx | None = None, + by_alias: bool = False, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + round_trip: bool = False, + warnings: bool | Literal["none", "warn", "error"] = True, + context: dict[str, Any] | None = None, + serialize_as_any: bool = False, + ) -> str: + """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump_json + + Generates a JSON representation of the model using Pydantic's `to_json` method. + + Args: + indent: Indentation to use in the JSON output. If None is passed, the output will be compact. + include: Field(s) to include in the JSON output. Can take either a string or set of strings. + exclude: Field(s) to exclude from the JSON output. Can take either a string or set of strings. + by_alias: Whether to serialize using field aliases. + exclude_unset: Whether to exclude fields that have not been explicitly set. + exclude_defaults: Whether to exclude fields that have the default value. + exclude_none: Whether to exclude fields that have a value of `None`. + round_trip: Whether to use serialization/deserialization between JSON and class instance. + warnings: Whether to show any warnings that occurred during serialization. + + Returns: + A JSON string representation of the model. + """ + if round_trip != False: + raise ValueError("round_trip is only supported in Pydantic v2") + if warnings != True: + raise ValueError("warnings is only supported in Pydantic v2") + if context is not None: + raise ValueError("context is only supported in Pydantic v2") + if serialize_as_any != False: + raise ValueError("serialize_as_any is only supported in Pydantic v2") + return super().json( # type: ignore[reportDeprecated] + indent=indent, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + + +def _construct_field(value: object, field: FieldInfo, key: str) -> object: + if value is None: + return field_get_default(field) + + if PYDANTIC_V2: + type_ = field.annotation + else: + type_ = cast(type, field.outer_type_) # type: ignore + + if type_ is None: + raise RuntimeError(f"Unexpected field type is None for {key}") + + return construct_type(value=value, type_=type_, metadata=getattr(field, "metadata", None)) + + +def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None: + if not PYDANTIC_V2: + # TODO + return None + + schema = cls.__pydantic_core_schema__ + if schema["type"] == "model": + fields = schema["schema"] + if fields["type"] == "model-fields": + extras = fields.get("extras_schema") + if extras and "cls" in extras: + # mypy can't narrow the type + return extras["cls"] # type: ignore[no-any-return] + + return None + + +def is_basemodel(type_: type) -> bool: + """Returns whether or not the given type is either a `BaseModel` or a union of `BaseModel`""" + if is_union(type_): + for variant in get_args(type_): + if is_basemodel(variant): + return True + + return False + + return is_basemodel_type(type_) + + +def is_basemodel_type(type_: type) -> TypeGuard[type[BaseModel] | type[GenericModel]]: + origin = get_origin(type_) or type_ + if not inspect.isclass(origin): + return False + return issubclass(origin, BaseModel) or issubclass(origin, GenericModel) + + +def build( + base_model_cls: Callable[P, _BaseModelT], + *args: P.args, + **kwargs: P.kwargs, +) -> _BaseModelT: + """Construct a BaseModel class without validation. + + This is useful for cases where you need to instantiate a `BaseModel` + from an API response as this provides type-safe params which isn't supported + by helpers like `construct_type()`. + + ```py + build(MyModel, my_field_a="foo", my_field_b=123) + ``` + """ + if args: + raise TypeError( + "Received positional arguments which are not supported; Keyword arguments must be used instead", + ) + + return cast(_BaseModelT, construct_type(type_=base_model_cls, value=kwargs)) + + +def construct_type_unchecked(*, value: object, type_: type[_T]) -> _T: + """Loose coercion to the expected type with construction of nested values. + + Note: the returned value from this function is not guaranteed to match the + given type. + """ + return cast(_T, construct_type(value=value, type_=type_)) + + +def construct_type(*, value: object, type_: object, metadata: Optional[List[Any]] = None) -> object: + """Loose coercion to the expected type with construction of nested values. + + If the given value does not match the expected type then it is returned as-is. + """ + + # store a reference to the original type we were given before we extract any inner + # types so that we can properly resolve forward references in `TypeAliasType` annotations + original_type = None + + # we allow `object` as the input type because otherwise, passing things like + # `Literal['value']` will be reported as a type error by type checkers + type_ = cast("type[object]", type_) + if is_type_alias_type(type_): + original_type = type_ # type: ignore[unreachable] + type_ = type_.__value__ # type: ignore[unreachable] + + # unwrap `Annotated[T, ...]` -> `T` + if metadata is not None and len(metadata) > 0: + meta: tuple[Any, ...] = tuple(metadata) + elif is_annotated_type(type_): + meta = get_args(type_)[1:] + type_ = extract_type_arg(type_, 0) + else: + meta = tuple() + + # we need to use the origin class for any types that are subscripted generics + # e.g. Dict[str, object] + origin = get_origin(type_) or type_ + args = get_args(type_) + + if is_union(origin): + try: + return validate_type(type_=cast("type[object]", original_type or type_), value=value) + except Exception: + pass + + # if the type is a discriminated union then we want to construct the right variant + # in the union, even if the data doesn't match exactly, otherwise we'd break code + # that relies on the constructed class types, e.g. + # + # class FooType: + # kind: Literal['foo'] + # value: str + # + # class BarType: + # kind: Literal['bar'] + # value: int + # + # without this block, if the data we get is something like `{'kind': 'bar', 'value': 'foo'}` then + # we'd end up constructing `FooType` when it should be `BarType`. + discriminator = _build_discriminated_union_meta(union=type_, meta_annotations=meta) + if discriminator and is_mapping(value): + variant_value = value.get(discriminator.field_alias_from or discriminator.field_name) + if variant_value and isinstance(variant_value, str): + variant_type = discriminator.mapping.get(variant_value) + if variant_type: + return construct_type(type_=variant_type, value=value) + + # if the data is not valid, use the first variant that doesn't fail while deserializing + for variant in args: + try: + return construct_type(value=value, type_=variant) + except Exception: + continue + + raise RuntimeError(f"Could not convert data into a valid instance of {type_}") + + if origin == dict: + if not is_mapping(value): + return value + + _, items_type = get_args(type_) # Dict[_, items_type] + return {key: construct_type(value=item, type_=items_type) for key, item in value.items()} + + if ( + not is_literal_type(type_) + and inspect.isclass(origin) + and (issubclass(origin, BaseModel) or issubclass(origin, GenericModel)) + ): + if is_list(value): + return [cast(Any, type_).construct(**entry) if is_mapping(entry) else entry for entry in value] + + if is_mapping(value): + if issubclass(type_, BaseModel): + return type_.construct(**value) # type: ignore[arg-type] + + return cast(Any, type_).construct(**value) + + if origin == list: + if not is_list(value): + return value + + inner_type = args[0] # List[inner_type] + return [construct_type(value=entry, type_=inner_type) for entry in value] + + if origin == float: + if isinstance(value, int): + coerced = float(value) + if coerced != value: + return value + return coerced + + return value + + if type_ == datetime: + try: + return parse_datetime(value) # type: ignore + except Exception: + return value + + if type_ == date: + try: + return parse_date(value) # type: ignore + except Exception: + return value + + return value + + +@runtime_checkable +class CachedDiscriminatorType(Protocol): + __discriminator__: DiscriminatorDetails + + +class DiscriminatorDetails: + field_name: str + """The name of the discriminator field in the variant class, e.g. + + ```py + class Foo(BaseModel): + type: Literal['foo'] + ``` + + Will result in field_name='type' + """ + + field_alias_from: str | None + """The name of the discriminator field in the API response, e.g. + + ```py + class Foo(BaseModel): + type: Literal['foo'] = Field(alias='type_from_api') + ``` + + Will result in field_alias_from='type_from_api' + """ + + mapping: dict[str, type] + """Mapping of discriminator value to variant type, e.g. + + {'foo': FooVariant, 'bar': BarVariant} + """ + + def __init__( + self, + *, + mapping: dict[str, type], + discriminator_field: str, + discriminator_alias: str | None, + ) -> None: + self.mapping = mapping + self.field_name = discriminator_field + self.field_alias_from = discriminator_alias + + +def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, ...]) -> DiscriminatorDetails | None: + if isinstance(union, CachedDiscriminatorType): + return union.__discriminator__ + + discriminator_field_name: str | None = None + + for annotation in meta_annotations: + if isinstance(annotation, PropertyInfo) and annotation.discriminator is not None: + discriminator_field_name = annotation.discriminator + break + + if not discriminator_field_name: + return None + + mapping: dict[str, type] = {} + discriminator_alias: str | None = None + + for variant in get_args(union): + variant = strip_annotated_type(variant) + if is_basemodel_type(variant): + if PYDANTIC_V2: + field = _extract_field_schema_pv2(variant, discriminator_field_name) + if not field: + continue + + # Note: if one variant defines an alias then they all should + discriminator_alias = field.get("serialization_alias") + + field_schema = field["schema"] + + if field_schema["type"] == "literal": + for entry in cast("LiteralSchema", field_schema)["expected"]: + if isinstance(entry, str): + mapping[entry] = variant + else: + field_info = cast("dict[str, FieldInfo]", variant.__fields__).get(discriminator_field_name) # pyright: ignore[reportDeprecated, reportUnnecessaryCast] + if not field_info: + continue + + # Note: if one variant defines an alias then they all should + discriminator_alias = field_info.alias + + if (annotation := getattr(field_info, "annotation", None)) and is_literal_type(annotation): + for entry in get_args(annotation): + if isinstance(entry, str): + mapping[entry] = variant + + if not mapping: + return None + + details = DiscriminatorDetails( + mapping=mapping, + discriminator_field=discriminator_field_name, + discriminator_alias=discriminator_alias, + ) + cast(CachedDiscriminatorType, union).__discriminator__ = details + return details + + +def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelField | None: + schema = model.__pydantic_core_schema__ + if schema["type"] == "definitions": + schema = schema["schema"] + + if schema["type"] != "model": + return None + + schema = cast("ModelSchema", schema) + fields_schema = schema["schema"] + if fields_schema["type"] != "model-fields": + return None + + fields_schema = cast("ModelFieldsSchema", fields_schema) + field = fields_schema["fields"].get(field_name) + if not field: + return None + + return cast("ModelField", field) # pyright: ignore[reportUnnecessaryCast] + + +def validate_type(*, type_: type[_T], value: object) -> _T: + """Strict validation that the given value matches the expected type""" + if inspect.isclass(type_) and issubclass(type_, pydantic.BaseModel): + return cast(_T, parse_obj(type_, value)) + + return cast(_T, _validate_non_model_type(type_=type_, value=value)) + + +def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None: + """Add a pydantic config for the given type. + + Note: this is a no-op on Pydantic v1. + """ + setattr(typ, "__pydantic_config__", config) # noqa: B010 + + +# our use of subclassing here causes weirdness for type checkers, +# so we just pretend that we don't subclass +if TYPE_CHECKING: + GenericModel = BaseModel +else: + + class GenericModel(BaseGenericModel, BaseModel): + pass + + +if PYDANTIC_V2: + from pydantic import TypeAdapter as _TypeAdapter + + _CachedTypeAdapter = cast("TypeAdapter[object]", lru_cache(maxsize=None)(_TypeAdapter)) + + if TYPE_CHECKING: + from pydantic import TypeAdapter + else: + TypeAdapter = _CachedTypeAdapter + + def _validate_non_model_type(*, type_: type[_T], value: object) -> _T: + return TypeAdapter(type_).validate_python(value) + +elif not TYPE_CHECKING: # TODO: condition is weird + + class RootModel(GenericModel, Generic[_T]): + """Used as a placeholder to easily convert runtime types to a Pydantic format + to provide validation. + + For example: + ```py + validated = RootModel[int](__root__="5").__root__ + # validated: 5 + ``` + """ + + __root__: _T + + def _validate_non_model_type(*, type_: type[_T], value: object) -> _T: + model = _create_pydantic_model(type_).validate(value) + return cast(_T, model.__root__) + + def _create_pydantic_model(type_: _T) -> Type[RootModel[_T]]: + return RootModel[type_] # type: ignore + + +class FinalRequestOptionsInput(TypedDict, total=False): + method: Required[str] + url: Required[str] + params: Query + headers: Headers + max_retries: int + timeout: float | Timeout | None + files: HttpxRequestFiles | None + idempotency_key: str + json_data: Body + extra_json: AnyMapping + follow_redirects: bool + + +@final +class FinalRequestOptions(pydantic.BaseModel): + method: str + url: str + params: Query = {} + headers: Union[Headers, NotGiven] = NotGiven() + max_retries: Union[int, NotGiven] = NotGiven() + timeout: Union[float, Timeout, None, NotGiven] = NotGiven() + files: Union[HttpxRequestFiles, None] = None + idempotency_key: Union[str, None] = None + post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() + follow_redirects: Union[bool, None] = None + + # It should be noted that we cannot use `json` here as that would override + # a BaseModel method in an incompatible fashion. + json_data: Union[Body, None] = None + extra_json: Union[AnyMapping, None] = None + + if PYDANTIC_V2: + model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True) + else: + + class Config(pydantic.BaseConfig): # pyright: ignore[reportDeprecated] + arbitrary_types_allowed: bool = True + + def get_max_retries(self, max_retries: int) -> int: + if isinstance(self.max_retries, NotGiven): + return max_retries + return self.max_retries + + def _strip_raw_response_header(self) -> None: + if not is_given(self.headers): + return + + if self.headers.get(RAW_RESPONSE_HEADER): + self.headers = {**self.headers} + self.headers.pop(RAW_RESPONSE_HEADER) + + # override the `construct` method so that we can run custom transformations. + # this is necessary as we don't want to do any actual runtime type checking + # (which means we can't use validators) but we do want to ensure that `NotGiven` + # values are not present + # + # type ignore required because we're adding explicit types to `**values` + @classmethod + def construct( # type: ignore + cls, + _fields_set: set[str] | None = None, + **values: Unpack[FinalRequestOptionsInput], + ) -> FinalRequestOptions: + kwargs: dict[str, Any] = { + # we unconditionally call `strip_not_given` on any value + # as it will just ignore any non-mapping types + key: strip_not_given(value) + for key, value in values.items() + } + if PYDANTIC_V2: + return super().model_construct(_fields_set, **kwargs) + return cast(FinalRequestOptions, super().construct(_fields_set, **kwargs)) # pyright: ignore[reportDeprecated] + + if not TYPE_CHECKING: + # type checkers incorrectly complain about this assignment + model_construct = construct diff --git a/src/imagekit/_qs.py b/src/imagekit/_qs.py new file mode 100644 index 0000000..274320c --- /dev/null +++ b/src/imagekit/_qs.py @@ -0,0 +1,150 @@ +from __future__ import annotations + +from typing import Any, List, Tuple, Union, Mapping, TypeVar +from urllib.parse import parse_qs, urlencode +from typing_extensions import Literal, get_args + +from ._types import NOT_GIVEN, NotGiven, NotGivenOr +from ._utils import flatten + +_T = TypeVar("_T") + + +ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] +NestedFormat = Literal["dots", "brackets"] + +PrimitiveData = Union[str, int, float, bool, None] +# this should be Data = Union[PrimitiveData, "List[Data]", "Tuple[Data]", "Mapping[str, Data]"] +# https://github.com/microsoft/pyright/issues/3555 +Data = Union[PrimitiveData, List[Any], Tuple[Any], "Mapping[str, Any]"] +Params = Mapping[str, Data] + + +class Querystring: + array_format: ArrayFormat + nested_format: NestedFormat + + def __init__( + self, + *, + array_format: ArrayFormat = "repeat", + nested_format: NestedFormat = "brackets", + ) -> None: + self.array_format = array_format + self.nested_format = nested_format + + def parse(self, query: str) -> Mapping[str, object]: + # Note: custom format syntax is not supported yet + return parse_qs(query) + + def stringify( + self, + params: Params, + *, + array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, + nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + ) -> str: + return urlencode( + self.stringify_items( + params, + array_format=array_format, + nested_format=nested_format, + ) + ) + + def stringify_items( + self, + params: Params, + *, + array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, + nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + ) -> list[tuple[str, str]]: + opts = Options( + qs=self, + array_format=array_format, + nested_format=nested_format, + ) + return flatten([self._stringify_item(key, value, opts) for key, value in params.items()]) + + def _stringify_item( + self, + key: str, + value: Data, + opts: Options, + ) -> list[tuple[str, str]]: + if isinstance(value, Mapping): + items: list[tuple[str, str]] = [] + nested_format = opts.nested_format + for subkey, subvalue in value.items(): + items.extend( + self._stringify_item( + # TODO: error if unknown format + f"{key}.{subkey}" if nested_format == "dots" else f"{key}[{subkey}]", + subvalue, + opts, + ) + ) + return items + + if isinstance(value, (list, tuple)): + array_format = opts.array_format + if array_format == "comma": + return [ + ( + key, + ",".join(self._primitive_value_to_str(item) for item in value if item is not None), + ), + ] + elif array_format == "repeat": + items = [] + for item in value: + items.extend(self._stringify_item(key, item, opts)) + return items + elif array_format == "indices": + raise NotImplementedError("The array indices format is not supported yet") + elif array_format == "brackets": + items = [] + key = key + "[]" + for item in value: + items.extend(self._stringify_item(key, item, opts)) + return items + else: + raise NotImplementedError( + f"Unknown array_format value: {array_format}, choose from {', '.join(get_args(ArrayFormat))}" + ) + + serialised = self._primitive_value_to_str(value) + if not serialised: + return [] + return [(key, serialised)] + + def _primitive_value_to_str(self, value: PrimitiveData) -> str: + # copied from httpx + if value is True: + return "true" + elif value is False: + return "false" + elif value is None: + return "" + return str(value) + + +_qs = Querystring() +parse = _qs.parse +stringify = _qs.stringify +stringify_items = _qs.stringify_items + + +class Options: + array_format: ArrayFormat + nested_format: NestedFormat + + def __init__( + self, + qs: Querystring = _qs, + *, + array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, + nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + ) -> None: + self.array_format = qs.array_format if isinstance(array_format, NotGiven) else array_format + self.nested_format = qs.nested_format if isinstance(nested_format, NotGiven) else nested_format diff --git a/src/imagekit/_resource.py b/src/imagekit/_resource.py new file mode 100644 index 0000000..f830660 --- /dev/null +++ b/src/imagekit/_resource.py @@ -0,0 +1,43 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import time +from typing import TYPE_CHECKING + +import anyio + +if TYPE_CHECKING: + from ._client import ImageKit, AsyncImageKit + + +class SyncAPIResource: + _client: ImageKit + + def __init__(self, client: ImageKit) -> None: + self._client = client + self._get = client.get + self._post = client.post + self._patch = client.patch + self._put = client.put + self._delete = client.delete + self._get_api_list = client.get_api_list + + def _sleep(self, seconds: float) -> None: + time.sleep(seconds) + + +class AsyncAPIResource: + _client: AsyncImageKit + + def __init__(self, client: AsyncImageKit) -> None: + self._client = client + self._get = client.get + self._post = client.post + self._patch = client.patch + self._put = client.put + self._delete = client.delete + self._get_api_list = client.get_api_list + + async def _sleep(self, seconds: float) -> None: + await anyio.sleep(seconds) diff --git a/src/imagekit/_response.py b/src/imagekit/_response.py new file mode 100644 index 0000000..c7bcdb4 --- /dev/null +++ b/src/imagekit/_response.py @@ -0,0 +1,830 @@ +from __future__ import annotations + +import os +import inspect +import logging +import datetime +import functools +from types import TracebackType +from typing import ( + TYPE_CHECKING, + Any, + Union, + Generic, + TypeVar, + Callable, + Iterator, + AsyncIterator, + cast, + overload, +) +from typing_extensions import Awaitable, ParamSpec, override, get_origin + +import anyio +import httpx +import pydantic + +from ._types import NoneType +from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type, extract_type_var_from_base +from ._models import BaseModel, is_basemodel +from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER +from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type +from ._exceptions import ImageKitError, APIResponseValidationError + +if TYPE_CHECKING: + from ._models import FinalRequestOptions + from ._base_client import BaseClient + + +P = ParamSpec("P") +R = TypeVar("R") +_T = TypeVar("_T") +_APIResponseT = TypeVar("_APIResponseT", bound="APIResponse[Any]") +_AsyncAPIResponseT = TypeVar("_AsyncAPIResponseT", bound="AsyncAPIResponse[Any]") + +log: logging.Logger = logging.getLogger(__name__) + + +class BaseAPIResponse(Generic[R]): + _cast_to: type[R] + _client: BaseClient[Any, Any] + _parsed_by_type: dict[type[Any], Any] + _is_sse_stream: bool + _stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None + _options: FinalRequestOptions + + http_response: httpx.Response + + retries_taken: int + """The number of retries made. If no retries happened this will be `0`""" + + def __init__( + self, + *, + raw: httpx.Response, + cast_to: type[R], + client: BaseClient[Any, Any], + stream: bool, + stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, + options: FinalRequestOptions, + retries_taken: int = 0, + ) -> None: + self._cast_to = cast_to + self._client = client + self._parsed_by_type = {} + self._is_sse_stream = stream + self._stream_cls = stream_cls + self._options = options + self.http_response = raw + self.retries_taken = retries_taken + + @property + def headers(self) -> httpx.Headers: + return self.http_response.headers + + @property + def http_request(self) -> httpx.Request: + """Returns the httpx Request instance associated with the current response.""" + return self.http_response.request + + @property + def status_code(self) -> int: + return self.http_response.status_code + + @property + def url(self) -> httpx.URL: + """Returns the URL for which the request was made.""" + return self.http_response.url + + @property + def method(self) -> str: + return self.http_request.method + + @property + def http_version(self) -> str: + return self.http_response.http_version + + @property + def elapsed(self) -> datetime.timedelta: + """The time taken for the complete request/response cycle to complete.""" + return self.http_response.elapsed + + @property + def is_closed(self) -> bool: + """Whether or not the response body has been closed. + + If this is False then there is response data that has not been read yet. + You must either fully consume the response body or call `.close()` + before discarding the response to prevent resource leaks. + """ + return self.http_response.is_closed + + @override + def __repr__(self) -> str: + return ( + f"<{self.__class__.__name__} [{self.status_code} {self.http_response.reason_phrase}] type={self._cast_to}>" + ) + + def _parse(self, *, to: type[_T] | None = None) -> R | _T: + cast_to = to if to is not None else self._cast_to + + # unwrap `TypeAlias('Name', T)` -> `T` + if is_type_alias_type(cast_to): + cast_to = cast_to.__value__ # type: ignore[unreachable] + + # unwrap `Annotated[T, ...]` -> `T` + if cast_to and is_annotated_type(cast_to): + cast_to = extract_type_arg(cast_to, 0) + + origin = get_origin(cast_to) or cast_to + + if self._is_sse_stream: + if to: + if not is_stream_class_type(to): + raise TypeError(f"Expected custom parse type to be a subclass of {Stream} or {AsyncStream}") + + return cast( + _T, + to( + cast_to=extract_stream_chunk_type( + to, + failure_message="Expected custom stream type to be passed with a type argument, e.g. Stream[ChunkType]", + ), + response=self.http_response, + client=cast(Any, self._client), + ), + ) + + if self._stream_cls: + return cast( + R, + self._stream_cls( + cast_to=extract_stream_chunk_type(self._stream_cls), + response=self.http_response, + client=cast(Any, self._client), + ), + ) + + stream_cls = cast("type[Stream[Any]] | type[AsyncStream[Any]] | None", self._client._default_stream_cls) + if stream_cls is None: + raise MissingStreamClassError() + + return cast( + R, + stream_cls( + cast_to=cast_to, + response=self.http_response, + client=cast(Any, self._client), + ), + ) + + if cast_to is NoneType: + return cast(R, None) + + response = self.http_response + if cast_to == str: + return cast(R, response.text) + + if cast_to == bytes: + return cast(R, response.content) + + if cast_to == int: + return cast(R, int(response.text)) + + if cast_to == float: + return cast(R, float(response.text)) + + if cast_to == bool: + return cast(R, response.text.lower() == "true") + + if origin == APIResponse: + raise RuntimeError("Unexpected state - cast_to is `APIResponse`") + + if inspect.isclass(origin) and issubclass(origin, httpx.Response): + # Because of the invariance of our ResponseT TypeVar, users can subclass httpx.Response + # and pass that class to our request functions. We cannot change the variance to be either + # covariant or contravariant as that makes our usage of ResponseT illegal. We could construct + # the response class ourselves but that is something that should be supported directly in httpx + # as it would be easy to incorrectly construct the Response object due to the multitude of arguments. + if cast_to != httpx.Response: + raise ValueError(f"Subclasses of httpx.Response cannot be passed to `cast_to`") + return cast(R, response) + + if ( + inspect.isclass( + origin # pyright: ignore[reportUnknownArgumentType] + ) + and not issubclass(origin, BaseModel) + and issubclass(origin, pydantic.BaseModel) + ): + raise TypeError("Pydantic models must subclass our base model type, e.g. `from imagekit import BaseModel`") + + if ( + cast_to is not object + and not origin is list + and not origin is dict + and not origin is Union + and not issubclass(origin, BaseModel) + ): + raise RuntimeError( + f"Unsupported type, expected {cast_to} to be a subclass of {BaseModel}, {dict}, {list}, {Union}, {NoneType}, {str} or {httpx.Response}." + ) + + # split is required to handle cases where additional information is included + # in the response, e.g. application/json; charset=utf-8 + content_type, *_ = response.headers.get("content-type", "*").split(";") + if not content_type.endswith("json"): + if is_basemodel(cast_to): + try: + data = response.json() + except Exception as exc: + log.debug("Could not read JSON from response data due to %s - %s", type(exc), exc) + else: + return self._client._process_response_data( + data=data, + cast_to=cast_to, # type: ignore + response=response, + ) + + if self._client._strict_response_validation: + raise APIResponseValidationError( + response=response, + message=f"Expected Content-Type response header to be `application/json` but received `{content_type}` instead.", + body=response.text, + ) + + # If the API responds with content that isn't JSON then we just return + # the (decoded) text without performing any parsing so that you can still + # handle the response however you need to. + return response.text # type: ignore + + data = response.json() + + return self._client._process_response_data( + data=data, + cast_to=cast_to, # type: ignore + response=response, + ) + + +class APIResponse(BaseAPIResponse[R]): + @overload + def parse(self, *, to: type[_T]) -> _T: ... + + @overload + def parse(self) -> R: ... + + def parse(self, *, to: type[_T] | None = None) -> R | _T: + """Returns the rich python representation of this response's data. + + For lower-level control, see `.read()`, `.json()`, `.iter_bytes()`. + + You can customise the type that the response is parsed into through + the `to` argument, e.g. + + ```py + from imagekit import BaseModel + + + class MyModel(BaseModel): + foo: str + + + obj = response.parse(to=MyModel) + print(obj.foo) + ``` + + We support parsing: + - `BaseModel` + - `dict` + - `list` + - `Union` + - `str` + - `int` + - `float` + - `httpx.Response` + """ + cache_key = to if to is not None else self._cast_to + cached = self._parsed_by_type.get(cache_key) + if cached is not None: + return cached # type: ignore[no-any-return] + + if not self._is_sse_stream: + self.read() + + parsed = self._parse(to=to) + if is_given(self._options.post_parser): + parsed = self._options.post_parser(parsed) + + self._parsed_by_type[cache_key] = parsed + return parsed + + def read(self) -> bytes: + """Read and return the binary response content.""" + try: + return self.http_response.read() + except httpx.StreamConsumed as exc: + # The default error raised by httpx isn't very + # helpful in our case so we re-raise it with + # a different error message. + raise StreamAlreadyConsumed() from exc + + def text(self) -> str: + """Read and decode the response content into a string.""" + self.read() + return self.http_response.text + + def json(self) -> object: + """Read and decode the JSON response content.""" + self.read() + return self.http_response.json() + + def close(self) -> None: + """Close the response and release the connection. + + Automatically called if the response body is read to completion. + """ + self.http_response.close() + + def iter_bytes(self, chunk_size: int | None = None) -> Iterator[bytes]: + """ + A byte-iterator over the decoded response content. + + This automatically handles gzip, deflate and brotli encoded responses. + """ + for chunk in self.http_response.iter_bytes(chunk_size): + yield chunk + + def iter_text(self, chunk_size: int | None = None) -> Iterator[str]: + """A str-iterator over the decoded response content + that handles both gzip, deflate, etc but also detects the content's + string encoding. + """ + for chunk in self.http_response.iter_text(chunk_size): + yield chunk + + def iter_lines(self) -> Iterator[str]: + """Like `iter_text()` but will only yield chunks for each line""" + for chunk in self.http_response.iter_lines(): + yield chunk + + +class AsyncAPIResponse(BaseAPIResponse[R]): + @overload + async def parse(self, *, to: type[_T]) -> _T: ... + + @overload + async def parse(self) -> R: ... + + async def parse(self, *, to: type[_T] | None = None) -> R | _T: + """Returns the rich python representation of this response's data. + + For lower-level control, see `.read()`, `.json()`, `.iter_bytes()`. + + You can customise the type that the response is parsed into through + the `to` argument, e.g. + + ```py + from imagekit import BaseModel + + + class MyModel(BaseModel): + foo: str + + + obj = response.parse(to=MyModel) + print(obj.foo) + ``` + + We support parsing: + - `BaseModel` + - `dict` + - `list` + - `Union` + - `str` + - `httpx.Response` + """ + cache_key = to if to is not None else self._cast_to + cached = self._parsed_by_type.get(cache_key) + if cached is not None: + return cached # type: ignore[no-any-return] + + if not self._is_sse_stream: + await self.read() + + parsed = self._parse(to=to) + if is_given(self._options.post_parser): + parsed = self._options.post_parser(parsed) + + self._parsed_by_type[cache_key] = parsed + return parsed + + async def read(self) -> bytes: + """Read and return the binary response content.""" + try: + return await self.http_response.aread() + except httpx.StreamConsumed as exc: + # the default error raised by httpx isn't very + # helpful in our case so we re-raise it with + # a different error message + raise StreamAlreadyConsumed() from exc + + async def text(self) -> str: + """Read and decode the response content into a string.""" + await self.read() + return self.http_response.text + + async def json(self) -> object: + """Read and decode the JSON response content.""" + await self.read() + return self.http_response.json() + + async def close(self) -> None: + """Close the response and release the connection. + + Automatically called if the response body is read to completion. + """ + await self.http_response.aclose() + + async def iter_bytes(self, chunk_size: int | None = None) -> AsyncIterator[bytes]: + """ + A byte-iterator over the decoded response content. + + This automatically handles gzip, deflate and brotli encoded responses. + """ + async for chunk in self.http_response.aiter_bytes(chunk_size): + yield chunk + + async def iter_text(self, chunk_size: int | None = None) -> AsyncIterator[str]: + """A str-iterator over the decoded response content + that handles both gzip, deflate, etc but also detects the content's + string encoding. + """ + async for chunk in self.http_response.aiter_text(chunk_size): + yield chunk + + async def iter_lines(self) -> AsyncIterator[str]: + """Like `iter_text()` but will only yield chunks for each line""" + async for chunk in self.http_response.aiter_lines(): + yield chunk + + +class BinaryAPIResponse(APIResponse[bytes]): + """Subclass of APIResponse providing helpers for dealing with binary data. + + Note: If you want to stream the response data instead of eagerly reading it + all at once then you should use `.with_streaming_response` when making + the API request, e.g. `.with_streaming_response.get_binary_response()` + """ + + def write_to_file( + self, + file: str | os.PathLike[str], + ) -> None: + """Write the output to the given file. + + Accepts a filename or any path-like object, e.g. pathlib.Path + + Note: if you want to stream the data to the file instead of writing + all at once then you should use `.with_streaming_response` when making + the API request, e.g. `.with_streaming_response.get_binary_response()` + """ + with open(file, mode="wb") as f: + for data in self.iter_bytes(): + f.write(data) + + +class AsyncBinaryAPIResponse(AsyncAPIResponse[bytes]): + """Subclass of APIResponse providing helpers for dealing with binary data. + + Note: If you want to stream the response data instead of eagerly reading it + all at once then you should use `.with_streaming_response` when making + the API request, e.g. `.with_streaming_response.get_binary_response()` + """ + + async def write_to_file( + self, + file: str | os.PathLike[str], + ) -> None: + """Write the output to the given file. + + Accepts a filename or any path-like object, e.g. pathlib.Path + + Note: if you want to stream the data to the file instead of writing + all at once then you should use `.with_streaming_response` when making + the API request, e.g. `.with_streaming_response.get_binary_response()` + """ + path = anyio.Path(file) + async with await path.open(mode="wb") as f: + async for data in self.iter_bytes(): + await f.write(data) + + +class StreamedBinaryAPIResponse(APIResponse[bytes]): + def stream_to_file( + self, + file: str | os.PathLike[str], + *, + chunk_size: int | None = None, + ) -> None: + """Streams the output to the given file. + + Accepts a filename or any path-like object, e.g. pathlib.Path + """ + with open(file, mode="wb") as f: + for data in self.iter_bytes(chunk_size): + f.write(data) + + +class AsyncStreamedBinaryAPIResponse(AsyncAPIResponse[bytes]): + async def stream_to_file( + self, + file: str | os.PathLike[str], + *, + chunk_size: int | None = None, + ) -> None: + """Streams the output to the given file. + + Accepts a filename or any path-like object, e.g. pathlib.Path + """ + path = anyio.Path(file) + async with await path.open(mode="wb") as f: + async for data in self.iter_bytes(chunk_size): + await f.write(data) + + +class MissingStreamClassError(TypeError): + def __init__(self) -> None: + super().__init__( + "The `stream` argument was set to `True` but the `stream_cls` argument was not given. See `imagekit._streaming` for reference", + ) + + +class StreamAlreadyConsumed(ImageKitError): + """ + Attempted to read or stream content, but the content has already + been streamed. + + This can happen if you use a method like `.iter_lines()` and then attempt + to read th entire response body afterwards, e.g. + + ```py + response = await client.post(...) + async for line in response.iter_lines(): + ... # do something with `line` + + content = await response.read() + # ^ error + ``` + + If you want this behaviour you'll need to either manually accumulate the response + content or call `await response.read()` before iterating over the stream. + """ + + def __init__(self) -> None: + message = ( + "Attempted to read or stream some content, but the content has " + "already been streamed. " + "This could be due to attempting to stream the response " + "content more than once." + "\n\n" + "You can fix this by manually accumulating the response content while streaming " + "or by calling `.read()` before starting to stream." + ) + super().__init__(message) + + +class ResponseContextManager(Generic[_APIResponseT]): + """Context manager for ensuring that a request is not made + until it is entered and that the response will always be closed + when the context manager exits + """ + + def __init__(self, request_func: Callable[[], _APIResponseT]) -> None: + self._request_func = request_func + self.__response: _APIResponseT | None = None + + def __enter__(self) -> _APIResponseT: + self.__response = self._request_func() + return self.__response + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + if self.__response is not None: + self.__response.close() + + +class AsyncResponseContextManager(Generic[_AsyncAPIResponseT]): + """Context manager for ensuring that a request is not made + until it is entered and that the response will always be closed + when the context manager exits + """ + + def __init__(self, api_request: Awaitable[_AsyncAPIResponseT]) -> None: + self._api_request = api_request + self.__response: _AsyncAPIResponseT | None = None + + async def __aenter__(self) -> _AsyncAPIResponseT: + self.__response = await self._api_request + return self.__response + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + if self.__response is not None: + await self.__response.close() + + +def to_streamed_response_wrapper(func: Callable[P, R]) -> Callable[P, ResponseContextManager[APIResponse[R]]]: + """Higher order function that takes one of our bound API methods and wraps it + to support streaming and returning the raw `APIResponse` object directly. + """ + + @functools.wraps(func) + def wrapped(*args: P.args, **kwargs: P.kwargs) -> ResponseContextManager[APIResponse[R]]: + extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})} + extra_headers[RAW_RESPONSE_HEADER] = "stream" + + kwargs["extra_headers"] = extra_headers + + make_request = functools.partial(func, *args, **kwargs) + + return ResponseContextManager(cast(Callable[[], APIResponse[R]], make_request)) + + return wrapped + + +def async_to_streamed_response_wrapper( + func: Callable[P, Awaitable[R]], +) -> Callable[P, AsyncResponseContextManager[AsyncAPIResponse[R]]]: + """Higher order function that takes one of our bound API methods and wraps it + to support streaming and returning the raw `APIResponse` object directly. + """ + + @functools.wraps(func) + def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncResponseContextManager[AsyncAPIResponse[R]]: + extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})} + extra_headers[RAW_RESPONSE_HEADER] = "stream" + + kwargs["extra_headers"] = extra_headers + + make_request = func(*args, **kwargs) + + return AsyncResponseContextManager(cast(Awaitable[AsyncAPIResponse[R]], make_request)) + + return wrapped + + +def to_custom_streamed_response_wrapper( + func: Callable[P, object], + response_cls: type[_APIResponseT], +) -> Callable[P, ResponseContextManager[_APIResponseT]]: + """Higher order function that takes one of our bound API methods and an `APIResponse` class + and wraps the method to support streaming and returning the given response class directly. + + Note: the given `response_cls` *must* be concrete, e.g. `class BinaryAPIResponse(APIResponse[bytes])` + """ + + @functools.wraps(func) + def wrapped(*args: P.args, **kwargs: P.kwargs) -> ResponseContextManager[_APIResponseT]: + extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})} + extra_headers[RAW_RESPONSE_HEADER] = "stream" + extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls + + kwargs["extra_headers"] = extra_headers + + make_request = functools.partial(func, *args, **kwargs) + + return ResponseContextManager(cast(Callable[[], _APIResponseT], make_request)) + + return wrapped + + +def async_to_custom_streamed_response_wrapper( + func: Callable[P, Awaitable[object]], + response_cls: type[_AsyncAPIResponseT], +) -> Callable[P, AsyncResponseContextManager[_AsyncAPIResponseT]]: + """Higher order function that takes one of our bound API methods and an `APIResponse` class + and wraps the method to support streaming and returning the given response class directly. + + Note: the given `response_cls` *must* be concrete, e.g. `class BinaryAPIResponse(APIResponse[bytes])` + """ + + @functools.wraps(func) + def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncResponseContextManager[_AsyncAPIResponseT]: + extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})} + extra_headers[RAW_RESPONSE_HEADER] = "stream" + extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls + + kwargs["extra_headers"] = extra_headers + + make_request = func(*args, **kwargs) + + return AsyncResponseContextManager(cast(Awaitable[_AsyncAPIResponseT], make_request)) + + return wrapped + + +def to_raw_response_wrapper(func: Callable[P, R]) -> Callable[P, APIResponse[R]]: + """Higher order function that takes one of our bound API methods and wraps it + to support returning the raw `APIResponse` object directly. + """ + + @functools.wraps(func) + def wrapped(*args: P.args, **kwargs: P.kwargs) -> APIResponse[R]: + extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})} + extra_headers[RAW_RESPONSE_HEADER] = "raw" + + kwargs["extra_headers"] = extra_headers + + return cast(APIResponse[R], func(*args, **kwargs)) + + return wrapped + + +def async_to_raw_response_wrapper(func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[AsyncAPIResponse[R]]]: + """Higher order function that takes one of our bound API methods and wraps it + to support returning the raw `APIResponse` object directly. + """ + + @functools.wraps(func) + async def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncAPIResponse[R]: + extra_headers: dict[str, str] = {**(cast(Any, kwargs.get("extra_headers")) or {})} + extra_headers[RAW_RESPONSE_HEADER] = "raw" + + kwargs["extra_headers"] = extra_headers + + return cast(AsyncAPIResponse[R], await func(*args, **kwargs)) + + return wrapped + + +def to_custom_raw_response_wrapper( + func: Callable[P, object], + response_cls: type[_APIResponseT], +) -> Callable[P, _APIResponseT]: + """Higher order function that takes one of our bound API methods and an `APIResponse` class + and wraps the method to support returning the given response class directly. + + Note: the given `response_cls` *must* be concrete, e.g. `class BinaryAPIResponse(APIResponse[bytes])` + """ + + @functools.wraps(func) + def wrapped(*args: P.args, **kwargs: P.kwargs) -> _APIResponseT: + extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})} + extra_headers[RAW_RESPONSE_HEADER] = "raw" + extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls + + kwargs["extra_headers"] = extra_headers + + return cast(_APIResponseT, func(*args, **kwargs)) + + return wrapped + + +def async_to_custom_raw_response_wrapper( + func: Callable[P, Awaitable[object]], + response_cls: type[_AsyncAPIResponseT], +) -> Callable[P, Awaitable[_AsyncAPIResponseT]]: + """Higher order function that takes one of our bound API methods and an `APIResponse` class + and wraps the method to support returning the given response class directly. + + Note: the given `response_cls` *must* be concrete, e.g. `class BinaryAPIResponse(APIResponse[bytes])` + """ + + @functools.wraps(func) + def wrapped(*args: P.args, **kwargs: P.kwargs) -> Awaitable[_AsyncAPIResponseT]: + extra_headers: dict[str, Any] = {**(cast(Any, kwargs.get("extra_headers")) or {})} + extra_headers[RAW_RESPONSE_HEADER] = "raw" + extra_headers[OVERRIDE_CAST_TO_HEADER] = response_cls + + kwargs["extra_headers"] = extra_headers + + return cast(Awaitable[_AsyncAPIResponseT], func(*args, **kwargs)) + + return wrapped + + +def extract_response_type(typ: type[BaseAPIResponse[Any]]) -> type: + """Given a type like `APIResponse[T]`, returns the generic type variable `T`. + + This also handles the case where a concrete subclass is given, e.g. + ```py + class MyResponse(APIResponse[bytes]): + ... + + extract_response_type(MyResponse) -> bytes + ``` + """ + return extract_type_var_from_base( + typ, + generic_bases=cast("tuple[type, ...]", (BaseAPIResponse, APIResponse, AsyncAPIResponse)), + index=0, + ) diff --git a/src/imagekit/_streaming.py b/src/imagekit/_streaming.py new file mode 100644 index 0000000..7fadf2a --- /dev/null +++ b/src/imagekit/_streaming.py @@ -0,0 +1,333 @@ +# Note: initially copied from https://github.com/florimondmanca/httpx-sse/blob/master/src/httpx_sse/_decoders.py +from __future__ import annotations + +import json +import inspect +from types import TracebackType +from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, AsyncIterator, cast +from typing_extensions import Self, Protocol, TypeGuard, override, get_origin, runtime_checkable + +import httpx + +from ._utils import extract_type_var_from_base + +if TYPE_CHECKING: + from ._client import ImageKit, AsyncImageKit + + +_T = TypeVar("_T") + + +class Stream(Generic[_T]): + """Provides the core interface to iterate over a synchronous stream response.""" + + response: httpx.Response + + _decoder: SSEBytesDecoder + + def __init__( + self, + *, + cast_to: type[_T], + response: httpx.Response, + client: ImageKit, + ) -> None: + self.response = response + self._cast_to = cast_to + self._client = client + self._decoder = client._make_sse_decoder() + self._iterator = self.__stream__() + + def __next__(self) -> _T: + return self._iterator.__next__() + + def __iter__(self) -> Iterator[_T]: + for item in self._iterator: + yield item + + def _iter_events(self) -> Iterator[ServerSentEvent]: + yield from self._decoder.iter_bytes(self.response.iter_bytes()) + + def __stream__(self) -> Iterator[_T]: + cast_to = cast(Any, self._cast_to) + response = self.response + process_data = self._client._process_response_data + iterator = self._iter_events() + + for sse in iterator: + yield process_data(data=sse.json(), cast_to=cast_to, response=response) + + # Ensure the entire stream is consumed + for _sse in iterator: + ... + + def __enter__(self) -> Self: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.close() + + def close(self) -> None: + """ + Close the response and release the connection. + + Automatically called if the response body is read to completion. + """ + self.response.close() + + +class AsyncStream(Generic[_T]): + """Provides the core interface to iterate over an asynchronous stream response.""" + + response: httpx.Response + + _decoder: SSEDecoder | SSEBytesDecoder + + def __init__( + self, + *, + cast_to: type[_T], + response: httpx.Response, + client: AsyncImageKit, + ) -> None: + self.response = response + self._cast_to = cast_to + self._client = client + self._decoder = client._make_sse_decoder() + self._iterator = self.__stream__() + + async def __anext__(self) -> _T: + return await self._iterator.__anext__() + + async def __aiter__(self) -> AsyncIterator[_T]: + async for item in self._iterator: + yield item + + async def _iter_events(self) -> AsyncIterator[ServerSentEvent]: + async for sse in self._decoder.aiter_bytes(self.response.aiter_bytes()): + yield sse + + async def __stream__(self) -> AsyncIterator[_T]: + cast_to = cast(Any, self._cast_to) + response = self.response + process_data = self._client._process_response_data + iterator = self._iter_events() + + async for sse in iterator: + yield process_data(data=sse.json(), cast_to=cast_to, response=response) + + # Ensure the entire stream is consumed + async for _sse in iterator: + ... + + async def __aenter__(self) -> Self: + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + await self.close() + + async def close(self) -> None: + """ + Close the response and release the connection. + + Automatically called if the response body is read to completion. + """ + await self.response.aclose() + + +class ServerSentEvent: + def __init__( + self, + *, + event: str | None = None, + data: str | None = None, + id: str | None = None, + retry: int | None = None, + ) -> None: + if data is None: + data = "" + + self._id = id + self._data = data + self._event = event or None + self._retry = retry + + @property + def event(self) -> str | None: + return self._event + + @property + def id(self) -> str | None: + return self._id + + @property + def retry(self) -> int | None: + return self._retry + + @property + def data(self) -> str: + return self._data + + def json(self) -> Any: + return json.loads(self.data) + + @override + def __repr__(self) -> str: + return f"ServerSentEvent(event={self.event}, data={self.data}, id={self.id}, retry={self.retry})" + + +class SSEDecoder: + _data: list[str] + _event: str | None + _retry: int | None + _last_event_id: str | None + + def __init__(self) -> None: + self._event = None + self._data = [] + self._last_event_id = None + self._retry = None + + def iter_bytes(self, iterator: Iterator[bytes]) -> Iterator[ServerSentEvent]: + """Given an iterator that yields raw binary data, iterate over it & yield every event encountered""" + for chunk in self._iter_chunks(iterator): + # Split before decoding so splitlines() only uses \r and \n + for raw_line in chunk.splitlines(): + line = raw_line.decode("utf-8") + sse = self.decode(line) + if sse: + yield sse + + def _iter_chunks(self, iterator: Iterator[bytes]) -> Iterator[bytes]: + """Given an iterator that yields raw binary data, iterate over it and yield individual SSE chunks""" + data = b"" + for chunk in iterator: + for line in chunk.splitlines(keepends=True): + data += line + if data.endswith((b"\r\r", b"\n\n", b"\r\n\r\n")): + yield data + data = b"" + if data: + yield data + + async def aiter_bytes(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[ServerSentEvent]: + """Given an iterator that yields raw binary data, iterate over it & yield every event encountered""" + async for chunk in self._aiter_chunks(iterator): + # Split before decoding so splitlines() only uses \r and \n + for raw_line in chunk.splitlines(): + line = raw_line.decode("utf-8") + sse = self.decode(line) + if sse: + yield sse + + async def _aiter_chunks(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[bytes]: + """Given an iterator that yields raw binary data, iterate over it and yield individual SSE chunks""" + data = b"" + async for chunk in iterator: + for line in chunk.splitlines(keepends=True): + data += line + if data.endswith((b"\r\r", b"\n\n", b"\r\n\r\n")): + yield data + data = b"" + if data: + yield data + + def decode(self, line: str) -> ServerSentEvent | None: + # See: https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation # noqa: E501 + + if not line: + if not self._event and not self._data and not self._last_event_id and self._retry is None: + return None + + sse = ServerSentEvent( + event=self._event, + data="\n".join(self._data), + id=self._last_event_id, + retry=self._retry, + ) + + # NOTE: as per the SSE spec, do not reset last_event_id. + self._event = None + self._data = [] + self._retry = None + + return sse + + if line.startswith(":"): + return None + + fieldname, _, value = line.partition(":") + + if value.startswith(" "): + value = value[1:] + + if fieldname == "event": + self._event = value + elif fieldname == "data": + self._data.append(value) + elif fieldname == "id": + if "\0" in value: + pass + else: + self._last_event_id = value + elif fieldname == "retry": + try: + self._retry = int(value) + except (TypeError, ValueError): + pass + else: + pass # Field is ignored. + + return None + + +@runtime_checkable +class SSEBytesDecoder(Protocol): + def iter_bytes(self, iterator: Iterator[bytes]) -> Iterator[ServerSentEvent]: + """Given an iterator that yields raw binary data, iterate over it & yield every event encountered""" + ... + + def aiter_bytes(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[ServerSentEvent]: + """Given an async iterator that yields raw binary data, iterate over it & yield every event encountered""" + ... + + +def is_stream_class_type(typ: type) -> TypeGuard[type[Stream[object]] | type[AsyncStream[object]]]: + """TypeGuard for determining whether or not the given type is a subclass of `Stream` / `AsyncStream`""" + origin = get_origin(typ) or typ + return inspect.isclass(origin) and issubclass(origin, (Stream, AsyncStream)) + + +def extract_stream_chunk_type( + stream_cls: type, + *, + failure_message: str | None = None, +) -> type: + """Given a type like `Stream[T]`, returns the generic type variable `T`. + + This also handles the case where a concrete subclass is given, e.g. + ```py + class MyStream(Stream[bytes]): + ... + + extract_stream_chunk_type(MyStream) -> bytes + ``` + """ + from ._base_client import Stream, AsyncStream + + return extract_type_var_from_base( + stream_cls, + index=0, + generic_bases=cast("tuple[type, ...]", (Stream, AsyncStream)), + failure_message=failure_message, + ) diff --git a/src/imagekit/_types.py b/src/imagekit/_types.py new file mode 100644 index 0000000..1a4bc72 --- /dev/null +++ b/src/imagekit/_types.py @@ -0,0 +1,219 @@ +from __future__ import annotations + +from os import PathLike +from typing import ( + IO, + TYPE_CHECKING, + Any, + Dict, + List, + Type, + Tuple, + Union, + Mapping, + TypeVar, + Callable, + Optional, + Sequence, +) +from typing_extensions import Set, Literal, Protocol, TypeAlias, TypedDict, override, runtime_checkable + +import httpx +import pydantic +from httpx import URL, Proxy, Timeout, Response, BaseTransport, AsyncBaseTransport + +if TYPE_CHECKING: + from ._models import BaseModel + from ._response import APIResponse, AsyncAPIResponse + +Transport = BaseTransport +AsyncTransport = AsyncBaseTransport +Query = Mapping[str, object] +Body = object +AnyMapping = Mapping[str, object] +ModelT = TypeVar("ModelT", bound=pydantic.BaseModel) +_T = TypeVar("_T") + + +# Approximates httpx internal ProxiesTypes and RequestFiles types +# while adding support for `PathLike` instances +ProxiesDict = Dict["str | URL", Union[None, str, URL, Proxy]] +ProxiesTypes = Union[str, Proxy, ProxiesDict] +if TYPE_CHECKING: + Base64FileInput = Union[IO[bytes], PathLike[str]] + FileContent = Union[IO[bytes], bytes, PathLike[str]] +else: + Base64FileInput = Union[IO[bytes], PathLike] + FileContent = Union[IO[bytes], bytes, PathLike] # PathLike is not subscriptable in Python 3.8. +FileTypes = Union[ + # file (or bytes) + FileContent, + # (filename, file (or bytes)) + Tuple[Optional[str], FileContent], + # (filename, file (or bytes), content_type) + Tuple[Optional[str], FileContent, Optional[str]], + # (filename, file (or bytes), content_type, headers) + Tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]], +] +RequestFiles = Union[Mapping[str, FileTypes], Sequence[Tuple[str, FileTypes]]] + +# duplicate of the above but without our custom file support +HttpxFileContent = Union[IO[bytes], bytes] +HttpxFileTypes = Union[ + # file (or bytes) + HttpxFileContent, + # (filename, file (or bytes)) + Tuple[Optional[str], HttpxFileContent], + # (filename, file (or bytes), content_type) + Tuple[Optional[str], HttpxFileContent, Optional[str]], + # (filename, file (or bytes), content_type, headers) + Tuple[Optional[str], HttpxFileContent, Optional[str], Mapping[str, str]], +] +HttpxRequestFiles = Union[Mapping[str, HttpxFileTypes], Sequence[Tuple[str, HttpxFileTypes]]] + +# Workaround to support (cast_to: Type[ResponseT]) -> ResponseT +# where ResponseT includes `None`. In order to support directly +# passing `None`, overloads would have to be defined for every +# method that uses `ResponseT` which would lead to an unacceptable +# amount of code duplication and make it unreadable. See _base_client.py +# for example usage. +# +# This unfortunately means that you will either have +# to import this type and pass it explicitly: +# +# from imagekit import NoneType +# client.get('/foo', cast_to=NoneType) +# +# or build it yourself: +# +# client.get('/foo', cast_to=type(None)) +if TYPE_CHECKING: + NoneType: Type[None] +else: + NoneType = type(None) + + +class RequestOptions(TypedDict, total=False): + headers: Headers + max_retries: int + timeout: float | Timeout | None + params: Query + extra_json: AnyMapping + idempotency_key: str + follow_redirects: bool + + +# Sentinel class used until PEP 0661 is accepted +class NotGiven: + """ + A sentinel singleton class used to distinguish omitted keyword arguments + from those passed in with the value None (which may have different behavior). + + For example: + + ```py + def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response: ... + + + get(timeout=1) # 1s timeout + get(timeout=None) # No timeout + get() # Default timeout behavior, which may not be statically known at the method definition. + ``` + """ + + def __bool__(self) -> Literal[False]: + return False + + @override + def __repr__(self) -> str: + return "NOT_GIVEN" + + +NotGivenOr = Union[_T, NotGiven] +NOT_GIVEN = NotGiven() + + +class Omit: + """In certain situations you need to be able to represent a case where a default value has + to be explicitly removed and `None` is not an appropriate substitute, for example: + + ```py + # as the default `Content-Type` header is `application/json` that will be sent + client.post("/upload/files", files={"file": b"my raw file content"}) + + # you can't explicitly override the header as it has to be dynamically generated + # to look something like: 'multipart/form-data; boundary=0d8382fcf5f8c3be01ca2e11002d2983' + client.post(..., headers={"Content-Type": "multipart/form-data"}) + + # instead you can remove the default `application/json` header by passing Omit + client.post(..., headers={"Content-Type": Omit()}) + ``` + """ + + def __bool__(self) -> Literal[False]: + return False + + +@runtime_checkable +class ModelBuilderProtocol(Protocol): + @classmethod + def build( + cls: type[_T], + *, + response: Response, + data: object, + ) -> _T: ... + + +Headers = Mapping[str, Union[str, Omit]] + + +class HeadersLikeProtocol(Protocol): + def get(self, __key: str) -> str | None: ... + + +HeadersLike = Union[Headers, HeadersLikeProtocol] + +ResponseT = TypeVar( + "ResponseT", + bound=Union[ + object, + str, + None, + "BaseModel", + List[Any], + Dict[str, Any], + Response, + ModelBuilderProtocol, + "APIResponse[Any]", + "AsyncAPIResponse[Any]", + ], +) + +StrBytesIntFloat = Union[str, bytes, int, float] + +# Note: copied from Pydantic +# https://github.com/pydantic/pydantic/blob/6f31f8f68ef011f84357330186f603ff295312fd/pydantic/main.py#L79 +IncEx: TypeAlias = Union[Set[int], Set[str], Mapping[int, Union["IncEx", bool]], Mapping[str, Union["IncEx", bool]]] + +PostParser = Callable[[Any], Any] + + +@runtime_checkable +class InheritsGeneric(Protocol): + """Represents a type that has inherited from `Generic` + + The `__orig_bases__` property can be used to determine the resolved + type variable for a given base class. + """ + + __orig_bases__: tuple[_GenericAlias] + + +class _GenericAlias(Protocol): + __origin__: type[object] + + +class HttpxSendArgs(TypedDict, total=False): + auth: httpx.Auth + follow_redirects: bool diff --git a/src/imagekit/_utils/__init__.py b/src/imagekit/_utils/__init__.py new file mode 100644 index 0000000..d4fda26 --- /dev/null +++ b/src/imagekit/_utils/__init__.py @@ -0,0 +1,57 @@ +from ._sync import asyncify as asyncify +from ._proxy import LazyProxy as LazyProxy +from ._utils import ( + flatten as flatten, + is_dict as is_dict, + is_list as is_list, + is_given as is_given, + is_tuple as is_tuple, + json_safe as json_safe, + lru_cache as lru_cache, + is_mapping as is_mapping, + is_tuple_t as is_tuple_t, + parse_date as parse_date, + is_iterable as is_iterable, + is_sequence as is_sequence, + coerce_float as coerce_float, + is_mapping_t as is_mapping_t, + removeprefix as removeprefix, + removesuffix as removesuffix, + extract_files as extract_files, + is_sequence_t as is_sequence_t, + required_args as required_args, + coerce_boolean as coerce_boolean, + coerce_integer as coerce_integer, + file_from_path as file_from_path, + parse_datetime as parse_datetime, + strip_not_given as strip_not_given, + deepcopy_minimal as deepcopy_minimal, + get_async_library as get_async_library, + maybe_coerce_float as maybe_coerce_float, + get_required_header as get_required_header, + maybe_coerce_boolean as maybe_coerce_boolean, + maybe_coerce_integer as maybe_coerce_integer, +) +from ._typing import ( + is_list_type as is_list_type, + is_union_type as is_union_type, + extract_type_arg as extract_type_arg, + is_iterable_type as is_iterable_type, + is_required_type as is_required_type, + is_annotated_type as is_annotated_type, + is_type_alias_type as is_type_alias_type, + strip_annotated_type as strip_annotated_type, + extract_type_var_from_base as extract_type_var_from_base, +) +from ._streams import consume_sync_iterator as consume_sync_iterator, consume_async_iterator as consume_async_iterator +from ._transform import ( + PropertyInfo as PropertyInfo, + transform as transform, + async_transform as async_transform, + maybe_transform as maybe_transform, + async_maybe_transform as async_maybe_transform, +) +from ._reflection import ( + function_has_argument as function_has_argument, + assert_signatures_in_sync as assert_signatures_in_sync, +) diff --git a/src/imagekit/_utils/_logs.py b/src/imagekit/_utils/_logs.py new file mode 100644 index 0000000..f896bb6 --- /dev/null +++ b/src/imagekit/_utils/_logs.py @@ -0,0 +1,25 @@ +import os +import logging + +logger: logging.Logger = logging.getLogger("imagekit") +httpx_logger: logging.Logger = logging.getLogger("httpx") + + +def _basic_config() -> None: + # e.g. [2023-10-05 14:12:26 - imagekit._base_client:818 - DEBUG] HTTP Request: POST http://127.0.0.1:4010/foo/bar "200 OK" + logging.basicConfig( + format="[%(asctime)s - %(name)s:%(lineno)d - %(levelname)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + + +def setup_logging() -> None: + env = os.environ.get("IMAGE_KIT_LOG") + if env == "debug": + _basic_config() + logger.setLevel(logging.DEBUG) + httpx_logger.setLevel(logging.DEBUG) + elif env == "info": + _basic_config() + logger.setLevel(logging.INFO) + httpx_logger.setLevel(logging.INFO) diff --git a/src/imagekit/_utils/_proxy.py b/src/imagekit/_utils/_proxy.py new file mode 100644 index 0000000..0f239a3 --- /dev/null +++ b/src/imagekit/_utils/_proxy.py @@ -0,0 +1,65 @@ +from __future__ import annotations + +from abc import ABC, abstractmethod +from typing import Generic, TypeVar, Iterable, cast +from typing_extensions import override + +T = TypeVar("T") + + +class LazyProxy(Generic[T], ABC): + """Implements data methods to pretend that an instance is another instance. + + This includes forwarding attribute access and other methods. + """ + + # Note: we have to special case proxies that themselves return proxies + # to support using a proxy as a catch-all for any random access, e.g. `proxy.foo.bar.baz` + + def __getattr__(self, attr: str) -> object: + proxied = self.__get_proxied__() + if isinstance(proxied, LazyProxy): + return proxied # pyright: ignore + return getattr(proxied, attr) + + @override + def __repr__(self) -> str: + proxied = self.__get_proxied__() + if isinstance(proxied, LazyProxy): + return proxied.__class__.__name__ + return repr(self.__get_proxied__()) + + @override + def __str__(self) -> str: + proxied = self.__get_proxied__() + if isinstance(proxied, LazyProxy): + return proxied.__class__.__name__ + return str(proxied) + + @override + def __dir__(self) -> Iterable[str]: + proxied = self.__get_proxied__() + if isinstance(proxied, LazyProxy): + return [] + return proxied.__dir__() + + @property # type: ignore + @override + def __class__(self) -> type: # pyright: ignore + try: + proxied = self.__get_proxied__() + except Exception: + return type(self) + if issubclass(type(proxied), LazyProxy): + return type(proxied) + return proxied.__class__ + + def __get_proxied__(self) -> T: + return self.__load__() + + def __as_proxied__(self) -> T: + """Helper method that returns the current proxy, typed as the loaded object""" + return cast(T, self) + + @abstractmethod + def __load__(self) -> T: ... diff --git a/src/imagekit/_utils/_reflection.py b/src/imagekit/_utils/_reflection.py new file mode 100644 index 0000000..89aa712 --- /dev/null +++ b/src/imagekit/_utils/_reflection.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +import inspect +from typing import Any, Callable + + +def function_has_argument(func: Callable[..., Any], arg_name: str) -> bool: + """Returns whether or not the given function has a specific parameter""" + sig = inspect.signature(func) + return arg_name in sig.parameters + + +def assert_signatures_in_sync( + source_func: Callable[..., Any], + check_func: Callable[..., Any], + *, + exclude_params: set[str] = set(), +) -> None: + """Ensure that the signature of the second function matches the first.""" + + check_sig = inspect.signature(check_func) + source_sig = inspect.signature(source_func) + + errors: list[str] = [] + + for name, source_param in source_sig.parameters.items(): + if name in exclude_params: + continue + + custom_param = check_sig.parameters.get(name) + if not custom_param: + errors.append(f"the `{name}` param is missing") + continue + + if custom_param.annotation != source_param.annotation: + errors.append( + f"types for the `{name}` param are do not match; source={repr(source_param.annotation)} checking={repr(custom_param.annotation)}" + ) + continue + + if errors: + raise AssertionError(f"{len(errors)} errors encountered when comparing signatures:\n\n" + "\n\n".join(errors)) diff --git a/src/imagekit/_utils/_resources_proxy.py b/src/imagekit/_utils/_resources_proxy.py new file mode 100644 index 0000000..6421783 --- /dev/null +++ b/src/imagekit/_utils/_resources_proxy.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +from typing import Any +from typing_extensions import override + +from ._proxy import LazyProxy + + +class ResourcesProxy(LazyProxy[Any]): + """A proxy for the `imagekit.resources` module. + + This is used so that we can lazily import `imagekit.resources` only when + needed *and* so that users can just import `imagekit` and reference `imagekit.resources` + """ + + @override + def __load__(self) -> Any: + import importlib + + mod = importlib.import_module("imagekit.resources") + return mod + + +resources = ResourcesProxy().__as_proxied__() diff --git a/src/imagekit/_utils/_streams.py b/src/imagekit/_utils/_streams.py new file mode 100644 index 0000000..f4a0208 --- /dev/null +++ b/src/imagekit/_utils/_streams.py @@ -0,0 +1,12 @@ +from typing import Any +from typing_extensions import Iterator, AsyncIterator + + +def consume_sync_iterator(iterator: Iterator[Any]) -> None: + for _ in iterator: + ... + + +async def consume_async_iterator(iterator: AsyncIterator[Any]) -> None: + async for _ in iterator: + ... diff --git a/src/imagekit/_utils/_sync.py b/src/imagekit/_utils/_sync.py new file mode 100644 index 0000000..ad7ec71 --- /dev/null +++ b/src/imagekit/_utils/_sync.py @@ -0,0 +1,86 @@ +from __future__ import annotations + +import sys +import asyncio +import functools +import contextvars +from typing import Any, TypeVar, Callable, Awaitable +from typing_extensions import ParamSpec + +import anyio +import sniffio +import anyio.to_thread + +T_Retval = TypeVar("T_Retval") +T_ParamSpec = ParamSpec("T_ParamSpec") + + +if sys.version_info >= (3, 9): + _asyncio_to_thread = asyncio.to_thread +else: + # backport of https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread + # for Python 3.8 support + async def _asyncio_to_thread( + func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs + ) -> Any: + """Asynchronously run function *func* in a separate thread. + + Any *args and **kwargs supplied for this function are directly passed + to *func*. Also, the current :class:`contextvars.Context` is propagated, + allowing context variables from the main thread to be accessed in the + separate thread. + + Returns a coroutine that can be awaited to get the eventual result of *func*. + """ + loop = asyncio.events.get_running_loop() + ctx = contextvars.copy_context() + func_call = functools.partial(ctx.run, func, *args, **kwargs) + return await loop.run_in_executor(None, func_call) + + +async def to_thread( + func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs +) -> T_Retval: + if sniffio.current_async_library() == "asyncio": + return await _asyncio_to_thread(func, *args, **kwargs) + + return await anyio.to_thread.run_sync( + functools.partial(func, *args, **kwargs), + ) + + +# inspired by `asyncer`, https://github.com/tiangolo/asyncer +def asyncify(function: Callable[T_ParamSpec, T_Retval]) -> Callable[T_ParamSpec, Awaitable[T_Retval]]: + """ + Take a blocking function and create an async one that receives the same + positional and keyword arguments. For python version 3.9 and above, it uses + asyncio.to_thread to run the function in a separate thread. For python version + 3.8, it uses locally defined copy of the asyncio.to_thread function which was + introduced in python 3.9. + + Usage: + + ```python + def blocking_func(arg1, arg2, kwarg1=None): + # blocking code + return result + + + result = asyncify(blocking_function)(arg1, arg2, kwarg1=value1) + ``` + + ## Arguments + + `function`: a blocking regular callable (e.g. a function) + + ## Return + + An async function that takes the same positional and keyword arguments as the + original one, that when called runs the same original function in a thread worker + and returns the result. + """ + + async def wrapper(*args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs) -> T_Retval: + return await to_thread(function, *args, **kwargs) + + return wrapper diff --git a/src/imagekit/_utils/_transform.py b/src/imagekit/_utils/_transform.py new file mode 100644 index 0000000..b0cc20a --- /dev/null +++ b/src/imagekit/_utils/_transform.py @@ -0,0 +1,447 @@ +from __future__ import annotations + +import io +import base64 +import pathlib +from typing import Any, Mapping, TypeVar, cast +from datetime import date, datetime +from typing_extensions import Literal, get_args, override, get_type_hints as _get_type_hints + +import anyio +import pydantic + +from ._utils import ( + is_list, + is_given, + lru_cache, + is_mapping, + is_iterable, +) +from .._files import is_base64_file_input +from ._typing import ( + is_list_type, + is_union_type, + extract_type_arg, + is_iterable_type, + is_required_type, + is_annotated_type, + strip_annotated_type, +) +from .._compat import get_origin, model_dump, is_typeddict + +_T = TypeVar("_T") + + +# TODO: support for drilling globals() and locals() +# TODO: ensure works correctly with forward references in all cases + + +PropertyFormat = Literal["iso8601", "base64", "custom"] + + +class PropertyInfo: + """Metadata class to be used in Annotated types to provide information about a given type. + + For example: + + class MyParams(TypedDict): + account_holder_name: Annotated[str, PropertyInfo(alias='accountHolderName')] + + This means that {'account_holder_name': 'Robert'} will be transformed to {'accountHolderName': 'Robert'} before being sent to the API. + """ + + alias: str | None + format: PropertyFormat | None + format_template: str | None + discriminator: str | None + + def __init__( + self, + *, + alias: str | None = None, + format: PropertyFormat | None = None, + format_template: str | None = None, + discriminator: str | None = None, + ) -> None: + self.alias = alias + self.format = format + self.format_template = format_template + self.discriminator = discriminator + + @override + def __repr__(self) -> str: + return f"{self.__class__.__name__}(alias='{self.alias}', format={self.format}, format_template='{self.format_template}', discriminator='{self.discriminator}')" + + +def maybe_transform( + data: object, + expected_type: object, +) -> Any | None: + """Wrapper over `transform()` that allows `None` to be passed. + + See `transform()` for more details. + """ + if data is None: + return None + return transform(data, expected_type) + + +# Wrapper over _transform_recursive providing fake types +def transform( + data: _T, + expected_type: object, +) -> _T: + """Transform dictionaries based off of type information from the given type, for example: + + ```py + class Params(TypedDict, total=False): + card_id: Required[Annotated[str, PropertyInfo(alias="cardID")]] + + + transformed = transform({"card_id": ""}, Params) + # {'cardID': ''} + ``` + + Any keys / data that does not have type information given will be included as is. + + It should be noted that the transformations that this function does are not represented in the type system. + """ + transformed = _transform_recursive(data, annotation=cast(type, expected_type)) + return cast(_T, transformed) + + +@lru_cache(maxsize=8096) +def _get_annotated_type(type_: type) -> type | None: + """If the given type is an `Annotated` type then it is returned, if not `None` is returned. + + This also unwraps the type when applicable, e.g. `Required[Annotated[T, ...]]` + """ + if is_required_type(type_): + # Unwrap `Required[Annotated[T, ...]]` to `Annotated[T, ...]` + type_ = get_args(type_)[0] + + if is_annotated_type(type_): + return type_ + + return None + + +def _maybe_transform_key(key: str, type_: type) -> str: + """Transform the given `data` based on the annotations provided in `type_`. + + Note: this function only looks at `Annotated` types that contain `PropertyInfo` metadata. + """ + annotated_type = _get_annotated_type(type_) + if annotated_type is None: + # no `Annotated` definition for this type, no transformation needed + return key + + # ignore the first argument as it is the actual type + annotations = get_args(annotated_type)[1:] + for annotation in annotations: + if isinstance(annotation, PropertyInfo) and annotation.alias is not None: + return annotation.alias + + return key + + +def _no_transform_needed(annotation: type) -> bool: + return annotation == float or annotation == int + + +def _transform_recursive( + data: object, + *, + annotation: type, + inner_type: type | None = None, +) -> object: + """Transform the given data against the expected type. + + Args: + annotation: The direct type annotation given to the particular piece of data. + This may or may not be wrapped in metadata types, e.g. `Required[T]`, `Annotated[T, ...]` etc + + inner_type: If applicable, this is the "inside" type. This is useful in certain cases where the outside type + is a container type such as `List[T]`. In that case `inner_type` should be set to `T` so that each entry in + the list can be transformed using the metadata from the container type. + + Defaults to the same value as the `annotation` argument. + """ + if inner_type is None: + inner_type = annotation + + stripped_type = strip_annotated_type(inner_type) + origin = get_origin(stripped_type) or stripped_type + if is_typeddict(stripped_type) and is_mapping(data): + return _transform_typeddict(data, stripped_type) + + if origin == dict and is_mapping(data): + items_type = get_args(stripped_type)[1] + return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} + + if ( + # List[T] + (is_list_type(stripped_type) and is_list(data)) + # Iterable[T] + or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str)) + ): + # dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually + # intended as an iterable, so we don't transform it. + if isinstance(data, dict): + return cast(object, data) + + inner_type = extract_type_arg(stripped_type, 0) + if _no_transform_needed(inner_type): + # for some types there is no need to transform anything, so we can get a small + # perf boost from skipping that work. + # + # but we still need to convert to a list to ensure the data is json-serializable + if is_list(data): + return data + return list(data) + + return [_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data] + + if is_union_type(stripped_type): + # For union types we run the transformation against all subtypes to ensure that everything is transformed. + # + # TODO: there may be edge cases where the same normalized field name will transform to two different names + # in different subtypes. + for subtype in get_args(stripped_type): + data = _transform_recursive(data, annotation=annotation, inner_type=subtype) + return data + + if isinstance(data, pydantic.BaseModel): + return model_dump(data, exclude_unset=True, mode="json") + + annotated_type = _get_annotated_type(annotation) + if annotated_type is None: + return data + + # ignore the first argument as it is the actual type + annotations = get_args(annotated_type)[1:] + for annotation in annotations: + if isinstance(annotation, PropertyInfo) and annotation.format is not None: + return _format_data(data, annotation.format, annotation.format_template) + + return data + + +def _format_data(data: object, format_: PropertyFormat, format_template: str | None) -> object: + if isinstance(data, (date, datetime)): + if format_ == "iso8601": + return data.isoformat() + + if format_ == "custom" and format_template is not None: + return data.strftime(format_template) + + if format_ == "base64" and is_base64_file_input(data): + binary: str | bytes | None = None + + if isinstance(data, pathlib.Path): + binary = data.read_bytes() + elif isinstance(data, io.IOBase): + binary = data.read() + + if isinstance(binary, str): # type: ignore[unreachable] + binary = binary.encode() + + if not isinstance(binary, bytes): + raise RuntimeError(f"Could not read bytes from {data}; Received {type(binary)}") + + return base64.b64encode(binary).decode("ascii") + + return data + + +def _transform_typeddict( + data: Mapping[str, object], + expected_type: type, +) -> Mapping[str, object]: + result: dict[str, object] = {} + annotations = get_type_hints(expected_type, include_extras=True) + for key, value in data.items(): + if not is_given(value): + # we don't need to include `NotGiven` values here as they'll + # be stripped out before the request is sent anyway + continue + + type_ = annotations.get(key) + if type_ is None: + # we do not have a type annotation for this field, leave it as is + result[key] = value + else: + result[_maybe_transform_key(key, type_)] = _transform_recursive(value, annotation=type_) + return result + + +async def async_maybe_transform( + data: object, + expected_type: object, +) -> Any | None: + """Wrapper over `async_transform()` that allows `None` to be passed. + + See `async_transform()` for more details. + """ + if data is None: + return None + return await async_transform(data, expected_type) + + +async def async_transform( + data: _T, + expected_type: object, +) -> _T: + """Transform dictionaries based off of type information from the given type, for example: + + ```py + class Params(TypedDict, total=False): + card_id: Required[Annotated[str, PropertyInfo(alias="cardID")]] + + + transformed = transform({"card_id": ""}, Params) + # {'cardID': ''} + ``` + + Any keys / data that does not have type information given will be included as is. + + It should be noted that the transformations that this function does are not represented in the type system. + """ + transformed = await _async_transform_recursive(data, annotation=cast(type, expected_type)) + return cast(_T, transformed) + + +async def _async_transform_recursive( + data: object, + *, + annotation: type, + inner_type: type | None = None, +) -> object: + """Transform the given data against the expected type. + + Args: + annotation: The direct type annotation given to the particular piece of data. + This may or may not be wrapped in metadata types, e.g. `Required[T]`, `Annotated[T, ...]` etc + + inner_type: If applicable, this is the "inside" type. This is useful in certain cases where the outside type + is a container type such as `List[T]`. In that case `inner_type` should be set to `T` so that each entry in + the list can be transformed using the metadata from the container type. + + Defaults to the same value as the `annotation` argument. + """ + if inner_type is None: + inner_type = annotation + + stripped_type = strip_annotated_type(inner_type) + origin = get_origin(stripped_type) or stripped_type + if is_typeddict(stripped_type) and is_mapping(data): + return await _async_transform_typeddict(data, stripped_type) + + if origin == dict and is_mapping(data): + items_type = get_args(stripped_type)[1] + return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} + + if ( + # List[T] + (is_list_type(stripped_type) and is_list(data)) + # Iterable[T] + or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str)) + ): + # dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually + # intended as an iterable, so we don't transform it. + if isinstance(data, dict): + return cast(object, data) + + inner_type = extract_type_arg(stripped_type, 0) + if _no_transform_needed(inner_type): + # for some types there is no need to transform anything, so we can get a small + # perf boost from skipping that work. + # + # but we still need to convert to a list to ensure the data is json-serializable + if is_list(data): + return data + return list(data) + + return [await _async_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data] + + if is_union_type(stripped_type): + # For union types we run the transformation against all subtypes to ensure that everything is transformed. + # + # TODO: there may be edge cases where the same normalized field name will transform to two different names + # in different subtypes. + for subtype in get_args(stripped_type): + data = await _async_transform_recursive(data, annotation=annotation, inner_type=subtype) + return data + + if isinstance(data, pydantic.BaseModel): + return model_dump(data, exclude_unset=True, mode="json") + + annotated_type = _get_annotated_type(annotation) + if annotated_type is None: + return data + + # ignore the first argument as it is the actual type + annotations = get_args(annotated_type)[1:] + for annotation in annotations: + if isinstance(annotation, PropertyInfo) and annotation.format is not None: + return await _async_format_data(data, annotation.format, annotation.format_template) + + return data + + +async def _async_format_data(data: object, format_: PropertyFormat, format_template: str | None) -> object: + if isinstance(data, (date, datetime)): + if format_ == "iso8601": + return data.isoformat() + + if format_ == "custom" and format_template is not None: + return data.strftime(format_template) + + if format_ == "base64" and is_base64_file_input(data): + binary: str | bytes | None = None + + if isinstance(data, pathlib.Path): + binary = await anyio.Path(data).read_bytes() + elif isinstance(data, io.IOBase): + binary = data.read() + + if isinstance(binary, str): # type: ignore[unreachable] + binary = binary.encode() + + if not isinstance(binary, bytes): + raise RuntimeError(f"Could not read bytes from {data}; Received {type(binary)}") + + return base64.b64encode(binary).decode("ascii") + + return data + + +async def _async_transform_typeddict( + data: Mapping[str, object], + expected_type: type, +) -> Mapping[str, object]: + result: dict[str, object] = {} + annotations = get_type_hints(expected_type, include_extras=True) + for key, value in data.items(): + if not is_given(value): + # we don't need to include `NotGiven` values here as they'll + # be stripped out before the request is sent anyway + continue + + type_ = annotations.get(key) + if type_ is None: + # we do not have a type annotation for this field, leave it as is + result[key] = value + else: + result[_maybe_transform_key(key, type_)] = await _async_transform_recursive(value, annotation=type_) + return result + + +@lru_cache(maxsize=8096) +def get_type_hints( + obj: Any, + globalns: dict[str, Any] | None = None, + localns: Mapping[str, Any] | None = None, + include_extras: bool = False, +) -> dict[str, Any]: + return _get_type_hints(obj, globalns=globalns, localns=localns, include_extras=include_extras) diff --git a/src/imagekit/_utils/_typing.py b/src/imagekit/_utils/_typing.py new file mode 100644 index 0000000..1bac954 --- /dev/null +++ b/src/imagekit/_utils/_typing.py @@ -0,0 +1,151 @@ +from __future__ import annotations + +import sys +import typing +import typing_extensions +from typing import Any, TypeVar, Iterable, cast +from collections import abc as _c_abc +from typing_extensions import ( + TypeIs, + Required, + Annotated, + get_args, + get_origin, +) + +from ._utils import lru_cache +from .._types import InheritsGeneric +from .._compat import is_union as _is_union + + +def is_annotated_type(typ: type) -> bool: + return get_origin(typ) == Annotated + + +def is_list_type(typ: type) -> bool: + return (get_origin(typ) or typ) == list + + +def is_iterable_type(typ: type) -> bool: + """If the given type is `typing.Iterable[T]`""" + origin = get_origin(typ) or typ + return origin == Iterable or origin == _c_abc.Iterable + + +def is_union_type(typ: type) -> bool: + return _is_union(get_origin(typ)) + + +def is_required_type(typ: type) -> bool: + return get_origin(typ) == Required + + +def is_typevar(typ: type) -> bool: + # type ignore is required because type checkers + # think this expression will always return False + return type(typ) == TypeVar # type: ignore + + +_TYPE_ALIAS_TYPES: tuple[type[typing_extensions.TypeAliasType], ...] = (typing_extensions.TypeAliasType,) +if sys.version_info >= (3, 12): + _TYPE_ALIAS_TYPES = (*_TYPE_ALIAS_TYPES, typing.TypeAliasType) + + +def is_type_alias_type(tp: Any, /) -> TypeIs[typing_extensions.TypeAliasType]: + """Return whether the provided argument is an instance of `TypeAliasType`. + + ```python + type Int = int + is_type_alias_type(Int) + # > True + Str = TypeAliasType("Str", str) + is_type_alias_type(Str) + # > True + ``` + """ + return isinstance(tp, _TYPE_ALIAS_TYPES) + + +# Extracts T from Annotated[T, ...] or from Required[Annotated[T, ...]] +@lru_cache(maxsize=8096) +def strip_annotated_type(typ: type) -> type: + if is_required_type(typ) or is_annotated_type(typ): + return strip_annotated_type(cast(type, get_args(typ)[0])) + + return typ + + +def extract_type_arg(typ: type, index: int) -> type: + args = get_args(typ) + try: + return cast(type, args[index]) + except IndexError as err: + raise RuntimeError(f"Expected type {typ} to have a type argument at index {index} but it did not") from err + + +def extract_type_var_from_base( + typ: type, + *, + generic_bases: tuple[type, ...], + index: int, + failure_message: str | None = None, +) -> type: + """Given a type like `Foo[T]`, returns the generic type variable `T`. + + This also handles the case where a concrete subclass is given, e.g. + ```py + class MyResponse(Foo[bytes]): + ... + + extract_type_var(MyResponse, bases=(Foo,), index=0) -> bytes + ``` + + And where a generic subclass is given: + ```py + _T = TypeVar('_T') + class MyResponse(Foo[_T]): + ... + + extract_type_var(MyResponse[bytes], bases=(Foo,), index=0) -> bytes + ``` + """ + cls = cast(object, get_origin(typ) or typ) + if cls in generic_bases: # pyright: ignore[reportUnnecessaryContains] + # we're given the class directly + return extract_type_arg(typ, index) + + # if a subclass is given + # --- + # this is needed as __orig_bases__ is not present in the typeshed stubs + # because it is intended to be for internal use only, however there does + # not seem to be a way to resolve generic TypeVars for inherited subclasses + # without using it. + if isinstance(cls, InheritsGeneric): + target_base_class: Any | None = None + for base in cls.__orig_bases__: + if base.__origin__ in generic_bases: + target_base_class = base + break + + if target_base_class is None: + raise RuntimeError( + "Could not find the generic base class;\n" + "This should never happen;\n" + f"Does {cls} inherit from one of {generic_bases} ?" + ) + + extracted = extract_type_arg(target_base_class, index) + if is_typevar(extracted): + # If the extracted type argument is itself a type variable + # then that means the subclass itself is generic, so we have + # to resolve the type argument from the class itself, not + # the base class. + # + # Note: if there is more than 1 type argument, the subclass could + # change the ordering of the type arguments, this is not currently + # supported. + return extract_type_arg(typ, index) + + return extracted + + raise RuntimeError(failure_message or f"Could not resolve inner type variable at index {index} for {typ}") diff --git a/src/imagekit/_utils/_utils.py b/src/imagekit/_utils/_utils.py new file mode 100644 index 0000000..ea3cf3f --- /dev/null +++ b/src/imagekit/_utils/_utils.py @@ -0,0 +1,422 @@ +from __future__ import annotations + +import os +import re +import inspect +import functools +from typing import ( + Any, + Tuple, + Mapping, + TypeVar, + Callable, + Iterable, + Sequence, + cast, + overload, +) +from pathlib import Path +from datetime import date, datetime +from typing_extensions import TypeGuard + +import sniffio + +from .._types import NotGiven, FileTypes, NotGivenOr, HeadersLike +from .._compat import parse_date as parse_date, parse_datetime as parse_datetime + +_T = TypeVar("_T") +_TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) +_MappingT = TypeVar("_MappingT", bound=Mapping[str, object]) +_SequenceT = TypeVar("_SequenceT", bound=Sequence[object]) +CallableT = TypeVar("CallableT", bound=Callable[..., Any]) + + +def flatten(t: Iterable[Iterable[_T]]) -> list[_T]: + return [item for sublist in t for item in sublist] + + +def extract_files( + # TODO: this needs to take Dict but variance issues..... + # create protocol type ? + query: Mapping[str, object], + *, + paths: Sequence[Sequence[str]], +) -> list[tuple[str, FileTypes]]: + """Recursively extract files from the given dictionary based on specified paths. + + A path may look like this ['foo', 'files', '', 'data']. + + Note: this mutates the given dictionary. + """ + files: list[tuple[str, FileTypes]] = [] + for path in paths: + files.extend(_extract_items(query, path, index=0, flattened_key=None)) + return files + + +def _extract_items( + obj: object, + path: Sequence[str], + *, + index: int, + flattened_key: str | None, +) -> list[tuple[str, FileTypes]]: + try: + key = path[index] + except IndexError: + if isinstance(obj, NotGiven): + # no value was provided - we can safely ignore + return [] + + # cyclical import + from .._files import assert_is_file_content + + # We have exhausted the path, return the entry we found. + assert flattened_key is not None + + if is_list(obj): + files: list[tuple[str, FileTypes]] = [] + for entry in obj: + assert_is_file_content(entry, key=flattened_key + "[]" if flattened_key else "") + files.append((flattened_key + "[]", cast(FileTypes, entry))) + return files + + assert_is_file_content(obj, key=flattened_key) + return [(flattened_key, cast(FileTypes, obj))] + + index += 1 + if is_dict(obj): + try: + # We are at the last entry in the path so we must remove the field + if (len(path)) == index: + item = obj.pop(key) + else: + item = obj[key] + except KeyError: + # Key was not present in the dictionary, this is not indicative of an error + # as the given path may not point to a required field. We also do not want + # to enforce required fields as the API may differ from the spec in some cases. + return [] + if flattened_key is None: + flattened_key = key + else: + flattened_key += f"[{key}]" + return _extract_items( + item, + path, + index=index, + flattened_key=flattened_key, + ) + elif is_list(obj): + if key != "": + return [] + + return flatten( + [ + _extract_items( + item, + path, + index=index, + flattened_key=flattened_key + "[]" if flattened_key is not None else "[]", + ) + for item in obj + ] + ) + + # Something unexpected was passed, just ignore it. + return [] + + +def is_given(obj: NotGivenOr[_T]) -> TypeGuard[_T]: + return not isinstance(obj, NotGiven) + + +# Type safe methods for narrowing types with TypeVars. +# The default narrowing for isinstance(obj, dict) is dict[unknown, unknown], +# however this cause Pyright to rightfully report errors. As we know we don't +# care about the contained types we can safely use `object` in it's place. +# +# There are two separate functions defined, `is_*` and `is_*_t` for different use cases. +# `is_*` is for when you're dealing with an unknown input +# `is_*_t` is for when you're narrowing a known union type to a specific subset + + +def is_tuple(obj: object) -> TypeGuard[tuple[object, ...]]: + return isinstance(obj, tuple) + + +def is_tuple_t(obj: _TupleT | object) -> TypeGuard[_TupleT]: + return isinstance(obj, tuple) + + +def is_sequence(obj: object) -> TypeGuard[Sequence[object]]: + return isinstance(obj, Sequence) + + +def is_sequence_t(obj: _SequenceT | object) -> TypeGuard[_SequenceT]: + return isinstance(obj, Sequence) + + +def is_mapping(obj: object) -> TypeGuard[Mapping[str, object]]: + return isinstance(obj, Mapping) + + +def is_mapping_t(obj: _MappingT | object) -> TypeGuard[_MappingT]: + return isinstance(obj, Mapping) + + +def is_dict(obj: object) -> TypeGuard[dict[object, object]]: + return isinstance(obj, dict) + + +def is_list(obj: object) -> TypeGuard[list[object]]: + return isinstance(obj, list) + + +def is_iterable(obj: object) -> TypeGuard[Iterable[object]]: + return isinstance(obj, Iterable) + + +def deepcopy_minimal(item: _T) -> _T: + """Minimal reimplementation of copy.deepcopy() that will only copy certain object types: + + - mappings, e.g. `dict` + - list + + This is done for performance reasons. + """ + if is_mapping(item): + return cast(_T, {k: deepcopy_minimal(v) for k, v in item.items()}) + if is_list(item): + return cast(_T, [deepcopy_minimal(entry) for entry in item]) + return item + + +# copied from https://github.com/Rapptz/RoboDanny +def human_join(seq: Sequence[str], *, delim: str = ", ", final: str = "or") -> str: + size = len(seq) + if size == 0: + return "" + + if size == 1: + return seq[0] + + if size == 2: + return f"{seq[0]} {final} {seq[1]}" + + return delim.join(seq[:-1]) + f" {final} {seq[-1]}" + + +def quote(string: str) -> str: + """Add single quotation marks around the given string. Does *not* do any escaping.""" + return f"'{string}'" + + +def required_args(*variants: Sequence[str]) -> Callable[[CallableT], CallableT]: + """Decorator to enforce a given set of arguments or variants of arguments are passed to the decorated function. + + Useful for enforcing runtime validation of overloaded functions. + + Example usage: + ```py + @overload + def foo(*, a: str) -> str: ... + + + @overload + def foo(*, b: bool) -> str: ... + + + # This enforces the same constraints that a static type checker would + # i.e. that either a or b must be passed to the function + @required_args(["a"], ["b"]) + def foo(*, a: str | None = None, b: bool | None = None) -> str: ... + ``` + """ + + def inner(func: CallableT) -> CallableT: + params = inspect.signature(func).parameters + positional = [ + name + for name, param in params.items() + if param.kind + in { + param.POSITIONAL_ONLY, + param.POSITIONAL_OR_KEYWORD, + } + ] + + @functools.wraps(func) + def wrapper(*args: object, **kwargs: object) -> object: + given_params: set[str] = set() + for i, _ in enumerate(args): + try: + given_params.add(positional[i]) + except IndexError: + raise TypeError( + f"{func.__name__}() takes {len(positional)} argument(s) but {len(args)} were given" + ) from None + + for key in kwargs.keys(): + given_params.add(key) + + for variant in variants: + matches = all((param in given_params for param in variant)) + if matches: + break + else: # no break + if len(variants) > 1: + variations = human_join( + ["(" + human_join([quote(arg) for arg in variant], final="and") + ")" for variant in variants] + ) + msg = f"Missing required arguments; Expected either {variations} arguments to be given" + else: + assert len(variants) > 0 + + # TODO: this error message is not deterministic + missing = list(set(variants[0]) - given_params) + if len(missing) > 1: + msg = f"Missing required arguments: {human_join([quote(arg) for arg in missing])}" + else: + msg = f"Missing required argument: {quote(missing[0])}" + raise TypeError(msg) + return func(*args, **kwargs) + + return wrapper # type: ignore + + return inner + + +_K = TypeVar("_K") +_V = TypeVar("_V") + + +@overload +def strip_not_given(obj: None) -> None: ... + + +@overload +def strip_not_given(obj: Mapping[_K, _V | NotGiven]) -> dict[_K, _V]: ... + + +@overload +def strip_not_given(obj: object) -> object: ... + + +def strip_not_given(obj: object | None) -> object: + """Remove all top-level keys where their values are instances of `NotGiven`""" + if obj is None: + return None + + if not is_mapping(obj): + return obj + + return {key: value for key, value in obj.items() if not isinstance(value, NotGiven)} + + +def coerce_integer(val: str) -> int: + return int(val, base=10) + + +def coerce_float(val: str) -> float: + return float(val) + + +def coerce_boolean(val: str) -> bool: + return val == "true" or val == "1" or val == "on" + + +def maybe_coerce_integer(val: str | None) -> int | None: + if val is None: + return None + return coerce_integer(val) + + +def maybe_coerce_float(val: str | None) -> float | None: + if val is None: + return None + return coerce_float(val) + + +def maybe_coerce_boolean(val: str | None) -> bool | None: + if val is None: + return None + return coerce_boolean(val) + + +def removeprefix(string: str, prefix: str) -> str: + """Remove a prefix from a string. + + Backport of `str.removeprefix` for Python < 3.9 + """ + if string.startswith(prefix): + return string[len(prefix) :] + return string + + +def removesuffix(string: str, suffix: str) -> str: + """Remove a suffix from a string. + + Backport of `str.removesuffix` for Python < 3.9 + """ + if string.endswith(suffix): + return string[: -len(suffix)] + return string + + +def file_from_path(path: str) -> FileTypes: + contents = Path(path).read_bytes() + file_name = os.path.basename(path) + return (file_name, contents) + + +def get_required_header(headers: HeadersLike, header: str) -> str: + lower_header = header.lower() + if is_mapping_t(headers): + # mypy doesn't understand the type narrowing here + for k, v in headers.items(): # type: ignore + if k.lower() == lower_header and isinstance(v, str): + return v + + # to deal with the case where the header looks like Stainless-Event-Id + intercaps_header = re.sub(r"([^\w])(\w)", lambda pat: pat.group(1) + pat.group(2).upper(), header.capitalize()) + + for normalized_header in [header, lower_header, header.upper(), intercaps_header]: + value = headers.get(normalized_header) + if value: + return value + + raise ValueError(f"Could not find {header} header") + + +def get_async_library() -> str: + try: + return sniffio.current_async_library() + except Exception: + return "false" + + +def lru_cache(*, maxsize: int | None = 128) -> Callable[[CallableT], CallableT]: + """A version of functools.lru_cache that retains the type signature + for the wrapped function arguments. + """ + wrapper = functools.lru_cache( # noqa: TID251 + maxsize=maxsize, + ) + return cast(Any, wrapper) # type: ignore[no-any-return] + + +def json_safe(data: object) -> object: + """Translates a mapping / sequence recursively in the same fashion + as `pydantic` v2's `model_dump(mode="json")`. + """ + if is_mapping(data): + return {json_safe(key): json_safe(value) for key, value in data.items()} + + if is_iterable(data) and not isinstance(data, (str, bytes, bytearray)): + return [json_safe(item) for item in data] + + if isinstance(data, (datetime, date)): + return data.isoformat() + + return data diff --git a/src/imagekit/_version.py b/src/imagekit/_version.py new file mode 100644 index 0000000..3eb6f6a --- /dev/null +++ b/src/imagekit/_version.py @@ -0,0 +1,4 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +__title__ = "imagekit" +__version__ = "0.0.1" diff --git a/src/imagekit/lib/.keep b/src/imagekit/lib/.keep new file mode 100644 index 0000000..5e2c99f --- /dev/null +++ b/src/imagekit/lib/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store custom files to expand the SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/src/imagekit/py.typed b/src/imagekit/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/src/imagekit/resources/__init__.py b/src/imagekit/resources/__init__.py new file mode 100644 index 0000000..b53b5b0 --- /dev/null +++ b/src/imagekit/resources/__init__.py @@ -0,0 +1,75 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .files import ( + FilesResource, + AsyncFilesResource, + FilesResourceWithRawResponse, + AsyncFilesResourceWithRawResponse, + FilesResourceWithStreamingResponse, + AsyncFilesResourceWithStreamingResponse, +) +from .folder import ( + FolderResource, + AsyncFolderResource, + FolderResourceWithRawResponse, + AsyncFolderResourceWithRawResponse, + FolderResourceWithStreamingResponse, + AsyncFolderResourceWithStreamingResponse, +) +from .accounts import ( + AccountsResource, + AsyncAccountsResource, + AccountsResourceWithRawResponse, + AsyncAccountsResourceWithRawResponse, + AccountsResourceWithStreamingResponse, + AsyncAccountsResourceWithStreamingResponse, +) +from .bulk_jobs import ( + BulkJobsResource, + AsyncBulkJobsResource, + BulkJobsResourceWithRawResponse, + AsyncBulkJobsResourceWithRawResponse, + BulkJobsResourceWithStreamingResponse, + AsyncBulkJobsResourceWithStreamingResponse, +) +from .custom_metadata_fields import ( + CustomMetadataFieldsResource, + AsyncCustomMetadataFieldsResource, + CustomMetadataFieldsResourceWithRawResponse, + AsyncCustomMetadataFieldsResourceWithRawResponse, + CustomMetadataFieldsResourceWithStreamingResponse, + AsyncCustomMetadataFieldsResourceWithStreamingResponse, +) + +__all__ = [ + "CustomMetadataFieldsResource", + "AsyncCustomMetadataFieldsResource", + "CustomMetadataFieldsResourceWithRawResponse", + "AsyncCustomMetadataFieldsResourceWithRawResponse", + "CustomMetadataFieldsResourceWithStreamingResponse", + "AsyncCustomMetadataFieldsResourceWithStreamingResponse", + "FilesResource", + "AsyncFilesResource", + "FilesResourceWithRawResponse", + "AsyncFilesResourceWithRawResponse", + "FilesResourceWithStreamingResponse", + "AsyncFilesResourceWithStreamingResponse", + "FolderResource", + "AsyncFolderResource", + "FolderResourceWithRawResponse", + "AsyncFolderResourceWithRawResponse", + "FolderResourceWithStreamingResponse", + "AsyncFolderResourceWithStreamingResponse", + "BulkJobsResource", + "AsyncBulkJobsResource", + "BulkJobsResourceWithRawResponse", + "AsyncBulkJobsResourceWithRawResponse", + "BulkJobsResourceWithStreamingResponse", + "AsyncBulkJobsResourceWithStreamingResponse", + "AccountsResource", + "AsyncAccountsResource", + "AccountsResourceWithRawResponse", + "AsyncAccountsResourceWithRawResponse", + "AccountsResourceWithStreamingResponse", + "AsyncAccountsResourceWithStreamingResponse", +] diff --git a/src/imagekit/resources/accounts.py b/src/imagekit/resources/accounts.py new file mode 100644 index 0000000..b63e01b --- /dev/null +++ b/src/imagekit/resources/accounts.py @@ -0,0 +1,206 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import date + +import httpx + +from ..types import account_get_usage_params +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.account_get_usage_response import AccountGetUsageResponse + +__all__ = ["AccountsResource", "AsyncAccountsResource"] + + +class AccountsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> AccountsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AccountsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AccountsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AccountsResourceWithStreamingResponse(self) + + def get_usage( + self, + *, + end_date: Union[str, date], + start_date: Union[str, date], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> AccountGetUsageResponse: + """Get the account usage information between two dates. + + Note that the API response + includes data from the start date while excluding data from the end date. In + other words, the data covers the period starting from the specified start date + up to, but not including, the end date. + + Args: + end_date: Specify a `endDate` in `YYYY-MM-DD` format. It should be after the `startDate`. + The difference between `startDate` and `endDate` should be less than 90 days. + + start_date: Specify a `startDate` in `YYYY-MM-DD` format. It should be before the `endDate`. + The difference between `startDate` and `endDate` should be less than 90 days. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/v1/accounts/usage", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "end_date": end_date, + "start_date": start_date, + }, + account_get_usage_params.AccountGetUsageParams, + ), + ), + cast_to=AccountGetUsageResponse, + ) + + +class AsyncAccountsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncAccountsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncAccountsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAccountsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncAccountsResourceWithStreamingResponse(self) + + async def get_usage( + self, + *, + end_date: Union[str, date], + start_date: Union[str, date], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> AccountGetUsageResponse: + """Get the account usage information between two dates. + + Note that the API response + includes data from the start date while excluding data from the end date. In + other words, the data covers the period starting from the specified start date + up to, but not including, the end date. + + Args: + end_date: Specify a `endDate` in `YYYY-MM-DD` format. It should be after the `startDate`. + The difference between `startDate` and `endDate` should be less than 90 days. + + start_date: Specify a `startDate` in `YYYY-MM-DD` format. It should be before the `endDate`. + The difference between `startDate` and `endDate` should be less than 90 days. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/v1/accounts/usage", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "end_date": end_date, + "start_date": start_date, + }, + account_get_usage_params.AccountGetUsageParams, + ), + ), + cast_to=AccountGetUsageResponse, + ) + + +class AccountsResourceWithRawResponse: + def __init__(self, accounts: AccountsResource) -> None: + self._accounts = accounts + + self.get_usage = to_raw_response_wrapper( + accounts.get_usage, + ) + + +class AsyncAccountsResourceWithRawResponse: + def __init__(self, accounts: AsyncAccountsResource) -> None: + self._accounts = accounts + + self.get_usage = async_to_raw_response_wrapper( + accounts.get_usage, + ) + + +class AccountsResourceWithStreamingResponse: + def __init__(self, accounts: AccountsResource) -> None: + self._accounts = accounts + + self.get_usage = to_streamed_response_wrapper( + accounts.get_usage, + ) + + +class AsyncAccountsResourceWithStreamingResponse: + def __init__(self, accounts: AsyncAccountsResource) -> None: + self._accounts = accounts + + self.get_usage = async_to_streamed_response_wrapper( + accounts.get_usage, + ) diff --git a/src/imagekit/resources/bulk_jobs.py b/src/imagekit/resources/bulk_jobs.py new file mode 100644 index 0000000..6ba9632 --- /dev/null +++ b/src/imagekit/resources/bulk_jobs.py @@ -0,0 +1,397 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..types import bulk_job_copy_folder_params, bulk_job_move_folder_params +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.bulk_job_copy_folder_response import BulkJobCopyFolderResponse +from ..types.bulk_job_move_folder_response import BulkJobMoveFolderResponse +from ..types.bulk_job_retrieve_status_response import BulkJobRetrieveStatusResponse + +__all__ = ["BulkJobsResource", "AsyncBulkJobsResource"] + + +class BulkJobsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> BulkJobsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return BulkJobsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> BulkJobsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return BulkJobsResourceWithStreamingResponse(self) + + def copy_folder( + self, + *, + destination_path: str, + source_folder_path: str, + include_versions: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkJobCopyFolderResponse: + """This will copy one folder into another. + + The selected folder, its nested folders, + files, and their versions (in `includeVersions` is set to true) are copied in + this operation. Note: If any file at the destination has the same name as the + source file, then the source file and its versions will be appended to the + destination file version history. + + Args: + destination_path: Full path to the destination folder where you want to copy the source folder + into. + + source_folder_path: The full path to the source folder you want to copy. + + include_versions: Option to copy all versions of files that are nested inside the selected folder. + By default, only the current version of each file will be copied. When set to + true, all versions of each file will be copied. Default value - `false`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/bulkJobs/copyFolder", + body=maybe_transform( + { + "destination_path": destination_path, + "source_folder_path": source_folder_path, + "include_versions": include_versions, + }, + bulk_job_copy_folder_params.BulkJobCopyFolderParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkJobCopyFolderResponse, + ) + + def move_folder( + self, + *, + destination_path: str, + source_folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkJobMoveFolderResponse: + """This will move one folder into another. + + The selected folder, its nested folders, + files, and their versions are moved in this operation. Note: If any file at the + destination has the same name as the source file, then the source file and its + versions will be appended to the destination file version history. + + Args: + destination_path: Full path to the destination folder where you want to move the source folder + into. + + source_folder_path: The full path to the source folder you want to move. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/bulkJobs/moveFolder", + body=maybe_transform( + { + "destination_path": destination_path, + "source_folder_path": source_folder_path, + }, + bulk_job_move_folder_params.BulkJobMoveFolderParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkJobMoveFolderResponse, + ) + + def retrieve_status( + self, + job_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkJobRetrieveStatusResponse: + """ + This API returns the status of a bulk job like copy and move folder operations. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not job_id: + raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}") + return self._get( + f"/v1/bulkJobs/{job_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkJobRetrieveStatusResponse, + ) + + +class AsyncBulkJobsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncBulkJobsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncBulkJobsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncBulkJobsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncBulkJobsResourceWithStreamingResponse(self) + + async def copy_folder( + self, + *, + destination_path: str, + source_folder_path: str, + include_versions: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkJobCopyFolderResponse: + """This will copy one folder into another. + + The selected folder, its nested folders, + files, and their versions (in `includeVersions` is set to true) are copied in + this operation. Note: If any file at the destination has the same name as the + source file, then the source file and its versions will be appended to the + destination file version history. + + Args: + destination_path: Full path to the destination folder where you want to copy the source folder + into. + + source_folder_path: The full path to the source folder you want to copy. + + include_versions: Option to copy all versions of files that are nested inside the selected folder. + By default, only the current version of each file will be copied. When set to + true, all versions of each file will be copied. Default value - `false`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/bulkJobs/copyFolder", + body=await async_maybe_transform( + { + "destination_path": destination_path, + "source_folder_path": source_folder_path, + "include_versions": include_versions, + }, + bulk_job_copy_folder_params.BulkJobCopyFolderParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkJobCopyFolderResponse, + ) + + async def move_folder( + self, + *, + destination_path: str, + source_folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkJobMoveFolderResponse: + """This will move one folder into another. + + The selected folder, its nested folders, + files, and their versions are moved in this operation. Note: If any file at the + destination has the same name as the source file, then the source file and its + versions will be appended to the destination file version history. + + Args: + destination_path: Full path to the destination folder where you want to move the source folder + into. + + source_folder_path: The full path to the source folder you want to move. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/bulkJobs/moveFolder", + body=await async_maybe_transform( + { + "destination_path": destination_path, + "source_folder_path": source_folder_path, + }, + bulk_job_move_folder_params.BulkJobMoveFolderParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkJobMoveFolderResponse, + ) + + async def retrieve_status( + self, + job_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkJobRetrieveStatusResponse: + """ + This API returns the status of a bulk job like copy and move folder operations. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not job_id: + raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}") + return await self._get( + f"/v1/bulkJobs/{job_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkJobRetrieveStatusResponse, + ) + + +class BulkJobsResourceWithRawResponse: + def __init__(self, bulk_jobs: BulkJobsResource) -> None: + self._bulk_jobs = bulk_jobs + + self.copy_folder = to_raw_response_wrapper( + bulk_jobs.copy_folder, + ) + self.move_folder = to_raw_response_wrapper( + bulk_jobs.move_folder, + ) + self.retrieve_status = to_raw_response_wrapper( + bulk_jobs.retrieve_status, + ) + + +class AsyncBulkJobsResourceWithRawResponse: + def __init__(self, bulk_jobs: AsyncBulkJobsResource) -> None: + self._bulk_jobs = bulk_jobs + + self.copy_folder = async_to_raw_response_wrapper( + bulk_jobs.copy_folder, + ) + self.move_folder = async_to_raw_response_wrapper( + bulk_jobs.move_folder, + ) + self.retrieve_status = async_to_raw_response_wrapper( + bulk_jobs.retrieve_status, + ) + + +class BulkJobsResourceWithStreamingResponse: + def __init__(self, bulk_jobs: BulkJobsResource) -> None: + self._bulk_jobs = bulk_jobs + + self.copy_folder = to_streamed_response_wrapper( + bulk_jobs.copy_folder, + ) + self.move_folder = to_streamed_response_wrapper( + bulk_jobs.move_folder, + ) + self.retrieve_status = to_streamed_response_wrapper( + bulk_jobs.retrieve_status, + ) + + +class AsyncBulkJobsResourceWithStreamingResponse: + def __init__(self, bulk_jobs: AsyncBulkJobsResource) -> None: + self._bulk_jobs = bulk_jobs + + self.copy_folder = async_to_streamed_response_wrapper( + bulk_jobs.copy_folder, + ) + self.move_folder = async_to_streamed_response_wrapper( + bulk_jobs.move_folder, + ) + self.retrieve_status = async_to_streamed_response_wrapper( + bulk_jobs.retrieve_status, + ) diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py new file mode 100644 index 0000000..acdbc6b --- /dev/null +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -0,0 +1,509 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..types import ( + custom_metadata_field_list_params, + custom_metadata_field_create_params, + custom_metadata_field_update_params, +) +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.custom_metadata_field_list_response import CustomMetadataFieldListResponse +from ..types.custom_metadata_field_create_response import CustomMetadataFieldCreateResponse +from ..types.custom_metadata_field_update_response import CustomMetadataFieldUpdateResponse + +__all__ = ["CustomMetadataFieldsResource", "AsyncCustomMetadataFieldsResource"] + + +class CustomMetadataFieldsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> CustomMetadataFieldsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return CustomMetadataFieldsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CustomMetadataFieldsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return CustomMetadataFieldsResourceWithStreamingResponse(self) + + def create( + self, + *, + label: str, + name: str, + schema: custom_metadata_field_create_params.Schema, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> CustomMetadataFieldCreateResponse: + """This API creates a new custom metadata field. + + Once a custom metadata field is + created either through this API or using the dashboard UI, its value can be set + on the assets. The value of a field for an asset can be set using the media + library UI or programmatically through upload or update assets API. + + Args: + label: Human readable name of the custom metadata field. This should be unique across + all non deleted custom metadata fields. This name is displayed as form field + label to the users while setting field value on an asset in the media library + UI. + + name: API name of the custom metadata field. This should be unique across all + (including deleted) custom metadata fields. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/customMetadataFields", + body=maybe_transform( + { + "label": label, + "name": name, + "schema": schema, + }, + custom_metadata_field_create_params.CustomMetadataFieldCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CustomMetadataFieldCreateResponse, + ) + + def update( + self, + id: str, + *, + label: str | NotGiven = NOT_GIVEN, + schema: custom_metadata_field_update_params.Schema | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> CustomMetadataFieldUpdateResponse: + """ + This API updates the label or schema of an existing custom metadata field. + + Args: + label: Human readable name of the custom metadata field. This should be unique across + all non deleted custom metadata fields. This name is displayed as form field + label to the users while setting field value on an asset in the media library + UI. This parameter is required if `schema` is not provided. + + schema: An object that describes the rules for the custom metadata key. This parameter + is required if `label` is not provided. Note: `type` cannot be updated and will + be ignored if sent with the `schema`. The schema will be validated as per the + existing `type`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._patch( + f"/v1/customMetadataFields/{id}", + body=maybe_transform( + { + "label": label, + "schema": schema, + }, + custom_metadata_field_update_params.CustomMetadataFieldUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CustomMetadataFieldUpdateResponse, + ) + + def list( + self, + *, + include_deleted: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> CustomMetadataFieldListResponse: + """This API returns the array of created custom metadata field objects. + + By default + the API returns only non deleted field objects, but you can include deleted + fields in the API response. + + Args: + include_deleted: Set it to `true` to include deleted field objects in the API response. Default + value is `false`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/v1/customMetadataFields", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + {"include_deleted": include_deleted}, + custom_metadata_field_list_params.CustomMetadataFieldListParams, + ), + ), + cast_to=CustomMetadataFieldListResponse, + ) + + def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This API deletes a custom metadata field. + + Even after deleting a custom metadata + field, you cannot create any new custom metadata field with the same name. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._delete( + f"/v1/customMetadataFields/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + +class AsyncCustomMetadataFieldsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncCustomMetadataFieldsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncCustomMetadataFieldsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCustomMetadataFieldsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncCustomMetadataFieldsResourceWithStreamingResponse(self) + + async def create( + self, + *, + label: str, + name: str, + schema: custom_metadata_field_create_params.Schema, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> CustomMetadataFieldCreateResponse: + """This API creates a new custom metadata field. + + Once a custom metadata field is + created either through this API or using the dashboard UI, its value can be set + on the assets. The value of a field for an asset can be set using the media + library UI or programmatically through upload or update assets API. + + Args: + label: Human readable name of the custom metadata field. This should be unique across + all non deleted custom metadata fields. This name is displayed as form field + label to the users while setting field value on an asset in the media library + UI. + + name: API name of the custom metadata field. This should be unique across all + (including deleted) custom metadata fields. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/customMetadataFields", + body=await async_maybe_transform( + { + "label": label, + "name": name, + "schema": schema, + }, + custom_metadata_field_create_params.CustomMetadataFieldCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CustomMetadataFieldCreateResponse, + ) + + async def update( + self, + id: str, + *, + label: str | NotGiven = NOT_GIVEN, + schema: custom_metadata_field_update_params.Schema | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> CustomMetadataFieldUpdateResponse: + """ + This API updates the label or schema of an existing custom metadata field. + + Args: + label: Human readable name of the custom metadata field. This should be unique across + all non deleted custom metadata fields. This name is displayed as form field + label to the users while setting field value on an asset in the media library + UI. This parameter is required if `schema` is not provided. + + schema: An object that describes the rules for the custom metadata key. This parameter + is required if `label` is not provided. Note: `type` cannot be updated and will + be ignored if sent with the `schema`. The schema will be validated as per the + existing `type`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._patch( + f"/v1/customMetadataFields/{id}", + body=await async_maybe_transform( + { + "label": label, + "schema": schema, + }, + custom_metadata_field_update_params.CustomMetadataFieldUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CustomMetadataFieldUpdateResponse, + ) + + async def list( + self, + *, + include_deleted: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> CustomMetadataFieldListResponse: + """This API returns the array of created custom metadata field objects. + + By default + the API returns only non deleted field objects, but you can include deleted + fields in the API response. + + Args: + include_deleted: Set it to `true` to include deleted field objects in the API response. Default + value is `false`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/v1/customMetadataFields", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"include_deleted": include_deleted}, + custom_metadata_field_list_params.CustomMetadataFieldListParams, + ), + ), + cast_to=CustomMetadataFieldListResponse, + ) + + async def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This API deletes a custom metadata field. + + Even after deleting a custom metadata + field, you cannot create any new custom metadata field with the same name. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._delete( + f"/v1/customMetadataFields/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + +class CustomMetadataFieldsResourceWithRawResponse: + def __init__(self, custom_metadata_fields: CustomMetadataFieldsResource) -> None: + self._custom_metadata_fields = custom_metadata_fields + + self.create = to_raw_response_wrapper( + custom_metadata_fields.create, + ) + self.update = to_raw_response_wrapper( + custom_metadata_fields.update, + ) + self.list = to_raw_response_wrapper( + custom_metadata_fields.list, + ) + self.delete = to_raw_response_wrapper( + custom_metadata_fields.delete, + ) + + +class AsyncCustomMetadataFieldsResourceWithRawResponse: + def __init__(self, custom_metadata_fields: AsyncCustomMetadataFieldsResource) -> None: + self._custom_metadata_fields = custom_metadata_fields + + self.create = async_to_raw_response_wrapper( + custom_metadata_fields.create, + ) + self.update = async_to_raw_response_wrapper( + custom_metadata_fields.update, + ) + self.list = async_to_raw_response_wrapper( + custom_metadata_fields.list, + ) + self.delete = async_to_raw_response_wrapper( + custom_metadata_fields.delete, + ) + + +class CustomMetadataFieldsResourceWithStreamingResponse: + def __init__(self, custom_metadata_fields: CustomMetadataFieldsResource) -> None: + self._custom_metadata_fields = custom_metadata_fields + + self.create = to_streamed_response_wrapper( + custom_metadata_fields.create, + ) + self.update = to_streamed_response_wrapper( + custom_metadata_fields.update, + ) + self.list = to_streamed_response_wrapper( + custom_metadata_fields.list, + ) + self.delete = to_streamed_response_wrapper( + custom_metadata_fields.delete, + ) + + +class AsyncCustomMetadataFieldsResourceWithStreamingResponse: + def __init__(self, custom_metadata_fields: AsyncCustomMetadataFieldsResource) -> None: + self._custom_metadata_fields = custom_metadata_fields + + self.create = async_to_streamed_response_wrapper( + custom_metadata_fields.create, + ) + self.update = async_to_streamed_response_wrapper( + custom_metadata_fields.update, + ) + self.list = async_to_streamed_response_wrapper( + custom_metadata_fields.list, + ) + self.delete = async_to_streamed_response_wrapper( + custom_metadata_fields.delete, + ) diff --git a/src/imagekit/resources/files/__init__.py b/src/imagekit/resources/files/__init__.py new file mode 100644 index 0000000..55cfc51 --- /dev/null +++ b/src/imagekit/resources/files/__init__.py @@ -0,0 +1,89 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .batch import ( + BatchResource, + AsyncBatchResource, + BatchResourceWithRawResponse, + AsyncBatchResourceWithRawResponse, + BatchResourceWithStreamingResponse, + AsyncBatchResourceWithStreamingResponse, +) +from .files import ( + FilesResource, + AsyncFilesResource, + FilesResourceWithRawResponse, + AsyncFilesResourceWithRawResponse, + FilesResourceWithStreamingResponse, + AsyncFilesResourceWithStreamingResponse, +) +from .purge import ( + PurgeResource, + AsyncPurgeResource, + PurgeResourceWithRawResponse, + AsyncPurgeResourceWithRawResponse, + PurgeResourceWithStreamingResponse, + AsyncPurgeResourceWithStreamingResponse, +) +from .details import ( + DetailsResource, + AsyncDetailsResource, + DetailsResourceWithRawResponse, + AsyncDetailsResourceWithRawResponse, + DetailsResourceWithStreamingResponse, + AsyncDetailsResourceWithStreamingResponse, +) +from .metadata import ( + MetadataResource, + AsyncMetadataResource, + MetadataResourceWithRawResponse, + AsyncMetadataResourceWithRawResponse, + MetadataResourceWithStreamingResponse, + AsyncMetadataResourceWithStreamingResponse, +) +from .versions import ( + VersionsResource, + AsyncVersionsResource, + VersionsResourceWithRawResponse, + AsyncVersionsResourceWithRawResponse, + VersionsResourceWithStreamingResponse, + AsyncVersionsResourceWithStreamingResponse, +) + +__all__ = [ + "DetailsResource", + "AsyncDetailsResource", + "DetailsResourceWithRawResponse", + "AsyncDetailsResourceWithRawResponse", + "DetailsResourceWithStreamingResponse", + "AsyncDetailsResourceWithStreamingResponse", + "BatchResource", + "AsyncBatchResource", + "BatchResourceWithRawResponse", + "AsyncBatchResourceWithRawResponse", + "BatchResourceWithStreamingResponse", + "AsyncBatchResourceWithStreamingResponse", + "VersionsResource", + "AsyncVersionsResource", + "VersionsResourceWithRawResponse", + "AsyncVersionsResourceWithRawResponse", + "VersionsResourceWithStreamingResponse", + "AsyncVersionsResourceWithStreamingResponse", + "PurgeResource", + "AsyncPurgeResource", + "PurgeResourceWithRawResponse", + "AsyncPurgeResourceWithRawResponse", + "PurgeResourceWithStreamingResponse", + "AsyncPurgeResourceWithStreamingResponse", + "MetadataResource", + "AsyncMetadataResource", + "MetadataResourceWithRawResponse", + "AsyncMetadataResourceWithRawResponse", + "MetadataResourceWithStreamingResponse", + "AsyncMetadataResourceWithStreamingResponse", + "FilesResource", + "AsyncFilesResource", + "FilesResourceWithRawResponse", + "AsyncFilesResourceWithRawResponse", + "FilesResourceWithStreamingResponse", + "AsyncFilesResourceWithStreamingResponse", +] diff --git a/src/imagekit/resources/files/batch.py b/src/imagekit/resources/files/batch.py new file mode 100644 index 0000000..7c5e14b --- /dev/null +++ b/src/imagekit/resources/files/batch.py @@ -0,0 +1,181 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.files import batch_delete_params +from ..._base_client import make_request_options +from ...types.files.batch_delete_response import BatchDeleteResponse + +__all__ = ["BatchResource", "AsyncBatchResource"] + + +class BatchResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> BatchResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return BatchResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> BatchResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return BatchResourceWithStreamingResponse(self) + + def delete( + self, + *, + file_ids: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BatchDeleteResponse: + """ + This API deletes multiple files and all their file versions permanently. + + Note: If a file or specific transformation has been requested in the past, then + the response is cached. Deleting a file does not purge the cache. You can purge + the cache using purge cache API. + + A maximum of 100 files can be deleted at a time. + + Args: + file_ids: An array of fileIds which you want to delete. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/batch/deleteByFileIds", + body=maybe_transform({"file_ids": file_ids}, batch_delete_params.BatchDeleteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BatchDeleteResponse, + ) + + +class AsyncBatchResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncBatchResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncBatchResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncBatchResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncBatchResourceWithStreamingResponse(self) + + async def delete( + self, + *, + file_ids: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BatchDeleteResponse: + """ + This API deletes multiple files and all their file versions permanently. + + Note: If a file or specific transformation has been requested in the past, then + the response is cached. Deleting a file does not purge the cache. You can purge + the cache using purge cache API. + + A maximum of 100 files can be deleted at a time. + + Args: + file_ids: An array of fileIds which you want to delete. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/batch/deleteByFileIds", + body=await async_maybe_transform({"file_ids": file_ids}, batch_delete_params.BatchDeleteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BatchDeleteResponse, + ) + + +class BatchResourceWithRawResponse: + def __init__(self, batch: BatchResource) -> None: + self._batch = batch + + self.delete = to_raw_response_wrapper( + batch.delete, + ) + + +class AsyncBatchResourceWithRawResponse: + def __init__(self, batch: AsyncBatchResource) -> None: + self._batch = batch + + self.delete = async_to_raw_response_wrapper( + batch.delete, + ) + + +class BatchResourceWithStreamingResponse: + def __init__(self, batch: BatchResource) -> None: + self._batch = batch + + self.delete = to_streamed_response_wrapper( + batch.delete, + ) + + +class AsyncBatchResourceWithStreamingResponse: + def __init__(self, batch: AsyncBatchResource) -> None: + self._batch = batch + + self.delete = async_to_streamed_response_wrapper( + batch.delete, + ) diff --git a/src/imagekit/resources/files/details.py b/src/imagekit/resources/files/details.py new file mode 100644 index 0000000..234d2ab --- /dev/null +++ b/src/imagekit/resources/files/details.py @@ -0,0 +1,447 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union, Iterable, Optional +from typing_extensions import Literal, overload + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.files import detail_update_params +from ..._base_client import make_request_options +from ...types.files.detail_update_response import DetailUpdateResponse +from ...types.files.detail_retrieve_response import DetailRetrieveResponse + +__all__ = ["DetailsResource", "AsyncDetailsResource"] + + +class DetailsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> DetailsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return DetailsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DetailsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return DetailsResourceWithStreamingResponse(self) + + def retrieve( + self, + file_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DetailRetrieveResponse: + """ + This API returns an object with details or attributes about the current version + of the file. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return self._get( + f"/v1/files/{file_id}/details", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DetailRetrieveResponse, + ) + + @overload + def update( + self, + file_id: str, + *, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: object | NotGiven = NOT_GIVEN, + extensions: Iterable[detail_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DetailUpdateResponse: + """ + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. + + Args: + custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. + `10,10,100,100`. Send `null` to unset this value. + + custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` + value for that key. Before setting any custom metadata on an asset you have to + create the field using custom metadata fields API. + + extensions: Array of extensions to be applied to the asset. Each extension can be configured + with specific parameters based on the extension type. + + remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". + + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + + tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send + `null` to unset all tags associated with the file. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + file_id: str, + *, + publish: detail_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DetailUpdateResponse: + """ + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. + + Args: + publish: Configure the publication status of a file and its versions. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + def update( + self, + file_id: str, + *, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: object | NotGiven = NOT_GIVEN, + extensions: Iterable[detail_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + publish: detail_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DetailUpdateResponse: + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return self._patch( + f"/v1/files/{file_id}/details", + body=maybe_transform( + { + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "extensions": extensions, + "remove_ai_tags": remove_ai_tags, + "tags": tags, + "webhook_url": webhook_url, + "publish": publish, + }, + detail_update_params.DetailUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DetailUpdateResponse, + ) + + +class AsyncDetailsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncDetailsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncDetailsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDetailsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncDetailsResourceWithStreamingResponse(self) + + async def retrieve( + self, + file_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DetailRetrieveResponse: + """ + This API returns an object with details or attributes about the current version + of the file. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return await self._get( + f"/v1/files/{file_id}/details", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DetailRetrieveResponse, + ) + + @overload + async def update( + self, + file_id: str, + *, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: object | NotGiven = NOT_GIVEN, + extensions: Iterable[detail_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DetailUpdateResponse: + """ + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. + + Args: + custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. + `10,10,100,100`. Send `null` to unset this value. + + custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` + value for that key. Before setting any custom metadata on an asset you have to + create the field using custom metadata fields API. + + extensions: Array of extensions to be applied to the asset. Each extension can be configured + with specific parameters based on the extension type. + + remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". + + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + + tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send + `null` to unset all tags associated with the file. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def update( + self, + file_id: str, + *, + publish: detail_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DetailUpdateResponse: + """ + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. + + Args: + publish: Configure the publication status of a file and its versions. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + async def update( + self, + file_id: str, + *, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: object | NotGiven = NOT_GIVEN, + extensions: Iterable[detail_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + publish: detail_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DetailUpdateResponse: + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return await self._patch( + f"/v1/files/{file_id}/details", + body=await async_maybe_transform( + { + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "extensions": extensions, + "remove_ai_tags": remove_ai_tags, + "tags": tags, + "webhook_url": webhook_url, + "publish": publish, + }, + detail_update_params.DetailUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DetailUpdateResponse, + ) + + +class DetailsResourceWithRawResponse: + def __init__(self, details: DetailsResource) -> None: + self._details = details + + self.retrieve = to_raw_response_wrapper( + details.retrieve, + ) + self.update = to_raw_response_wrapper( + details.update, + ) + + +class AsyncDetailsResourceWithRawResponse: + def __init__(self, details: AsyncDetailsResource) -> None: + self._details = details + + self.retrieve = async_to_raw_response_wrapper( + details.retrieve, + ) + self.update = async_to_raw_response_wrapper( + details.update, + ) + + +class DetailsResourceWithStreamingResponse: + def __init__(self, details: DetailsResource) -> None: + self._details = details + + self.retrieve = to_streamed_response_wrapper( + details.retrieve, + ) + self.update = to_streamed_response_wrapper( + details.update, + ) + + +class AsyncDetailsResourceWithStreamingResponse: + def __init__(self, details: AsyncDetailsResource) -> None: + self._details = details + + self.retrieve = async_to_streamed_response_wrapper( + details.retrieve, + ) + self.update = async_to_streamed_response_wrapper( + details.update, + ) diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py new file mode 100644 index 0000000..52db743 --- /dev/null +++ b/src/imagekit/resources/files/files.py @@ -0,0 +1,2258 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Literal + +import httpx + +from .batch import ( + BatchResource, + AsyncBatchResource, + BatchResourceWithRawResponse, + AsyncBatchResourceWithRawResponse, + BatchResourceWithStreamingResponse, + AsyncBatchResourceWithStreamingResponse, +) +from .purge import ( + PurgeResource, + AsyncPurgeResource, + PurgeResourceWithRawResponse, + AsyncPurgeResourceWithRawResponse, + PurgeResourceWithStreamingResponse, + AsyncPurgeResourceWithStreamingResponse, +) +from ...types import ( + file_copy_params, + file_list_params, + file_move_params, + file_rename_params, + file_add_tags_params, + file_upload_v1_params, + file_upload_v2_params, + file_remove_tags_params, + file_remove_ai_tags_params, +) +from .details import ( + DetailsResource, + AsyncDetailsResource, + DetailsResourceWithRawResponse, + AsyncDetailsResourceWithRawResponse, + DetailsResourceWithStreamingResponse, + AsyncDetailsResourceWithStreamingResponse, +) +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +from ..._utils import maybe_transform, async_maybe_transform +from .metadata import ( + MetadataResource, + AsyncMetadataResource, + MetadataResourceWithRawResponse, + AsyncMetadataResourceWithRawResponse, + MetadataResourceWithStreamingResponse, + AsyncMetadataResourceWithStreamingResponse, +) +from .versions import ( + VersionsResource, + AsyncVersionsResource, + VersionsResourceWithRawResponse, + AsyncVersionsResourceWithRawResponse, + VersionsResourceWithStreamingResponse, + AsyncVersionsResourceWithStreamingResponse, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.file_list_response import FileListResponse +from ...types.file_rename_response import FileRenameResponse +from ...types.file_add_tags_response import FileAddTagsResponse +from ...types.file_upload_v1_response import FileUploadV1Response +from ...types.file_upload_v2_response import FileUploadV2Response +from ...types.file_remove_tags_response import FileRemoveTagsResponse +from ...types.file_remove_ai_tags_response import FileRemoveAITagsResponse + +__all__ = ["FilesResource", "AsyncFilesResource"] + + +class FilesResource(SyncAPIResource): + @cached_property + def details(self) -> DetailsResource: + return DetailsResource(self._client) + + @cached_property + def batch(self) -> BatchResource: + return BatchResource(self._client) + + @cached_property + def versions(self) -> VersionsResource: + return VersionsResource(self._client) + + @cached_property + def purge(self) -> PurgeResource: + return PurgeResource(self._client) + + @cached_property + def metadata(self) -> MetadataResource: + return MetadataResource(self._client) + + @cached_property + def with_raw_response(self) -> FilesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return FilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FilesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return FilesResourceWithStreamingResponse(self) + + def list( + self, + *, + file_type: str | NotGiven = NOT_GIVEN, + limit: str | NotGiven = NOT_GIVEN, + path: str | NotGiven = NOT_GIVEN, + search_query: str | NotGiven = NOT_GIVEN, + skip: str | NotGiven = NOT_GIVEN, + sort: str | NotGiven = NOT_GIVEN, + type: Literal["file", "file-version", "folder", "all"] | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileListResponse: + """ + This API can list all the uploaded files and folders in your ImageKit.io media + library. In addition, you can fine-tune your query by specifying various filters + by generating a query string in a Lucene-like syntax and provide this generated + string as the value of the `searchQuery`. + + Args: + file_type: + Type of files to include in the result set. Accepts three values: + + `all` - include all types of files in the result set. `image` - only search in + image type files. `non-image` - only search in files that are not images, e.g., + JS or CSS or video files. + + Default value - `all` + + limit: + The maximum number of results to return in response: + + Minimum value - 1 + + Maximum value - 1000 + + Default value - 1000 + + path: Folder path if you want to limit the search within a specific folder. For + example, `/sales-banner/` will only search in folder sales-banner. + + search_query: Query string in a Lucene-like query language e.g. `createdAt > "7d"`. + + Note : When the searchQuery parameter is present, the following query parameters + will have no effect on the result: + + 1. `tags` + 2. `type` + 3. `name` + + [Learn more](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#advanced-search-queries) + from examples. + + skip: + The number of results to skip before returning results: + + Minimum value - 0 + + Default value - 0 + + sort: + You can sort based on the following fields: + + 1. name - `ASC_NAME` or `DESC_NAME` + 2. createdAt - `ASC_CREATED` or `DESC_CREATED` + 3. updatedAt - `ASC_UPDATED` or `DESC_UPDATED` + 4. height - `ASC_HEIGHT` or `DESC_HEIGHT` + 5. width - `ASC_WIDTH` or `DESC_WIDTH` + 6. size - `ASC_SIZE` or `DESC_SIZE` + + Default value - `ASC_CREATED` + + type: Limit search to one of `file`, `file-version`, or `folder`. Pass `all` to + include `files` and `folders` in search results (`file-version` will not be + included in this case). + + Default value - `file` + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/v1/files", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "file_type": file_type, + "limit": limit, + "path": path, + "search_query": search_query, + "skip": skip, + "sort": sort, + "type": type, + }, + file_list_params.FileListParams, + ), + ), + cast_to=FileListResponse, + ) + + def delete( + self, + file_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """ + This API deletes the file and all its file versions permanently. + + Note: If a file or specific transformation has been requested in the past, then + the response is cached. Deleting a file does not purge the cache. You can purge + the cache using purge cache API. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/v1/files/{file_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def add_tags( + self, + *, + file_ids: List[str], + tags: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileAddTagsResponse: + """This API adds tags to multiple files in bulk. + + A maximum of 50 files can be + specified at a time. + + Args: + file_ids: An array of fileIds to which you want to add tags. + + tags: An array of tags that you want to add to the files. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/addTags", + body=maybe_transform( + { + "file_ids": file_ids, + "tags": tags, + }, + file_add_tags_params.FileAddTagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileAddTagsResponse, + ) + + def copy( + self, + *, + destination_path: str, + source_file_path: str, + include_file_versions: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """ + This will copy a file from one folder to another. + + Note: If any file at the destination has the same name as the source file, then + the source file and its versions (if `includeFileVersions` is set to true) will + be appended to the destination file version history. + + Args: + destination_path: Full path to the folder you want to copy the above file into. + + source_file_path: The full path of the file you want to copy. + + include_file_versions: Option to copy all versions of a file. By default, only the current version of + the file is copied. When set to true, all versions of the file will be copied. + Default value - `false`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/copy", + body=maybe_transform( + { + "destination_path": destination_path, + "source_file_path": source_file_path, + "include_file_versions": include_file_versions, + }, + file_copy_params.FileCopyParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + def move( + self, + *, + destination_path: str, + source_file_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """ + This will move a file and all its versions from one folder to another. + + Note: If any file at the destination has the same name as the source file, then + the source file and its versions will be appended to the destination file. + + Args: + destination_path: Full path to the folder you want to move the above file into. + + source_file_path: The full path of the file you want to move. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/move", + body=maybe_transform( + { + "destination_path": destination_path, + "source_file_path": source_file_path, + }, + file_move_params.FileMoveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + def remove_ai_tags( + self, + *, + ai_tags: List[str], + file_ids: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileRemoveAITagsResponse: + """This API removes AITags from multiple files in bulk. + + A maximum of 50 files can + be specified at a time. + + Args: + ai_tags: An array of AITags that you want to remove from the files. + + file_ids: An array of fileIds from which you want to remove AITags. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/removeAITags", + body=maybe_transform( + { + "ai_tags": ai_tags, + "file_ids": file_ids, + }, + file_remove_ai_tags_params.FileRemoveAITagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileRemoveAITagsResponse, + ) + + def remove_tags( + self, + *, + file_ids: List[str], + tags: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileRemoveTagsResponse: + """This API removes tags from multiple files in bulk. + + A maximum of 50 files can be + specified at a time. + + Args: + file_ids: An array of fileIds from which you want to remove tags. + + tags: An array of tags that you want to remove from the files. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/removeTags", + body=maybe_transform( + { + "file_ids": file_ids, + "tags": tags, + }, + file_remove_tags_params.FileRemoveTagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileRemoveTagsResponse, + ) + + def rename( + self, + *, + file_path: str, + new_file_name: str, + purge_cache: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileRenameResponse: + """ + You can rename an already existing file in the media library using rename file + API. This operation would rename all file versions of the file. + + Note: The old URLs will stop working. The file/file version URLs cached on CDN + will continue to work unless a purge is requested. + + Args: + file_path: The full path of the file you want to rename. + + new_file_name: + The new name of the file. A filename can contain: + + Alphanumeric Characters: `a-z`, `A-Z`, `0-9` (including Unicode letters, marks, + and numerals in other languages). Special Characters: `.`, `_`, and `-`. + + Any other character, including space, will be replaced by `_`. + + purge_cache: Option to purge cache for the old file and its versions' URLs. + + When set to true, it will internally issue a purge cache request on CDN to + remove cached content of old file and its versions. This purge request is + counted against your monthly purge quota. + + Note: If the old file were accessible at + `https://ik.imagekit.io/demo/old-filename.jpg`, a purge cache request would be + issued against `https://ik.imagekit.io/demo/old-filename.jpg*` (with a wildcard + at the end). It will remove the file and its versions' URLs and any + transformations made using query parameters on this file or its versions. + However, the cache for file transformations made using path parameters will + persist. You can purge them using the purge API. For more details, refer to the + purge API documentation. + + Default value - `false` + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._put( + "/v1/files/rename", + body=maybe_transform( + { + "file_path": file_path, + "new_file_name": new_file_name, + "purge_cache": purge_cache, + }, + file_rename_params.FileRenameParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileRenameResponse, + ) + + def upload_v1( + self, + *, + file: str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: str | NotGiven = NOT_GIVEN, + expire: str | NotGiven = NOT_GIVEN, + extensions: str | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: Literal["true", "false"] | NotGiven = NOT_GIVEN, + is_published: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_ai_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_file: str | NotGiven = NOT_GIVEN, + overwrite_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, + public_key: str | NotGiven = NOT_GIVEN, + response_fields: str | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + tags: str | NotGiven = NOT_GIVEN, + transformation: str | NotGiven = NOT_GIVEN, + use_unique_file_name: Literal["true", "false"] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadV1Response: + """ + ImageKit.io allows you to upload files directly from both the server and client + sides. For server-side uploads, private API key authentication is used. For + client-side uploads, generate a one-time `token`, `signature`, and `expiration` + from your secure backend using private API. + [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) + about how to implement client-side file upload. + + The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security + by verifying the entire payload using JWT. + + **File size limit** \\ + On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw + files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, + audio, and raw files and 2GB for videos. These limits can be further increased with + higher-tier plans. + + **Version limit** \\ + A file can have a maximum of 100 versions. + + **Demo applications** + + - A full-fledged + [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + supporting file selections from local storage, URL, Dropbox, Google Drive, + Instagram, and more. + - [Quick start guides](/docs/quick-start-guides) for various frameworks and + technologies. + + Args: + file: Pass the HTTP URL or base64 string. When passing a URL in the file parameter, + please ensure that our servers can access the URL. In case ImageKit is unable to + download the file from the specified URL, a `400` error response is returned. + This will also result in a `400` error if the file download request is aborted + if response headers are not received in 8 seconds. + + file_name: + The name with which the file has to be uploaded. The file name can contain: + + - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + - Special Characters: `.`, `-` + + Any other character including space will be replaced by `_` + + token: A unique value that the ImageKit.io server will use to recognize and prevent + subsequent retries for the same request. We suggest using V4 UUIDs, or another + random string with enough entropy to avoid collisions. This field is only + required for authentication when uploading a file from the client side. + + **Note**: Sending a value that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new value for this field. + + checks: Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + + custom_coordinates: Define an important area in the image. This is only relevant for image type + files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + + custom_metadata: Stringified JSON key-value data to be associated with the asset. + + expire: The time until your signature is valid. It must be a + [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into + the future. It should be in seconds. This field is only required for + authentication when uploading a file from the client side. + + extensions: Stringified JSON object with an array of extensions to be applied to the image. + Refer to extensions schema in + [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). + + folder: The folder path in which the image has to be uploaded. If the folder(s) didn't + exist before, a new folder(s) is created. + + The folder name can contain: + + - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + - Special Characters: `/` , `_` , `-` + + Using multiple `/` creates a nested folder. + + is_private_file: Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + + is_published: Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + + overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + + overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + + overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + + overwrite_tags: If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + + public_key: Your ImageKit.io public key. This field is only required for authentication when + uploading a file from the client side. + + response_fields: Comma-separated values of the fields that you want the API to return in the + response. + + For example, set the value of this field to + `tags,customCoordinates,isPrivateFile` to get the value of `tags`, + `customCoordinates`, and `isPrivateFile` in the response. + + Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, + `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. + + signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a + key. Learn how to create a signature on the page below. This should be in + lowercase. + + Signature must be calculated on the server-side. This field is only required for + authentication when uploading a file from the client side. + + tags: Set the tags while uploading the file. + + Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length + of all characters should not exceed 500. `%` is not allowed. + + If this field is not specified and the file is overwritten then the tags will be + removed. + + transformation: + Stringified JSON object with properties for pre and post transformations: + + `pre` - Accepts a "string" containing a valid transformation used for requesting + a pre-transformation for an image or a video file. + + `post` - Accepts an array of objects with properties: + + - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` + (Adaptive bitrate streaming). + - `value`: A "string" corresponding to the required transformation. Required if + `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or + `thumbnail`. + - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. + + Read more about + [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). + + use_unique_file_name: Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return self._post( + "/api/v1/files/upload" + if self._client._base_url_overridden + else "https://upload.imagekit.io/api/v1/files/upload", + body=maybe_transform( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "expire": expire, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "public_key": public_key, + "response_fields": response_fields, + "signature": signature, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + }, + file_upload_v1_params.FileUploadV1Params, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileUploadV1Response, + ) + + def upload_v2( + self, + *, + file: str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: str | NotGiven = NOT_GIVEN, + extensions: str | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: Literal["true", "false"] | NotGiven = NOT_GIVEN, + is_published: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_ai_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_file: str | NotGiven = NOT_GIVEN, + overwrite_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, + response_fields: str | NotGiven = NOT_GIVEN, + tags: str | NotGiven = NOT_GIVEN, + transformation: str | NotGiven = NOT_GIVEN, + use_unique_file_name: Literal["true", "false"] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadV2Response: + """The V2 API enhances security by verifying the entire payload using JWT. + + This API + is in beta. + + ImageKit.io allows you to upload files directly from both the server and client + sides. For server-side uploads, private API key authentication is used. For + client-side uploads, generate a one-time `token` from your secure backend using + private API. + [Learn more](/docs/api-reference/upload-file/upload-file-v2#how-to-implement-secure-client-side-file-upload) + about how to implement secure client-side file upload. + + **File size limit** \\ + On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw + files, and 100MB for videos. On the paid plan, these limits increase to 40MB for + images, audio, and raw files, and 2GB for videos. These limits can be further increased + with higher-tier plans. + + **Version limit** \\ + A file can have a maximum of 100 versions. + + **Demo applications** + + - A full-fledged + [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + supporting file selections from local storage, URL, Dropbox, Google Drive, + Instagram, and more. + - [Quick start guides](/docs/quick-start-guides) for various frameworks and + technologies. + + Args: + file: Pass the HTTP URL or base64 string. When passing a URL in the file parameter, + please ensure that our servers can access the URL. In case ImageKit is unable to + download the file from the specified URL, a `400` error response is returned. + This will also result in a `400` error if the file download request is aborted + if response headers are not received in 8 seconds. + + file_name: The name with which the file has to be uploaded. + + token: This is the client-generated JSON Web Token (JWT). The ImageKit.io server uses + it to authenticate and check that the upload request parameters have not been + tampered with after the token has been generated. Learn how to create the token + on the page below. This field is only required for authentication when uploading + a file from the client side. + + **Note**: Sending a JWT that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new token. + + **⚠️Warning**: JWT must be generated on the server-side because it is generated + using your account's private API key. This field is required for authentication + when uploading a file from the client-side. + + checks: Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file-v2#upload-api-checks). + + custom_coordinates: Define an important area in the image. This is only relevant for image type + files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + + custom_metadata: Stringified JSON key-value data to be associated with the asset. + + extensions: Stringified JSON object with an array of extensions to be applied to the image. + Refer to extensions schema in + [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). + + folder: The folder path in which the image has to be uploaded. If the folder(s) didn't + exist before, a new folder(s) is created. Using multiple `/` creates a nested + folder. + + is_private_file: Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + + is_published: Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + + overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + + overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + + overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + + overwrite_tags: If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + + response_fields: Comma-separated values of the fields that you want the API to return in the + response. + + For example, set the value of this field to + `tags,customCoordinates,isPrivateFile` to get the value of `tags`, + `customCoordinates`, and `isPrivateFile` in the response. + + Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, + `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. + + tags: Set the tags while uploading the file. + + Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length + of all characters should not exceed 500. `%` is not allowed. + + If this field is not specified and the file is overwritten then the tags will be + removed. + + transformation: + Stringified JSON object with properties for pre and post transformations: + + `pre` - Accepts a "string" containing a valid transformation used for requesting + a pre-transformation for an image or a video file. + + `post` - Accepts an array of objects with properties: + + - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` + (Adaptive bitrate streaming). + - `value`: A "string" corresponding to the required transformation. Required if + `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or + `thumbnail`. + - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. + + Read more about + [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). + + use_unique_file_name: Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return self._post( + "/api/v2/files/upload" + if self._client._base_url_overridden + else "https://upload.imagekit.io/api/v2/files/upload", + body=maybe_transform( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "response_fields": response_fields, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + }, + file_upload_v2_params.FileUploadV2Params, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileUploadV2Response, + ) + + +class AsyncFilesResource(AsyncAPIResource): + @cached_property + def details(self) -> AsyncDetailsResource: + return AsyncDetailsResource(self._client) + + @cached_property + def batch(self) -> AsyncBatchResource: + return AsyncBatchResource(self._client) + + @cached_property + def versions(self) -> AsyncVersionsResource: + return AsyncVersionsResource(self._client) + + @cached_property + def purge(self) -> AsyncPurgeResource: + return AsyncPurgeResource(self._client) + + @cached_property + def metadata(self) -> AsyncMetadataResource: + return AsyncMetadataResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncFilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncFilesResourceWithStreamingResponse(self) + + async def list( + self, + *, + file_type: str | NotGiven = NOT_GIVEN, + limit: str | NotGiven = NOT_GIVEN, + path: str | NotGiven = NOT_GIVEN, + search_query: str | NotGiven = NOT_GIVEN, + skip: str | NotGiven = NOT_GIVEN, + sort: str | NotGiven = NOT_GIVEN, + type: Literal["file", "file-version", "folder", "all"] | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileListResponse: + """ + This API can list all the uploaded files and folders in your ImageKit.io media + library. In addition, you can fine-tune your query by specifying various filters + by generating a query string in a Lucene-like syntax and provide this generated + string as the value of the `searchQuery`. + + Args: + file_type: + Type of files to include in the result set. Accepts three values: + + `all` - include all types of files in the result set. `image` - only search in + image type files. `non-image` - only search in files that are not images, e.g., + JS or CSS or video files. + + Default value - `all` + + limit: + The maximum number of results to return in response: + + Minimum value - 1 + + Maximum value - 1000 + + Default value - 1000 + + path: Folder path if you want to limit the search within a specific folder. For + example, `/sales-banner/` will only search in folder sales-banner. + + search_query: Query string in a Lucene-like query language e.g. `createdAt > "7d"`. + + Note : When the searchQuery parameter is present, the following query parameters + will have no effect on the result: + + 1. `tags` + 2. `type` + 3. `name` + + [Learn more](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#advanced-search-queries) + from examples. + + skip: + The number of results to skip before returning results: + + Minimum value - 0 + + Default value - 0 + + sort: + You can sort based on the following fields: + + 1. name - `ASC_NAME` or `DESC_NAME` + 2. createdAt - `ASC_CREATED` or `DESC_CREATED` + 3. updatedAt - `ASC_UPDATED` or `DESC_UPDATED` + 4. height - `ASC_HEIGHT` or `DESC_HEIGHT` + 5. width - `ASC_WIDTH` or `DESC_WIDTH` + 6. size - `ASC_SIZE` or `DESC_SIZE` + + Default value - `ASC_CREATED` + + type: Limit search to one of `file`, `file-version`, or `folder`. Pass `all` to + include `files` and `folders` in search results (`file-version` will not be + included in this case). + + Default value - `file` + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/v1/files", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "file_type": file_type, + "limit": limit, + "path": path, + "search_query": search_query, + "skip": skip, + "sort": sort, + "type": type, + }, + file_list_params.FileListParams, + ), + ), + cast_to=FileListResponse, + ) + + async def delete( + self, + file_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """ + This API deletes the file and all its file versions permanently. + + Note: If a file or specific transformation has been requested in the past, then + the response is cached. Deleting a file does not purge the cache. You can purge + the cache using purge cache API. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + f"/v1/files/{file_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def add_tags( + self, + *, + file_ids: List[str], + tags: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileAddTagsResponse: + """This API adds tags to multiple files in bulk. + + A maximum of 50 files can be + specified at a time. + + Args: + file_ids: An array of fileIds to which you want to add tags. + + tags: An array of tags that you want to add to the files. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/addTags", + body=await async_maybe_transform( + { + "file_ids": file_ids, + "tags": tags, + }, + file_add_tags_params.FileAddTagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileAddTagsResponse, + ) + + async def copy( + self, + *, + destination_path: str, + source_file_path: str, + include_file_versions: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """ + This will copy a file from one folder to another. + + Note: If any file at the destination has the same name as the source file, then + the source file and its versions (if `includeFileVersions` is set to true) will + be appended to the destination file version history. + + Args: + destination_path: Full path to the folder you want to copy the above file into. + + source_file_path: The full path of the file you want to copy. + + include_file_versions: Option to copy all versions of a file. By default, only the current version of + the file is copied. When set to true, all versions of the file will be copied. + Default value - `false`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/copy", + body=await async_maybe_transform( + { + "destination_path": destination_path, + "source_file_path": source_file_path, + "include_file_versions": include_file_versions, + }, + file_copy_params.FileCopyParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + async def move( + self, + *, + destination_path: str, + source_file_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """ + This will move a file and all its versions from one folder to another. + + Note: If any file at the destination has the same name as the source file, then + the source file and its versions will be appended to the destination file. + + Args: + destination_path: Full path to the folder you want to move the above file into. + + source_file_path: The full path of the file you want to move. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/move", + body=await async_maybe_transform( + { + "destination_path": destination_path, + "source_file_path": source_file_path, + }, + file_move_params.FileMoveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + async def remove_ai_tags( + self, + *, + ai_tags: List[str], + file_ids: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileRemoveAITagsResponse: + """This API removes AITags from multiple files in bulk. + + A maximum of 50 files can + be specified at a time. + + Args: + ai_tags: An array of AITags that you want to remove from the files. + + file_ids: An array of fileIds from which you want to remove AITags. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/removeAITags", + body=await async_maybe_transform( + { + "ai_tags": ai_tags, + "file_ids": file_ids, + }, + file_remove_ai_tags_params.FileRemoveAITagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileRemoveAITagsResponse, + ) + + async def remove_tags( + self, + *, + file_ids: List[str], + tags: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileRemoveTagsResponse: + """This API removes tags from multiple files in bulk. + + A maximum of 50 files can be + specified at a time. + + Args: + file_ids: An array of fileIds from which you want to remove tags. + + tags: An array of tags that you want to remove from the files. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/removeTags", + body=await async_maybe_transform( + { + "file_ids": file_ids, + "tags": tags, + }, + file_remove_tags_params.FileRemoveTagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileRemoveTagsResponse, + ) + + async def rename( + self, + *, + file_path: str, + new_file_name: str, + purge_cache: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileRenameResponse: + """ + You can rename an already existing file in the media library using rename file + API. This operation would rename all file versions of the file. + + Note: The old URLs will stop working. The file/file version URLs cached on CDN + will continue to work unless a purge is requested. + + Args: + file_path: The full path of the file you want to rename. + + new_file_name: + The new name of the file. A filename can contain: + + Alphanumeric Characters: `a-z`, `A-Z`, `0-9` (including Unicode letters, marks, + and numerals in other languages). Special Characters: `.`, `_`, and `-`. + + Any other character, including space, will be replaced by `_`. + + purge_cache: Option to purge cache for the old file and its versions' URLs. + + When set to true, it will internally issue a purge cache request on CDN to + remove cached content of old file and its versions. This purge request is + counted against your monthly purge quota. + + Note: If the old file were accessible at + `https://ik.imagekit.io/demo/old-filename.jpg`, a purge cache request would be + issued against `https://ik.imagekit.io/demo/old-filename.jpg*` (with a wildcard + at the end). It will remove the file and its versions' URLs and any + transformations made using query parameters on this file or its versions. + However, the cache for file transformations made using path parameters will + persist. You can purge them using the purge API. For more details, refer to the + purge API documentation. + + Default value - `false` + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._put( + "/v1/files/rename", + body=await async_maybe_transform( + { + "file_path": file_path, + "new_file_name": new_file_name, + "purge_cache": purge_cache, + }, + file_rename_params.FileRenameParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileRenameResponse, + ) + + async def upload_v1( + self, + *, + file: str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: str | NotGiven = NOT_GIVEN, + expire: str | NotGiven = NOT_GIVEN, + extensions: str | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: Literal["true", "false"] | NotGiven = NOT_GIVEN, + is_published: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_ai_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_file: str | NotGiven = NOT_GIVEN, + overwrite_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, + public_key: str | NotGiven = NOT_GIVEN, + response_fields: str | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + tags: str | NotGiven = NOT_GIVEN, + transformation: str | NotGiven = NOT_GIVEN, + use_unique_file_name: Literal["true", "false"] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadV1Response: + """ + ImageKit.io allows you to upload files directly from both the server and client + sides. For server-side uploads, private API key authentication is used. For + client-side uploads, generate a one-time `token`, `signature`, and `expiration` + from your secure backend using private API. + [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) + about how to implement client-side file upload. + + The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security + by verifying the entire payload using JWT. + + **File size limit** \\ + On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw + files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, + audio, and raw files and 2GB for videos. These limits can be further increased with + higher-tier plans. + + **Version limit** \\ + A file can have a maximum of 100 versions. + + **Demo applications** + + - A full-fledged + [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + supporting file selections from local storage, URL, Dropbox, Google Drive, + Instagram, and more. + - [Quick start guides](/docs/quick-start-guides) for various frameworks and + technologies. + + Args: + file: Pass the HTTP URL or base64 string. When passing a URL in the file parameter, + please ensure that our servers can access the URL. In case ImageKit is unable to + download the file from the specified URL, a `400` error response is returned. + This will also result in a `400` error if the file download request is aborted + if response headers are not received in 8 seconds. + + file_name: + The name with which the file has to be uploaded. The file name can contain: + + - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + - Special Characters: `.`, `-` + + Any other character including space will be replaced by `_` + + token: A unique value that the ImageKit.io server will use to recognize and prevent + subsequent retries for the same request. We suggest using V4 UUIDs, or another + random string with enough entropy to avoid collisions. This field is only + required for authentication when uploading a file from the client side. + + **Note**: Sending a value that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new value for this field. + + checks: Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + + custom_coordinates: Define an important area in the image. This is only relevant for image type + files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + + custom_metadata: Stringified JSON key-value data to be associated with the asset. + + expire: The time until your signature is valid. It must be a + [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into + the future. It should be in seconds. This field is only required for + authentication when uploading a file from the client side. + + extensions: Stringified JSON object with an array of extensions to be applied to the image. + Refer to extensions schema in + [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). + + folder: The folder path in which the image has to be uploaded. If the folder(s) didn't + exist before, a new folder(s) is created. + + The folder name can contain: + + - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + - Special Characters: `/` , `_` , `-` + + Using multiple `/` creates a nested folder. + + is_private_file: Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + + is_published: Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + + overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + + overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + + overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + + overwrite_tags: If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + + public_key: Your ImageKit.io public key. This field is only required for authentication when + uploading a file from the client side. + + response_fields: Comma-separated values of the fields that you want the API to return in the + response. + + For example, set the value of this field to + `tags,customCoordinates,isPrivateFile` to get the value of `tags`, + `customCoordinates`, and `isPrivateFile` in the response. + + Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, + `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. + + signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a + key. Learn how to create a signature on the page below. This should be in + lowercase. + + Signature must be calculated on the server-side. This field is only required for + authentication when uploading a file from the client side. + + tags: Set the tags while uploading the file. + + Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length + of all characters should not exceed 500. `%` is not allowed. + + If this field is not specified and the file is overwritten then the tags will be + removed. + + transformation: + Stringified JSON object with properties for pre and post transformations: + + `pre` - Accepts a "string" containing a valid transformation used for requesting + a pre-transformation for an image or a video file. + + `post` - Accepts an array of objects with properties: + + - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` + (Adaptive bitrate streaming). + - `value`: A "string" corresponding to the required transformation. Required if + `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or + `thumbnail`. + - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. + + Read more about + [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). + + use_unique_file_name: Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return await self._post( + "/api/v1/files/upload" + if self._client._base_url_overridden + else "https://upload.imagekit.io/api/v1/files/upload", + body=await async_maybe_transform( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "expire": expire, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "public_key": public_key, + "response_fields": response_fields, + "signature": signature, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + }, + file_upload_v1_params.FileUploadV1Params, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileUploadV1Response, + ) + + async def upload_v2( + self, + *, + file: str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: str | NotGiven = NOT_GIVEN, + extensions: str | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: Literal["true", "false"] | NotGiven = NOT_GIVEN, + is_published: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_ai_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: Literal["true", "false"] | NotGiven = NOT_GIVEN, + overwrite_file: str | NotGiven = NOT_GIVEN, + overwrite_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, + response_fields: str | NotGiven = NOT_GIVEN, + tags: str | NotGiven = NOT_GIVEN, + transformation: str | NotGiven = NOT_GIVEN, + use_unique_file_name: Literal["true", "false"] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadV2Response: + """The V2 API enhances security by verifying the entire payload using JWT. + + This API + is in beta. + + ImageKit.io allows you to upload files directly from both the server and client + sides. For server-side uploads, private API key authentication is used. For + client-side uploads, generate a one-time `token` from your secure backend using + private API. + [Learn more](/docs/api-reference/upload-file/upload-file-v2#how-to-implement-secure-client-side-file-upload) + about how to implement secure client-side file upload. + + **File size limit** \\ + On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw + files, and 100MB for videos. On the paid plan, these limits increase to 40MB for + images, audio, and raw files, and 2GB for videos. These limits can be further increased + with higher-tier plans. + + **Version limit** \\ + A file can have a maximum of 100 versions. + + **Demo applications** + + - A full-fledged + [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + supporting file selections from local storage, URL, Dropbox, Google Drive, + Instagram, and more. + - [Quick start guides](/docs/quick-start-guides) for various frameworks and + technologies. + + Args: + file: Pass the HTTP URL or base64 string. When passing a URL in the file parameter, + please ensure that our servers can access the URL. In case ImageKit is unable to + download the file from the specified URL, a `400` error response is returned. + This will also result in a `400` error if the file download request is aborted + if response headers are not received in 8 seconds. + + file_name: The name with which the file has to be uploaded. + + token: This is the client-generated JSON Web Token (JWT). The ImageKit.io server uses + it to authenticate and check that the upload request parameters have not been + tampered with after the token has been generated. Learn how to create the token + on the page below. This field is only required for authentication when uploading + a file from the client side. + + **Note**: Sending a JWT that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new token. + + **⚠️Warning**: JWT must be generated on the server-side because it is generated + using your account's private API key. This field is required for authentication + when uploading a file from the client-side. + + checks: Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file-v2#upload-api-checks). + + custom_coordinates: Define an important area in the image. This is only relevant for image type + files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + + custom_metadata: Stringified JSON key-value data to be associated with the asset. + + extensions: Stringified JSON object with an array of extensions to be applied to the image. + Refer to extensions schema in + [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). + + folder: The folder path in which the image has to be uploaded. If the folder(s) didn't + exist before, a new folder(s) is created. Using multiple `/` creates a nested + folder. + + is_private_file: Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + + is_published: Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + + overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + + overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + + overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + + overwrite_tags: If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + + response_fields: Comma-separated values of the fields that you want the API to return in the + response. + + For example, set the value of this field to + `tags,customCoordinates,isPrivateFile` to get the value of `tags`, + `customCoordinates`, and `isPrivateFile` in the response. + + Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, + `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. + + tags: Set the tags while uploading the file. + + Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length + of all characters should not exceed 500. `%` is not allowed. + + If this field is not specified and the file is overwritten then the tags will be + removed. + + transformation: + Stringified JSON object with properties for pre and post transformations: + + `pre` - Accepts a "string" containing a valid transformation used for requesting + a pre-transformation for an image or a video file. + + `post` - Accepts an array of objects with properties: + + - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` + (Adaptive bitrate streaming). + - `value`: A "string" corresponding to the required transformation. Required if + `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or + `thumbnail`. + - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. + + Read more about + [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). + + use_unique_file_name: Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return await self._post( + "/api/v2/files/upload" + if self._client._base_url_overridden + else "https://upload.imagekit.io/api/v2/files/upload", + body=await async_maybe_transform( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "response_fields": response_fields, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + }, + file_upload_v2_params.FileUploadV2Params, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileUploadV2Response, + ) + + +class FilesResourceWithRawResponse: + def __init__(self, files: FilesResource) -> None: + self._files = files + + self.list = to_raw_response_wrapper( + files.list, + ) + self.delete = to_raw_response_wrapper( + files.delete, + ) + self.add_tags = to_raw_response_wrapper( + files.add_tags, + ) + self.copy = to_raw_response_wrapper( + files.copy, + ) + self.move = to_raw_response_wrapper( + files.move, + ) + self.remove_ai_tags = to_raw_response_wrapper( + files.remove_ai_tags, + ) + self.remove_tags = to_raw_response_wrapper( + files.remove_tags, + ) + self.rename = to_raw_response_wrapper( + files.rename, + ) + self.upload_v1 = to_raw_response_wrapper( + files.upload_v1, + ) + self.upload_v2 = to_raw_response_wrapper( + files.upload_v2, + ) + + @cached_property + def details(self) -> DetailsResourceWithRawResponse: + return DetailsResourceWithRawResponse(self._files.details) + + @cached_property + def batch(self) -> BatchResourceWithRawResponse: + return BatchResourceWithRawResponse(self._files.batch) + + @cached_property + def versions(self) -> VersionsResourceWithRawResponse: + return VersionsResourceWithRawResponse(self._files.versions) + + @cached_property + def purge(self) -> PurgeResourceWithRawResponse: + return PurgeResourceWithRawResponse(self._files.purge) + + @cached_property + def metadata(self) -> MetadataResourceWithRawResponse: + return MetadataResourceWithRawResponse(self._files.metadata) + + +class AsyncFilesResourceWithRawResponse: + def __init__(self, files: AsyncFilesResource) -> None: + self._files = files + + self.list = async_to_raw_response_wrapper( + files.list, + ) + self.delete = async_to_raw_response_wrapper( + files.delete, + ) + self.add_tags = async_to_raw_response_wrapper( + files.add_tags, + ) + self.copy = async_to_raw_response_wrapper( + files.copy, + ) + self.move = async_to_raw_response_wrapper( + files.move, + ) + self.remove_ai_tags = async_to_raw_response_wrapper( + files.remove_ai_tags, + ) + self.remove_tags = async_to_raw_response_wrapper( + files.remove_tags, + ) + self.rename = async_to_raw_response_wrapper( + files.rename, + ) + self.upload_v1 = async_to_raw_response_wrapper( + files.upload_v1, + ) + self.upload_v2 = async_to_raw_response_wrapper( + files.upload_v2, + ) + + @cached_property + def details(self) -> AsyncDetailsResourceWithRawResponse: + return AsyncDetailsResourceWithRawResponse(self._files.details) + + @cached_property + def batch(self) -> AsyncBatchResourceWithRawResponse: + return AsyncBatchResourceWithRawResponse(self._files.batch) + + @cached_property + def versions(self) -> AsyncVersionsResourceWithRawResponse: + return AsyncVersionsResourceWithRawResponse(self._files.versions) + + @cached_property + def purge(self) -> AsyncPurgeResourceWithRawResponse: + return AsyncPurgeResourceWithRawResponse(self._files.purge) + + @cached_property + def metadata(self) -> AsyncMetadataResourceWithRawResponse: + return AsyncMetadataResourceWithRawResponse(self._files.metadata) + + +class FilesResourceWithStreamingResponse: + def __init__(self, files: FilesResource) -> None: + self._files = files + + self.list = to_streamed_response_wrapper( + files.list, + ) + self.delete = to_streamed_response_wrapper( + files.delete, + ) + self.add_tags = to_streamed_response_wrapper( + files.add_tags, + ) + self.copy = to_streamed_response_wrapper( + files.copy, + ) + self.move = to_streamed_response_wrapper( + files.move, + ) + self.remove_ai_tags = to_streamed_response_wrapper( + files.remove_ai_tags, + ) + self.remove_tags = to_streamed_response_wrapper( + files.remove_tags, + ) + self.rename = to_streamed_response_wrapper( + files.rename, + ) + self.upload_v1 = to_streamed_response_wrapper( + files.upload_v1, + ) + self.upload_v2 = to_streamed_response_wrapper( + files.upload_v2, + ) + + @cached_property + def details(self) -> DetailsResourceWithStreamingResponse: + return DetailsResourceWithStreamingResponse(self._files.details) + + @cached_property + def batch(self) -> BatchResourceWithStreamingResponse: + return BatchResourceWithStreamingResponse(self._files.batch) + + @cached_property + def versions(self) -> VersionsResourceWithStreamingResponse: + return VersionsResourceWithStreamingResponse(self._files.versions) + + @cached_property + def purge(self) -> PurgeResourceWithStreamingResponse: + return PurgeResourceWithStreamingResponse(self._files.purge) + + @cached_property + def metadata(self) -> MetadataResourceWithStreamingResponse: + return MetadataResourceWithStreamingResponse(self._files.metadata) + + +class AsyncFilesResourceWithStreamingResponse: + def __init__(self, files: AsyncFilesResource) -> None: + self._files = files + + self.list = async_to_streamed_response_wrapper( + files.list, + ) + self.delete = async_to_streamed_response_wrapper( + files.delete, + ) + self.add_tags = async_to_streamed_response_wrapper( + files.add_tags, + ) + self.copy = async_to_streamed_response_wrapper( + files.copy, + ) + self.move = async_to_streamed_response_wrapper( + files.move, + ) + self.remove_ai_tags = async_to_streamed_response_wrapper( + files.remove_ai_tags, + ) + self.remove_tags = async_to_streamed_response_wrapper( + files.remove_tags, + ) + self.rename = async_to_streamed_response_wrapper( + files.rename, + ) + self.upload_v1 = async_to_streamed_response_wrapper( + files.upload_v1, + ) + self.upload_v2 = async_to_streamed_response_wrapper( + files.upload_v2, + ) + + @cached_property + def details(self) -> AsyncDetailsResourceWithStreamingResponse: + return AsyncDetailsResourceWithStreamingResponse(self._files.details) + + @cached_property + def batch(self) -> AsyncBatchResourceWithStreamingResponse: + return AsyncBatchResourceWithStreamingResponse(self._files.batch) + + @cached_property + def versions(self) -> AsyncVersionsResourceWithStreamingResponse: + return AsyncVersionsResourceWithStreamingResponse(self._files.versions) + + @cached_property + def purge(self) -> AsyncPurgeResourceWithStreamingResponse: + return AsyncPurgeResourceWithStreamingResponse(self._files.purge) + + @cached_property + def metadata(self) -> AsyncMetadataResourceWithStreamingResponse: + return AsyncMetadataResourceWithStreamingResponse(self._files.metadata) diff --git a/src/imagekit/resources/files/metadata.py b/src/imagekit/resources/files/metadata.py new file mode 100644 index 0000000..7a019cd --- /dev/null +++ b/src/imagekit/resources/files/metadata.py @@ -0,0 +1,264 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.files import metadata_from_url_params +from ..._base_client import make_request_options +from ...types.files.metadata_from_url_response import MetadataFromURLResponse +from ...types.files.metadata_retrieve_response import MetadataRetrieveResponse + +__all__ = ["MetadataResource", "AsyncMetadataResource"] + + +class MetadataResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> MetadataResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return MetadataResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> MetadataResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return MetadataResourceWithStreamingResponse(self) + + def retrieve( + self, + file_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> MetadataRetrieveResponse: + """ + You can programmatically get image EXIF, pHash, and other metadata for uploaded + files in the ImageKit.io media library using this API. + + You can also get the metadata in upload API response by passing `metadata` in + `responseFields` parameter. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return self._get( + f"/v1/files/{file_id}/metadata", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MetadataRetrieveResponse, + ) + + def from_url( + self, + *, + url: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> MetadataFromURLResponse: + """ + Get image EXIF, pHash, and other metadata from ImageKit.io powered remote URL + using this API. + + Args: + url: Should be a valid file URL. It should be accessible using your ImageKit.io + account. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/v1/files/metadata", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"url": url}, metadata_from_url_params.MetadataFromURLParams), + ), + cast_to=MetadataFromURLResponse, + ) + + +class AsyncMetadataResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncMetadataResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncMetadataResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncMetadataResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncMetadataResourceWithStreamingResponse(self) + + async def retrieve( + self, + file_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> MetadataRetrieveResponse: + """ + You can programmatically get image EXIF, pHash, and other metadata for uploaded + files in the ImageKit.io media library using this API. + + You can also get the metadata in upload API response by passing `metadata` in + `responseFields` parameter. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return await self._get( + f"/v1/files/{file_id}/metadata", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MetadataRetrieveResponse, + ) + + async def from_url( + self, + *, + url: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> MetadataFromURLResponse: + """ + Get image EXIF, pHash, and other metadata from ImageKit.io powered remote URL + using this API. + + Args: + url: Should be a valid file URL. It should be accessible using your ImageKit.io + account. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/v1/files/metadata", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"url": url}, metadata_from_url_params.MetadataFromURLParams), + ), + cast_to=MetadataFromURLResponse, + ) + + +class MetadataResourceWithRawResponse: + def __init__(self, metadata: MetadataResource) -> None: + self._metadata = metadata + + self.retrieve = to_raw_response_wrapper( + metadata.retrieve, + ) + self.from_url = to_raw_response_wrapper( + metadata.from_url, + ) + + +class AsyncMetadataResourceWithRawResponse: + def __init__(self, metadata: AsyncMetadataResource) -> None: + self._metadata = metadata + + self.retrieve = async_to_raw_response_wrapper( + metadata.retrieve, + ) + self.from_url = async_to_raw_response_wrapper( + metadata.from_url, + ) + + +class MetadataResourceWithStreamingResponse: + def __init__(self, metadata: MetadataResource) -> None: + self._metadata = metadata + + self.retrieve = to_streamed_response_wrapper( + metadata.retrieve, + ) + self.from_url = to_streamed_response_wrapper( + metadata.from_url, + ) + + +class AsyncMetadataResourceWithStreamingResponse: + def __init__(self, metadata: AsyncMetadataResource) -> None: + self._metadata = metadata + + self.retrieve = async_to_streamed_response_wrapper( + metadata.retrieve, + ) + self.from_url = async_to_streamed_response_wrapper( + metadata.from_url, + ) diff --git a/src/imagekit/resources/files/purge.py b/src/imagekit/resources/files/purge.py new file mode 100644 index 0000000..6282979 --- /dev/null +++ b/src/imagekit/resources/files/purge.py @@ -0,0 +1,252 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.files import purge_execute_params +from ..._base_client import make_request_options +from ...types.files.purge_status_response import PurgeStatusResponse +from ...types.files.purge_execute_response import PurgeExecuteResponse + +__all__ = ["PurgeResource", "AsyncPurgeResource"] + + +class PurgeResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> PurgeResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return PurgeResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> PurgeResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return PurgeResourceWithStreamingResponse(self) + + def execute( + self, + *, + url: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> PurgeExecuteResponse: + """This API will purge CDN cache and ImageKit.io's internal cache for a file. + + Note: + Purge cache is an asynchronous process and it may take some time to reflect the + changes. + + Args: + url: The full URL of the file to be purged. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/purge", + body=maybe_transform({"url": url}, purge_execute_params.PurgeExecuteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PurgeExecuteResponse, + ) + + def status( + self, + request_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> PurgeStatusResponse: + """ + This API returns the status of a purge cache request. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not request_id: + raise ValueError(f"Expected a non-empty value for `request_id` but received {request_id!r}") + return self._get( + f"/v1/files/purge/{request_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PurgeStatusResponse, + ) + + +class AsyncPurgeResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncPurgeResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncPurgeResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncPurgeResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncPurgeResourceWithStreamingResponse(self) + + async def execute( + self, + *, + url: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> PurgeExecuteResponse: + """This API will purge CDN cache and ImageKit.io's internal cache for a file. + + Note: + Purge cache is an asynchronous process and it may take some time to reflect the + changes. + + Args: + url: The full URL of the file to be purged. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/purge", + body=await async_maybe_transform({"url": url}, purge_execute_params.PurgeExecuteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PurgeExecuteResponse, + ) + + async def status( + self, + request_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> PurgeStatusResponse: + """ + This API returns the status of a purge cache request. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not request_id: + raise ValueError(f"Expected a non-empty value for `request_id` but received {request_id!r}") + return await self._get( + f"/v1/files/purge/{request_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PurgeStatusResponse, + ) + + +class PurgeResourceWithRawResponse: + def __init__(self, purge: PurgeResource) -> None: + self._purge = purge + + self.execute = to_raw_response_wrapper( + purge.execute, + ) + self.status = to_raw_response_wrapper( + purge.status, + ) + + +class AsyncPurgeResourceWithRawResponse: + def __init__(self, purge: AsyncPurgeResource) -> None: + self._purge = purge + + self.execute = async_to_raw_response_wrapper( + purge.execute, + ) + self.status = async_to_raw_response_wrapper( + purge.status, + ) + + +class PurgeResourceWithStreamingResponse: + def __init__(self, purge: PurgeResource) -> None: + self._purge = purge + + self.execute = to_streamed_response_wrapper( + purge.execute, + ) + self.status = to_streamed_response_wrapper( + purge.status, + ) + + +class AsyncPurgeResourceWithStreamingResponse: + def __init__(self, purge: AsyncPurgeResource) -> None: + self._purge = purge + + self.execute = async_to_streamed_response_wrapper( + purge.execute, + ) + self.status = async_to_streamed_response_wrapper( + purge.status, + ) diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py new file mode 100644 index 0000000..c99c590 --- /dev/null +++ b/src/imagekit/resources/files/versions.py @@ -0,0 +1,425 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.files.version_list_response import VersionListResponse +from ...types.files.version_restore_response import VersionRestoreResponse +from ...types.files.version_retrieve_response import VersionRetrieveResponse + +__all__ = ["VersionsResource", "AsyncVersionsResource"] + + +class VersionsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> VersionsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return VersionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> VersionsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return VersionsResourceWithStreamingResponse(self) + + def retrieve( + self, + version_id: str, + *, + file_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> VersionRetrieveResponse: + """ + This API returns an object with details or attributes of a file version. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + if not version_id: + raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") + return self._get( + f"/v1/files/{file_id}/versions/{version_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VersionRetrieveResponse, + ) + + def list( + self, + file_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> VersionListResponse: + """ + This API returns details of all versions of a file. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return self._get( + f"/v1/files/{file_id}/versions", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VersionListResponse, + ) + + def delete( + self, + version_id: str, + *, + file_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This API deletes a non-current file version permanently. + + The API returns an + empty response. + + Note: If you want to delete all versions of a file, use the delete file API. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + if not version_id: + raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") + return self._delete( + f"/v1/files/{file_id}/versions/{version_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + def restore( + self, + version_id: str, + *, + file_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> VersionRestoreResponse: + """ + This API restores a file version as the current file version. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + if not version_id: + raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") + return self._put( + f"/v1/files/{file_id}/versions/{version_id}/restore", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VersionRestoreResponse, + ) + + +class AsyncVersionsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncVersionsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncVersionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncVersionsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncVersionsResourceWithStreamingResponse(self) + + async def retrieve( + self, + version_id: str, + *, + file_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> VersionRetrieveResponse: + """ + This API returns an object with details or attributes of a file version. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + if not version_id: + raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") + return await self._get( + f"/v1/files/{file_id}/versions/{version_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VersionRetrieveResponse, + ) + + async def list( + self, + file_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> VersionListResponse: + """ + This API returns details of all versions of a file. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return await self._get( + f"/v1/files/{file_id}/versions", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VersionListResponse, + ) + + async def delete( + self, + version_id: str, + *, + file_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This API deletes a non-current file version permanently. + + The API returns an + empty response. + + Note: If you want to delete all versions of a file, use the delete file API. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + if not version_id: + raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") + return await self._delete( + f"/v1/files/{file_id}/versions/{version_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + async def restore( + self, + version_id: str, + *, + file_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> VersionRestoreResponse: + """ + This API restores a file version as the current file version. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + if not version_id: + raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") + return await self._put( + f"/v1/files/{file_id}/versions/{version_id}/restore", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VersionRestoreResponse, + ) + + +class VersionsResourceWithRawResponse: + def __init__(self, versions: VersionsResource) -> None: + self._versions = versions + + self.retrieve = to_raw_response_wrapper( + versions.retrieve, + ) + self.list = to_raw_response_wrapper( + versions.list, + ) + self.delete = to_raw_response_wrapper( + versions.delete, + ) + self.restore = to_raw_response_wrapper( + versions.restore, + ) + + +class AsyncVersionsResourceWithRawResponse: + def __init__(self, versions: AsyncVersionsResource) -> None: + self._versions = versions + + self.retrieve = async_to_raw_response_wrapper( + versions.retrieve, + ) + self.list = async_to_raw_response_wrapper( + versions.list, + ) + self.delete = async_to_raw_response_wrapper( + versions.delete, + ) + self.restore = async_to_raw_response_wrapper( + versions.restore, + ) + + +class VersionsResourceWithStreamingResponse: + def __init__(self, versions: VersionsResource) -> None: + self._versions = versions + + self.retrieve = to_streamed_response_wrapper( + versions.retrieve, + ) + self.list = to_streamed_response_wrapper( + versions.list, + ) + self.delete = to_streamed_response_wrapper( + versions.delete, + ) + self.restore = to_streamed_response_wrapper( + versions.restore, + ) + + +class AsyncVersionsResourceWithStreamingResponse: + def __init__(self, versions: AsyncVersionsResource) -> None: + self._versions = versions + + self.retrieve = async_to_streamed_response_wrapper( + versions.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + versions.list, + ) + self.delete = async_to_streamed_response_wrapper( + versions.delete, + ) + self.restore = async_to_streamed_response_wrapper( + versions.restore, + ) diff --git a/src/imagekit/resources/folder.py b/src/imagekit/resources/folder.py new file mode 100644 index 0000000..15c5aa3 --- /dev/null +++ b/src/imagekit/resources/folder.py @@ -0,0 +1,292 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..types import folder_create_params, folder_delete_params +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options + +__all__ = ["FolderResource", "AsyncFolderResource"] + + +class FolderResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> FolderResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return FolderResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FolderResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return FolderResourceWithStreamingResponse(self) + + def create( + self, + *, + folder_name: str, + parent_folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This will create a new folder. + + You can specify the folder name and location of + the parent folder where this new folder should be created. + + Args: + folder_name: The folder will be created with this name. + + All characters except alphabets and numbers (inclusive of unicode letters, + marks, and numerals in other languages) will be replaced by an underscore i.e. + `_`. + + parent_folder_path: The folder where the new folder should be created, for root use `/` else the + path e.g. `containing/folder/`. + + Note: If any folder(s) is not present in the parentFolderPath parameter, it will + be automatically created. For example, if you pass `/product/images/summer`, + then `product`, `images`, and `summer` folders will be created if they don't + already exist. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/folder", + body=maybe_transform( + { + "folder_name": folder_name, + "parent_folder_path": parent_folder_path, + }, + folder_create_params.FolderCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + def delete( + self, + *, + folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This will delete a folder and all its contents permanently. + + The API returns an + empty response. + + Args: + folder_path: Full path to the folder you want to delete. For example `/folder/to/delete/`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._delete( + "/v1/folder", + body=maybe_transform({"folder_path": folder_path}, folder_delete_params.FolderDeleteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + +class AsyncFolderResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncFolderResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncFolderResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFolderResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncFolderResourceWithStreamingResponse(self) + + async def create( + self, + *, + folder_name: str, + parent_folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This will create a new folder. + + You can specify the folder name and location of + the parent folder where this new folder should be created. + + Args: + folder_name: The folder will be created with this name. + + All characters except alphabets and numbers (inclusive of unicode letters, + marks, and numerals in other languages) will be replaced by an underscore i.e. + `_`. + + parent_folder_path: The folder where the new folder should be created, for root use `/` else the + path e.g. `containing/folder/`. + + Note: If any folder(s) is not present in the parentFolderPath parameter, it will + be automatically created. For example, if you pass `/product/images/summer`, + then `product`, `images`, and `summer` folders will be created if they don't + already exist. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/folder", + body=await async_maybe_transform( + { + "folder_name": folder_name, + "parent_folder_path": parent_folder_path, + }, + folder_create_params.FolderCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + async def delete( + self, + *, + folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This will delete a folder and all its contents permanently. + + The API returns an + empty response. + + Args: + folder_path: Full path to the folder you want to delete. For example `/folder/to/delete/`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._delete( + "/v1/folder", + body=await async_maybe_transform({"folder_path": folder_path}, folder_delete_params.FolderDeleteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + +class FolderResourceWithRawResponse: + def __init__(self, folder: FolderResource) -> None: + self._folder = folder + + self.create = to_raw_response_wrapper( + folder.create, + ) + self.delete = to_raw_response_wrapper( + folder.delete, + ) + + +class AsyncFolderResourceWithRawResponse: + def __init__(self, folder: AsyncFolderResource) -> None: + self._folder = folder + + self.create = async_to_raw_response_wrapper( + folder.create, + ) + self.delete = async_to_raw_response_wrapper( + folder.delete, + ) + + +class FolderResourceWithStreamingResponse: + def __init__(self, folder: FolderResource) -> None: + self._folder = folder + + self.create = to_streamed_response_wrapper( + folder.create, + ) + self.delete = to_streamed_response_wrapper( + folder.delete, + ) + + +class AsyncFolderResourceWithStreamingResponse: + def __init__(self, folder: AsyncFolderResource) -> None: + self._folder = folder + + self.create = async_to_streamed_response_wrapper( + folder.create, + ) + self.delete = async_to_streamed_response_wrapper( + folder.delete, + ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py new file mode 100644 index 0000000..ce57f06 --- /dev/null +++ b/src/imagekit/types/__init__.py @@ -0,0 +1,39 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .file_copy_params import FileCopyParams as FileCopyParams +from .file_list_params import FileListParams as FileListParams +from .file_move_params import FileMoveParams as FileMoveParams +from .file_list_response import FileListResponse as FileListResponse +from .file_rename_params import FileRenameParams as FileRenameParams +from .file_add_tags_params import FileAddTagsParams as FileAddTagsParams +from .file_rename_response import FileRenameResponse as FileRenameResponse +from .folder_create_params import FolderCreateParams as FolderCreateParams +from .folder_delete_params import FolderDeleteParams as FolderDeleteParams +from .file_upload_v1_params import FileUploadV1Params as FileUploadV1Params +from .file_upload_v2_params import FileUploadV2Params as FileUploadV2Params +from .file_add_tags_response import FileAddTagsResponse as FileAddTagsResponse +from .file_remove_tags_params import FileRemoveTagsParams as FileRemoveTagsParams +from .file_upload_v1_response import FileUploadV1Response as FileUploadV1Response +from .file_upload_v2_response import FileUploadV2Response as FileUploadV2Response +from .account_get_usage_params import AccountGetUsageParams as AccountGetUsageParams +from .file_remove_tags_response import FileRemoveTagsResponse as FileRemoveTagsResponse +from .account_get_usage_response import AccountGetUsageResponse as AccountGetUsageResponse +from .file_remove_ai_tags_params import FileRemoveAITagsParams as FileRemoveAITagsParams +from .bulk_job_copy_folder_params import BulkJobCopyFolderParams as BulkJobCopyFolderParams +from .bulk_job_move_folder_params import BulkJobMoveFolderParams as BulkJobMoveFolderParams +from .file_remove_ai_tags_response import FileRemoveAITagsResponse as FileRemoveAITagsResponse +from .bulk_job_copy_folder_response import BulkJobCopyFolderResponse as BulkJobCopyFolderResponse +from .bulk_job_move_folder_response import BulkJobMoveFolderResponse as BulkJobMoveFolderResponse +from .bulk_job_retrieve_status_response import BulkJobRetrieveStatusResponse as BulkJobRetrieveStatusResponse +from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams +from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams +from .custom_metadata_field_list_response import CustomMetadataFieldListResponse as CustomMetadataFieldListResponse +from .custom_metadata_field_update_params import CustomMetadataFieldUpdateParams as CustomMetadataFieldUpdateParams +from .custom_metadata_field_create_response import ( + CustomMetadataFieldCreateResponse as CustomMetadataFieldCreateResponse, +) +from .custom_metadata_field_update_response import ( + CustomMetadataFieldUpdateResponse as CustomMetadataFieldUpdateResponse, +) diff --git a/src/imagekit/types/account_get_usage_params.py b/src/imagekit/types/account_get_usage_params.py new file mode 100644 index 0000000..ab07ac0 --- /dev/null +++ b/src/imagekit/types/account_get_usage_params.py @@ -0,0 +1,27 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import date +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["AccountGetUsageParams"] + + +class AccountGetUsageParams(TypedDict, total=False): + end_date: Required[Annotated[Union[str, date], PropertyInfo(alias="endDate", format="iso8601")]] + """Specify a `endDate` in `YYYY-MM-DD` format. + + It should be after the `startDate`. The difference between `startDate` and + `endDate` should be less than 90 days. + """ + + start_date: Required[Annotated[Union[str, date], PropertyInfo(alias="startDate", format="iso8601")]] + """Specify a `startDate` in `YYYY-MM-DD` format. + + It should be before the `endDate`. The difference between `startDate` and + `endDate` should be less than 90 days. + """ diff --git a/src/imagekit/types/account_get_usage_response.py b/src/imagekit/types/account_get_usage_response.py new file mode 100644 index 0000000..524d9f3 --- /dev/null +++ b/src/imagekit/types/account_get_usage_response.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["AccountGetUsageResponse"] + + +class AccountGetUsageResponse(BaseModel): + bandwidth_bytes: Optional[int] = FieldInfo(alias="bandwidthBytes", default=None) + """Amount of bandwidth used in bytes.""" + + extension_units_count: Optional[int] = FieldInfo(alias="extensionUnitsCount", default=None) + """Number of extension units used.""" + + media_library_storage_bytes: Optional[int] = FieldInfo(alias="mediaLibraryStorageBytes", default=None) + """Storage used by media library in bytes.""" + + original_cache_storage_bytes: Optional[int] = FieldInfo(alias="originalCacheStorageBytes", default=None) + """Storage used by the original cache in bytes.""" + + video_processing_units_count: Optional[int] = FieldInfo(alias="videoProcessingUnitsCount", default=None) + """Number of video processing units used.""" diff --git a/src/imagekit/types/bulk_job_copy_folder_params.py b/src/imagekit/types/bulk_job_copy_folder_params.py new file mode 100644 index 0000000..b6c36b7 --- /dev/null +++ b/src/imagekit/types/bulk_job_copy_folder_params.py @@ -0,0 +1,27 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["BulkJobCopyFolderParams"] + + +class BulkJobCopyFolderParams(TypedDict, total=False): + destination_path: Required[Annotated[str, PropertyInfo(alias="destinationPath")]] + """ + Full path to the destination folder where you want to copy the source folder + into. + """ + + source_folder_path: Required[Annotated[str, PropertyInfo(alias="sourceFolderPath")]] + """The full path to the source folder you want to copy.""" + + include_versions: Annotated[bool, PropertyInfo(alias="includeVersions")] + """Option to copy all versions of files that are nested inside the selected folder. + + By default, only the current version of each file will be copied. When set to + true, all versions of each file will be copied. Default value - `false`. + """ diff --git a/src/imagekit/types/bulk_job_copy_folder_response.py b/src/imagekit/types/bulk_job_copy_folder_response.py new file mode 100644 index 0000000..088c6c8 --- /dev/null +++ b/src/imagekit/types/bulk_job_copy_folder_response.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["BulkJobCopyFolderResponse"] + + +class BulkJobCopyFolderResponse(BaseModel): + job_id: Optional[str] = FieldInfo(alias="jobId", default=None) + """Unique identifier of the bulk job. + + This can be used to check the status of the bulk job. + """ diff --git a/src/imagekit/types/bulk_job_move_folder_params.py b/src/imagekit/types/bulk_job_move_folder_params.py new file mode 100644 index 0000000..3414b45 --- /dev/null +++ b/src/imagekit/types/bulk_job_move_folder_params.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["BulkJobMoveFolderParams"] + + +class BulkJobMoveFolderParams(TypedDict, total=False): + destination_path: Required[Annotated[str, PropertyInfo(alias="destinationPath")]] + """ + Full path to the destination folder where you want to move the source folder + into. + """ + + source_folder_path: Required[Annotated[str, PropertyInfo(alias="sourceFolderPath")]] + """The full path to the source folder you want to move.""" diff --git a/src/imagekit/types/bulk_job_move_folder_response.py b/src/imagekit/types/bulk_job_move_folder_response.py new file mode 100644 index 0000000..d6e72c3 --- /dev/null +++ b/src/imagekit/types/bulk_job_move_folder_response.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["BulkJobMoveFolderResponse"] + + +class BulkJobMoveFolderResponse(BaseModel): + job_id: Optional[str] = FieldInfo(alias="jobId", default=None) + """Unique identifier of the bulk job. + + This can be used to check the status of the bulk job. + """ diff --git a/src/imagekit/types/bulk_job_retrieve_status_response.py b/src/imagekit/types/bulk_job_retrieve_status_response.py new file mode 100644 index 0000000..5d50476 --- /dev/null +++ b/src/imagekit/types/bulk_job_retrieve_status_response.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["BulkJobRetrieveStatusResponse"] + + +class BulkJobRetrieveStatusResponse(BaseModel): + job_id: Optional[str] = FieldInfo(alias="jobId", default=None) + """Unique identifier of the bulk job.""" + + status: Optional[str] = None + """Status of the bulk job. Possible values - `Pending`, `Completed`.""" + + type: Optional[str] = None + """Type of the bulk job. Possible values - `COPY_FOLDER`, `MOVE_FOLDER`.""" diff --git a/src/imagekit/types/custom_metadata_field_create_params.py b/src/imagekit/types/custom_metadata_field_create_params.py new file mode 100644 index 0000000..a971d1a --- /dev/null +++ b/src/imagekit/types/custom_metadata_field_create_params.py @@ -0,0 +1,82 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union +from typing_extensions import Literal, Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["CustomMetadataFieldCreateParams", "Schema"] + + +class CustomMetadataFieldCreateParams(TypedDict, total=False): + label: Required[str] + """Human readable name of the custom metadata field. + + This should be unique across all non deleted custom metadata fields. This name + is displayed as form field label to the users while setting field value on an + asset in the media library UI. + """ + + name: Required[str] + """API name of the custom metadata field. + + This should be unique across all (including deleted) custom metadata fields. + """ + + schema: Required[Schema] + + +class Schema(TypedDict, total=False): + type: Required[Literal["Text", "TextArea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"]] + """Type of the custom metadata field.""" + + default_value: Annotated[Union[str, float, bool, List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue")] + """The default value for this custom metadata field. + + This property is only required if `isValueRequired` property is set to `true`. + The value should match the `type` of custom metadata field. + """ + + is_value_required: Annotated[bool, PropertyInfo(alias="isValueRequired")] + """Sets this custom metadata field as required. + + Setting custom metadata fields on an asset will throw error if the value for all + required fields are not present in upload or update asset API request body. + """ + + max_length: Annotated[float, PropertyInfo(alias="maxLength")] + """Maximum length of string. + + Only set this property if `type` is set to `Text` or `Textarea`. + """ + + max_value: Annotated[Union[str, float], PropertyInfo(alias="maxValue")] + """Maximum value of the field. + + Only set this property if field type is `Date` or `Number`. For `Date` type + field, set the minimum date in ISO8601 string format. For `Number` type field, + set the minimum numeric value. + """ + + min_length: Annotated[float, PropertyInfo(alias="minLength")] + """Minimum length of string. + + Only set this property if `type` is set to `Text` or `Textarea`. + """ + + min_value: Annotated[Union[str, float], PropertyInfo(alias="minValue")] + """Minimum value of the field. + + Only set this property if field type is `Date` or `Number`. For `Date` type + field, set the minimum date in ISO8601 string format. For `Number` type field, + set the minimum numeric value. + """ + + select_options: Annotated[List[Union[str, float, bool]], PropertyInfo(alias="selectOptions")] + """An array of allowed values. + + This property is only required if `type` property is set to `SingleSelect` or + `MultiSelect`. + """ diff --git a/src/imagekit/types/custom_metadata_field_create_response.py b/src/imagekit/types/custom_metadata_field_create_response.py new file mode 100644 index 0000000..7113c1f --- /dev/null +++ b/src/imagekit/types/custom_metadata_field_create_response.py @@ -0,0 +1,73 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["CustomMetadataFieldCreateResponse", "Schema"] + + +class Schema(BaseModel): + type: Literal["Text", "TextArea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] + """Type of the custom metadata field.""" + + default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( + alias="defaultValue", default=None + ) + """The default value for this custom metadata field. + + Date type of default value depends on the field type. + """ + + is_value_required: Optional[bool] = FieldInfo(alias="isValueRequired", default=None) + """Specifies if the this custom metadata field is required or not.""" + + max_length: Optional[float] = FieldInfo(alias="maxLength", default=None) + """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + max_value: Union[str, float, None] = FieldInfo(alias="maxValue", default=None) + """Maximum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + min_length: Optional[float] = FieldInfo(alias="minLength", default=None) + """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + min_value: Union[str, float, None] = FieldInfo(alias="minValue", default=None) + """Minimum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + select_options: Optional[List[Union[str, float, bool]]] = FieldInfo(alias="selectOptions", default=None) + """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" + + +class CustomMetadataFieldCreateResponse(BaseModel): + id: str + """Unique identifier for the custom metadata field. Use this to update the field.""" + + label: str + """Human readable name of the custom metadata field. + + This name is displayed as form field label to the users while setting field + value on the asset in the media library UI. + """ + + name: str + """API name of the custom metadata field. + + This becomes the key while setting `customMetadata` (key-value object) for an + asset using upload or update API. + """ + + schema_: Schema = FieldInfo(alias="schema") + """An object that describes the rules for the custom metadata field value.""" diff --git a/src/imagekit/types/custom_metadata_field_list_params.py b/src/imagekit/types/custom_metadata_field_list_params.py new file mode 100644 index 0000000..f6df562 --- /dev/null +++ b/src/imagekit/types/custom_metadata_field_list_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["CustomMetadataFieldListParams"] + + +class CustomMetadataFieldListParams(TypedDict, total=False): + include_deleted: Annotated[bool, PropertyInfo(alias="includeDeleted")] + """Set it to `true` to include deleted field objects in the API response. + + Default value is `false`. + """ diff --git a/src/imagekit/types/custom_metadata_field_list_response.py b/src/imagekit/types/custom_metadata_field_list_response.py new file mode 100644 index 0000000..90c7bce --- /dev/null +++ b/src/imagekit/types/custom_metadata_field_list_response.py @@ -0,0 +1,80 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = [ + "CustomMetadataFieldListResponse", + "CustomMetadataFieldListResponseItem", + "CustomMetadataFieldListResponseItemSchema", +] + + +class CustomMetadataFieldListResponseItemSchema(BaseModel): + type: Literal["Text", "TextArea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] + """Type of the custom metadata field.""" + + default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( + alias="defaultValue", default=None + ) + """The default value for this custom metadata field. + + Date type of default value depends on the field type. + """ + + is_value_required: Optional[bool] = FieldInfo(alias="isValueRequired", default=None) + """Specifies if the this custom metadata field is required or not.""" + + max_length: Optional[float] = FieldInfo(alias="maxLength", default=None) + """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + max_value: Union[str, float, None] = FieldInfo(alias="maxValue", default=None) + """Maximum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + min_length: Optional[float] = FieldInfo(alias="minLength", default=None) + """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + min_value: Union[str, float, None] = FieldInfo(alias="minValue", default=None) + """Minimum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + select_options: Optional[List[Union[str, float, bool]]] = FieldInfo(alias="selectOptions", default=None) + """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" + + +class CustomMetadataFieldListResponseItem(BaseModel): + id: str + """Unique identifier for the custom metadata field. Use this to update the field.""" + + label: str + """Human readable name of the custom metadata field. + + This name is displayed as form field label to the users while setting field + value on the asset in the media library UI. + """ + + name: str + """API name of the custom metadata field. + + This becomes the key while setting `customMetadata` (key-value object) for an + asset using upload or update API. + """ + + schema_: CustomMetadataFieldListResponseItemSchema = FieldInfo(alias="schema") + """An object that describes the rules for the custom metadata field value.""" + + +CustomMetadataFieldListResponse: TypeAlias = List[CustomMetadataFieldListResponseItem] diff --git a/src/imagekit/types/custom_metadata_field_update_params.py b/src/imagekit/types/custom_metadata_field_update_params.py new file mode 100644 index 0000000..ba751cc --- /dev/null +++ b/src/imagekit/types/custom_metadata_field_update_params.py @@ -0,0 +1,80 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union +from typing_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["CustomMetadataFieldUpdateParams", "Schema"] + + +class CustomMetadataFieldUpdateParams(TypedDict, total=False): + label: str + """Human readable name of the custom metadata field. + + This should be unique across all non deleted custom metadata fields. This name + is displayed as form field label to the users while setting field value on an + asset in the media library UI. This parameter is required if `schema` is not + provided. + """ + + schema: Schema + """An object that describes the rules for the custom metadata key. + + This parameter is required if `label` is not provided. Note: `type` cannot be + updated and will be ignored if sent with the `schema`. The schema will be + validated as per the existing `type`. + """ + + +class Schema(TypedDict, total=False): + default_value: Annotated[Union[str, float, bool, List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue")] + """The default value for this custom metadata field. + + This property is only required if `isValueRequired` property is set to `true`. + The value should match the `type` of custom metadata field. + """ + + is_value_required: Annotated[bool, PropertyInfo(alias="isValueRequired")] + """Sets this custom metadata field as required. + + Setting custom metadata fields on an asset will throw error if the value for all + required fields are not present in upload or update asset API request body. + """ + + max_length: Annotated[float, PropertyInfo(alias="maxLength")] + """Maximum length of string. + + Only set this property if `type` is set to `Text` or `Textarea`. + """ + + max_value: Annotated[Union[str, float], PropertyInfo(alias="maxValue")] + """Maximum value of the field. + + Only set this property if field type is `Date` or `Number`. For `Date` type + field, set the minimum date in ISO8601 string format. For `Number` type field, + set the minimum numeric value. + """ + + min_length: Annotated[float, PropertyInfo(alias="minLength")] + """Minimum length of string. + + Only set this property if `type` is set to `Text` or `Textarea`. + """ + + min_value: Annotated[Union[str, float], PropertyInfo(alias="minValue")] + """Minimum value of the field. + + Only set this property if field type is `Date` or `Number`. For `Date` type + field, set the minimum date in ISO8601 string format. For `Number` type field, + set the minimum numeric value. + """ + + select_options: Annotated[List[Union[str, float, bool]], PropertyInfo(alias="selectOptions")] + """An array of allowed values. + + This property is only required if `type` property is set to `SingleSelect` or + `MultiSelect`. + """ diff --git a/src/imagekit/types/custom_metadata_field_update_response.py b/src/imagekit/types/custom_metadata_field_update_response.py new file mode 100644 index 0000000..dd98d10 --- /dev/null +++ b/src/imagekit/types/custom_metadata_field_update_response.py @@ -0,0 +1,73 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["CustomMetadataFieldUpdateResponse", "Schema"] + + +class Schema(BaseModel): + type: Literal["Text", "TextArea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] + """Type of the custom metadata field.""" + + default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( + alias="defaultValue", default=None + ) + """The default value for this custom metadata field. + + Date type of default value depends on the field type. + """ + + is_value_required: Optional[bool] = FieldInfo(alias="isValueRequired", default=None) + """Specifies if the this custom metadata field is required or not.""" + + max_length: Optional[float] = FieldInfo(alias="maxLength", default=None) + """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + max_value: Union[str, float, None] = FieldInfo(alias="maxValue", default=None) + """Maximum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + min_length: Optional[float] = FieldInfo(alias="minLength", default=None) + """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + min_value: Union[str, float, None] = FieldInfo(alias="minValue", default=None) + """Minimum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + select_options: Optional[List[Union[str, float, bool]]] = FieldInfo(alias="selectOptions", default=None) + """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" + + +class CustomMetadataFieldUpdateResponse(BaseModel): + id: str + """Unique identifier for the custom metadata field. Use this to update the field.""" + + label: str + """Human readable name of the custom metadata field. + + This name is displayed as form field label to the users while setting field + value on the asset in the media library UI. + """ + + name: str + """API name of the custom metadata field. + + This becomes the key while setting `customMetadata` (key-value object) for an + asset using upload or update API. + """ + + schema_: Schema = FieldInfo(alias="schema") + """An object that describes the rules for the custom metadata field value.""" diff --git a/src/imagekit/types/file_add_tags_params.py b/src/imagekit/types/file_add_tags_params.py new file mode 100644 index 0000000..bfedb89 --- /dev/null +++ b/src/imagekit/types/file_add_tags_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FileAddTagsParams"] + + +class FileAddTagsParams(TypedDict, total=False): + file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] + """An array of fileIds to which you want to add tags.""" + + tags: Required[List[str]] + """An array of tags that you want to add to the files.""" diff --git a/src/imagekit/types/file_add_tags_response.py b/src/imagekit/types/file_add_tags_response.py new file mode 100644 index 0000000..d4ac397 --- /dev/null +++ b/src/imagekit/types/file_add_tags_response.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["FileAddTagsResponse"] + + +class FileAddTagsResponse(BaseModel): + successfully_updated_file_ids: Optional[List[str]] = FieldInfo(alias="successfullyUpdatedFileIds", default=None) + """An array of fileIds that in which tags were successfully added.""" diff --git a/src/imagekit/types/file_copy_params.py b/src/imagekit/types/file_copy_params.py new file mode 100644 index 0000000..e8a8f94 --- /dev/null +++ b/src/imagekit/types/file_copy_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FileCopyParams"] + + +class FileCopyParams(TypedDict, total=False): + destination_path: Required[Annotated[str, PropertyInfo(alias="destinationPath")]] + """Full path to the folder you want to copy the above file into.""" + + source_file_path: Required[Annotated[str, PropertyInfo(alias="sourceFilePath")]] + """The full path of the file you want to copy.""" + + include_file_versions: Annotated[bool, PropertyInfo(alias="includeFileVersions")] + """Option to copy all versions of a file. + + By default, only the current version of the file is copied. When set to true, + all versions of the file will be copied. Default value - `false`. + """ diff --git a/src/imagekit/types/file_list_params.py b/src/imagekit/types/file_list_params.py new file mode 100644 index 0000000..2cfe153 --- /dev/null +++ b/src/imagekit/types/file_list_params.py @@ -0,0 +1,81 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FileListParams"] + + +class FileListParams(TypedDict, total=False): + file_type: Annotated[str, PropertyInfo(alias="fileType")] + """Type of files to include in the result set. Accepts three values: + + `all` - include all types of files in the result set. `image` - only search in + image type files. `non-image` - only search in files that are not images, e.g., + JS or CSS or video files. + + Default value - `all` + """ + + limit: str + """The maximum number of results to return in response: + + Minimum value - 1 + + Maximum value - 1000 + + Default value - 1000 + """ + + path: str + """Folder path if you want to limit the search within a specific folder. + + For example, `/sales-banner/` will only search in folder sales-banner. + """ + + search_query: Annotated[str, PropertyInfo(alias="searchQuery")] + """Query string in a Lucene-like query language e.g. `createdAt > "7d"`. + + Note : When the searchQuery parameter is present, the following query parameters + will have no effect on the result: + + 1. `tags` + 2. `type` + 3. `name` + + [Learn more](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#advanced-search-queries) + from examples. + """ + + skip: str + """The number of results to skip before returning results: + + Minimum value - 0 + + Default value - 0 + """ + + sort: str + """You can sort based on the following fields: + + 1. name - `ASC_NAME` or `DESC_NAME` + 2. createdAt - `ASC_CREATED` or `DESC_CREATED` + 3. updatedAt - `ASC_UPDATED` or `DESC_UPDATED` + 4. height - `ASC_HEIGHT` or `DESC_HEIGHT` + 5. width - `ASC_WIDTH` or `DESC_WIDTH` + 6. size - `ASC_SIZE` or `DESC_SIZE` + + Default value - `ASC_CREATED` + """ + + type: Literal["file", "file-version", "folder", "all"] + """Limit search to one of `file`, `file-version`, or `folder`. + + Pass `all` to include `files` and `folders` in search results (`file-version` + will not be included in this case). + + Default value - `file` + """ diff --git a/src/imagekit/types/file_list_response.py b/src/imagekit/types/file_list_response.py new file mode 100644 index 0000000..cc6fd58 --- /dev/null +++ b/src/imagekit/types/file_list_response.py @@ -0,0 +1,117 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import TypeAlias + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["FileListResponse", "FileListResponseItem", "FileListResponseItemAITag", "FileListResponseItemVersionInfo"] + + +class FileListResponseItemAITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Source of the tag. + + Possible values are `google-auto-tagging` and `aws-auto-tagging`. + """ + + +class FileListResponseItemVersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class FileListResponseItem(BaseModel): + ai_tags: Optional[List[FileListResponseItemAITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the file by auto tagging.""" + + created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + """Date and time when the file was uploaded. + + The date and time is in ISO8601 format. + """ + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """An string with custom coordinates of the file.""" + + custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + """An object with custom metadata for the file.""" + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique identifier of the asset.""" + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """Path of the file. + + This is the path you would use in the URL to access the file. For example, if + the file is at the root of the media library, the path will be `/file.jpg`. If + the file is inside a folder named `images`, the path will be `/images/file.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the file. Possible values are `image`, `non-image`.""" + + has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) + """Specifies if the image has an alpha channel.""" + + height: Optional[float] = None + """Height of the file.""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Specifies if the file is private or not.""" + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Specifies if the file is published or not.""" + + mime: Optional[str] = None + """MIME type of the file.""" + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the file in bytes.""" + + tags: Optional[List[str]] = None + """An array of tags assigned to the file. + + Tags are used to search files in the media library. + """ + + thumbnail: Optional[str] = None + """URL of the thumbnail image. + + This URL is used to access the thumbnail image of the file in the media library. + """ + + type: Optional[str] = None + """Type of the asset.""" + + updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + """Date and time when the file was last updated. + + The date and time is in ISO8601 format. + """ + + url: Optional[str] = None + """URL of the file.""" + + version_info: Optional[FileListResponseItemVersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object with details of the file version.""" + + width: Optional[float] = None + """Width of the file.""" + + +FileListResponse: TypeAlias = List[FileListResponseItem] diff --git a/src/imagekit/types/file_move_params.py b/src/imagekit/types/file_move_params.py new file mode 100644 index 0000000..1fc2a9e --- /dev/null +++ b/src/imagekit/types/file_move_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FileMoveParams"] + + +class FileMoveParams(TypedDict, total=False): + destination_path: Required[Annotated[str, PropertyInfo(alias="destinationPath")]] + """Full path to the folder you want to move the above file into.""" + + source_file_path: Required[Annotated[str, PropertyInfo(alias="sourceFilePath")]] + """The full path of the file you want to move.""" diff --git a/src/imagekit/types/file_remove_ai_tags_params.py b/src/imagekit/types/file_remove_ai_tags_params.py new file mode 100644 index 0000000..b00b379 --- /dev/null +++ b/src/imagekit/types/file_remove_ai_tags_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FileRemoveAITagsParams"] + + +class FileRemoveAITagsParams(TypedDict, total=False): + ai_tags: Required[Annotated[List[str], PropertyInfo(alias="AITags")]] + """An array of AITags that you want to remove from the files.""" + + file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] + """An array of fileIds from which you want to remove AITags.""" diff --git a/src/imagekit/types/file_remove_ai_tags_response.py b/src/imagekit/types/file_remove_ai_tags_response.py new file mode 100644 index 0000000..3e3a5f2 --- /dev/null +++ b/src/imagekit/types/file_remove_ai_tags_response.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["FileRemoveAITagsResponse"] + + +class FileRemoveAITagsResponse(BaseModel): + successfully_updated_file_ids: Optional[List[str]] = FieldInfo(alias="successfullyUpdatedFileIds", default=None) + """An array of fileIds that in which AITags were successfully removed.""" diff --git a/src/imagekit/types/file_remove_tags_params.py b/src/imagekit/types/file_remove_tags_params.py new file mode 100644 index 0000000..33903de --- /dev/null +++ b/src/imagekit/types/file_remove_tags_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FileRemoveTagsParams"] + + +class FileRemoveTagsParams(TypedDict, total=False): + file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] + """An array of fileIds from which you want to remove tags.""" + + tags: Required[List[str]] + """An array of tags that you want to remove from the files.""" diff --git a/src/imagekit/types/file_remove_tags_response.py b/src/imagekit/types/file_remove_tags_response.py new file mode 100644 index 0000000..016caca --- /dev/null +++ b/src/imagekit/types/file_remove_tags_response.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["FileRemoveTagsResponse"] + + +class FileRemoveTagsResponse(BaseModel): + successfully_updated_file_ids: Optional[List[str]] = FieldInfo(alias="successfullyUpdatedFileIds", default=None) + """An array of fileIds that in which tags were successfully removed.""" diff --git a/src/imagekit/types/file_rename_params.py b/src/imagekit/types/file_rename_params.py new file mode 100644 index 0000000..22ada89 --- /dev/null +++ b/src/imagekit/types/file_rename_params.py @@ -0,0 +1,42 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FileRenameParams"] + + +class FileRenameParams(TypedDict, total=False): + file_path: Required[Annotated[str, PropertyInfo(alias="filePath")]] + """The full path of the file you want to rename.""" + + new_file_name: Required[Annotated[str, PropertyInfo(alias="newFileName")]] + """The new name of the file. A filename can contain: + + Alphanumeric Characters: `a-z`, `A-Z`, `0-9` (including Unicode letters, marks, + and numerals in other languages). Special Characters: `.`, `_`, and `-`. + + Any other character, including space, will be replaced by `_`. + """ + + purge_cache: Annotated[bool, PropertyInfo(alias="purgeCache")] + """Option to purge cache for the old file and its versions' URLs. + + When set to true, it will internally issue a purge cache request on CDN to + remove cached content of old file and its versions. This purge request is + counted against your monthly purge quota. + + Note: If the old file were accessible at + `https://ik.imagekit.io/demo/old-filename.jpg`, a purge cache request would be + issued against `https://ik.imagekit.io/demo/old-filename.jpg*` (with a wildcard + at the end). It will remove the file and its versions' URLs and any + transformations made using query parameters on this file or its versions. + However, the cache for file transformations made using path parameters will + persist. You can purge them using the purge API. For more details, refer to the + purge API documentation. + + Default value - `false` + """ diff --git a/src/imagekit/types/file_rename_response.py b/src/imagekit/types/file_rename_response.py new file mode 100644 index 0000000..2ef8d82 --- /dev/null +++ b/src/imagekit/types/file_rename_response.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["FileRenameResponse"] + + +class FileRenameResponse(BaseModel): + purge_request_id: Optional[str] = FieldInfo(alias="purgeRequestId", default=None) + """Unique identifier of the purge request. + + This can be used to check the status of the purge request. + """ diff --git a/src/imagekit/types/file_upload_v1_params.py b/src/imagekit/types/file_upload_v1_params.py new file mode 100644 index 0000000..01b7a31 --- /dev/null +++ b/src/imagekit/types/file_upload_v1_params.py @@ -0,0 +1,211 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FileUploadV1Params"] + + +class FileUploadV1Params(TypedDict, total=False): + file: Required[str] + """Pass the HTTP URL or base64 string. + + When passing a URL in the file parameter, please ensure that our servers can + access the URL. In case ImageKit is unable to download the file from the + specified URL, a `400` error response is returned. This will also result in a + `400` error if the file download request is aborted if response headers are not + received in 8 seconds. + """ + + file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] + """The name with which the file has to be uploaded. The file name can contain: + + - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + - Special Characters: `.`, `-` + + Any other character including space will be replaced by `_` + """ + + token: str + """ + A unique value that the ImageKit.io server will use to recognize and prevent + subsequent retries for the same request. We suggest using V4 UUIDs, or another + random string with enough entropy to avoid collisions. This field is only + required for authentication when uploading a file from the client side. + + **Note**: Sending a value that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new value for this field. + """ + + checks: str + """ + Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + """ + + custom_coordinates: Annotated[str, PropertyInfo(alias="customCoordinates")] + """Define an important area in the image. + + This is only relevant for image type files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + """ + + custom_metadata: Annotated[str, PropertyInfo(alias="customMetadata")] + """Stringified JSON key-value data to be associated with the asset.""" + + expire: str + """The time until your signature is valid. + + It must be a [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 + hour into the future. It should be in seconds. This field is only required for + authentication when uploading a file from the client side. + """ + + extensions: str + """Stringified JSON object with an array of extensions to be applied to the image. + + Refer to extensions schema in + [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). + """ + + folder: str + """The folder path in which the image has to be uploaded. + + If the folder(s) didn't exist before, a new folder(s) is created. + + The folder name can contain: + + - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + - Special Characters: `/` , `_` , `-` + + Using multiple `/` creates a nested folder. + """ + + is_private_file: Annotated[Literal["true", "false"], PropertyInfo(alias="isPrivateFile")] + """Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + """ + + is_published: Annotated[Literal["true", "false"], PropertyInfo(alias="isPublished")] + """Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + """ + + overwrite_ai_tags: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteAITags")] + """ + If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + """ + + overwrite_custom_metadata: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteCustomMetadata")] + """ + If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + """ + + overwrite_file: Annotated[str, PropertyInfo(alias="overwriteFile")] + """ + If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + """ + + overwrite_tags: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteTags")] + """ + If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + """ + + public_key: Annotated[str, PropertyInfo(alias="publicKey")] + """Your ImageKit.io public key. + + This field is only required for authentication when uploading a file from the + client side. + """ + + response_fields: Annotated[str, PropertyInfo(alias="responseFields")] + """ + Comma-separated values of the fields that you want the API to return in the + response. + + For example, set the value of this field to + `tags,customCoordinates,isPrivateFile` to get the value of `tags`, + `customCoordinates`, and `isPrivateFile` in the response. + + Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, + `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. + """ + + signature: str + """ + HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a + key. Learn how to create a signature on the page below. This should be in + lowercase. + + Signature must be calculated on the server-side. This field is only required for + authentication when uploading a file from the client side. + """ + + tags: str + """Set the tags while uploading the file. + + Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length + of all characters should not exceed 500. `%` is not allowed. + + If this field is not specified and the file is overwritten then the tags will be + removed. + """ + + transformation: str + """Stringified JSON object with properties for pre and post transformations: + + `pre` - Accepts a "string" containing a valid transformation used for requesting + a pre-transformation for an image or a video file. + + `post` - Accepts an array of objects with properties: + + - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` + (Adaptive bitrate streaming). + - `value`: A "string" corresponding to the required transformation. Required if + `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or + `thumbnail`. + - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. + + Read more about + [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). + """ + + use_unique_file_name: Annotated[Literal["true", "false"], PropertyInfo(alias="useUniqueFileName")] + """Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + """ + + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ diff --git a/src/imagekit/types/file_upload_v1_response.py b/src/imagekit/types/file_upload_v1_response.py new file mode 100644 index 0000000..cb428ec --- /dev/null +++ b/src/imagekit/types/file_upload_v1_response.py @@ -0,0 +1,715 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = [ + "FileUploadV1Response", + "AITag", + "EmbeddedMetadata", + "ExtensionStatus", + "Metadata", + "MetadataExif", + "MetadataExifExif", + "MetadataExifGps", + "MetadataExifImage", + "MetadataExifInteroperability", + "MetadataExifThumbnail", + "VersionInfo", +] + + +class AITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Array of `AITags` associated with the image. + + If no `AITags` are set, it will be null. These tags can be added using the + `google-auto-tagging` or `aws-auto-tagging` extensions. + """ + + +class EmbeddedMetadata(BaseModel): + about_cv_term_cv_id: Optional[str] = FieldInfo(alias="AboutCvTermCvId", default=None) + + about_cv_term_id: Optional[str] = FieldInfo(alias="AboutCvTermId", default=None) + + about_cv_term_name: Optional[str] = FieldInfo(alias="AboutCvTermName", default=None) + + about_cv_term_refined_about: Optional[str] = FieldInfo(alias="AboutCvTermRefinedAbout", default=None) + + additional_model_information: Optional[str] = FieldInfo(alias="AdditionalModelInformation", default=None) + + application_record_version: Optional[int] = FieldInfo(alias="ApplicationRecordVersion", default=None) + + artist: Optional[str] = FieldInfo(alias="Artist", default=None) + + artwork_circa_date_created: Optional[str] = FieldInfo(alias="ArtworkCircaDateCreated", default=None) + + artwork_content_description: Optional[str] = FieldInfo(alias="ArtworkContentDescription", default=None) + + artwork_contribution_description: Optional[str] = FieldInfo(alias="ArtworkContributionDescription", default=None) + + artwork_copyright_notice: Optional[str] = FieldInfo(alias="ArtworkCopyrightNotice", default=None) + + artwork_copyright_owner_id: Optional[str] = FieldInfo(alias="ArtworkCopyrightOwnerID", default=None) + + artwork_copyright_owner_name: Optional[str] = FieldInfo(alias="ArtworkCopyrightOwnerName", default=None) + + artwork_creator: Optional[List[str]] = FieldInfo(alias="ArtworkCreator", default=None) + + artwork_creator_id: Optional[List[str]] = FieldInfo(alias="ArtworkCreatorID", default=None) + + artwork_date_created: Optional[datetime] = FieldInfo(alias="ArtworkDateCreated", default=None) + + artwork_licensor_id: Optional[str] = FieldInfo(alias="ArtworkLicensorID", default=None) + + artwork_licensor_name: Optional[str] = FieldInfo(alias="ArtworkLicensorName", default=None) + + artwork_physical_description: Optional[str] = FieldInfo(alias="ArtworkPhysicalDescription", default=None) + + artwork_source: Optional[str] = FieldInfo(alias="ArtworkSource", default=None) + + artwork_source_inventory_no: Optional[str] = FieldInfo(alias="ArtworkSourceInventoryNo", default=None) + + artwork_source_inv_url: Optional[str] = FieldInfo(alias="ArtworkSourceInvURL", default=None) + + artwork_style_period: Optional[List[str]] = FieldInfo(alias="ArtworkStylePeriod", default=None) + + artwork_title: Optional[str] = FieldInfo(alias="ArtworkTitle", default=None) + + authors_position: Optional[str] = FieldInfo(alias="AuthorsPosition", default=None) + + byline: Optional[str] = FieldInfo(alias="Byline", default=None) + + byline_title: Optional[str] = FieldInfo(alias="BylineTitle", default=None) + + caption: Optional[str] = FieldInfo(alias="Caption", default=None) + + caption_abstract: Optional[str] = FieldInfo(alias="CaptionAbstract", default=None) + + caption_writer: Optional[str] = FieldInfo(alias="CaptionWriter", default=None) + + city: Optional[str] = FieldInfo(alias="City", default=None) + + color_space: Optional[str] = FieldInfo(alias="ColorSpace", default=None) + + components_configuration: Optional[str] = FieldInfo(alias="ComponentsConfiguration", default=None) + + copyright: Optional[str] = FieldInfo(alias="Copyright", default=None) + + copyright_notice: Optional[str] = FieldInfo(alias="CopyrightNotice", default=None) + + copyright_owner_id: Optional[List[str]] = FieldInfo(alias="CopyrightOwnerID", default=None) + + copyright_owner_name: Optional[List[str]] = FieldInfo(alias="CopyrightOwnerName", default=None) + + country: Optional[str] = FieldInfo(alias="Country", default=None) + + country_code: Optional[str] = FieldInfo(alias="CountryCode", default=None) + + country_primary_location_code: Optional[str] = FieldInfo(alias="CountryPrimaryLocationCode", default=None) + + country_primary_location_name: Optional[str] = FieldInfo(alias="CountryPrimaryLocationName", default=None) + + creator: Optional[str] = FieldInfo(alias="Creator", default=None) + + creator_address: Optional[str] = FieldInfo(alias="CreatorAddress", default=None) + + creator_city: Optional[str] = FieldInfo(alias="CreatorCity", default=None) + + creator_country: Optional[str] = FieldInfo(alias="CreatorCountry", default=None) + + creator_postal_code: Optional[str] = FieldInfo(alias="CreatorPostalCode", default=None) + + creator_region: Optional[str] = FieldInfo(alias="CreatorRegion", default=None) + + creator_work_email: Optional[str] = FieldInfo(alias="CreatorWorkEmail", default=None) + + creator_work_telephone: Optional[str] = FieldInfo(alias="CreatorWorkTelephone", default=None) + + creator_work_url: Optional[str] = FieldInfo(alias="CreatorWorkURL", default=None) + + credit: Optional[str] = FieldInfo(alias="Credit", default=None) + + date_created: Optional[datetime] = FieldInfo(alias="DateCreated", default=None) + + date_time_created: Optional[datetime] = FieldInfo(alias="DateTimeCreated", default=None) + + date_time_original: Optional[datetime] = FieldInfo(alias="DateTimeOriginal", default=None) + + description: Optional[str] = FieldInfo(alias="Description", default=None) + + digital_image_guid: Optional[str] = FieldInfo(alias="DigitalImageGUID", default=None) + + digital_source_type: Optional[str] = FieldInfo(alias="DigitalSourceType", default=None) + + embedded_encoded_rights_expr: Optional[str] = FieldInfo(alias="EmbeddedEncodedRightsExpr", default=None) + + embedded_encoded_rights_expr_lang_id: Optional[str] = FieldInfo( + alias="EmbeddedEncodedRightsExprLangID", default=None + ) + + embedded_encoded_rights_expr_type: Optional[str] = FieldInfo(alias="EmbeddedEncodedRightsExprType", default=None) + + event: Optional[str] = FieldInfo(alias="Event", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + genre_cv_id: Optional[str] = FieldInfo(alias="GenreCvId", default=None) + + genre_cv_term_id: Optional[str] = FieldInfo(alias="GenreCvTermId", default=None) + + genre_cv_term_name: Optional[str] = FieldInfo(alias="GenreCvTermName", default=None) + + genre_cv_term_refined_about: Optional[str] = FieldInfo(alias="GenreCvTermRefinedAbout", default=None) + + headline: Optional[str] = FieldInfo(alias="Headline", default=None) + + image_creator_id: Optional[str] = FieldInfo(alias="ImageCreatorID", default=None) + + image_creator_image_id: Optional[str] = FieldInfo(alias="ImageCreatorImageID", default=None) + + image_creator_name: Optional[str] = FieldInfo(alias="ImageCreatorName", default=None) + + image_description: Optional[str] = FieldInfo(alias="ImageDescription", default=None) + + image_region_boundary_h: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryH", default=None) + + image_region_boundary_rx: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryRx", default=None) + + image_region_boundary_shape: Optional[List[str]] = FieldInfo(alias="ImageRegionBoundaryShape", default=None) + + image_region_boundary_unit: Optional[List[str]] = FieldInfo(alias="ImageRegionBoundaryUnit", default=None) + + image_region_boundary_vertices_x: Optional[List[float]] = FieldInfo( + alias="ImageRegionBoundaryVerticesX", default=None + ) + + image_region_boundary_vertices_y: Optional[List[float]] = FieldInfo( + alias="ImageRegionBoundaryVerticesY", default=None + ) + + image_region_boundary_w: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryW", default=None) + + image_region_boundary_x: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryX", default=None) + + image_region_boundary_y: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryY", default=None) + + image_region_ctype_identifier: Optional[List[str]] = FieldInfo(alias="ImageRegionCtypeIdentifier", default=None) + + image_region_ctype_name: Optional[List[str]] = FieldInfo(alias="ImageRegionCtypeName", default=None) + + image_region_id: Optional[List[str]] = FieldInfo(alias="ImageRegionID", default=None) + + image_region_name: Optional[List[str]] = FieldInfo(alias="ImageRegionName", default=None) + + image_region_organisation_in_image_name: Optional[List[str]] = FieldInfo( + alias="ImageRegionOrganisationInImageName", default=None + ) + + image_region_person_in_image: Optional[List[str]] = FieldInfo(alias="ImageRegionPersonInImage", default=None) + + image_region_role_identifier: Optional[List[str]] = FieldInfo(alias="ImageRegionRoleIdentifier", default=None) + + image_region_role_name: Optional[List[str]] = FieldInfo(alias="ImageRegionRoleName", default=None) + + image_supplier_id: Optional[str] = FieldInfo(alias="ImageSupplierID", default=None) + + image_supplier_image_id: Optional[str] = FieldInfo(alias="ImageSupplierImageID", default=None) + + image_supplier_name: Optional[str] = FieldInfo(alias="ImageSupplierName", default=None) + + instructions: Optional[str] = FieldInfo(alias="Instructions", default=None) + + intellectual_genre: Optional[str] = FieldInfo(alias="IntellectualGenre", default=None) + + keywords: Optional[List[str]] = FieldInfo(alias="Keywords", default=None) + + licensor_city: Optional[List[str]] = FieldInfo(alias="LicensorCity", default=None) + + licensor_country: Optional[List[str]] = FieldInfo(alias="LicensorCountry", default=None) + + licensor_email: Optional[List[str]] = FieldInfo(alias="LicensorEmail", default=None) + + licensor_extended_address: Optional[List[str]] = FieldInfo(alias="LicensorExtendedAddress", default=None) + + licensor_id: Optional[List[str]] = FieldInfo(alias="LicensorID", default=None) + + licensor_name: Optional[List[str]] = FieldInfo(alias="LicensorName", default=None) + + licensor_postal_code: Optional[List[str]] = FieldInfo(alias="LicensorPostalCode", default=None) + + licensor_region: Optional[List[str]] = FieldInfo(alias="LicensorRegion", default=None) + + licensor_street_address: Optional[List[str]] = FieldInfo(alias="LicensorStreetAddress", default=None) + + licensor_telephone1: Optional[List[str]] = FieldInfo(alias="LicensorTelephone1", default=None) + + licensor_telephone2: Optional[List[str]] = FieldInfo(alias="LicensorTelephone2", default=None) + + licensor_url: Optional[List[str]] = FieldInfo(alias="LicensorURL", default=None) + + linked_encoded_rights_expr: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExpr", default=None) + + linked_encoded_rights_expr_lang_id: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExprLangID", default=None) + + linked_encoded_rights_expr_type: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExprType", default=None) + + location: Optional[str] = FieldInfo(alias="Location", default=None) + + location_created_city: Optional[str] = FieldInfo(alias="LocationCreatedCity", default=None) + + location_created_country_code: Optional[str] = FieldInfo(alias="LocationCreatedCountryCode", default=None) + + location_created_country_name: Optional[str] = FieldInfo(alias="LocationCreatedCountryName", default=None) + + location_created_gps_altitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSAltitude", default=None) + + location_created_gps_latitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSLatitude", default=None) + + location_created_gps_longitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSLongitude", default=None) + + location_created_location_id: Optional[str] = FieldInfo(alias="LocationCreatedLocationId", default=None) + + location_created_location_name: Optional[str] = FieldInfo(alias="LocationCreatedLocationName", default=None) + + location_created_province_state: Optional[str] = FieldInfo(alias="LocationCreatedProvinceState", default=None) + + location_created_sublocation: Optional[str] = FieldInfo(alias="LocationCreatedSublocation", default=None) + + location_created_world_region: Optional[str] = FieldInfo(alias="LocationCreatedWorldRegion", default=None) + + location_shown_city: Optional[List[str]] = FieldInfo(alias="LocationShownCity", default=None) + + location_shown_country_code: Optional[List[str]] = FieldInfo(alias="LocationShownCountryCode", default=None) + + location_shown_country_name: Optional[List[str]] = FieldInfo(alias="LocationShownCountryName", default=None) + + location_shown_gps_altitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSAltitude", default=None) + + location_shown_gps_latitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSLatitude", default=None) + + location_shown_gps_longitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSLongitude", default=None) + + location_shown_location_id: Optional[List[str]] = FieldInfo(alias="LocationShownLocationId", default=None) + + location_shown_location_name: Optional[List[str]] = FieldInfo(alias="LocationShownLocationName", default=None) + + location_shown_province_state: Optional[List[str]] = FieldInfo(alias="LocationShownProvinceState", default=None) + + location_shown_sublocation: Optional[List[str]] = FieldInfo(alias="LocationShownSublocation", default=None) + + location_shown_world_region: Optional[List[str]] = FieldInfo(alias="LocationShownWorldRegion", default=None) + + max_avail_height: Optional[float] = FieldInfo(alias="MaxAvailHeight", default=None) + + max_avail_width: Optional[float] = FieldInfo(alias="MaxAvailWidth", default=None) + + api_model_age: Optional[List[float]] = FieldInfo(alias="ModelAge", default=None) + + api_model_release_id: Optional[List[str]] = FieldInfo(alias="ModelReleaseID", default=None) + + object_attribute_reference: Optional[str] = FieldInfo(alias="ObjectAttributeReference", default=None) + + object_name: Optional[str] = FieldInfo(alias="ObjectName", default=None) + + offset_time_original: Optional[str] = FieldInfo(alias="OffsetTimeOriginal", default=None) + + organisation_in_image_code: Optional[List[str]] = FieldInfo(alias="OrganisationInImageCode", default=None) + + organisation_in_image_name: Optional[List[str]] = FieldInfo(alias="OrganisationInImageName", default=None) + + orientation: Optional[str] = FieldInfo(alias="Orientation", default=None) + + original_transmission_reference: Optional[str] = FieldInfo(alias="OriginalTransmissionReference", default=None) + + person_in_image: Optional[List[str]] = FieldInfo(alias="PersonInImage", default=None) + + person_in_image_cv_term_cv_id: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermCvId", default=None) + + person_in_image_cv_term_id: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermId", default=None) + + person_in_image_cv_term_name: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermName", default=None) + + person_in_image_cv_term_refined_about: Optional[List[str]] = FieldInfo( + alias="PersonInImageCvTermRefinedAbout", default=None + ) + + person_in_image_description: Optional[List[str]] = FieldInfo(alias="PersonInImageDescription", default=None) + + person_in_image_id: Optional[List[str]] = FieldInfo(alias="PersonInImageId", default=None) + + person_in_image_name: Optional[List[str]] = FieldInfo(alias="PersonInImageName", default=None) + + product_in_image_description: Optional[List[str]] = FieldInfo(alias="ProductInImageDescription", default=None) + + product_in_image_gtin: Optional[List[float]] = FieldInfo(alias="ProductInImageGTIN", default=None) + + product_in_image_name: Optional[List[str]] = FieldInfo(alias="ProductInImageName", default=None) + + property_release_id: Optional[List[str]] = FieldInfo(alias="PropertyReleaseID", default=None) + + province_state: Optional[str] = FieldInfo(alias="ProvinceState", default=None) + + rating: Optional[int] = FieldInfo(alias="Rating", default=None) + + registry_entry_role: Optional[List[str]] = FieldInfo(alias="RegistryEntryRole", default=None) + + registry_item_id: Optional[List[str]] = FieldInfo(alias="RegistryItemID", default=None) + + registry_organisation_id: Optional[List[str]] = FieldInfo(alias="RegistryOrganisationID", default=None) + + resolution_unit: Optional[str] = FieldInfo(alias="ResolutionUnit", default=None) + + rights: Optional[str] = FieldInfo(alias="Rights", default=None) + + scene: Optional[List[str]] = FieldInfo(alias="Scene", default=None) + + source: Optional[str] = FieldInfo(alias="Source", default=None) + + special_instructions: Optional[str] = FieldInfo(alias="SpecialInstructions", default=None) + + state: Optional[str] = FieldInfo(alias="State", default=None) + + subject: Optional[List[str]] = FieldInfo(alias="Subject", default=None) + + subject_code: Optional[List[str]] = FieldInfo(alias="SubjectCode", default=None) + + subject_reference: Optional[List[str]] = FieldInfo(alias="SubjectReference", default=None) + + sublocation: Optional[str] = FieldInfo(alias="Sublocation", default=None) + + time_created: Optional[str] = FieldInfo(alias="TimeCreated", default=None) + + title: Optional[str] = FieldInfo(alias="Title", default=None) + + transmission_reference: Optional[str] = FieldInfo(alias="TransmissionReference", default=None) + + usage_terms: Optional[str] = FieldInfo(alias="UsageTerms", default=None) + + web_statement: Optional[str] = FieldInfo(alias="WebStatement", default=None) + + writer: Optional[str] = FieldInfo(alias="Writer", default=None) + + writer_editor: Optional[str] = FieldInfo(alias="WriterEditor", default=None) + + x_resolution: Optional[float] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[float] = FieldInfo(alias="YResolution", default=None) + + +class ExtensionStatus(BaseModel): + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="aws-auto-tagging", default=None + ) + + google_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="google-auto-tagging", default=None + ) + + remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) + + +class MetadataExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class MetadataExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class MetadataExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class MetadataExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class MetadataExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class MetadataExif(BaseModel): + exif: Optional[MetadataExifExif] = None + """Object containing Exif details.""" + + gps: Optional[MetadataExifGps] = None + """Object containing GPS information.""" + + image: Optional[MetadataExifImage] = None + """Object containing EXIF image information.""" + + interoperability: Optional[MetadataExifInteroperability] = None + """JSON object.""" + + makernote: Optional[Dict[str, object]] = None + + thumbnail: Optional[MetadataExifThumbnail] = None + """Object containing Thumbnail information.""" + + +class Metadata(BaseModel): + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + density: Optional[int] = None + """The density of the image in DPI.""" + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + exif: Optional[MetadataExif] = None + + format: Optional[str] = None + """The format of the file (e.g., 'jpg', 'mp4').""" + + has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) + """Indicates if the image has a color profile.""" + + has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) + """Indicates if the image contains transparent areas.""" + + height: Optional[int] = None + """The height of the image or video in pixels.""" + + p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) + """Perceptual hash of the image.""" + + quality: Optional[int] = None + """The quality indicator of the image.""" + + size: Optional[int] = None + """The file size in bytes.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[int] = None + """The width of the image or video in pixels.""" + + +class VersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class FileUploadV1Response(BaseModel): + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the uploaded file by auto tagging.""" + + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """ + Value of custom coordinates associated with the image in the format + `x,y,width,height`. If `customCoordinates` are not defined, then it is `null`. + Send `customCoordinates` in `responseFields` in API request to get the value of + this field. + """ + + custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + """A key-value data associated with the asset. + + Use `responseField` in API request to get `customMetadata` in the upload API + response. Before setting any custom metadata on an asset, you have to create the + field using custom metadata fields API. Send `customMetadata` in + `responseFields` in API request to get the value of this field. + """ + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + embedded_metadata: Optional[EmbeddedMetadata] = FieldInfo(alias="embeddedMetadata", default=None) + """Consolidated embedded metadata associated with the file. + + It includes exif, iptc, and xmp data. Send `embeddedMetadata` in + `responseFields` in API request to get embeddedMetadata in the upload API + response. + """ + + extension_status: Optional[ExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) + """ + Extension names with their processing status at the time of completion of the + request. It could have one of the following status values: + + `success`: The extension has been successfully applied. `failed`: The extension + has failed and will not be retried. `pending`: The extension will finish + processing in some time. On completion, the final status (success / failed) will + be sent to the `webhookUrl` provided. + + If no extension was requested, then this parameter is not returned. + """ + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique fileId. + + Store this fileld in your database, as this will be used to perform update + action on this file. + """ + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """The relative path of the file in the media library e.g. + + `/marketing-assets/new-banner.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the uploaded file. Possible values are `image`, `non-image`.""" + + height: Optional[float] = None + """Height of the image in pixels (Only for images)""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Is the file marked as private. + + It can be either `true` or `false`. Send `isPrivateFile` in `responseFields` in + API request to get the value of this field. + """ + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Is the file published or in draft state. + + It can be either `true` or `false`. Send `isPublished` in `responseFields` in + API request to get the value of this field. + """ + + metadata: Optional[Metadata] = None + """Legacy metadata. + + Send `metadata` in `responseFields` in API request to get metadata in the upload + API response. + """ + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the image file in Bytes.""" + + tags: Optional[List[str]] = None + """The array of tags associated with the asset. + + If no tags are set, it will be `null`. Send `tags` in `responseFields` in API + request to get the value of this field. + """ + + thumbnail_url: Optional[str] = FieldInfo(alias="thumbnailUrl", default=None) + """In the case of an image, a small thumbnail URL.""" + + url: Optional[str] = None + """A publicly accessible URL of the file.""" + + version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object containing the file or file version's `id` (versionId) and `name`.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[float] = None + """Width of the image in pixels (Only for Images)""" diff --git a/src/imagekit/types/file_upload_v2_params.py b/src/imagekit/types/file_upload_v2_params.py new file mode 100644 index 0000000..92c2c17 --- /dev/null +++ b/src/imagekit/types/file_upload_v2_params.py @@ -0,0 +1,179 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FileUploadV2Params"] + + +class FileUploadV2Params(TypedDict, total=False): + file: Required[str] + """Pass the HTTP URL or base64 string. + + When passing a URL in the file parameter, please ensure that our servers can + access the URL. In case ImageKit is unable to download the file from the + specified URL, a `400` error response is returned. This will also result in a + `400` error if the file download request is aborted if response headers are not + received in 8 seconds. + """ + + file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] + """The name with which the file has to be uploaded.""" + + token: str + """This is the client-generated JSON Web Token (JWT). + + The ImageKit.io server uses it to authenticate and check that the upload request + parameters have not been tampered with after the token has been generated. Learn + how to create the token on the page below. This field is only required for + authentication when uploading a file from the client side. + + **Note**: Sending a JWT that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new token. + + **⚠️Warning**: JWT must be generated on the server-side because it is generated + using your account's private API key. This field is required for authentication + when uploading a file from the client-side. + """ + + checks: str + """ + Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file-v2#upload-api-checks). + """ + + custom_coordinates: Annotated[str, PropertyInfo(alias="customCoordinates")] + """Define an important area in the image. + + This is only relevant for image type files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + """ + + custom_metadata: Annotated[str, PropertyInfo(alias="customMetadata")] + """Stringified JSON key-value data to be associated with the asset.""" + + extensions: str + """Stringified JSON object with an array of extensions to be applied to the image. + + Refer to extensions schema in + [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). + """ + + folder: str + """The folder path in which the image has to be uploaded. + + If the folder(s) didn't exist before, a new folder(s) is created. Using multiple + `/` creates a nested folder. + """ + + is_private_file: Annotated[Literal["true", "false"], PropertyInfo(alias="isPrivateFile")] + """Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + """ + + is_published: Annotated[Literal["true", "false"], PropertyInfo(alias="isPublished")] + """Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + """ + + overwrite_ai_tags: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteAITags")] + """ + If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + """ + + overwrite_custom_metadata: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteCustomMetadata")] + """ + If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + """ + + overwrite_file: Annotated[str, PropertyInfo(alias="overwriteFile")] + """ + If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + """ + + overwrite_tags: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteTags")] + """ + If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + """ + + response_fields: Annotated[str, PropertyInfo(alias="responseFields")] + """ + Comma-separated values of the fields that you want the API to return in the + response. + + For example, set the value of this field to + `tags,customCoordinates,isPrivateFile` to get the value of `tags`, + `customCoordinates`, and `isPrivateFile` in the response. + + Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, + `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. + """ + + tags: str + """Set the tags while uploading the file. + + Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length + of all characters should not exceed 500. `%` is not allowed. + + If this field is not specified and the file is overwritten then the tags will be + removed. + """ + + transformation: str + """Stringified JSON object with properties for pre and post transformations: + + `pre` - Accepts a "string" containing a valid transformation used for requesting + a pre-transformation for an image or a video file. + + `post` - Accepts an array of objects with properties: + + - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` + (Adaptive bitrate streaming). + - `value`: A "string" corresponding to the required transformation. Required if + `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or + `thumbnail`. + - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. + + Read more about + [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). + """ + + use_unique_file_name: Annotated[Literal["true", "false"], PropertyInfo(alias="useUniqueFileName")] + """Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + """ + + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ diff --git a/src/imagekit/types/file_upload_v2_response.py b/src/imagekit/types/file_upload_v2_response.py new file mode 100644 index 0000000..27d44da --- /dev/null +++ b/src/imagekit/types/file_upload_v2_response.py @@ -0,0 +1,715 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = [ + "FileUploadV2Response", + "AITag", + "EmbeddedMetadata", + "ExtensionStatus", + "Metadata", + "MetadataExif", + "MetadataExifExif", + "MetadataExifGps", + "MetadataExifImage", + "MetadataExifInteroperability", + "MetadataExifThumbnail", + "VersionInfo", +] + + +class AITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Array of `AITags` associated with the image. + + If no `AITags` are set, it will be null. These tags can be added using the + `google-auto-tagging` or `aws-auto-tagging` extensions. + """ + + +class EmbeddedMetadata(BaseModel): + about_cv_term_cv_id: Optional[str] = FieldInfo(alias="AboutCvTermCvId", default=None) + + about_cv_term_id: Optional[str] = FieldInfo(alias="AboutCvTermId", default=None) + + about_cv_term_name: Optional[str] = FieldInfo(alias="AboutCvTermName", default=None) + + about_cv_term_refined_about: Optional[str] = FieldInfo(alias="AboutCvTermRefinedAbout", default=None) + + additional_model_information: Optional[str] = FieldInfo(alias="AdditionalModelInformation", default=None) + + application_record_version: Optional[int] = FieldInfo(alias="ApplicationRecordVersion", default=None) + + artist: Optional[str] = FieldInfo(alias="Artist", default=None) + + artwork_circa_date_created: Optional[str] = FieldInfo(alias="ArtworkCircaDateCreated", default=None) + + artwork_content_description: Optional[str] = FieldInfo(alias="ArtworkContentDescription", default=None) + + artwork_contribution_description: Optional[str] = FieldInfo(alias="ArtworkContributionDescription", default=None) + + artwork_copyright_notice: Optional[str] = FieldInfo(alias="ArtworkCopyrightNotice", default=None) + + artwork_copyright_owner_id: Optional[str] = FieldInfo(alias="ArtworkCopyrightOwnerID", default=None) + + artwork_copyright_owner_name: Optional[str] = FieldInfo(alias="ArtworkCopyrightOwnerName", default=None) + + artwork_creator: Optional[List[str]] = FieldInfo(alias="ArtworkCreator", default=None) + + artwork_creator_id: Optional[List[str]] = FieldInfo(alias="ArtworkCreatorID", default=None) + + artwork_date_created: Optional[datetime] = FieldInfo(alias="ArtworkDateCreated", default=None) + + artwork_licensor_id: Optional[str] = FieldInfo(alias="ArtworkLicensorID", default=None) + + artwork_licensor_name: Optional[str] = FieldInfo(alias="ArtworkLicensorName", default=None) + + artwork_physical_description: Optional[str] = FieldInfo(alias="ArtworkPhysicalDescription", default=None) + + artwork_source: Optional[str] = FieldInfo(alias="ArtworkSource", default=None) + + artwork_source_inventory_no: Optional[str] = FieldInfo(alias="ArtworkSourceInventoryNo", default=None) + + artwork_source_inv_url: Optional[str] = FieldInfo(alias="ArtworkSourceInvURL", default=None) + + artwork_style_period: Optional[List[str]] = FieldInfo(alias="ArtworkStylePeriod", default=None) + + artwork_title: Optional[str] = FieldInfo(alias="ArtworkTitle", default=None) + + authors_position: Optional[str] = FieldInfo(alias="AuthorsPosition", default=None) + + byline: Optional[str] = FieldInfo(alias="Byline", default=None) + + byline_title: Optional[str] = FieldInfo(alias="BylineTitle", default=None) + + caption: Optional[str] = FieldInfo(alias="Caption", default=None) + + caption_abstract: Optional[str] = FieldInfo(alias="CaptionAbstract", default=None) + + caption_writer: Optional[str] = FieldInfo(alias="CaptionWriter", default=None) + + city: Optional[str] = FieldInfo(alias="City", default=None) + + color_space: Optional[str] = FieldInfo(alias="ColorSpace", default=None) + + components_configuration: Optional[str] = FieldInfo(alias="ComponentsConfiguration", default=None) + + copyright: Optional[str] = FieldInfo(alias="Copyright", default=None) + + copyright_notice: Optional[str] = FieldInfo(alias="CopyrightNotice", default=None) + + copyright_owner_id: Optional[List[str]] = FieldInfo(alias="CopyrightOwnerID", default=None) + + copyright_owner_name: Optional[List[str]] = FieldInfo(alias="CopyrightOwnerName", default=None) + + country: Optional[str] = FieldInfo(alias="Country", default=None) + + country_code: Optional[str] = FieldInfo(alias="CountryCode", default=None) + + country_primary_location_code: Optional[str] = FieldInfo(alias="CountryPrimaryLocationCode", default=None) + + country_primary_location_name: Optional[str] = FieldInfo(alias="CountryPrimaryLocationName", default=None) + + creator: Optional[str] = FieldInfo(alias="Creator", default=None) + + creator_address: Optional[str] = FieldInfo(alias="CreatorAddress", default=None) + + creator_city: Optional[str] = FieldInfo(alias="CreatorCity", default=None) + + creator_country: Optional[str] = FieldInfo(alias="CreatorCountry", default=None) + + creator_postal_code: Optional[str] = FieldInfo(alias="CreatorPostalCode", default=None) + + creator_region: Optional[str] = FieldInfo(alias="CreatorRegion", default=None) + + creator_work_email: Optional[str] = FieldInfo(alias="CreatorWorkEmail", default=None) + + creator_work_telephone: Optional[str] = FieldInfo(alias="CreatorWorkTelephone", default=None) + + creator_work_url: Optional[str] = FieldInfo(alias="CreatorWorkURL", default=None) + + credit: Optional[str] = FieldInfo(alias="Credit", default=None) + + date_created: Optional[datetime] = FieldInfo(alias="DateCreated", default=None) + + date_time_created: Optional[datetime] = FieldInfo(alias="DateTimeCreated", default=None) + + date_time_original: Optional[datetime] = FieldInfo(alias="DateTimeOriginal", default=None) + + description: Optional[str] = FieldInfo(alias="Description", default=None) + + digital_image_guid: Optional[str] = FieldInfo(alias="DigitalImageGUID", default=None) + + digital_source_type: Optional[str] = FieldInfo(alias="DigitalSourceType", default=None) + + embedded_encoded_rights_expr: Optional[str] = FieldInfo(alias="EmbeddedEncodedRightsExpr", default=None) + + embedded_encoded_rights_expr_lang_id: Optional[str] = FieldInfo( + alias="EmbeddedEncodedRightsExprLangID", default=None + ) + + embedded_encoded_rights_expr_type: Optional[str] = FieldInfo(alias="EmbeddedEncodedRightsExprType", default=None) + + event: Optional[str] = FieldInfo(alias="Event", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + genre_cv_id: Optional[str] = FieldInfo(alias="GenreCvId", default=None) + + genre_cv_term_id: Optional[str] = FieldInfo(alias="GenreCvTermId", default=None) + + genre_cv_term_name: Optional[str] = FieldInfo(alias="GenreCvTermName", default=None) + + genre_cv_term_refined_about: Optional[str] = FieldInfo(alias="GenreCvTermRefinedAbout", default=None) + + headline: Optional[str] = FieldInfo(alias="Headline", default=None) + + image_creator_id: Optional[str] = FieldInfo(alias="ImageCreatorID", default=None) + + image_creator_image_id: Optional[str] = FieldInfo(alias="ImageCreatorImageID", default=None) + + image_creator_name: Optional[str] = FieldInfo(alias="ImageCreatorName", default=None) + + image_description: Optional[str] = FieldInfo(alias="ImageDescription", default=None) + + image_region_boundary_h: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryH", default=None) + + image_region_boundary_rx: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryRx", default=None) + + image_region_boundary_shape: Optional[List[str]] = FieldInfo(alias="ImageRegionBoundaryShape", default=None) + + image_region_boundary_unit: Optional[List[str]] = FieldInfo(alias="ImageRegionBoundaryUnit", default=None) + + image_region_boundary_vertices_x: Optional[List[float]] = FieldInfo( + alias="ImageRegionBoundaryVerticesX", default=None + ) + + image_region_boundary_vertices_y: Optional[List[float]] = FieldInfo( + alias="ImageRegionBoundaryVerticesY", default=None + ) + + image_region_boundary_w: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryW", default=None) + + image_region_boundary_x: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryX", default=None) + + image_region_boundary_y: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryY", default=None) + + image_region_ctype_identifier: Optional[List[str]] = FieldInfo(alias="ImageRegionCtypeIdentifier", default=None) + + image_region_ctype_name: Optional[List[str]] = FieldInfo(alias="ImageRegionCtypeName", default=None) + + image_region_id: Optional[List[str]] = FieldInfo(alias="ImageRegionID", default=None) + + image_region_name: Optional[List[str]] = FieldInfo(alias="ImageRegionName", default=None) + + image_region_organisation_in_image_name: Optional[List[str]] = FieldInfo( + alias="ImageRegionOrganisationInImageName", default=None + ) + + image_region_person_in_image: Optional[List[str]] = FieldInfo(alias="ImageRegionPersonInImage", default=None) + + image_region_role_identifier: Optional[List[str]] = FieldInfo(alias="ImageRegionRoleIdentifier", default=None) + + image_region_role_name: Optional[List[str]] = FieldInfo(alias="ImageRegionRoleName", default=None) + + image_supplier_id: Optional[str] = FieldInfo(alias="ImageSupplierID", default=None) + + image_supplier_image_id: Optional[str] = FieldInfo(alias="ImageSupplierImageID", default=None) + + image_supplier_name: Optional[str] = FieldInfo(alias="ImageSupplierName", default=None) + + instructions: Optional[str] = FieldInfo(alias="Instructions", default=None) + + intellectual_genre: Optional[str] = FieldInfo(alias="IntellectualGenre", default=None) + + keywords: Optional[List[str]] = FieldInfo(alias="Keywords", default=None) + + licensor_city: Optional[List[str]] = FieldInfo(alias="LicensorCity", default=None) + + licensor_country: Optional[List[str]] = FieldInfo(alias="LicensorCountry", default=None) + + licensor_email: Optional[List[str]] = FieldInfo(alias="LicensorEmail", default=None) + + licensor_extended_address: Optional[List[str]] = FieldInfo(alias="LicensorExtendedAddress", default=None) + + licensor_id: Optional[List[str]] = FieldInfo(alias="LicensorID", default=None) + + licensor_name: Optional[List[str]] = FieldInfo(alias="LicensorName", default=None) + + licensor_postal_code: Optional[List[str]] = FieldInfo(alias="LicensorPostalCode", default=None) + + licensor_region: Optional[List[str]] = FieldInfo(alias="LicensorRegion", default=None) + + licensor_street_address: Optional[List[str]] = FieldInfo(alias="LicensorStreetAddress", default=None) + + licensor_telephone1: Optional[List[str]] = FieldInfo(alias="LicensorTelephone1", default=None) + + licensor_telephone2: Optional[List[str]] = FieldInfo(alias="LicensorTelephone2", default=None) + + licensor_url: Optional[List[str]] = FieldInfo(alias="LicensorURL", default=None) + + linked_encoded_rights_expr: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExpr", default=None) + + linked_encoded_rights_expr_lang_id: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExprLangID", default=None) + + linked_encoded_rights_expr_type: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExprType", default=None) + + location: Optional[str] = FieldInfo(alias="Location", default=None) + + location_created_city: Optional[str] = FieldInfo(alias="LocationCreatedCity", default=None) + + location_created_country_code: Optional[str] = FieldInfo(alias="LocationCreatedCountryCode", default=None) + + location_created_country_name: Optional[str] = FieldInfo(alias="LocationCreatedCountryName", default=None) + + location_created_gps_altitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSAltitude", default=None) + + location_created_gps_latitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSLatitude", default=None) + + location_created_gps_longitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSLongitude", default=None) + + location_created_location_id: Optional[str] = FieldInfo(alias="LocationCreatedLocationId", default=None) + + location_created_location_name: Optional[str] = FieldInfo(alias="LocationCreatedLocationName", default=None) + + location_created_province_state: Optional[str] = FieldInfo(alias="LocationCreatedProvinceState", default=None) + + location_created_sublocation: Optional[str] = FieldInfo(alias="LocationCreatedSublocation", default=None) + + location_created_world_region: Optional[str] = FieldInfo(alias="LocationCreatedWorldRegion", default=None) + + location_shown_city: Optional[List[str]] = FieldInfo(alias="LocationShownCity", default=None) + + location_shown_country_code: Optional[List[str]] = FieldInfo(alias="LocationShownCountryCode", default=None) + + location_shown_country_name: Optional[List[str]] = FieldInfo(alias="LocationShownCountryName", default=None) + + location_shown_gps_altitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSAltitude", default=None) + + location_shown_gps_latitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSLatitude", default=None) + + location_shown_gps_longitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSLongitude", default=None) + + location_shown_location_id: Optional[List[str]] = FieldInfo(alias="LocationShownLocationId", default=None) + + location_shown_location_name: Optional[List[str]] = FieldInfo(alias="LocationShownLocationName", default=None) + + location_shown_province_state: Optional[List[str]] = FieldInfo(alias="LocationShownProvinceState", default=None) + + location_shown_sublocation: Optional[List[str]] = FieldInfo(alias="LocationShownSublocation", default=None) + + location_shown_world_region: Optional[List[str]] = FieldInfo(alias="LocationShownWorldRegion", default=None) + + max_avail_height: Optional[float] = FieldInfo(alias="MaxAvailHeight", default=None) + + max_avail_width: Optional[float] = FieldInfo(alias="MaxAvailWidth", default=None) + + api_model_age: Optional[List[float]] = FieldInfo(alias="ModelAge", default=None) + + api_model_release_id: Optional[List[str]] = FieldInfo(alias="ModelReleaseID", default=None) + + object_attribute_reference: Optional[str] = FieldInfo(alias="ObjectAttributeReference", default=None) + + object_name: Optional[str] = FieldInfo(alias="ObjectName", default=None) + + offset_time_original: Optional[str] = FieldInfo(alias="OffsetTimeOriginal", default=None) + + organisation_in_image_code: Optional[List[str]] = FieldInfo(alias="OrganisationInImageCode", default=None) + + organisation_in_image_name: Optional[List[str]] = FieldInfo(alias="OrganisationInImageName", default=None) + + orientation: Optional[str] = FieldInfo(alias="Orientation", default=None) + + original_transmission_reference: Optional[str] = FieldInfo(alias="OriginalTransmissionReference", default=None) + + person_in_image: Optional[List[str]] = FieldInfo(alias="PersonInImage", default=None) + + person_in_image_cv_term_cv_id: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermCvId", default=None) + + person_in_image_cv_term_id: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermId", default=None) + + person_in_image_cv_term_name: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermName", default=None) + + person_in_image_cv_term_refined_about: Optional[List[str]] = FieldInfo( + alias="PersonInImageCvTermRefinedAbout", default=None + ) + + person_in_image_description: Optional[List[str]] = FieldInfo(alias="PersonInImageDescription", default=None) + + person_in_image_id: Optional[List[str]] = FieldInfo(alias="PersonInImageId", default=None) + + person_in_image_name: Optional[List[str]] = FieldInfo(alias="PersonInImageName", default=None) + + product_in_image_description: Optional[List[str]] = FieldInfo(alias="ProductInImageDescription", default=None) + + product_in_image_gtin: Optional[List[float]] = FieldInfo(alias="ProductInImageGTIN", default=None) + + product_in_image_name: Optional[List[str]] = FieldInfo(alias="ProductInImageName", default=None) + + property_release_id: Optional[List[str]] = FieldInfo(alias="PropertyReleaseID", default=None) + + province_state: Optional[str] = FieldInfo(alias="ProvinceState", default=None) + + rating: Optional[int] = FieldInfo(alias="Rating", default=None) + + registry_entry_role: Optional[List[str]] = FieldInfo(alias="RegistryEntryRole", default=None) + + registry_item_id: Optional[List[str]] = FieldInfo(alias="RegistryItemID", default=None) + + registry_organisation_id: Optional[List[str]] = FieldInfo(alias="RegistryOrganisationID", default=None) + + resolution_unit: Optional[str] = FieldInfo(alias="ResolutionUnit", default=None) + + rights: Optional[str] = FieldInfo(alias="Rights", default=None) + + scene: Optional[List[str]] = FieldInfo(alias="Scene", default=None) + + source: Optional[str] = FieldInfo(alias="Source", default=None) + + special_instructions: Optional[str] = FieldInfo(alias="SpecialInstructions", default=None) + + state: Optional[str] = FieldInfo(alias="State", default=None) + + subject: Optional[List[str]] = FieldInfo(alias="Subject", default=None) + + subject_code: Optional[List[str]] = FieldInfo(alias="SubjectCode", default=None) + + subject_reference: Optional[List[str]] = FieldInfo(alias="SubjectReference", default=None) + + sublocation: Optional[str] = FieldInfo(alias="Sublocation", default=None) + + time_created: Optional[str] = FieldInfo(alias="TimeCreated", default=None) + + title: Optional[str] = FieldInfo(alias="Title", default=None) + + transmission_reference: Optional[str] = FieldInfo(alias="TransmissionReference", default=None) + + usage_terms: Optional[str] = FieldInfo(alias="UsageTerms", default=None) + + web_statement: Optional[str] = FieldInfo(alias="WebStatement", default=None) + + writer: Optional[str] = FieldInfo(alias="Writer", default=None) + + writer_editor: Optional[str] = FieldInfo(alias="WriterEditor", default=None) + + x_resolution: Optional[float] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[float] = FieldInfo(alias="YResolution", default=None) + + +class ExtensionStatus(BaseModel): + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="aws-auto-tagging", default=None + ) + + google_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="google-auto-tagging", default=None + ) + + remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) + + +class MetadataExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class MetadataExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class MetadataExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class MetadataExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class MetadataExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class MetadataExif(BaseModel): + exif: Optional[MetadataExifExif] = None + """Object containing Exif details.""" + + gps: Optional[MetadataExifGps] = None + """Object containing GPS information.""" + + image: Optional[MetadataExifImage] = None + """Object containing EXIF image information.""" + + interoperability: Optional[MetadataExifInteroperability] = None + """JSON object.""" + + makernote: Optional[Dict[str, object]] = None + + thumbnail: Optional[MetadataExifThumbnail] = None + """Object containing Thumbnail information.""" + + +class Metadata(BaseModel): + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + density: Optional[int] = None + """The density of the image in DPI.""" + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + exif: Optional[MetadataExif] = None + + format: Optional[str] = None + """The format of the file (e.g., 'jpg', 'mp4').""" + + has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) + """Indicates if the image has a color profile.""" + + has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) + """Indicates if the image contains transparent areas.""" + + height: Optional[int] = None + """The height of the image or video in pixels.""" + + p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) + """Perceptual hash of the image.""" + + quality: Optional[int] = None + """The quality indicator of the image.""" + + size: Optional[int] = None + """The file size in bytes.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[int] = None + """The width of the image or video in pixels.""" + + +class VersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class FileUploadV2Response(BaseModel): + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the uploaded file by auto tagging.""" + + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """ + Value of custom coordinates associated with the image in the format + `x,y,width,height`. If `customCoordinates` are not defined, then it is `null`. + Send `customCoordinates` in `responseFields` in API request to get the value of + this field. + """ + + custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + """A key-value data associated with the asset. + + Use `responseField` in API request to get `customMetadata` in the upload API + response. Before setting any custom metadata on an asset, you have to create the + field using custom metadata fields API. Send `customMetadata` in + `responseFields` in API request to get the value of this field. + """ + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + embedded_metadata: Optional[EmbeddedMetadata] = FieldInfo(alias="embeddedMetadata", default=None) + """Consolidated embedded metadata associated with the file. + + It includes exif, iptc, and xmp data. Send `embeddedMetadata` in + `responseFields` in API request to get embeddedMetadata in the upload API + response. + """ + + extension_status: Optional[ExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) + """ + Extension names with their processing status at the time of completion of the + request. It could have one of the following status values: + + `success`: The extension has been successfully applied. `failed`: The extension + has failed and will not be retried. `pending`: The extension will finish + processing in some time. On completion, the final status (success / failed) will + be sent to the `webhookUrl` provided. + + If no extension was requested, then this parameter is not returned. + """ + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique fileId. + + Store this fileld in your database, as this will be used to perform update + action on this file. + """ + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """The relative path of the file in the media library e.g. + + `/marketing-assets/new-banner.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the uploaded file. Possible values are `image`, `non-image`.""" + + height: Optional[float] = None + """Height of the image in pixels (Only for images)""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Is the file marked as private. + + It can be either `true` or `false`. Send `isPrivateFile` in `responseFields` in + API request to get the value of this field. + """ + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Is the file published or in draft state. + + It can be either `true` or `false`. Send `isPublished` in `responseFields` in + API request to get the value of this field. + """ + + metadata: Optional[Metadata] = None + """Legacy metadata. + + Send `metadata` in `responseFields` in API request to get metadata in the upload + API response. + """ + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the image file in Bytes.""" + + tags: Optional[List[str]] = None + """The array of tags associated with the asset. + + If no tags are set, it will be `null`. Send `tags` in `responseFields` in API + request to get the value of this field. + """ + + thumbnail_url: Optional[str] = FieldInfo(alias="thumbnailUrl", default=None) + """In the case of an image, a small thumbnail URL.""" + + url: Optional[str] = None + """A publicly accessible URL of the file.""" + + version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object containing the file or file version's `id` (versionId) and `name`.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[float] = None + """Width of the image in pixels (Only for Images)""" diff --git a/src/imagekit/types/files/__init__.py b/src/imagekit/types/files/__init__.py new file mode 100644 index 0000000..f82cdc3 --- /dev/null +++ b/src/imagekit/types/files/__init__.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .batch_delete_params import BatchDeleteParams as BatchDeleteParams +from .detail_update_params import DetailUpdateParams as DetailUpdateParams +from .purge_execute_params import PurgeExecuteParams as PurgeExecuteParams +from .batch_delete_response import BatchDeleteResponse as BatchDeleteResponse +from .purge_status_response import PurgeStatusResponse as PurgeStatusResponse +from .version_list_response import VersionListResponse as VersionListResponse +from .detail_update_response import DetailUpdateResponse as DetailUpdateResponse +from .purge_execute_response import PurgeExecuteResponse as PurgeExecuteResponse +from .detail_retrieve_response import DetailRetrieveResponse as DetailRetrieveResponse +from .metadata_from_url_params import MetadataFromURLParams as MetadataFromURLParams +from .version_restore_response import VersionRestoreResponse as VersionRestoreResponse +from .version_retrieve_response import VersionRetrieveResponse as VersionRetrieveResponse +from .metadata_from_url_response import MetadataFromURLResponse as MetadataFromURLResponse +from .metadata_retrieve_response import MetadataRetrieveResponse as MetadataRetrieveResponse diff --git a/src/imagekit/types/files/batch_delete_params.py b/src/imagekit/types/files/batch_delete_params.py new file mode 100644 index 0000000..ed7a66d --- /dev/null +++ b/src/imagekit/types/files/batch_delete_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["BatchDeleteParams"] + + +class BatchDeleteParams(TypedDict, total=False): + file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] + """An array of fileIds which you want to delete.""" diff --git a/src/imagekit/types/files/batch_delete_response.py b/src/imagekit/types/files/batch_delete_response.py new file mode 100644 index 0000000..00090fb --- /dev/null +++ b/src/imagekit/types/files/batch_delete_response.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["BatchDeleteResponse"] + + +class BatchDeleteResponse(BaseModel): + successfully_deleted_file_ids: Optional[List[str]] = FieldInfo(alias="successfullyDeletedFileIds", default=None) + """An array of fileIds that were successfully deleted.""" diff --git a/src/imagekit/types/files/detail_retrieve_response.py b/src/imagekit/types/files/detail_retrieve_response.py new file mode 100644 index 0000000..b5c6331 --- /dev/null +++ b/src/imagekit/types/files/detail_retrieve_response.py @@ -0,0 +1,113 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["DetailRetrieveResponse", "AITag", "VersionInfo"] + + +class AITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Source of the tag. + + Possible values are `google-auto-tagging` and `aws-auto-tagging`. + """ + + +class VersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class DetailRetrieveResponse(BaseModel): + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the file by auto tagging.""" + + created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + """Date and time when the file was uploaded. + + The date and time is in ISO8601 format. + """ + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """An string with custom coordinates of the file.""" + + custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + """An object with custom metadata for the file.""" + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique identifier of the asset.""" + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """Path of the file. + + This is the path you would use in the URL to access the file. For example, if + the file is at the root of the media library, the path will be `/file.jpg`. If + the file is inside a folder named `images`, the path will be `/images/file.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the file. Possible values are `image`, `non-image`.""" + + has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) + """Specifies if the image has an alpha channel.""" + + height: Optional[float] = None + """Height of the file.""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Specifies if the file is private or not.""" + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Specifies if the file is published or not.""" + + mime: Optional[str] = None + """MIME type of the file.""" + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the file in bytes.""" + + tags: Optional[List[str]] = None + """An array of tags assigned to the file. + + Tags are used to search files in the media library. + """ + + thumbnail: Optional[str] = None + """URL of the thumbnail image. + + This URL is used to access the thumbnail image of the file in the media library. + """ + + type: Optional[str] = None + """Type of the asset.""" + + updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + """Date and time when the file was last updated. + + The date and time is in ISO8601 format. + """ + + url: Optional[str] = None + """URL of the file.""" + + version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object with details of the file version.""" + + width: Optional[float] = None + """Width of the file.""" diff --git a/src/imagekit/types/files/detail_update_params.py b/src/imagekit/types/files/detail_update_params.py new file mode 100644 index 0000000..c524d76 --- /dev/null +++ b/src/imagekit/types/files/detail_update_params.py @@ -0,0 +1,139 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union, Iterable, Optional +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from ..._utils import PropertyInfo + +__all__ = [ + "DetailUpdateParams", + "UpdateFileDetails", + "UpdateFileDetailsExtension", + "UpdateFileDetailsExtensionRemovedotBgExtension", + "UpdateFileDetailsExtensionRemovedotBgExtensionOptions", + "UpdateFileDetailsExtensionAutoTaggingExtension", + "ChangePublicationStatus", + "ChangePublicationStatusPublish", +] + + +class UpdateFileDetails(TypedDict, total=False): + custom_coordinates: Annotated[Optional[str], PropertyInfo(alias="customCoordinates")] + """Define an important area in the image in the format `x,y,width,height` e.g. + + `10,10,100,100`. Send `null` to unset this value. + """ + + custom_metadata: Annotated[object, PropertyInfo(alias="customMetadata")] + """A key-value data to be associated with the asset. + + To unset a key, send `null` value for that key. Before setting any custom + metadata on an asset you have to create the field using custom metadata fields + API. + """ + + extensions: Iterable[UpdateFileDetailsExtension] + """Array of extensions to be applied to the asset. + + Each extension can be configured with specific parameters based on the extension + type. + """ + + remove_ai_tags: Annotated[Union[List[str], Literal["all"]], PropertyInfo(alias="removeAITags")] + """An array of AITags associated with the file that you want to remove, e.g. + + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". + + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + """ + + tags: Optional[List[str]] + """An array of tags associated with the file, such as `["tag1", "tag2"]`. + + Send `null` to unset all tags associated with the file. + """ + + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ + + +class UpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, total=False): + add_shadow: bool + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: str + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: str + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: bool + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class UpdateFileDetailsExtensionRemovedotBgExtension(TypedDict, total=False): + name: Required[Literal["remove-bg"]] + """Specifies the background removal extension.""" + + options: UpdateFileDetailsExtensionRemovedotBgExtensionOptions + + +class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): + max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] + """Maximum number of tags to attach to the asset.""" + + min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] + """Minimum confidence level for tags to be considered valid.""" + + name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] + """Specifies the auto-tagging extension used.""" + + +UpdateFileDetailsExtension: TypeAlias = Union[ + UpdateFileDetailsExtensionRemovedotBgExtension, UpdateFileDetailsExtensionAutoTaggingExtension +] + + +class ChangePublicationStatus(TypedDict, total=False): + publish: ChangePublicationStatusPublish + """Configure the publication status of a file and its versions.""" + + +class ChangePublicationStatusPublish(TypedDict, total=False): + is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] + """Set to `true` to publish the file. Set to `false` to unpublish the file.""" + + include_file_versions: Annotated[bool, PropertyInfo(alias="includeFileVersions")] + """Set to `true` to publish/unpublish all versions of the file. + + Set to `false` to publish/unpublish only the current version of the file. + """ + + +DetailUpdateParams: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] diff --git a/src/imagekit/types/files/detail_update_response.py b/src/imagekit/types/files/detail_update_response.py new file mode 100644 index 0000000..baaeff9 --- /dev/null +++ b/src/imagekit/types/files/detail_update_response.py @@ -0,0 +1,128 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["DetailUpdateResponse", "AITag", "ExtensionStatus", "VersionInfo"] + + +class AITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Source of the tag. + + Possible values are `google-auto-tagging` and `aws-auto-tagging`. + """ + + +class ExtensionStatus(BaseModel): + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="aws-auto-tagging", default=None + ) + + google_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="google-auto-tagging", default=None + ) + + remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) + + +class VersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class DetailUpdateResponse(BaseModel): + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the file by auto tagging.""" + + created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + """Date and time when the file was uploaded. + + The date and time is in ISO8601 format. + """ + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """An string with custom coordinates of the file.""" + + custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + """An object with custom metadata for the file.""" + + extension_status: Optional[ExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique identifier of the asset.""" + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """Path of the file. + + This is the path you would use in the URL to access the file. For example, if + the file is at the root of the media library, the path will be `/file.jpg`. If + the file is inside a folder named `images`, the path will be `/images/file.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the file. Possible values are `image`, `non-image`.""" + + has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) + """Specifies if the image has an alpha channel.""" + + height: Optional[float] = None + """Height of the file.""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Specifies if the file is private or not.""" + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Specifies if the file is published or not.""" + + mime: Optional[str] = None + """MIME type of the file.""" + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the file in bytes.""" + + tags: Optional[List[str]] = None + """An array of tags assigned to the file. + + Tags are used to search files in the media library. + """ + + thumbnail: Optional[str] = None + """URL of the thumbnail image. + + This URL is used to access the thumbnail image of the file in the media library. + """ + + type: Optional[str] = None + """Type of the asset.""" + + updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + """Date and time when the file was last updated. + + The date and time is in ISO8601 format. + """ + + url: Optional[str] = None + """URL of the file.""" + + version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object with details of the file version.""" + + width: Optional[float] = None + """Width of the file.""" diff --git a/src/imagekit/types/files/metadata_from_url_params.py b/src/imagekit/types/files/metadata_from_url_params.py new file mode 100644 index 0000000..b00e09b --- /dev/null +++ b/src/imagekit/types/files/metadata_from_url_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["MetadataFromURLParams"] + + +class MetadataFromURLParams(TypedDict, total=False): + url: Required[str] + """Should be a valid file URL. + + It should be accessible using your ImageKit.io account. + """ diff --git a/src/imagekit/types/files/metadata_from_url_response.py b/src/imagekit/types/files/metadata_from_url_response.py new file mode 100644 index 0000000..4d48455 --- /dev/null +++ b/src/imagekit/types/files/metadata_from_url_response.py @@ -0,0 +1,181 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "MetadataFromURLResponse", + "Exif", + "ExifExif", + "ExifGps", + "ExifImage", + "ExifInteroperability", + "ExifThumbnail", +] + + +class ExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class ExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class ExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class ExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class ExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class Exif(BaseModel): + exif: Optional[ExifExif] = None + """Object containing Exif details.""" + + gps: Optional[ExifGps] = None + """Object containing GPS information.""" + + image: Optional[ExifImage] = None + """Object containing EXIF image information.""" + + interoperability: Optional[ExifInteroperability] = None + """JSON object.""" + + makernote: Optional[Dict[str, object]] = None + + thumbnail: Optional[ExifThumbnail] = None + """Object containing Thumbnail information.""" + + +class MetadataFromURLResponse(BaseModel): + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + density: Optional[int] = None + """The density of the image in DPI.""" + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + exif: Optional[Exif] = None + + format: Optional[str] = None + """The format of the file (e.g., 'jpg', 'mp4').""" + + has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) + """Indicates if the image has a color profile.""" + + has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) + """Indicates if the image contains transparent areas.""" + + height: Optional[int] = None + """The height of the image or video in pixels.""" + + p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) + """Perceptual hash of the image.""" + + quality: Optional[int] = None + """The quality indicator of the image.""" + + size: Optional[int] = None + """The file size in bytes.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[int] = None + """The width of the image or video in pixels.""" diff --git a/src/imagekit/types/files/metadata_retrieve_response.py b/src/imagekit/types/files/metadata_retrieve_response.py new file mode 100644 index 0000000..a6c7a25 --- /dev/null +++ b/src/imagekit/types/files/metadata_retrieve_response.py @@ -0,0 +1,181 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "MetadataRetrieveResponse", + "Exif", + "ExifExif", + "ExifGps", + "ExifImage", + "ExifInteroperability", + "ExifThumbnail", +] + + +class ExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class ExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class ExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class ExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class ExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class Exif(BaseModel): + exif: Optional[ExifExif] = None + """Object containing Exif details.""" + + gps: Optional[ExifGps] = None + """Object containing GPS information.""" + + image: Optional[ExifImage] = None + """Object containing EXIF image information.""" + + interoperability: Optional[ExifInteroperability] = None + """JSON object.""" + + makernote: Optional[Dict[str, object]] = None + + thumbnail: Optional[ExifThumbnail] = None + """Object containing Thumbnail information.""" + + +class MetadataRetrieveResponse(BaseModel): + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + density: Optional[int] = None + """The density of the image in DPI.""" + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + exif: Optional[Exif] = None + + format: Optional[str] = None + """The format of the file (e.g., 'jpg', 'mp4').""" + + has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) + """Indicates if the image has a color profile.""" + + has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) + """Indicates if the image contains transparent areas.""" + + height: Optional[int] = None + """The height of the image or video in pixels.""" + + p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) + """Perceptual hash of the image.""" + + quality: Optional[int] = None + """The quality indicator of the image.""" + + size: Optional[int] = None + """The file size in bytes.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[int] = None + """The width of the image or video in pixels.""" diff --git a/src/imagekit/types/files/purge_execute_params.py b/src/imagekit/types/files/purge_execute_params.py new file mode 100644 index 0000000..aa1e93d --- /dev/null +++ b/src/imagekit/types/files/purge_execute_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["PurgeExecuteParams"] + + +class PurgeExecuteParams(TypedDict, total=False): + url: Required[str] + """The full URL of the file to be purged.""" diff --git a/src/imagekit/types/files/purge_execute_response.py b/src/imagekit/types/files/purge_execute_response.py new file mode 100644 index 0000000..bba594a --- /dev/null +++ b/src/imagekit/types/files/purge_execute_response.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["PurgeExecuteResponse"] + + +class PurgeExecuteResponse(BaseModel): + request_id: Optional[str] = FieldInfo(alias="requestId", default=None) + """Unique identifier of the purge request. + + This can be used to check the status of the purge request. + """ diff --git a/src/imagekit/types/files/purge_status_response.py b/src/imagekit/types/files/purge_status_response.py new file mode 100644 index 0000000..c80f1d3 --- /dev/null +++ b/src/imagekit/types/files/purge_status_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["PurgeStatusResponse"] + + +class PurgeStatusResponse(BaseModel): + status: Optional[Literal["Pending", "Completed"]] = None + """Status of the purge request.""" diff --git a/src/imagekit/types/files/version_list_response.py b/src/imagekit/types/files/version_list_response.py new file mode 100644 index 0000000..bbe701f --- /dev/null +++ b/src/imagekit/types/files/version_list_response.py @@ -0,0 +1,122 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "VersionListResponse", + "VersionListResponseItem", + "VersionListResponseItemAITag", + "VersionListResponseItemVersionInfo", +] + + +class VersionListResponseItemAITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Source of the tag. + + Possible values are `google-auto-tagging` and `aws-auto-tagging`. + """ + + +class VersionListResponseItemVersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class VersionListResponseItem(BaseModel): + ai_tags: Optional[List[VersionListResponseItemAITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the file by auto tagging.""" + + created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + """Date and time when the file was uploaded. + + The date and time is in ISO8601 format. + """ + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """An string with custom coordinates of the file.""" + + custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + """An object with custom metadata for the file.""" + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique identifier of the asset.""" + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """Path of the file. + + This is the path you would use in the URL to access the file. For example, if + the file is at the root of the media library, the path will be `/file.jpg`. If + the file is inside a folder named `images`, the path will be `/images/file.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the file. Possible values are `image`, `non-image`.""" + + has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) + """Specifies if the image has an alpha channel.""" + + height: Optional[float] = None + """Height of the file.""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Specifies if the file is private or not.""" + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Specifies if the file is published or not.""" + + mime: Optional[str] = None + """MIME type of the file.""" + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the file in bytes.""" + + tags: Optional[List[str]] = None + """An array of tags assigned to the file. + + Tags are used to search files in the media library. + """ + + thumbnail: Optional[str] = None + """URL of the thumbnail image. + + This URL is used to access the thumbnail image of the file in the media library. + """ + + type: Optional[str] = None + """Type of the asset.""" + + updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + """Date and time when the file was last updated. + + The date and time is in ISO8601 format. + """ + + url: Optional[str] = None + """URL of the file.""" + + version_info: Optional[VersionListResponseItemVersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object with details of the file version.""" + + width: Optional[float] = None + """Width of the file.""" + + +VersionListResponse: TypeAlias = List[VersionListResponseItem] diff --git a/src/imagekit/types/files/version_restore_response.py b/src/imagekit/types/files/version_restore_response.py new file mode 100644 index 0000000..27bb064 --- /dev/null +++ b/src/imagekit/types/files/version_restore_response.py @@ -0,0 +1,113 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["VersionRestoreResponse", "AITag", "VersionInfo"] + + +class AITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Source of the tag. + + Possible values are `google-auto-tagging` and `aws-auto-tagging`. + """ + + +class VersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class VersionRestoreResponse(BaseModel): + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the file by auto tagging.""" + + created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + """Date and time when the file was uploaded. + + The date and time is in ISO8601 format. + """ + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """An string with custom coordinates of the file.""" + + custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + """An object with custom metadata for the file.""" + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique identifier of the asset.""" + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """Path of the file. + + This is the path you would use in the URL to access the file. For example, if + the file is at the root of the media library, the path will be `/file.jpg`. If + the file is inside a folder named `images`, the path will be `/images/file.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the file. Possible values are `image`, `non-image`.""" + + has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) + """Specifies if the image has an alpha channel.""" + + height: Optional[float] = None + """Height of the file.""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Specifies if the file is private or not.""" + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Specifies if the file is published or not.""" + + mime: Optional[str] = None + """MIME type of the file.""" + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the file in bytes.""" + + tags: Optional[List[str]] = None + """An array of tags assigned to the file. + + Tags are used to search files in the media library. + """ + + thumbnail: Optional[str] = None + """URL of the thumbnail image. + + This URL is used to access the thumbnail image of the file in the media library. + """ + + type: Optional[str] = None + """Type of the asset.""" + + updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + """Date and time when the file was last updated. + + The date and time is in ISO8601 format. + """ + + url: Optional[str] = None + """URL of the file.""" + + version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object with details of the file version.""" + + width: Optional[float] = None + """Width of the file.""" diff --git a/src/imagekit/types/files/version_retrieve_response.py b/src/imagekit/types/files/version_retrieve_response.py new file mode 100644 index 0000000..9d7d883 --- /dev/null +++ b/src/imagekit/types/files/version_retrieve_response.py @@ -0,0 +1,113 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["VersionRetrieveResponse", "AITag", "VersionInfo"] + + +class AITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Source of the tag. + + Possible values are `google-auto-tagging` and `aws-auto-tagging`. + """ + + +class VersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class VersionRetrieveResponse(BaseModel): + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the file by auto tagging.""" + + created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + """Date and time when the file was uploaded. + + The date and time is in ISO8601 format. + """ + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """An string with custom coordinates of the file.""" + + custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + """An object with custom metadata for the file.""" + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique identifier of the asset.""" + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """Path of the file. + + This is the path you would use in the URL to access the file. For example, if + the file is at the root of the media library, the path will be `/file.jpg`. If + the file is inside a folder named `images`, the path will be `/images/file.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the file. Possible values are `image`, `non-image`.""" + + has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) + """Specifies if the image has an alpha channel.""" + + height: Optional[float] = None + """Height of the file.""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Specifies if the file is private or not.""" + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Specifies if the file is published or not.""" + + mime: Optional[str] = None + """MIME type of the file.""" + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the file in bytes.""" + + tags: Optional[List[str]] = None + """An array of tags assigned to the file. + + Tags are used to search files in the media library. + """ + + thumbnail: Optional[str] = None + """URL of the thumbnail image. + + This URL is used to access the thumbnail image of the file in the media library. + """ + + type: Optional[str] = None + """Type of the asset.""" + + updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + """Date and time when the file was last updated. + + The date and time is in ISO8601 format. + """ + + url: Optional[str] = None + """URL of the file.""" + + version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object with details of the file version.""" + + width: Optional[float] = None + """Width of the file.""" diff --git a/src/imagekit/types/folder_create_params.py b/src/imagekit/types/folder_create_params.py new file mode 100644 index 0000000..82863b5 --- /dev/null +++ b/src/imagekit/types/folder_create_params.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FolderCreateParams"] + + +class FolderCreateParams(TypedDict, total=False): + folder_name: Required[Annotated[str, PropertyInfo(alias="folderName")]] + """The folder will be created with this name. + + All characters except alphabets and numbers (inclusive of unicode letters, + marks, and numerals in other languages) will be replaced by an underscore i.e. + `_`. + """ + + parent_folder_path: Required[Annotated[str, PropertyInfo(alias="parentFolderPath")]] + """ + The folder where the new folder should be created, for root use `/` else the + path e.g. `containing/folder/`. + + Note: If any folder(s) is not present in the parentFolderPath parameter, it will + be automatically created. For example, if you pass `/product/images/summer`, + then `product`, `images`, and `summer` folders will be created if they don't + already exist. + """ diff --git a/src/imagekit/types/folder_delete_params.py b/src/imagekit/types/folder_delete_params.py new file mode 100644 index 0000000..8b5ff52 --- /dev/null +++ b/src/imagekit/types/folder_delete_params.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FolderDeleteParams"] + + +class FolderDeleteParams(TypedDict, total=False): + folder_path: Required[Annotated[str, PropertyInfo(alias="folderPath")]] + """Full path to the folder you want to delete. For example `/folder/to/delete/`.""" diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/__init__.py b/tests/api_resources/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/files/__init__.py b/tests/api_resources/files/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/files/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/files/test_batch.py b/tests/api_resources/files/test_batch.py new file mode 100644 index 0000000..08f8ff9 --- /dev/null +++ b/tests/api_resources/files/test_batch.py @@ -0,0 +1,92 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types.files import BatchDeleteResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestBatch: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + batch = client.files.batch.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + assert_matches_type(BatchDeleteResponse, batch, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.files.batch.with_raw_response.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + batch = response.parse() + assert_matches_type(BatchDeleteResponse, batch, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.files.batch.with_streaming_response.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + batch = response.parse() + assert_matches_type(BatchDeleteResponse, batch, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncBatch: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncImageKit) -> None: + batch = await async_client.files.batch.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + assert_matches_type(BatchDeleteResponse, batch, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.batch.with_raw_response.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + batch = await response.parse() + assert_matches_type(BatchDeleteResponse, batch, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: + async with async_client.files.batch.with_streaming_response.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + batch = await response.parse() + assert_matches_type(BatchDeleteResponse, batch, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/files/test_details.py b/tests/api_resources/files/test_details.py new file mode 100644 index 0000000..6191ac1 --- /dev/null +++ b/tests/api_resources/files/test_details.py @@ -0,0 +1,348 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types.files import DetailUpdateResponse, DetailRetrieveResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestDetails: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve(self, client: ImageKit) -> None: + detail = client.files.details.retrieve( + "fileId", + ) + assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: ImageKit) -> None: + response = client.files.details.with_raw_response.retrieve( + "fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + detail = response.parse() + assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: ImageKit) -> None: + with client.files.details.with_streaming_response.retrieve( + "fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + detail = response.parse() + assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.details.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_1(self, client: ImageKit) -> None: + detail = client.files.details.update( + file_id="fileId", + ) + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: + detail = client.files.details.update( + file_id="fileId", + custom_coordinates="customCoordinates", + custom_metadata={}, + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + } + ], + remove_ai_tags=["string"], + tags=["tag1", "tag2"], + webhook_url="webhookUrl", + ) + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_1(self, client: ImageKit) -> None: + response = client.files.details.with_raw_response.update( + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + detail = response.parse() + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: + with client.files.details.with_streaming_response.update( + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + detail = response.parse() + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_1(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.details.with_raw_response.update( + file_id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_2(self, client: ImageKit) -> None: + detail = client.files.details.update( + file_id="fileId", + ) + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: + detail = client.files.details.update( + file_id="fileId", + publish={ + "is_published": True, + "include_file_versions": True, + }, + ) + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_2(self, client: ImageKit) -> None: + response = client.files.details.with_raw_response.update( + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + detail = response.parse() + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: + with client.files.details.with_streaming_response.update( + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + detail = response.parse() + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_2(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.details.with_raw_response.update( + file_id="", + ) + + +class TestAsyncDetails: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncImageKit) -> None: + detail = await async_client.files.details.retrieve( + "fileId", + ) + assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.details.with_raw_response.retrieve( + "fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + detail = await response.parse() + assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncImageKit) -> None: + async with async_client.files.details.with_streaming_response.retrieve( + "fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + detail = await response.parse() + assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.details.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: + detail = await async_client.files.details.update( + file_id="fileId", + ) + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + detail = await async_client.files.details.update( + file_id="fileId", + custom_coordinates="customCoordinates", + custom_metadata={}, + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + } + ], + remove_ai_tags=["string"], + tags=["tag1", "tag2"], + webhook_url="webhookUrl", + ) + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.details.with_raw_response.update( + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + detail = await response.parse() + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + async with async_client.files.details.with_streaming_response.update( + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + detail = await response.parse() + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.details.with_raw_response.update( + file_id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: + detail = await async_client.files.details.update( + file_id="fileId", + ) + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + detail = await async_client.files.details.update( + file_id="fileId", + publish={ + "is_published": True, + "include_file_versions": True, + }, + ) + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.details.with_raw_response.update( + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + detail = await response.parse() + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + async with async_client.files.details.with_streaming_response.update( + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + detail = await response.parse() + assert_matches_type(DetailUpdateResponse, detail, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.details.with_raw_response.update( + file_id="", + ) diff --git a/tests/api_resources/files/test_metadata.py b/tests/api_resources/files/test_metadata.py new file mode 100644 index 0000000..9689998 --- /dev/null +++ b/tests/api_resources/files/test_metadata.py @@ -0,0 +1,176 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types.files import MetadataFromURLResponse, MetadataRetrieveResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestMetadata: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve(self, client: ImageKit) -> None: + metadata = client.files.metadata.retrieve( + "fileId", + ) + assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: ImageKit) -> None: + response = client.files.metadata.with_raw_response.retrieve( + "fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + metadata = response.parse() + assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: ImageKit) -> None: + with client.files.metadata.with_streaming_response.retrieve( + "fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + metadata = response.parse() + assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.metadata.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_from_url(self, client: ImageKit) -> None: + metadata = client.files.metadata.from_url( + url="url", + ) + assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_from_url(self, client: ImageKit) -> None: + response = client.files.metadata.with_raw_response.from_url( + url="url", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + metadata = response.parse() + assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_from_url(self, client: ImageKit) -> None: + with client.files.metadata.with_streaming_response.from_url( + url="url", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + metadata = response.parse() + assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncMetadata: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncImageKit) -> None: + metadata = await async_client.files.metadata.retrieve( + "fileId", + ) + assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.metadata.with_raw_response.retrieve( + "fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + metadata = await response.parse() + assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncImageKit) -> None: + async with async_client.files.metadata.with_streaming_response.retrieve( + "fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + metadata = await response.parse() + assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.metadata.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_from_url(self, async_client: AsyncImageKit) -> None: + metadata = await async_client.files.metadata.from_url( + url="url", + ) + assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_from_url(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.metadata.with_raw_response.from_url( + url="url", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + metadata = await response.parse() + assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_from_url(self, async_client: AsyncImageKit) -> None: + async with async_client.files.metadata.with_streaming_response.from_url( + url="url", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + metadata = await response.parse() + assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/files/test_purge.py b/tests/api_resources/files/test_purge.py new file mode 100644 index 0000000..5bb67f3 --- /dev/null +++ b/tests/api_resources/files/test_purge.py @@ -0,0 +1,176 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types.files import PurgeStatusResponse, PurgeExecuteResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestPurge: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_execute(self, client: ImageKit) -> None: + purge = client.files.purge.execute( + url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", + ) + assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_execute(self, client: ImageKit) -> None: + response = client.files.purge.with_raw_response.execute( + url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + purge = response.parse() + assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_execute(self, client: ImageKit) -> None: + with client.files.purge.with_streaming_response.execute( + url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + purge = response.parse() + assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_status(self, client: ImageKit) -> None: + purge = client.files.purge.status( + "requestId", + ) + assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_status(self, client: ImageKit) -> None: + response = client.files.purge.with_raw_response.status( + "requestId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + purge = response.parse() + assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_status(self, client: ImageKit) -> None: + with client.files.purge.with_streaming_response.status( + "requestId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + purge = response.parse() + assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_status(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `request_id` but received ''"): + client.files.purge.with_raw_response.status( + "", + ) + + +class TestAsyncPurge: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_execute(self, async_client: AsyncImageKit) -> None: + purge = await async_client.files.purge.execute( + url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", + ) + assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_execute(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.purge.with_raw_response.execute( + url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + purge = await response.parse() + assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_execute(self, async_client: AsyncImageKit) -> None: + async with async_client.files.purge.with_streaming_response.execute( + url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + purge = await response.parse() + assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_status(self, async_client: AsyncImageKit) -> None: + purge = await async_client.files.purge.status( + "requestId", + ) + assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_status(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.purge.with_raw_response.status( + "requestId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + purge = await response.parse() + assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_status(self, async_client: AsyncImageKit) -> None: + async with async_client.files.purge.with_streaming_response.status( + "requestId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + purge = await response.parse() + assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_status(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `request_id` but received ''"): + await async_client.files.purge.with_raw_response.status( + "", + ) diff --git a/tests/api_resources/files/test_versions.py b/tests/api_resources/files/test_versions.py new file mode 100644 index 0000000..f6560ab --- /dev/null +++ b/tests/api_resources/files/test_versions.py @@ -0,0 +1,420 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types.files import VersionListResponse, VersionRestoreResponse, VersionRetrieveResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestVersions: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve(self, client: ImageKit) -> None: + version = client.files.versions.retrieve( + version_id="versionId", + file_id="fileId", + ) + assert_matches_type(VersionRetrieveResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: ImageKit) -> None: + response = client.files.versions.with_raw_response.retrieve( + version_id="versionId", + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = response.parse() + assert_matches_type(VersionRetrieveResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: ImageKit) -> None: + with client.files.versions.with_streaming_response.retrieve( + version_id="versionId", + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = response.parse() + assert_matches_type(VersionRetrieveResponse, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.versions.with_raw_response.retrieve( + version_id="versionId", + file_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): + client.files.versions.with_raw_response.retrieve( + version_id="", + file_id="fileId", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: ImageKit) -> None: + version = client.files.versions.list( + "fileId", + ) + assert_matches_type(VersionListResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: ImageKit) -> None: + response = client.files.versions.with_raw_response.list( + "fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = response.parse() + assert_matches_type(VersionListResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: ImageKit) -> None: + with client.files.versions.with_streaming_response.list( + "fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = response.parse() + assert_matches_type(VersionListResponse, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_list(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.versions.with_raw_response.list( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + version = client.files.versions.delete( + version_id="versionId", + file_id="fileId", + ) + assert_matches_type(object, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.files.versions.with_raw_response.delete( + version_id="versionId", + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = response.parse() + assert_matches_type(object, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.files.versions.with_streaming_response.delete( + version_id="versionId", + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = response.parse() + assert_matches_type(object, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.versions.with_raw_response.delete( + version_id="versionId", + file_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): + client.files.versions.with_raw_response.delete( + version_id="", + file_id="fileId", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_restore(self, client: ImageKit) -> None: + version = client.files.versions.restore( + version_id="versionId", + file_id="fileId", + ) + assert_matches_type(VersionRestoreResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_restore(self, client: ImageKit) -> None: + response = client.files.versions.with_raw_response.restore( + version_id="versionId", + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = response.parse() + assert_matches_type(VersionRestoreResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_restore(self, client: ImageKit) -> None: + with client.files.versions.with_streaming_response.restore( + version_id="versionId", + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = response.parse() + assert_matches_type(VersionRestoreResponse, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_restore(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.versions.with_raw_response.restore( + version_id="versionId", + file_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): + client.files.versions.with_raw_response.restore( + version_id="", + file_id="fileId", + ) + + +class TestAsyncVersions: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncImageKit) -> None: + version = await async_client.files.versions.retrieve( + version_id="versionId", + file_id="fileId", + ) + assert_matches_type(VersionRetrieveResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.versions.with_raw_response.retrieve( + version_id="versionId", + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = await response.parse() + assert_matches_type(VersionRetrieveResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncImageKit) -> None: + async with async_client.files.versions.with_streaming_response.retrieve( + version_id="versionId", + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = await response.parse() + assert_matches_type(VersionRetrieveResponse, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.versions.with_raw_response.retrieve( + version_id="versionId", + file_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): + await async_client.files.versions.with_raw_response.retrieve( + version_id="", + file_id="fileId", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncImageKit) -> None: + version = await async_client.files.versions.list( + "fileId", + ) + assert_matches_type(VersionListResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.versions.with_raw_response.list( + "fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = await response.parse() + assert_matches_type(VersionListResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncImageKit) -> None: + async with async_client.files.versions.with_streaming_response.list( + "fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = await response.parse() + assert_matches_type(VersionListResponse, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_list(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.versions.with_raw_response.list( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncImageKit) -> None: + version = await async_client.files.versions.delete( + version_id="versionId", + file_id="fileId", + ) + assert_matches_type(object, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.versions.with_raw_response.delete( + version_id="versionId", + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = await response.parse() + assert_matches_type(object, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: + async with async_client.files.versions.with_streaming_response.delete( + version_id="versionId", + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = await response.parse() + assert_matches_type(object, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.versions.with_raw_response.delete( + version_id="versionId", + file_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): + await async_client.files.versions.with_raw_response.delete( + version_id="", + file_id="fileId", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_restore(self, async_client: AsyncImageKit) -> None: + version = await async_client.files.versions.restore( + version_id="versionId", + file_id="fileId", + ) + assert_matches_type(VersionRestoreResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_restore(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.versions.with_raw_response.restore( + version_id="versionId", + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = await response.parse() + assert_matches_type(VersionRestoreResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_restore(self, async_client: AsyncImageKit) -> None: + async with async_client.files.versions.with_streaming_response.restore( + version_id="versionId", + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = await response.parse() + assert_matches_type(VersionRestoreResponse, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_restore(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.versions.with_raw_response.restore( + version_id="versionId", + file_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): + await async_client.files.versions.with_raw_response.restore( + version_id="", + file_id="fileId", + ) diff --git a/tests/api_resources/test_accounts.py b/tests/api_resources/test_accounts.py new file mode 100644 index 0000000..b136b5e --- /dev/null +++ b/tests/api_resources/test_accounts.py @@ -0,0 +1,99 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types import AccountGetUsageResponse +from imagekit._utils import parse_date + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAccounts: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_get_usage(self, client: ImageKit) -> None: + account = client.accounts.get_usage( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + ) + assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_get_usage(self, client: ImageKit) -> None: + response = client.accounts.with_raw_response.get_usage( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account = response.parse() + assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_get_usage(self, client: ImageKit) -> None: + with client.accounts.with_streaming_response.get_usage( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + account = response.parse() + assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncAccounts: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_get_usage(self, async_client: AsyncImageKit) -> None: + account = await async_client.accounts.get_usage( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + ) + assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_get_usage(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.with_raw_response.get_usage( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account = await response.parse() + assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_get_usage(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.with_streaming_response.get_usage( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + account = await response.parse() + assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_bulk_jobs.py b/tests/api_resources/test_bulk_jobs.py new file mode 100644 index 0000000..64d711f --- /dev/null +++ b/tests/api_resources/test_bulk_jobs.py @@ -0,0 +1,280 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types import ( + BulkJobCopyFolderResponse, + BulkJobMoveFolderResponse, + BulkJobRetrieveStatusResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestBulkJobs: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_copy_folder(self, client: ImageKit) -> None: + bulk_job = client.bulk_jobs.copy_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_copy_folder_with_all_params(self, client: ImageKit) -> None: + bulk_job = client.bulk_jobs.copy_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + include_versions=True, + ) + assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_copy_folder(self, client: ImageKit) -> None: + response = client.bulk_jobs.with_raw_response.copy_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_job = response.parse() + assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_copy_folder(self, client: ImageKit) -> None: + with client.bulk_jobs.with_streaming_response.copy_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_job = response.parse() + assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_move_folder(self, client: ImageKit) -> None: + bulk_job = client.bulk_jobs.move_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_move_folder(self, client: ImageKit) -> None: + response = client.bulk_jobs.with_raw_response.move_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_job = response.parse() + assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_move_folder(self, client: ImageKit) -> None: + with client.bulk_jobs.with_streaming_response.move_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_job = response.parse() + assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve_status(self, client: ImageKit) -> None: + bulk_job = client.bulk_jobs.retrieve_status( + "jobId", + ) + assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve_status(self, client: ImageKit) -> None: + response = client.bulk_jobs.with_raw_response.retrieve_status( + "jobId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_job = response.parse() + assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve_status(self, client: ImageKit) -> None: + with client.bulk_jobs.with_streaming_response.retrieve_status( + "jobId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_job = response.parse() + assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_retrieve_status(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"): + client.bulk_jobs.with_raw_response.retrieve_status( + "", + ) + + +class TestAsyncBulkJobs: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_copy_folder(self, async_client: AsyncImageKit) -> None: + bulk_job = await async_client.bulk_jobs.copy_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_copy_folder_with_all_params(self, async_client: AsyncImageKit) -> None: + bulk_job = await async_client.bulk_jobs.copy_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + include_versions=True, + ) + assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_copy_folder(self, async_client: AsyncImageKit) -> None: + response = await async_client.bulk_jobs.with_raw_response.copy_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_job = await response.parse() + assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_copy_folder(self, async_client: AsyncImageKit) -> None: + async with async_client.bulk_jobs.with_streaming_response.copy_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_job = await response.parse() + assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_move_folder(self, async_client: AsyncImageKit) -> None: + bulk_job = await async_client.bulk_jobs.move_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_move_folder(self, async_client: AsyncImageKit) -> None: + response = await async_client.bulk_jobs.with_raw_response.move_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_job = await response.parse() + assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_move_folder(self, async_client: AsyncImageKit) -> None: + async with async_client.bulk_jobs.with_streaming_response.move_folder( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_job = await response.parse() + assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve_status(self, async_client: AsyncImageKit) -> None: + bulk_job = await async_client.bulk_jobs.retrieve_status( + "jobId", + ) + assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_retrieve_status(self, async_client: AsyncImageKit) -> None: + response = await async_client.bulk_jobs.with_raw_response.retrieve_status( + "jobId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_job = await response.parse() + assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_retrieve_status(self, async_client: AsyncImageKit) -> None: + async with async_client.bulk_jobs.with_streaming_response.retrieve_status( + "jobId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_job = await response.parse() + assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_retrieve_status(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"): + await async_client.bulk_jobs.with_raw_response.retrieve_status( + "", + ) diff --git a/tests/api_resources/test_custom_metadata_fields.py b/tests/api_resources/test_custom_metadata_fields.py new file mode 100644 index 0000000..8f454cf --- /dev/null +++ b/tests/api_resources/test_custom_metadata_fields.py @@ -0,0 +1,422 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types import ( + CustomMetadataFieldListResponse, + CustomMetadataFieldCreateResponse, + CustomMetadataFieldUpdateResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestCustomMetadataFields: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create(self, client: ImageKit) -> None: + custom_metadata_field = client.custom_metadata_fields.create( + label="price", + name="price", + schema={"type": "Number"}, + ) + assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: ImageKit) -> None: + custom_metadata_field = client.custom_metadata_fields.create( + label="price", + name="price", + schema={ + "type": "Number", + "default_value": "string", + "is_value_required": True, + "max_length": 0, + "max_value": 3000, + "min_length": 0, + "min_value": 1000, + "select_options": ["small", "medium", "large", 30, 40, True], + }, + ) + assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create(self, client: ImageKit) -> None: + response = client.custom_metadata_fields.with_raw_response.create( + label="price", + name="price", + schema={"type": "Number"}, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + custom_metadata_field = response.parse() + assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create(self, client: ImageKit) -> None: + with client.custom_metadata_fields.with_streaming_response.create( + label="price", + name="price", + schema={"type": "Number"}, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + custom_metadata_field = response.parse() + assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update(self, client: ImageKit) -> None: + custom_metadata_field = client.custom_metadata_fields.update( + id="id", + ) + assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: ImageKit) -> None: + custom_metadata_field = client.custom_metadata_fields.update( + id="id", + label="price", + schema={ + "default_value": "string", + "is_value_required": True, + "max_length": 0, + "max_value": 3000, + "min_length": 0, + "min_value": 1000, + "select_options": ["small", "medium", "large", 30, 40, True], + }, + ) + assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update(self, client: ImageKit) -> None: + response = client.custom_metadata_fields.with_raw_response.update( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + custom_metadata_field = response.parse() + assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update(self, client: ImageKit) -> None: + with client.custom_metadata_fields.with_streaming_response.update( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + custom_metadata_field = response.parse() + assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.custom_metadata_fields.with_raw_response.update( + id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: ImageKit) -> None: + custom_metadata_field = client.custom_metadata_fields.list() + assert_matches_type(CustomMetadataFieldListResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: ImageKit) -> None: + custom_metadata_field = client.custom_metadata_fields.list( + include_deleted=True, + ) + assert_matches_type(CustomMetadataFieldListResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: ImageKit) -> None: + response = client.custom_metadata_fields.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + custom_metadata_field = response.parse() + assert_matches_type(CustomMetadataFieldListResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: ImageKit) -> None: + with client.custom_metadata_fields.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + custom_metadata_field = response.parse() + assert_matches_type(CustomMetadataFieldListResponse, custom_metadata_field, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + custom_metadata_field = client.custom_metadata_fields.delete( + "id", + ) + assert_matches_type(object, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.custom_metadata_fields.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + custom_metadata_field = response.parse() + assert_matches_type(object, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.custom_metadata_fields.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + custom_metadata_field = response.parse() + assert_matches_type(object, custom_metadata_field, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.custom_metadata_fields.with_raw_response.delete( + "", + ) + + +class TestAsyncCustomMetadataFields: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncImageKit) -> None: + custom_metadata_field = await async_client.custom_metadata_fields.create( + label="price", + name="price", + schema={"type": "Number"}, + ) + assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncImageKit) -> None: + custom_metadata_field = await async_client.custom_metadata_fields.create( + label="price", + name="price", + schema={ + "type": "Number", + "default_value": "string", + "is_value_required": True, + "max_length": 0, + "max_value": 3000, + "min_length": 0, + "min_value": 1000, + "select_options": ["small", "medium", "large", 30, 40, True], + }, + ) + assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: + response = await async_client.custom_metadata_fields.with_raw_response.create( + label="price", + name="price", + schema={"type": "Number"}, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + custom_metadata_field = await response.parse() + assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: + async with async_client.custom_metadata_fields.with_streaming_response.create( + label="price", + name="price", + schema={"type": "Number"}, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + custom_metadata_field = await response.parse() + assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncImageKit) -> None: + custom_metadata_field = await async_client.custom_metadata_fields.update( + id="id", + ) + assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncImageKit) -> None: + custom_metadata_field = await async_client.custom_metadata_fields.update( + id="id", + label="price", + schema={ + "default_value": "string", + "is_value_required": True, + "max_length": 0, + "max_value": 3000, + "min_length": 0, + "min_value": 1000, + "select_options": ["small", "medium", "large", 30, 40, True], + }, + ) + assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: + response = await async_client.custom_metadata_fields.with_raw_response.update( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + custom_metadata_field = await response.parse() + assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncImageKit) -> None: + async with async_client.custom_metadata_fields.with_streaming_response.update( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + custom_metadata_field = await response.parse() + assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.custom_metadata_fields.with_raw_response.update( + id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncImageKit) -> None: + custom_metadata_field = await async_client.custom_metadata_fields.list() + assert_matches_type(CustomMetadataFieldListResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncImageKit) -> None: + custom_metadata_field = await async_client.custom_metadata_fields.list( + include_deleted=True, + ) + assert_matches_type(CustomMetadataFieldListResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncImageKit) -> None: + response = await async_client.custom_metadata_fields.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + custom_metadata_field = await response.parse() + assert_matches_type(CustomMetadataFieldListResponse, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncImageKit) -> None: + async with async_client.custom_metadata_fields.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + custom_metadata_field = await response.parse() + assert_matches_type(CustomMetadataFieldListResponse, custom_metadata_field, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncImageKit) -> None: + custom_metadata_field = await async_client.custom_metadata_fields.delete( + "id", + ) + assert_matches_type(object, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: + response = await async_client.custom_metadata_fields.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + custom_metadata_field = await response.parse() + assert_matches_type(object, custom_metadata_field, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: + async with async_client.custom_metadata_fields.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + custom_metadata_field = await response.parse() + assert_matches_type(object, custom_metadata_field, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.custom_metadata_fields.with_raw_response.delete( + "", + ) diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py new file mode 100644 index 0000000..ee92064 --- /dev/null +++ b/tests/api_resources/test_files.py @@ -0,0 +1,942 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types import ( + FileListResponse, + FileRenameResponse, + FileAddTagsResponse, + FileUploadV1Response, + FileUploadV2Response, + FileRemoveTagsResponse, + FileRemoveAITagsResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFiles: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: ImageKit) -> None: + file = client.files.list() + assert_matches_type(FileListResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: ImageKit) -> None: + file = client.files.list( + file_type="fileType", + limit="limit", + path="path", + search_query="searchQuery", + skip="skip", + sort="sort", + type="file", + ) + assert_matches_type(FileListResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: ImageKit) -> None: + response = client.files.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileListResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: ImageKit) -> None: + with client.files.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileListResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + file = client.files.delete( + "fileId", + ) + assert file is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.files.with_raw_response.delete( + "fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert file is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.files.with_streaming_response.delete( + "fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert file is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_add_tags(self, client: ImageKit) -> None: + file = client.files.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + assert_matches_type(FileAddTagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_add_tags(self, client: ImageKit) -> None: + response = client.files.with_raw_response.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileAddTagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_add_tags(self, client: ImageKit) -> None: + with client.files.with_streaming_response.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileAddTagsResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_copy(self, client: ImageKit) -> None: + file = client.files.copy( + destination_path="/folder/to/copy/into/", + source_file_path="/path/to/file.jpg", + ) + assert_matches_type(object, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_copy_with_all_params(self, client: ImageKit) -> None: + file = client.files.copy( + destination_path="/folder/to/copy/into/", + source_file_path="/path/to/file.jpg", + include_file_versions=False, + ) + assert_matches_type(object, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_copy(self, client: ImageKit) -> None: + response = client.files.with_raw_response.copy( + destination_path="/folder/to/copy/into/", + source_file_path="/path/to/file.jpg", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(object, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_copy(self, client: ImageKit) -> None: + with client.files.with_streaming_response.copy( + destination_path="/folder/to/copy/into/", + source_file_path="/path/to/file.jpg", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(object, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_move(self, client: ImageKit) -> None: + file = client.files.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", + ) + assert_matches_type(object, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_move(self, client: ImageKit) -> None: + response = client.files.with_raw_response.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(object, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_move(self, client: ImageKit) -> None: + with client.files.with_streaming_response.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(object, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_remove_ai_tags(self, client: ImageKit) -> None: + file = client.files.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_remove_ai_tags(self, client: ImageKit) -> None: + response = client.files.with_raw_response.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_remove_ai_tags(self, client: ImageKit) -> None: + with client.files.with_streaming_response.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_remove_tags(self, client: ImageKit) -> None: + file = client.files.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_remove_tags(self, client: ImageKit) -> None: + response = client.files.with_raw_response.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_remove_tags(self, client: ImageKit) -> None: + with client.files.with_streaming_response.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_rename(self, client: ImageKit) -> None: + file = client.files.rename( + file_path="/path/to/file.jpg", + new_file_name="newFileName.jpg", + ) + assert_matches_type(FileRenameResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_rename_with_all_params(self, client: ImageKit) -> None: + file = client.files.rename( + file_path="/path/to/file.jpg", + new_file_name="newFileName.jpg", + purge_cache=True, + ) + assert_matches_type(FileRenameResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_rename(self, client: ImageKit) -> None: + response = client.files.with_raw_response.rename( + file_path="/path/to/file.jpg", + new_file_name="newFileName.jpg", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileRenameResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_rename(self, client: ImageKit) -> None: + with client.files.with_streaming_response.rename( + file_path="/path/to/file.jpg", + new_file_name="newFileName.jpg", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileRenameResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_upload_v1(self, client: ImageKit) -> None: + file = client.files.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) + assert_matches_type(FileUploadV1Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_upload_v1_with_all_params(self, client: ImageKit) -> None: + file = client.files.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + token="token", + checks='"request.folder" : "marketing/"\n', + custom_coordinates="customCoordinates", + custom_metadata='"\n {\n "brand": "Nike",\n "color":"red"\n }\n"\n', + expire="expire", + extensions='"\n[\n {"name":"remove-bg","options":{"add_shadow":true,"bg_colour":"green"}},\n {"name":"google-auto-tagging","maxTags":5,"minConfidence":95}\n]\n"\n', + folder="folder", + is_private_file="true", + is_published="true", + overwrite_ai_tags="true", + overwrite_custom_metadata="true", + overwrite_file="overwriteFile", + overwrite_tags="true", + public_key="publicKey", + response_fields="responseFields", + signature="signature", + tags="t-shirt,round-neck,men", + transformation='\'{"pre":"width:300,height:300,quality:80","post":[{"type":"thumbnail","value":"width:100,height:100"}]}\'\n', + use_unique_file_name="true", + webhook_url="webhookUrl", + ) + assert_matches_type(FileUploadV1Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_upload_v1(self, client: ImageKit) -> None: + response = client.files.with_raw_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileUploadV1Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_upload_v1(self, client: ImageKit) -> None: + with client.files.with_streaming_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileUploadV1Response, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_upload_v2(self, client: ImageKit) -> None: + file = client.files.upload_v2( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) + assert_matches_type(FileUploadV2Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_upload_v2_with_all_params(self, client: ImageKit) -> None: + file = client.files.upload_v2( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + token="token", + checks='"request.folder" : "marketing/"\n', + custom_coordinates="customCoordinates", + custom_metadata='"\n {\n "brand": "Nike",\n "color":"red"\n }\n"\n', + extensions='"\n[\n {"name":"remove-bg","options":{"add_shadow":true,"bg_colour":"green"}},\n {"name":"google-auto-tagging","maxTags":5,"minConfidence":95}\n]\n"\n', + folder="folder", + is_private_file="true", + is_published="true", + overwrite_ai_tags="true", + overwrite_custom_metadata="true", + overwrite_file="overwriteFile", + overwrite_tags="true", + response_fields="responseFields", + tags="t-shirt,round-neck,men", + transformation='\'{"pre":"width:300,height:300,quality:80","post":[{"type":"thumbnail","value":"width:100,height:100"}]}\'\n', + use_unique_file_name="true", + webhook_url="webhookUrl", + ) + assert_matches_type(FileUploadV2Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_upload_v2(self, client: ImageKit) -> None: + response = client.files.with_raw_response.upload_v2( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileUploadV2Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_upload_v2(self, client: ImageKit) -> None: + with client.files.with_streaming_response.upload_v2( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileUploadV2Response, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncFiles: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.list() + assert_matches_type(FileListResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.list( + file_type="fileType", + limit="limit", + path="path", + search_query="searchQuery", + skip="skip", + sort="sort", + type="file", + ) + assert_matches_type(FileListResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileListResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileListResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.delete( + "fileId", + ) + assert file is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.delete( + "fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert file is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.delete( + "fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert file is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_add_tags(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + assert_matches_type(FileAddTagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_add_tags(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileAddTagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_add_tags(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileAddTagsResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_copy(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.copy( + destination_path="/folder/to/copy/into/", + source_file_path="/path/to/file.jpg", + ) + assert_matches_type(object, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_copy_with_all_params(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.copy( + destination_path="/folder/to/copy/into/", + source_file_path="/path/to/file.jpg", + include_file_versions=False, + ) + assert_matches_type(object, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_copy(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.copy( + destination_path="/folder/to/copy/into/", + source_file_path="/path/to/file.jpg", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(object, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_copy(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.copy( + destination_path="/folder/to/copy/into/", + source_file_path="/path/to/file.jpg", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(object, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_move(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", + ) + assert_matches_type(object, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_move(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(object, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_move(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(object, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_remove_ai_tags(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_remove_ai_tags(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_remove_ai_tags(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_remove_tags(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_remove_tags(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_remove_tags(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_rename(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.rename( + file_path="/path/to/file.jpg", + new_file_name="newFileName.jpg", + ) + assert_matches_type(FileRenameResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_rename_with_all_params(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.rename( + file_path="/path/to/file.jpg", + new_file_name="newFileName.jpg", + purge_cache=True, + ) + assert_matches_type(FileRenameResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_rename(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.rename( + file_path="/path/to/file.jpg", + new_file_name="newFileName.jpg", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileRenameResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.rename( + file_path="/path/to/file.jpg", + new_file_name="newFileName.jpg", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileRenameResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_upload_v1(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) + assert_matches_type(FileUploadV1Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_upload_v1_with_all_params(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + token="token", + checks='"request.folder" : "marketing/"\n', + custom_coordinates="customCoordinates", + custom_metadata='"\n {\n "brand": "Nike",\n "color":"red"\n }\n"\n', + expire="expire", + extensions='"\n[\n {"name":"remove-bg","options":{"add_shadow":true,"bg_colour":"green"}},\n {"name":"google-auto-tagging","maxTags":5,"minConfidence":95}\n]\n"\n', + folder="folder", + is_private_file="true", + is_published="true", + overwrite_ai_tags="true", + overwrite_custom_metadata="true", + overwrite_file="overwriteFile", + overwrite_tags="true", + public_key="publicKey", + response_fields="responseFields", + signature="signature", + tags="t-shirt,round-neck,men", + transformation='\'{"pre":"width:300,height:300,quality:80","post":[{"type":"thumbnail","value":"width:100,height:100"}]}\'\n', + use_unique_file_name="true", + webhook_url="webhookUrl", + ) + assert_matches_type(FileUploadV1Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_upload_v1(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileUploadV1Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_upload_v1(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileUploadV1Response, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_upload_v2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.upload_v2( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) + assert_matches_type(FileUploadV2Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_upload_v2_with_all_params(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.upload_v2( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + token="token", + checks='"request.folder" : "marketing/"\n', + custom_coordinates="customCoordinates", + custom_metadata='"\n {\n "brand": "Nike",\n "color":"red"\n }\n"\n', + extensions='"\n[\n {"name":"remove-bg","options":{"add_shadow":true,"bg_colour":"green"}},\n {"name":"google-auto-tagging","maxTags":5,"minConfidence":95}\n]\n"\n', + folder="folder", + is_private_file="true", + is_published="true", + overwrite_ai_tags="true", + overwrite_custom_metadata="true", + overwrite_file="overwriteFile", + overwrite_tags="true", + response_fields="responseFields", + tags="t-shirt,round-neck,men", + transformation='\'{"pre":"width:300,height:300,quality:80","post":[{"type":"thumbnail","value":"width:100,height:100"}]}\'\n', + use_unique_file_name="true", + webhook_url="webhookUrl", + ) + assert_matches_type(FileUploadV2Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_upload_v2(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.upload_v2( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileUploadV2Response, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_upload_v2(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.upload_v2( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileUploadV2Response, file, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_folder.py b/tests/api_resources/test_folder.py new file mode 100644 index 0000000..9b87629 --- /dev/null +++ b/tests/api_resources/test_folder.py @@ -0,0 +1,165 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFolder: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create(self, client: ImageKit) -> None: + folder = client.folder.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create(self, client: ImageKit) -> None: + response = client.folder.with_raw_response.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = response.parse() + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create(self, client: ImageKit) -> None: + with client.folder.with_streaming_response.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = response.parse() + assert_matches_type(object, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + folder = client.folder.delete( + folder_path="/folder/to/delete/", + ) + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.folder.with_raw_response.delete( + folder_path="/folder/to/delete/", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = response.parse() + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.folder.with_streaming_response.delete( + folder_path="/folder/to/delete/", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = response.parse() + assert_matches_type(object, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncFolder: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncImageKit) -> None: + folder = await async_client.folder.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: + response = await async_client.folder.with_raw_response.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = await response.parse() + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: + async with async_client.folder.with_streaming_response.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = await response.parse() + assert_matches_type(object, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncImageKit) -> None: + folder = await async_client.folder.delete( + folder_path="/folder/to/delete/", + ) + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: + response = await async_client.folder.with_raw_response.delete( + folder_path="/folder/to/delete/", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = await response.parse() + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: + async with async_client.folder.with_streaming_response.delete( + folder_path="/folder/to/delete/", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = await response.parse() + assert_matches_type(object, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..347776e --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,91 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +import logging +from typing import TYPE_CHECKING, Iterator, AsyncIterator + +import httpx +import pytest +from pytest_asyncio import is_async_test + +from imagekit import ImageKit, AsyncImageKit, DefaultAioHttpClient +from imagekit._utils import is_dict + +if TYPE_CHECKING: + from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] + +pytest.register_assert_rewrite("tests.utils") + +logging.getLogger("imagekit").setLevel(logging.DEBUG) + + +# automatically add `pytest.mark.asyncio()` to all of our async tests +# so we don't have to add that boilerplate everywhere +def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: + pytest_asyncio_tests = (item for item in items if is_async_test(item)) + session_scope_marker = pytest.mark.asyncio(loop_scope="session") + for async_test in pytest_asyncio_tests: + async_test.add_marker(session_scope_marker, append=False) + + # We skip tests that use both the aiohttp client and respx_mock as respx_mock + # doesn't support custom transports. + for item in items: + if "async_client" not in item.fixturenames or "respx_mock" not in item.fixturenames: + continue + + if not hasattr(item, "callspec"): + continue + + async_client_param = item.callspec.params.get("async_client") + if is_dict(async_client_param) and async_client_param.get("http_client") == "aiohttp": + item.add_marker(pytest.mark.skip(reason="aiohttp client is not compatible with respx_mock")) + + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + +private_api_key = "My Private API Key" +password = "My Password" + + +@pytest.fixture(scope="session") +def client(request: FixtureRequest) -> Iterator[ImageKit]: + strict = getattr(request, "param", True) + if not isinstance(strict, bool): + raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") + + with ImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=strict + ) as client: + yield client + + +@pytest.fixture(scope="session") +async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncImageKit]: + param = getattr(request, "param", True) + + # defaults + strict = True + http_client: None | httpx.AsyncClient = None + + if isinstance(param, bool): + strict = param + elif is_dict(param): + strict = param.get("strict", True) + assert isinstance(strict, bool) + + http_client_type = param.get("http_client", "httpx") + if http_client_type == "aiohttp": + http_client = DefaultAioHttpClient() + else: + raise TypeError(f"Unexpected fixture parameter type {type(param)}, expected bool or dict") + + async with AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=strict, + http_client=http_client, + ) as client: + yield client diff --git a/tests/sample_file.txt b/tests/sample_file.txt new file mode 100644 index 0000000..af5626b --- /dev/null +++ b/tests/sample_file.txt @@ -0,0 +1 @@ +Hello, world! diff --git a/tests/test_client.py b/tests/test_client.py new file mode 100644 index 0000000..9681d18 --- /dev/null +++ b/tests/test_client.py @@ -0,0 +1,1919 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import gc +import os +import sys +import json +import time +import asyncio +import inspect +import subprocess +import tracemalloc +from typing import Any, Union, cast +from textwrap import dedent +from unittest import mock +from typing_extensions import Literal + +import httpx +import pytest +from respx import MockRouter +from pydantic import ValidationError + +from imagekit import ImageKit, AsyncImageKit, APIResponseValidationError +from imagekit._types import Omit +from imagekit._models import BaseModel, FinalRequestOptions +from imagekit._exceptions import ImageKitError, APIStatusError, APITimeoutError, APIResponseValidationError +from imagekit._base_client import ( + DEFAULT_TIMEOUT, + HTTPX_DEFAULT_TIMEOUT, + BaseClient, + DefaultHttpxClient, + DefaultAsyncHttpxClient, + make_request_options, +) + +from .utils import update_env + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") +private_api_key = "My Private API Key" +password = "My Password" + + +def _get_params(client: BaseClient[Any, Any]) -> dict[str, str]: + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + url = httpx.URL(request.url) + return dict(url.params) + + +def _low_retry_timeout(*_args: Any, **_kwargs: Any) -> float: + return 0.1 + + +def _get_open_connections(client: ImageKit | AsyncImageKit) -> int: + transport = client._client._transport + assert isinstance(transport, httpx.HTTPTransport) or isinstance(transport, httpx.AsyncHTTPTransport) + + pool = transport._pool + return len(pool._requests) + + +class TestImageKit: + client = ImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + + @pytest.mark.respx(base_url=base_url) + def test_raw_response(self, respx_mock: MockRouter) -> None: + respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + response = self.client.post("/foo", cast_to=httpx.Response) + assert response.status_code == 200 + assert isinstance(response, httpx.Response) + assert response.json() == {"foo": "bar"} + + @pytest.mark.respx(base_url=base_url) + def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + respx_mock.post("/foo").mock( + return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') + ) + + response = self.client.post("/foo", cast_to=httpx.Response) + assert response.status_code == 200 + assert isinstance(response, httpx.Response) + assert response.json() == {"foo": "bar"} + + def test_copy(self) -> None: + copied = self.client.copy() + assert id(copied) != id(self.client) + + copied = self.client.copy(private_api_key="another My Private API Key") + assert copied.private_api_key == "another My Private API Key" + assert self.client.private_api_key == "My Private API Key" + + copied = self.client.copy(password="another My Password") + assert copied.password == "another My Password" + assert self.client.password == "My Password" + + def test_copy_default_options(self) -> None: + # options that have a default are overridden correctly + copied = self.client.copy(max_retries=7) + assert copied.max_retries == 7 + assert self.client.max_retries == 2 + + copied2 = copied.copy(max_retries=6) + assert copied2.max_retries == 6 + assert copied.max_retries == 7 + + # timeout + assert isinstance(self.client.timeout, httpx.Timeout) + copied = self.client.copy(timeout=None) + assert copied.timeout is None + assert isinstance(self.client.timeout, httpx.Timeout) + + def test_copy_default_headers(self) -> None: + client = ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + default_headers={"X-Foo": "bar"}, + ) + assert client.default_headers["X-Foo"] == "bar" + + # does not override the already given value when not specified + copied = client.copy() + assert copied.default_headers["X-Foo"] == "bar" + + # merges already given headers + copied = client.copy(default_headers={"X-Bar": "stainless"}) + assert copied.default_headers["X-Foo"] == "bar" + assert copied.default_headers["X-Bar"] == "stainless" + + # uses new values for any already given headers + copied = client.copy(default_headers={"X-Foo": "stainless"}) + assert copied.default_headers["X-Foo"] == "stainless" + + # set_default_headers + + # completely overrides already set values + copied = client.copy(set_default_headers={}) + assert copied.default_headers.get("X-Foo") is None + + copied = client.copy(set_default_headers={"X-Bar": "Robert"}) + assert copied.default_headers["X-Bar"] == "Robert" + + with pytest.raises( + ValueError, + match="`default_headers` and `set_default_headers` arguments are mutually exclusive", + ): + client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) + + def test_copy_default_query(self) -> None: + client = ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + default_query={"foo": "bar"}, + ) + assert _get_params(client)["foo"] == "bar" + + # does not override the already given value when not specified + copied = client.copy() + assert _get_params(copied)["foo"] == "bar" + + # merges already given params + copied = client.copy(default_query={"bar": "stainless"}) + params = _get_params(copied) + assert params["foo"] == "bar" + assert params["bar"] == "stainless" + + # uses new values for any already given headers + copied = client.copy(default_query={"foo": "stainless"}) + assert _get_params(copied)["foo"] == "stainless" + + # set_default_query + + # completely overrides already set values + copied = client.copy(set_default_query={}) + assert _get_params(copied) == {} + + copied = client.copy(set_default_query={"bar": "Robert"}) + assert _get_params(copied)["bar"] == "Robert" + + with pytest.raises( + ValueError, + # TODO: update + match="`default_query` and `set_default_query` arguments are mutually exclusive", + ): + client.copy(set_default_query={}, default_query={"foo": "Bar"}) + + def test_copy_signature(self) -> None: + # ensure the same parameters that can be passed to the client are defined in the `.copy()` method + init_signature = inspect.signature( + # mypy doesn't like that we access the `__init__` property. + self.client.__init__, # type: ignore[misc] + ) + copy_signature = inspect.signature(self.client.copy) + exclude_params = {"transport", "proxies", "_strict_response_validation"} + + for name in init_signature.parameters.keys(): + if name in exclude_params: + continue + + copy_param = copy_signature.parameters.get(name) + assert copy_param is not None, f"copy() signature is missing the {name} param" + + @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") + def test_copy_build_request(self) -> None: + options = FinalRequestOptions(method="get", url="/foo") + + def build_request(options: FinalRequestOptions) -> None: + client = self.client.copy() + client._build_request(options) + + # ensure that the machinery is warmed up before tracing starts. + build_request(options) + gc.collect() + + tracemalloc.start(1000) + + snapshot_before = tracemalloc.take_snapshot() + + ITERATIONS = 10 + for _ in range(ITERATIONS): + build_request(options) + + gc.collect() + snapshot_after = tracemalloc.take_snapshot() + + tracemalloc.stop() + + def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.StatisticDiff) -> None: + if diff.count == 0: + # Avoid false positives by considering only leaks (i.e. allocations that persist). + return + + if diff.count % ITERATIONS != 0: + # Avoid false positives by considering only leaks that appear per iteration. + return + + for frame in diff.traceback: + if any( + frame.filename.endswith(fragment) + for fragment in [ + # to_raw_response_wrapper leaks through the @functools.wraps() decorator. + # + # removing the decorator fixes the leak for reasons we don't understand. + "imagekit/_legacy_response.py", + "imagekit/_response.py", + # pydantic.BaseModel.model_dump || pydantic.BaseModel.dict leak memory for some reason. + "imagekit/_compat.py", + # Standard library leaks we don't care about. + "/logging/__init__.py", + ] + ): + return + + leaks.append(diff) + + leaks: list[tracemalloc.StatisticDiff] = [] + for diff in snapshot_after.compare_to(snapshot_before, "traceback"): + add_leak(leaks, diff) + if leaks: + for leak in leaks: + print("MEMORY LEAK:", leak) + for frame in leak.traceback: + print(frame) + raise AssertionError() + + def test_request_timeout(self) -> None: + request = self.client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT + + request = self.client._build_request( + FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) + ) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == httpx.Timeout(100.0) + + def test_client_timeout_option(self) -> None: + client = ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + timeout=httpx.Timeout(0), + ) + + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == httpx.Timeout(0) + + def test_http_client_timeout_option(self) -> None: + # custom timeout given to the httpx client should be used + with httpx.Client(timeout=None) as http_client: + client = ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=http_client, + ) + + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == httpx.Timeout(None) + + # no timeout given to the httpx client should not use the httpx default + with httpx.Client() as http_client: + client = ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=http_client, + ) + + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT + + # explicitly passing the default timeout currently results in it being ignored + with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: + client = ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=http_client, + ) + + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT # our default + + async def test_invalid_http_client(self) -> None: + with pytest.raises(TypeError, match="Invalid `http_client` arg"): + async with httpx.AsyncClient() as http_client: + ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=cast(Any, http_client), + ) + + def test_default_headers_option(self) -> None: + client = ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + default_headers={"X-Foo": "bar"}, + ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + assert request.headers.get("x-foo") == "bar" + assert request.headers.get("x-stainless-lang") == "python" + + client2 = ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + default_headers={ + "X-Foo": "stainless", + "X-Stainless-Lang": "my-overriding-header", + }, + ) + request = client2._build_request(FinalRequestOptions(method="get", url="/foo")) + assert request.headers.get("x-foo") == "stainless" + assert request.headers.get("x-stainless-lang") == "my-overriding-header" + + def test_validate_headers(self) -> None: + client = ImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + assert "Basic" in request.headers.get("Authorization") + + with pytest.raises(ImageKitError): + with update_env( + **{ + "IMAGEKIT_PRIVATE_API_KEY": Omit(), + "ORG_MY_PASSWORD_TOKEN": Omit(), + } + ): + client2 = ImageKit( + base_url=base_url, private_api_key=None, password=None, _strict_response_validation=True + ) + _ = client2 + + def test_default_query_option(self) -> None: + client = ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + default_query={"query_param": "bar"}, + ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + url = httpx.URL(request.url) + assert dict(url.params) == {"query_param": "bar"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/foo", + params={"foo": "baz", "query_param": "overridden"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} + + def test_request_extra_json(self) -> None: + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + json_data={"foo": "bar"}, + extra_json={"baz": False}, + ), + ) + data = json.loads(request.content.decode("utf-8")) + assert data == {"foo": "bar", "baz": False} + + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + extra_json={"baz": False}, + ), + ) + data = json.loads(request.content.decode("utf-8")) + assert data == {"baz": False} + + # `extra_json` takes priority over `json_data` when keys clash + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + json_data={"foo": "bar", "baz": True}, + extra_json={"baz": None}, + ), + ) + data = json.loads(request.content.decode("utf-8")) + assert data == {"foo": "bar", "baz": None} + + def test_request_extra_headers(self) -> None: + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + **make_request_options(extra_headers={"X-Foo": "Foo"}), + ), + ) + assert request.headers.get("X-Foo") == "Foo" + + # `extra_headers` takes priority over `default_headers` when keys clash + request = self.client.with_options(default_headers={"X-Bar": "true"})._build_request( + FinalRequestOptions( + method="post", + url="/foo", + **make_request_options( + extra_headers={"X-Bar": "false"}, + ), + ), + ) + assert request.headers.get("X-Bar") == "false" + + def test_request_extra_query(self) -> None: + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + **make_request_options( + extra_query={"my_query_param": "Foo"}, + ), + ), + ) + params = dict(request.url.params) + assert params == {"my_query_param": "Foo"} + + # if both `query` and `extra_query` are given, they are merged + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + **make_request_options( + query={"bar": "1"}, + extra_query={"foo": "2"}, + ), + ), + ) + params = dict(request.url.params) + assert params == {"bar": "1", "foo": "2"} + + # `extra_query` takes priority over `query` when keys clash + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + **make_request_options( + query={"foo": "1"}, + extra_query={"foo": "2"}, + ), + ), + ) + params = dict(request.url.params) + assert params == {"foo": "2"} + + def test_multipart_repeating_array(self, client: ImageKit) -> None: + request = client._build_request( + FinalRequestOptions.construct( + method="post", + url="/foo", + headers={"Content-Type": "multipart/form-data; boundary=6b7ba517decee4a450543ea6ae821c82"}, + json_data={"array": ["foo", "bar"]}, + files=[("foo.txt", b"hello world")], + ) + ) + + assert request.read().split(b"\r\n") == [ + b"--6b7ba517decee4a450543ea6ae821c82", + b'Content-Disposition: form-data; name="array[]"', + b"", + b"foo", + b"--6b7ba517decee4a450543ea6ae821c82", + b'Content-Disposition: form-data; name="array[]"', + b"", + b"bar", + b"--6b7ba517decee4a450543ea6ae821c82", + b'Content-Disposition: form-data; name="foo.txt"; filename="upload"', + b"Content-Type: application/octet-stream", + b"", + b"hello world", + b"--6b7ba517decee4a450543ea6ae821c82--", + b"", + ] + + @pytest.mark.respx(base_url=base_url) + def test_basic_union_response(self, respx_mock: MockRouter) -> None: + class Model1(BaseModel): + name: str + + class Model2(BaseModel): + foo: str + + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + assert isinstance(response, Model2) + assert response.foo == "bar" + + @pytest.mark.respx(base_url=base_url) + def test_union_response_different_types(self, respx_mock: MockRouter) -> None: + """Union of objects with the same field name using a different type""" + + class Model1(BaseModel): + foo: int + + class Model2(BaseModel): + foo: str + + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + assert isinstance(response, Model2) + assert response.foo == "bar" + + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) + + response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + assert isinstance(response, Model1) + assert response.foo == 1 + + @pytest.mark.respx(base_url=base_url) + def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter) -> None: + """ + Response that sets Content-Type to something other than application/json but returns json data + """ + + class Model(BaseModel): + foo: int + + respx_mock.get("/foo").mock( + return_value=httpx.Response( + 200, + content=json.dumps({"foo": 2}), + headers={"Content-Type": "application/text"}, + ) + ) + + response = self.client.get("/foo", cast_to=Model) + assert isinstance(response, Model) + assert response.foo == 2 + + def test_base_url_setter(self) -> None: + client = ImageKit( + base_url="https://example.com/from_init", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + ) + assert client.base_url == "https://example.com/from_init/" + + client.base_url = "https://example.com/from_setter" # type: ignore[assignment] + + assert client.base_url == "https://example.com/from_setter/" + + def test_base_url_env(self) -> None: + with update_env(IMAGE_KIT_BASE_URL="http://localhost:5000/from/env"): + client = ImageKit(private_api_key=private_api_key, password=password, _strict_response_validation=True) + assert client.base_url == "http://localhost:5000/from/env/" + + @pytest.mark.parametrize( + "client", + [ + ImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + ), + ImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=httpx.Client(), + ), + ], + ids=["standard", "custom http client"], + ) + def test_base_url_trailing_slash(self, client: ImageKit) -> None: + request = client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + json_data={"foo": "bar"}, + ), + ) + assert request.url == "http://localhost:5000/custom/path/foo" + + @pytest.mark.parametrize( + "client", + [ + ImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + ), + ImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=httpx.Client(), + ), + ], + ids=["standard", "custom http client"], + ) + def test_base_url_no_trailing_slash(self, client: ImageKit) -> None: + request = client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + json_data={"foo": "bar"}, + ), + ) + assert request.url == "http://localhost:5000/custom/path/foo" + + @pytest.mark.parametrize( + "client", + [ + ImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + ), + ImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=httpx.Client(), + ), + ], + ids=["standard", "custom http client"], + ) + def test_absolute_request_url(self, client: ImageKit) -> None: + request = client._build_request( + FinalRequestOptions( + method="post", + url="https://myapi.com/foo", + json_data={"foo": "bar"}, + ), + ) + assert request.url == "https://myapi.com/foo" + + def test_copied_client_does_not_close_http(self) -> None: + client = ImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + assert not client.is_closed() + + copied = client.copy() + assert copied is not client + + del copied + + assert not client.is_closed() + + def test_client_context_manager(self) -> None: + client = ImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + with client as c2: + assert c2 is client + assert not c2.is_closed() + assert not client.is_closed() + assert client.is_closed() + + @pytest.mark.respx(base_url=base_url) + def test_client_response_validation_error(self, respx_mock: MockRouter) -> None: + class Model(BaseModel): + foo: str + + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) + + with pytest.raises(APIResponseValidationError) as exc: + self.client.get("/foo", cast_to=Model) + + assert isinstance(exc.value.__cause__, ValidationError) + + def test_client_max_retries_validation(self) -> None: + with pytest.raises(TypeError, match=r"max_retries cannot be None"): + ImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + max_retries=cast(Any, None), + ) + + @pytest.mark.respx(base_url=base_url) + def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: + class Model(BaseModel): + name: str + + respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) + + strict_client = ImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + + with pytest.raises(APIResponseValidationError): + strict_client.get("/foo", cast_to=Model) + + client = ImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=False + ) + + response = client.get("/foo", cast_to=Model) + assert isinstance(response, str) # type: ignore[unreachable] + + @pytest.mark.parametrize( + "remaining_retries,retry_after,timeout", + [ + [3, "20", 20], + [3, "0", 0.5], + [3, "-10", 0.5], + [3, "60", 60], + [3, "61", 0.5], + [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], + [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], + [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], + [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], + [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], + [3, "99999999999999999999999999999999999", 0.5], + [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], + [3, "", 0.5], + [2, "", 0.5 * 2.0], + [1, "", 0.5 * 4.0], + [-1100, "", 8], # test large number potentially overflowing + ], + ) + @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) + def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: + client = ImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + + headers = httpx.Headers({"retry-after": retry_after}) + options = FinalRequestOptions(method="get", url="/foo", max_retries=3) + calculated = client._calculate_retry_timeout(remaining_retries, options, headers) + assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] + + @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: ImageKit) -> None: + respx_mock.post("/api/v1/files/upload").mock(side_effect=httpx.TimeoutException("Test timeout error")) + + with pytest.raises(APITimeoutError): + client.files.with_streaming_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" + ).__enter__() + + assert _get_open_connections(self.client) == 0 + + @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: ImageKit) -> None: + respx_mock.post("/api/v1/files/upload").mock(return_value=httpx.Response(500)) + + with pytest.raises(APIStatusError): + client.files.with_streaming_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" + ).__enter__() + assert _get_open_connections(self.client) == 0 + + @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) + @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + @pytest.mark.parametrize("failure_mode", ["status", "exception"]) + def test_retries_taken( + self, + client: ImageKit, + failures_before_success: int, + failure_mode: Literal["status", "exception"], + respx_mock: MockRouter, + ) -> None: + client = client.with_options(max_retries=4) + + nb_retries = 0 + + def retry_handler(_request: httpx.Request) -> httpx.Response: + nonlocal nb_retries + if nb_retries < failures_before_success: + nb_retries += 1 + if failure_mode == "exception": + raise RuntimeError("oops") + return httpx.Response(500) + return httpx.Response(200) + + respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) + + response = client.files.with_raw_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" + ) + + assert response.retries_taken == failures_before_success + assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success + + @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) + @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + def test_omit_retry_count_header( + self, client: ImageKit, failures_before_success: int, respx_mock: MockRouter + ) -> None: + client = client.with_options(max_retries=4) + + nb_retries = 0 + + def retry_handler(_request: httpx.Request) -> httpx.Response: + nonlocal nb_retries + if nb_retries < failures_before_success: + nb_retries += 1 + return httpx.Response(500) + return httpx.Response(200) + + respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) + + response = client.files.with_raw_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + extra_headers={"x-stainless-retry-count": Omit()}, + ) + + assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 + + @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) + @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + def test_overwrite_retry_count_header( + self, client: ImageKit, failures_before_success: int, respx_mock: MockRouter + ) -> None: + client = client.with_options(max_retries=4) + + nb_retries = 0 + + def retry_handler(_request: httpx.Request) -> httpx.Response: + nonlocal nb_retries + if nb_retries < failures_before_success: + nb_retries += 1 + return httpx.Response(500) + return httpx.Response(200) + + respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) + + response = client.files.with_raw_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + extra_headers={"x-stainless-retry-count": "42"}, + ) + + assert response.http_request.headers.get("x-stainless-retry-count") == "42" + + def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: + # Test that the proxy environment variables are set correctly + monkeypatch.setenv("HTTPS_PROXY", "https://example.org") + + client = DefaultHttpxClient() + + mounts = tuple(client._mounts.items()) + assert len(mounts) == 1 + assert mounts[0][0].pattern == "https://" + + @pytest.mark.filterwarnings("ignore:.*deprecated.*:DeprecationWarning") + def test_default_client_creation(self) -> None: + # Ensure that the client can be initialized without any exceptions + DefaultHttpxClient( + verify=True, + cert=None, + trust_env=True, + http1=True, + http2=False, + limits=httpx.Limits(max_connections=100, max_keepalive_connections=20), + ) + + @pytest.mark.respx(base_url=base_url) + def test_follow_redirects(self, respx_mock: MockRouter) -> None: + # Test that the default follow_redirects=True allows following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) + + response = self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + assert response.status_code == 200 + assert response.json() == {"status": "ok"} + + @pytest.mark.respx(base_url=base_url) + def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + # Test that follow_redirects=False prevents following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + + with pytest.raises(APIStatusError) as exc_info: + self.client.post( + "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response + ) + + assert exc_info.value.response.status_code == 302 + assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" + + +class TestAsyncImageKit: + client = AsyncImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + + @pytest.mark.respx(base_url=base_url) + @pytest.mark.asyncio + async def test_raw_response(self, respx_mock: MockRouter) -> None: + respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + response = await self.client.post("/foo", cast_to=httpx.Response) + assert response.status_code == 200 + assert isinstance(response, httpx.Response) + assert response.json() == {"foo": "bar"} + + @pytest.mark.respx(base_url=base_url) + @pytest.mark.asyncio + async def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + respx_mock.post("/foo").mock( + return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') + ) + + response = await self.client.post("/foo", cast_to=httpx.Response) + assert response.status_code == 200 + assert isinstance(response, httpx.Response) + assert response.json() == {"foo": "bar"} + + def test_copy(self) -> None: + copied = self.client.copy() + assert id(copied) != id(self.client) + + copied = self.client.copy(private_api_key="another My Private API Key") + assert copied.private_api_key == "another My Private API Key" + assert self.client.private_api_key == "My Private API Key" + + copied = self.client.copy(password="another My Password") + assert copied.password == "another My Password" + assert self.client.password == "My Password" + + def test_copy_default_options(self) -> None: + # options that have a default are overridden correctly + copied = self.client.copy(max_retries=7) + assert copied.max_retries == 7 + assert self.client.max_retries == 2 + + copied2 = copied.copy(max_retries=6) + assert copied2.max_retries == 6 + assert copied.max_retries == 7 + + # timeout + assert isinstance(self.client.timeout, httpx.Timeout) + copied = self.client.copy(timeout=None) + assert copied.timeout is None + assert isinstance(self.client.timeout, httpx.Timeout) + + def test_copy_default_headers(self) -> None: + client = AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + default_headers={"X-Foo": "bar"}, + ) + assert client.default_headers["X-Foo"] == "bar" + + # does not override the already given value when not specified + copied = client.copy() + assert copied.default_headers["X-Foo"] == "bar" + + # merges already given headers + copied = client.copy(default_headers={"X-Bar": "stainless"}) + assert copied.default_headers["X-Foo"] == "bar" + assert copied.default_headers["X-Bar"] == "stainless" + + # uses new values for any already given headers + copied = client.copy(default_headers={"X-Foo": "stainless"}) + assert copied.default_headers["X-Foo"] == "stainless" + + # set_default_headers + + # completely overrides already set values + copied = client.copy(set_default_headers={}) + assert copied.default_headers.get("X-Foo") is None + + copied = client.copy(set_default_headers={"X-Bar": "Robert"}) + assert copied.default_headers["X-Bar"] == "Robert" + + with pytest.raises( + ValueError, + match="`default_headers` and `set_default_headers` arguments are mutually exclusive", + ): + client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) + + def test_copy_default_query(self) -> None: + client = AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + default_query={"foo": "bar"}, + ) + assert _get_params(client)["foo"] == "bar" + + # does not override the already given value when not specified + copied = client.copy() + assert _get_params(copied)["foo"] == "bar" + + # merges already given params + copied = client.copy(default_query={"bar": "stainless"}) + params = _get_params(copied) + assert params["foo"] == "bar" + assert params["bar"] == "stainless" + + # uses new values for any already given headers + copied = client.copy(default_query={"foo": "stainless"}) + assert _get_params(copied)["foo"] == "stainless" + + # set_default_query + + # completely overrides already set values + copied = client.copy(set_default_query={}) + assert _get_params(copied) == {} + + copied = client.copy(set_default_query={"bar": "Robert"}) + assert _get_params(copied)["bar"] == "Robert" + + with pytest.raises( + ValueError, + # TODO: update + match="`default_query` and `set_default_query` arguments are mutually exclusive", + ): + client.copy(set_default_query={}, default_query={"foo": "Bar"}) + + def test_copy_signature(self) -> None: + # ensure the same parameters that can be passed to the client are defined in the `.copy()` method + init_signature = inspect.signature( + # mypy doesn't like that we access the `__init__` property. + self.client.__init__, # type: ignore[misc] + ) + copy_signature = inspect.signature(self.client.copy) + exclude_params = {"transport", "proxies", "_strict_response_validation"} + + for name in init_signature.parameters.keys(): + if name in exclude_params: + continue + + copy_param = copy_signature.parameters.get(name) + assert copy_param is not None, f"copy() signature is missing the {name} param" + + @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") + def test_copy_build_request(self) -> None: + options = FinalRequestOptions(method="get", url="/foo") + + def build_request(options: FinalRequestOptions) -> None: + client = self.client.copy() + client._build_request(options) + + # ensure that the machinery is warmed up before tracing starts. + build_request(options) + gc.collect() + + tracemalloc.start(1000) + + snapshot_before = tracemalloc.take_snapshot() + + ITERATIONS = 10 + for _ in range(ITERATIONS): + build_request(options) + + gc.collect() + snapshot_after = tracemalloc.take_snapshot() + + tracemalloc.stop() + + def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.StatisticDiff) -> None: + if diff.count == 0: + # Avoid false positives by considering only leaks (i.e. allocations that persist). + return + + if diff.count % ITERATIONS != 0: + # Avoid false positives by considering only leaks that appear per iteration. + return + + for frame in diff.traceback: + if any( + frame.filename.endswith(fragment) + for fragment in [ + # to_raw_response_wrapper leaks through the @functools.wraps() decorator. + # + # removing the decorator fixes the leak for reasons we don't understand. + "imagekit/_legacy_response.py", + "imagekit/_response.py", + # pydantic.BaseModel.model_dump || pydantic.BaseModel.dict leak memory for some reason. + "imagekit/_compat.py", + # Standard library leaks we don't care about. + "/logging/__init__.py", + ] + ): + return + + leaks.append(diff) + + leaks: list[tracemalloc.StatisticDiff] = [] + for diff in snapshot_after.compare_to(snapshot_before, "traceback"): + add_leak(leaks, diff) + if leaks: + for leak in leaks: + print("MEMORY LEAK:", leak) + for frame in leak.traceback: + print(frame) + raise AssertionError() + + async def test_request_timeout(self) -> None: + request = self.client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT + + request = self.client._build_request( + FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) + ) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == httpx.Timeout(100.0) + + async def test_client_timeout_option(self) -> None: + client = AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + timeout=httpx.Timeout(0), + ) + + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == httpx.Timeout(0) + + async def test_http_client_timeout_option(self) -> None: + # custom timeout given to the httpx client should be used + async with httpx.AsyncClient(timeout=None) as http_client: + client = AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=http_client, + ) + + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == httpx.Timeout(None) + + # no timeout given to the httpx client should not use the httpx default + async with httpx.AsyncClient() as http_client: + client = AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=http_client, + ) + + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT + + # explicitly passing the default timeout currently results in it being ignored + async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: + client = AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=http_client, + ) + + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore + assert timeout == DEFAULT_TIMEOUT # our default + + def test_invalid_http_client(self) -> None: + with pytest.raises(TypeError, match="Invalid `http_client` arg"): + with httpx.Client() as http_client: + AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=cast(Any, http_client), + ) + + def test_default_headers_option(self) -> None: + client = AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + default_headers={"X-Foo": "bar"}, + ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + assert request.headers.get("x-foo") == "bar" + assert request.headers.get("x-stainless-lang") == "python" + + client2 = AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + default_headers={ + "X-Foo": "stainless", + "X-Stainless-Lang": "my-overriding-header", + }, + ) + request = client2._build_request(FinalRequestOptions(method="get", url="/foo")) + assert request.headers.get("x-foo") == "stainless" + assert request.headers.get("x-stainless-lang") == "my-overriding-header" + + def test_validate_headers(self) -> None: + client = AsyncImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + assert "Basic" in request.headers.get("Authorization") + + with pytest.raises(ImageKitError): + with update_env( + **{ + "IMAGEKIT_PRIVATE_API_KEY": Omit(), + "ORG_MY_PASSWORD_TOKEN": Omit(), + } + ): + client2 = AsyncImageKit( + base_url=base_url, private_api_key=None, password=None, _strict_response_validation=True + ) + _ = client2 + + def test_default_query_option(self) -> None: + client = AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + default_query={"query_param": "bar"}, + ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + url = httpx.URL(request.url) + assert dict(url.params) == {"query_param": "bar"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/foo", + params={"foo": "baz", "query_param": "overridden"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} + + def test_request_extra_json(self) -> None: + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + json_data={"foo": "bar"}, + extra_json={"baz": False}, + ), + ) + data = json.loads(request.content.decode("utf-8")) + assert data == {"foo": "bar", "baz": False} + + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + extra_json={"baz": False}, + ), + ) + data = json.loads(request.content.decode("utf-8")) + assert data == {"baz": False} + + # `extra_json` takes priority over `json_data` when keys clash + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + json_data={"foo": "bar", "baz": True}, + extra_json={"baz": None}, + ), + ) + data = json.loads(request.content.decode("utf-8")) + assert data == {"foo": "bar", "baz": None} + + def test_request_extra_headers(self) -> None: + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + **make_request_options(extra_headers={"X-Foo": "Foo"}), + ), + ) + assert request.headers.get("X-Foo") == "Foo" + + # `extra_headers` takes priority over `default_headers` when keys clash + request = self.client.with_options(default_headers={"X-Bar": "true"})._build_request( + FinalRequestOptions( + method="post", + url="/foo", + **make_request_options( + extra_headers={"X-Bar": "false"}, + ), + ), + ) + assert request.headers.get("X-Bar") == "false" + + def test_request_extra_query(self) -> None: + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + **make_request_options( + extra_query={"my_query_param": "Foo"}, + ), + ), + ) + params = dict(request.url.params) + assert params == {"my_query_param": "Foo"} + + # if both `query` and `extra_query` are given, they are merged + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + **make_request_options( + query={"bar": "1"}, + extra_query={"foo": "2"}, + ), + ), + ) + params = dict(request.url.params) + assert params == {"bar": "1", "foo": "2"} + + # `extra_query` takes priority over `query` when keys clash + request = self.client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + **make_request_options( + query={"foo": "1"}, + extra_query={"foo": "2"}, + ), + ), + ) + params = dict(request.url.params) + assert params == {"foo": "2"} + + def test_multipart_repeating_array(self, async_client: AsyncImageKit) -> None: + request = async_client._build_request( + FinalRequestOptions.construct( + method="post", + url="/foo", + headers={"Content-Type": "multipart/form-data; boundary=6b7ba517decee4a450543ea6ae821c82"}, + json_data={"array": ["foo", "bar"]}, + files=[("foo.txt", b"hello world")], + ) + ) + + assert request.read().split(b"\r\n") == [ + b"--6b7ba517decee4a450543ea6ae821c82", + b'Content-Disposition: form-data; name="array[]"', + b"", + b"foo", + b"--6b7ba517decee4a450543ea6ae821c82", + b'Content-Disposition: form-data; name="array[]"', + b"", + b"bar", + b"--6b7ba517decee4a450543ea6ae821c82", + b'Content-Disposition: form-data; name="foo.txt"; filename="upload"', + b"Content-Type: application/octet-stream", + b"", + b"hello world", + b"--6b7ba517decee4a450543ea6ae821c82--", + b"", + ] + + @pytest.mark.respx(base_url=base_url) + async def test_basic_union_response(self, respx_mock: MockRouter) -> None: + class Model1(BaseModel): + name: str + + class Model2(BaseModel): + foo: str + + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + assert isinstance(response, Model2) + assert response.foo == "bar" + + @pytest.mark.respx(base_url=base_url) + async def test_union_response_different_types(self, respx_mock: MockRouter) -> None: + """Union of objects with the same field name using a different type""" + + class Model1(BaseModel): + foo: int + + class Model2(BaseModel): + foo: str + + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + assert isinstance(response, Model2) + assert response.foo == "bar" + + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) + + response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + assert isinstance(response, Model1) + assert response.foo == 1 + + @pytest.mark.respx(base_url=base_url) + async def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter) -> None: + """ + Response that sets Content-Type to something other than application/json but returns json data + """ + + class Model(BaseModel): + foo: int + + respx_mock.get("/foo").mock( + return_value=httpx.Response( + 200, + content=json.dumps({"foo": 2}), + headers={"Content-Type": "application/text"}, + ) + ) + + response = await self.client.get("/foo", cast_to=Model) + assert isinstance(response, Model) + assert response.foo == 2 + + def test_base_url_setter(self) -> None: + client = AsyncImageKit( + base_url="https://example.com/from_init", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + ) + assert client.base_url == "https://example.com/from_init/" + + client.base_url = "https://example.com/from_setter" # type: ignore[assignment] + + assert client.base_url == "https://example.com/from_setter/" + + def test_base_url_env(self) -> None: + with update_env(IMAGE_KIT_BASE_URL="http://localhost:5000/from/env"): + client = AsyncImageKit(private_api_key=private_api_key, password=password, _strict_response_validation=True) + assert client.base_url == "http://localhost:5000/from/env/" + + @pytest.mark.parametrize( + "client", + [ + AsyncImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + ), + AsyncImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=httpx.AsyncClient(), + ), + ], + ids=["standard", "custom http client"], + ) + def test_base_url_trailing_slash(self, client: AsyncImageKit) -> None: + request = client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + json_data={"foo": "bar"}, + ), + ) + assert request.url == "http://localhost:5000/custom/path/foo" + + @pytest.mark.parametrize( + "client", + [ + AsyncImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + ), + AsyncImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=httpx.AsyncClient(), + ), + ], + ids=["standard", "custom http client"], + ) + def test_base_url_no_trailing_slash(self, client: AsyncImageKit) -> None: + request = client._build_request( + FinalRequestOptions( + method="post", + url="/foo", + json_data={"foo": "bar"}, + ), + ) + assert request.url == "http://localhost:5000/custom/path/foo" + + @pytest.mark.parametrize( + "client", + [ + AsyncImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + ), + AsyncImageKit( + base_url="http://localhost:5000/custom/path/", + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + http_client=httpx.AsyncClient(), + ), + ], + ids=["standard", "custom http client"], + ) + def test_absolute_request_url(self, client: AsyncImageKit) -> None: + request = client._build_request( + FinalRequestOptions( + method="post", + url="https://myapi.com/foo", + json_data={"foo": "bar"}, + ), + ) + assert request.url == "https://myapi.com/foo" + + async def test_copied_client_does_not_close_http(self) -> None: + client = AsyncImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + assert not client.is_closed() + + copied = client.copy() + assert copied is not client + + del copied + + await asyncio.sleep(0.2) + assert not client.is_closed() + + async def test_client_context_manager(self) -> None: + client = AsyncImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + async with client as c2: + assert c2 is client + assert not c2.is_closed() + assert not client.is_closed() + assert client.is_closed() + + @pytest.mark.respx(base_url=base_url) + @pytest.mark.asyncio + async def test_client_response_validation_error(self, respx_mock: MockRouter) -> None: + class Model(BaseModel): + foo: str + + respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) + + with pytest.raises(APIResponseValidationError) as exc: + await self.client.get("/foo", cast_to=Model) + + assert isinstance(exc.value.__cause__, ValidationError) + + async def test_client_max_retries_validation(self) -> None: + with pytest.raises(TypeError, match=r"max_retries cannot be None"): + AsyncImageKit( + base_url=base_url, + private_api_key=private_api_key, + password=password, + _strict_response_validation=True, + max_retries=cast(Any, None), + ) + + @pytest.mark.respx(base_url=base_url) + @pytest.mark.asyncio + async def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: + class Model(BaseModel): + name: str + + respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) + + strict_client = AsyncImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + + with pytest.raises(APIResponseValidationError): + await strict_client.get("/foo", cast_to=Model) + + client = AsyncImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=False + ) + + response = await client.get("/foo", cast_to=Model) + assert isinstance(response, str) # type: ignore[unreachable] + + @pytest.mark.parametrize( + "remaining_retries,retry_after,timeout", + [ + [3, "20", 20], + [3, "0", 0.5], + [3, "-10", 0.5], + [3, "60", 60], + [3, "61", 0.5], + [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], + [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], + [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], + [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], + [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], + [3, "99999999999999999999999999999999999", 0.5], + [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], + [3, "", 0.5], + [2, "", 0.5 * 2.0], + [1, "", 0.5 * 4.0], + [-1100, "", 8], # test large number potentially overflowing + ], + ) + @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) + @pytest.mark.asyncio + async def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: + client = AsyncImageKit( + base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + ) + + headers = httpx.Headers({"retry-after": retry_after}) + options = FinalRequestOptions(method="get", url="/foo", max_retries=3) + calculated = client._calculate_retry_timeout(remaining_retries, options, headers) + assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] + + @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + async def test_retrying_timeout_errors_doesnt_leak( + self, respx_mock: MockRouter, async_client: AsyncImageKit + ) -> None: + respx_mock.post("/api/v1/files/upload").mock(side_effect=httpx.TimeoutException("Test timeout error")) + + with pytest.raises(APITimeoutError): + await async_client.files.with_streaming_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" + ).__aenter__() + + assert _get_open_connections(self.client) == 0 + + @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + async def test_retrying_status_errors_doesnt_leak( + self, respx_mock: MockRouter, async_client: AsyncImageKit + ) -> None: + respx_mock.post("/api/v1/files/upload").mock(return_value=httpx.Response(500)) + + with pytest.raises(APIStatusError): + await async_client.files.with_streaming_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" + ).__aenter__() + assert _get_open_connections(self.client) == 0 + + @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) + @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + @pytest.mark.asyncio + @pytest.mark.parametrize("failure_mode", ["status", "exception"]) + async def test_retries_taken( + self, + async_client: AsyncImageKit, + failures_before_success: int, + failure_mode: Literal["status", "exception"], + respx_mock: MockRouter, + ) -> None: + client = async_client.with_options(max_retries=4) + + nb_retries = 0 + + def retry_handler(_request: httpx.Request) -> httpx.Response: + nonlocal nb_retries + if nb_retries < failures_before_success: + nb_retries += 1 + if failure_mode == "exception": + raise RuntimeError("oops") + return httpx.Response(500) + return httpx.Response(200) + + respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) + + response = await client.files.with_raw_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" + ) + + assert response.retries_taken == failures_before_success + assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success + + @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) + @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + @pytest.mark.asyncio + async def test_omit_retry_count_header( + self, async_client: AsyncImageKit, failures_before_success: int, respx_mock: MockRouter + ) -> None: + client = async_client.with_options(max_retries=4) + + nb_retries = 0 + + def retry_handler(_request: httpx.Request) -> httpx.Response: + nonlocal nb_retries + if nb_retries < failures_before_success: + nb_retries += 1 + return httpx.Response(500) + return httpx.Response(200) + + respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) + + response = await client.files.with_raw_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + extra_headers={"x-stainless-retry-count": Omit()}, + ) + + assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 + + @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) + @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + @pytest.mark.asyncio + async def test_overwrite_retry_count_header( + self, async_client: AsyncImageKit, failures_before_success: int, respx_mock: MockRouter + ) -> None: + client = async_client.with_options(max_retries=4) + + nb_retries = 0 + + def retry_handler(_request: httpx.Request) -> httpx.Response: + nonlocal nb_retries + if nb_retries < failures_before_success: + nb_retries += 1 + return httpx.Response(500) + return httpx.Response(200) + + respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) + + response = await client.files.with_raw_response.upload_v1( + file="https://www.example.com/rest-of-the-image-path.jpg", + file_name="fileName", + extra_headers={"x-stainless-retry-count": "42"}, + ) + + assert response.http_request.headers.get("x-stainless-retry-count") == "42" + + def test_get_platform(self) -> None: + # A previous implementation of asyncify could leave threads unterminated when + # used with nest_asyncio. + # + # Since nest_asyncio.apply() is global and cannot be un-applied, this + # test is run in a separate process to avoid affecting other tests. + test_code = dedent(""" + import asyncio + import nest_asyncio + import threading + + from imagekit._utils import asyncify + from imagekit._base_client import get_platform + + async def test_main() -> None: + result = await asyncify(get_platform)() + print(result) + for thread in threading.enumerate(): + print(thread.name) + + nest_asyncio.apply() + asyncio.run(test_main()) + """) + with subprocess.Popen( + [sys.executable, "-c", test_code], + text=True, + ) as process: + timeout = 10 # seconds + + start_time = time.monotonic() + while True: + return_code = process.poll() + if return_code is not None: + if return_code != 0: + raise AssertionError("calling get_platform using asyncify resulted in a non-zero exit code") + + # success + break + + if time.monotonic() - start_time > timeout: + process.kill() + raise AssertionError("calling get_platform using asyncify resulted in a hung process") + + time.sleep(0.1) + + async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: + # Test that the proxy environment variables are set correctly + monkeypatch.setenv("HTTPS_PROXY", "https://example.org") + + client = DefaultAsyncHttpxClient() + + mounts = tuple(client._mounts.items()) + assert len(mounts) == 1 + assert mounts[0][0].pattern == "https://" + + @pytest.mark.filterwarnings("ignore:.*deprecated.*:DeprecationWarning") + async def test_default_client_creation(self) -> None: + # Ensure that the client can be initialized without any exceptions + DefaultAsyncHttpxClient( + verify=True, + cert=None, + trust_env=True, + http1=True, + http2=False, + limits=httpx.Limits(max_connections=100, max_keepalive_connections=20), + ) + + @pytest.mark.respx(base_url=base_url) + async def test_follow_redirects(self, respx_mock: MockRouter) -> None: + # Test that the default follow_redirects=True allows following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) + + response = await self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + assert response.status_code == 200 + assert response.json() == {"status": "ok"} + + @pytest.mark.respx(base_url=base_url) + async def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + # Test that follow_redirects=False prevents following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + + with pytest.raises(APIStatusError) as exc_info: + await self.client.post( + "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response + ) + + assert exc_info.value.response.status_code == 302 + assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" diff --git a/tests/test_deepcopy.py b/tests/test_deepcopy.py new file mode 100644 index 0000000..0a12266 --- /dev/null +++ b/tests/test_deepcopy.py @@ -0,0 +1,58 @@ +from imagekit._utils import deepcopy_minimal + + +def assert_different_identities(obj1: object, obj2: object) -> None: + assert obj1 == obj2 + assert id(obj1) != id(obj2) + + +def test_simple_dict() -> None: + obj1 = {"foo": "bar"} + obj2 = deepcopy_minimal(obj1) + assert_different_identities(obj1, obj2) + + +def test_nested_dict() -> None: + obj1 = {"foo": {"bar": True}} + obj2 = deepcopy_minimal(obj1) + assert_different_identities(obj1, obj2) + assert_different_identities(obj1["foo"], obj2["foo"]) + + +def test_complex_nested_dict() -> None: + obj1 = {"foo": {"bar": [{"hello": "world"}]}} + obj2 = deepcopy_minimal(obj1) + assert_different_identities(obj1, obj2) + assert_different_identities(obj1["foo"], obj2["foo"]) + assert_different_identities(obj1["foo"]["bar"], obj2["foo"]["bar"]) + assert_different_identities(obj1["foo"]["bar"][0], obj2["foo"]["bar"][0]) + + +def test_simple_list() -> None: + obj1 = ["a", "b", "c"] + obj2 = deepcopy_minimal(obj1) + assert_different_identities(obj1, obj2) + + +def test_nested_list() -> None: + obj1 = ["a", [1, 2, 3]] + obj2 = deepcopy_minimal(obj1) + assert_different_identities(obj1, obj2) + assert_different_identities(obj1[1], obj2[1]) + + +class MyObject: ... + + +def test_ignores_other_types() -> None: + # custom classes + my_obj = MyObject() + obj1 = {"foo": my_obj} + obj2 = deepcopy_minimal(obj1) + assert_different_identities(obj1, obj2) + assert obj1["foo"] is my_obj + + # tuples + obj3 = ("a", "b") + obj4 = deepcopy_minimal(obj3) + assert obj3 is obj4 diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py new file mode 100644 index 0000000..d55e402 --- /dev/null +++ b/tests/test_extract_files.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +from typing import Sequence + +import pytest + +from imagekit._types import FileTypes +from imagekit._utils import extract_files + + +def test_removes_files_from_input() -> None: + query = {"foo": "bar"} + assert extract_files(query, paths=[]) == [] + assert query == {"foo": "bar"} + + query2 = {"foo": b"Bar", "hello": "world"} + assert extract_files(query2, paths=[["foo"]]) == [("foo", b"Bar")] + assert query2 == {"hello": "world"} + + query3 = {"foo": {"foo": {"bar": b"Bar"}}, "hello": "world"} + assert extract_files(query3, paths=[["foo", "foo", "bar"]]) == [("foo[foo][bar]", b"Bar")] + assert query3 == {"foo": {"foo": {}}, "hello": "world"} + + query4 = {"foo": {"bar": b"Bar", "baz": "foo"}, "hello": "world"} + assert extract_files(query4, paths=[["foo", "bar"]]) == [("foo[bar]", b"Bar")] + assert query4 == {"hello": "world", "foo": {"baz": "foo"}} + + +def test_multiple_files() -> None: + query = {"documents": [{"file": b"My first file"}, {"file": b"My second file"}]} + assert extract_files(query, paths=[["documents", "", "file"]]) == [ + ("documents[][file]", b"My first file"), + ("documents[][file]", b"My second file"), + ] + assert query == {"documents": [{}, {}]} + + +@pytest.mark.parametrize( + "query,paths,expected", + [ + [ + {"foo": {"bar": "baz"}}, + [["foo", "", "bar"]], + [], + ], + [ + {"foo": ["bar", "baz"]}, + [["foo", "bar"]], + [], + ], + [ + {"foo": {"bar": "baz"}}, + [["foo", "foo"]], + [], + ], + ], + ids=["dict expecting array", "array expecting dict", "unknown keys"], +) +def test_ignores_incorrect_paths( + query: dict[str, object], + paths: Sequence[Sequence[str]], + expected: list[tuple[str, FileTypes]], +) -> None: + assert extract_files(query, paths=paths) == expected diff --git a/tests/test_files.py b/tests/test_files.py new file mode 100644 index 0000000..d37ddba --- /dev/null +++ b/tests/test_files.py @@ -0,0 +1,51 @@ +from pathlib import Path + +import anyio +import pytest +from dirty_equals import IsDict, IsList, IsBytes, IsTuple + +from imagekit._files import to_httpx_files, async_to_httpx_files + +readme_path = Path(__file__).parent.parent.joinpath("README.md") + + +def test_pathlib_includes_file_name() -> None: + result = to_httpx_files({"file": readme_path}) + print(result) + assert result == IsDict({"file": IsTuple("README.md", IsBytes())}) + + +def test_tuple_input() -> None: + result = to_httpx_files([("file", readme_path)]) + print(result) + assert result == IsList(IsTuple("file", IsTuple("README.md", IsBytes()))) + + +@pytest.mark.asyncio +async def test_async_pathlib_includes_file_name() -> None: + result = await async_to_httpx_files({"file": readme_path}) + print(result) + assert result == IsDict({"file": IsTuple("README.md", IsBytes())}) + + +@pytest.mark.asyncio +async def test_async_supports_anyio_path() -> None: + result = await async_to_httpx_files({"file": anyio.Path(readme_path)}) + print(result) + assert result == IsDict({"file": IsTuple("README.md", IsBytes())}) + + +@pytest.mark.asyncio +async def test_async_tuple_input() -> None: + result = await async_to_httpx_files([("file", readme_path)]) + print(result) + assert result == IsList(IsTuple("file", IsTuple("README.md", IsBytes()))) + + +def test_string_not_allowed() -> None: + with pytest.raises(TypeError, match="Expected file types input to be a FileContent type or to be a tuple"): + to_httpx_files( + { + "file": "foo", # type: ignore + } + ) diff --git a/tests/test_models.py b/tests/test_models.py new file mode 100644 index 0000000..5203983 --- /dev/null +++ b/tests/test_models.py @@ -0,0 +1,963 @@ +import json +from typing import TYPE_CHECKING, Any, Dict, List, Union, Optional, cast +from datetime import datetime, timezone +from typing_extensions import Literal, Annotated, TypeAliasType + +import pytest +import pydantic +from pydantic import Field + +from imagekit._utils import PropertyInfo +from imagekit._compat import PYDANTIC_V2, parse_obj, model_dump, model_json +from imagekit._models import BaseModel, construct_type + + +class BasicModel(BaseModel): + foo: str + + +@pytest.mark.parametrize("value", ["hello", 1], ids=["correct type", "mismatched"]) +def test_basic(value: object) -> None: + m = BasicModel.construct(foo=value) + assert m.foo == value + + +def test_directly_nested_model() -> None: + class NestedModel(BaseModel): + nested: BasicModel + + m = NestedModel.construct(nested={"foo": "Foo!"}) + assert m.nested.foo == "Foo!" + + # mismatched types + m = NestedModel.construct(nested="hello!") + assert cast(Any, m.nested) == "hello!" + + +def test_optional_nested_model() -> None: + class NestedModel(BaseModel): + nested: Optional[BasicModel] + + m1 = NestedModel.construct(nested=None) + assert m1.nested is None + + m2 = NestedModel.construct(nested={"foo": "bar"}) + assert m2.nested is not None + assert m2.nested.foo == "bar" + + # mismatched types + m3 = NestedModel.construct(nested={"foo"}) + assert isinstance(cast(Any, m3.nested), set) + assert cast(Any, m3.nested) == {"foo"} + + +def test_list_nested_model() -> None: + class NestedModel(BaseModel): + nested: List[BasicModel] + + m = NestedModel.construct(nested=[{"foo": "bar"}, {"foo": "2"}]) + assert m.nested is not None + assert isinstance(m.nested, list) + assert len(m.nested) == 2 + assert m.nested[0].foo == "bar" + assert m.nested[1].foo == "2" + + # mismatched types + m = NestedModel.construct(nested=True) + assert cast(Any, m.nested) is True + + m = NestedModel.construct(nested=[False]) + assert cast(Any, m.nested) == [False] + + +def test_optional_list_nested_model() -> None: + class NestedModel(BaseModel): + nested: Optional[List[BasicModel]] + + m1 = NestedModel.construct(nested=[{"foo": "bar"}, {"foo": "2"}]) + assert m1.nested is not None + assert isinstance(m1.nested, list) + assert len(m1.nested) == 2 + assert m1.nested[0].foo == "bar" + assert m1.nested[1].foo == "2" + + m2 = NestedModel.construct(nested=None) + assert m2.nested is None + + # mismatched types + m3 = NestedModel.construct(nested={1}) + assert cast(Any, m3.nested) == {1} + + m4 = NestedModel.construct(nested=[False]) + assert cast(Any, m4.nested) == [False] + + +def test_list_optional_items_nested_model() -> None: + class NestedModel(BaseModel): + nested: List[Optional[BasicModel]] + + m = NestedModel.construct(nested=[None, {"foo": "bar"}]) + assert m.nested is not None + assert isinstance(m.nested, list) + assert len(m.nested) == 2 + assert m.nested[0] is None + assert m.nested[1] is not None + assert m.nested[1].foo == "bar" + + # mismatched types + m3 = NestedModel.construct(nested="foo") + assert cast(Any, m3.nested) == "foo" + + m4 = NestedModel.construct(nested=[False]) + assert cast(Any, m4.nested) == [False] + + +def test_list_mismatched_type() -> None: + class NestedModel(BaseModel): + nested: List[str] + + m = NestedModel.construct(nested=False) + assert cast(Any, m.nested) is False + + +def test_raw_dictionary() -> None: + class NestedModel(BaseModel): + nested: Dict[str, str] + + m = NestedModel.construct(nested={"hello": "world"}) + assert m.nested == {"hello": "world"} + + # mismatched types + m = NestedModel.construct(nested=False) + assert cast(Any, m.nested) is False + + +def test_nested_dictionary_model() -> None: + class NestedModel(BaseModel): + nested: Dict[str, BasicModel] + + m = NestedModel.construct(nested={"hello": {"foo": "bar"}}) + assert isinstance(m.nested, dict) + assert m.nested["hello"].foo == "bar" + + # mismatched types + m = NestedModel.construct(nested={"hello": False}) + assert cast(Any, m.nested["hello"]) is False + + +def test_unknown_fields() -> None: + m1 = BasicModel.construct(foo="foo", unknown=1) + assert m1.foo == "foo" + assert cast(Any, m1).unknown == 1 + + m2 = BasicModel.construct(foo="foo", unknown={"foo_bar": True}) + assert m2.foo == "foo" + assert cast(Any, m2).unknown == {"foo_bar": True} + + assert model_dump(m2) == {"foo": "foo", "unknown": {"foo_bar": True}} + + +def test_strict_validation_unknown_fields() -> None: + class Model(BaseModel): + foo: str + + model = parse_obj(Model, dict(foo="hello!", user="Robert")) + assert model.foo == "hello!" + assert cast(Any, model).user == "Robert" + + assert model_dump(model) == {"foo": "hello!", "user": "Robert"} + + +def test_aliases() -> None: + class Model(BaseModel): + my_field: int = Field(alias="myField") + + m = Model.construct(myField=1) + assert m.my_field == 1 + + # mismatched types + m = Model.construct(myField={"hello": False}) + assert cast(Any, m.my_field) == {"hello": False} + + +def test_repr() -> None: + model = BasicModel(foo="bar") + assert str(model) == "BasicModel(foo='bar')" + assert repr(model) == "BasicModel(foo='bar')" + + +def test_repr_nested_model() -> None: + class Child(BaseModel): + name: str + age: int + + class Parent(BaseModel): + name: str + child: Child + + model = Parent(name="Robert", child=Child(name="Foo", age=5)) + assert str(model) == "Parent(name='Robert', child=Child(name='Foo', age=5))" + assert repr(model) == "Parent(name='Robert', child=Child(name='Foo', age=5))" + + +def test_optional_list() -> None: + class Submodel(BaseModel): + name: str + + class Model(BaseModel): + items: Optional[List[Submodel]] + + m = Model.construct(items=None) + assert m.items is None + + m = Model.construct(items=[]) + assert m.items == [] + + m = Model.construct(items=[{"name": "Robert"}]) + assert m.items is not None + assert len(m.items) == 1 + assert m.items[0].name == "Robert" + + +def test_nested_union_of_models() -> None: + class Submodel1(BaseModel): + bar: bool + + class Submodel2(BaseModel): + thing: str + + class Model(BaseModel): + foo: Union[Submodel1, Submodel2] + + m = Model.construct(foo={"thing": "hello"}) + assert isinstance(m.foo, Submodel2) + assert m.foo.thing == "hello" + + +def test_nested_union_of_mixed_types() -> None: + class Submodel1(BaseModel): + bar: bool + + class Model(BaseModel): + foo: Union[Submodel1, Literal[True], Literal["CARD_HOLDER"]] + + m = Model.construct(foo=True) + assert m.foo is True + + m = Model.construct(foo="CARD_HOLDER") + assert m.foo == "CARD_HOLDER" + + m = Model.construct(foo={"bar": False}) + assert isinstance(m.foo, Submodel1) + assert m.foo.bar is False + + +def test_nested_union_multiple_variants() -> None: + class Submodel1(BaseModel): + bar: bool + + class Submodel2(BaseModel): + thing: str + + class Submodel3(BaseModel): + foo: int + + class Model(BaseModel): + foo: Union[Submodel1, Submodel2, None, Submodel3] + + m = Model.construct(foo={"thing": "hello"}) + assert isinstance(m.foo, Submodel2) + assert m.foo.thing == "hello" + + m = Model.construct(foo=None) + assert m.foo is None + + m = Model.construct() + assert m.foo is None + + m = Model.construct(foo={"foo": "1"}) + assert isinstance(m.foo, Submodel3) + assert m.foo.foo == 1 + + +def test_nested_union_invalid_data() -> None: + class Submodel1(BaseModel): + level: int + + class Submodel2(BaseModel): + name: str + + class Model(BaseModel): + foo: Union[Submodel1, Submodel2] + + m = Model.construct(foo=True) + assert cast(bool, m.foo) is True + + m = Model.construct(foo={"name": 3}) + if PYDANTIC_V2: + assert isinstance(m.foo, Submodel1) + assert m.foo.name == 3 # type: ignore + else: + assert isinstance(m.foo, Submodel2) + assert m.foo.name == "3" + + +def test_list_of_unions() -> None: + class Submodel1(BaseModel): + level: int + + class Submodel2(BaseModel): + name: str + + class Model(BaseModel): + items: List[Union[Submodel1, Submodel2]] + + m = Model.construct(items=[{"level": 1}, {"name": "Robert"}]) + assert len(m.items) == 2 + assert isinstance(m.items[0], Submodel1) + assert m.items[0].level == 1 + assert isinstance(m.items[1], Submodel2) + assert m.items[1].name == "Robert" + + m = Model.construct(items=[{"level": -1}, 156]) + assert len(m.items) == 2 + assert isinstance(m.items[0], Submodel1) + assert m.items[0].level == -1 + assert cast(Any, m.items[1]) == 156 + + +def test_union_of_lists() -> None: + class SubModel1(BaseModel): + level: int + + class SubModel2(BaseModel): + name: str + + class Model(BaseModel): + items: Union[List[SubModel1], List[SubModel2]] + + # with one valid entry + m = Model.construct(items=[{"name": "Robert"}]) + assert len(m.items) == 1 + assert isinstance(m.items[0], SubModel2) + assert m.items[0].name == "Robert" + + # with two entries pointing to different types + m = Model.construct(items=[{"level": 1}, {"name": "Robert"}]) + assert len(m.items) == 2 + assert isinstance(m.items[0], SubModel1) + assert m.items[0].level == 1 + assert isinstance(m.items[1], SubModel1) + assert cast(Any, m.items[1]).name == "Robert" + + # with two entries pointing to *completely* different types + m = Model.construct(items=[{"level": -1}, 156]) + assert len(m.items) == 2 + assert isinstance(m.items[0], SubModel1) + assert m.items[0].level == -1 + assert cast(Any, m.items[1]) == 156 + + +def test_dict_of_union() -> None: + class SubModel1(BaseModel): + name: str + + class SubModel2(BaseModel): + foo: str + + class Model(BaseModel): + data: Dict[str, Union[SubModel1, SubModel2]] + + m = Model.construct(data={"hello": {"name": "there"}, "foo": {"foo": "bar"}}) + assert len(list(m.data.keys())) == 2 + assert isinstance(m.data["hello"], SubModel1) + assert m.data["hello"].name == "there" + assert isinstance(m.data["foo"], SubModel2) + assert m.data["foo"].foo == "bar" + + # TODO: test mismatched type + + +def test_double_nested_union() -> None: + class SubModel1(BaseModel): + name: str + + class SubModel2(BaseModel): + bar: str + + class Model(BaseModel): + data: Dict[str, List[Union[SubModel1, SubModel2]]] + + m = Model.construct(data={"foo": [{"bar": "baz"}, {"name": "Robert"}]}) + assert len(m.data["foo"]) == 2 + + entry1 = m.data["foo"][0] + assert isinstance(entry1, SubModel2) + assert entry1.bar == "baz" + + entry2 = m.data["foo"][1] + assert isinstance(entry2, SubModel1) + assert entry2.name == "Robert" + + # TODO: test mismatched type + + +def test_union_of_dict() -> None: + class SubModel1(BaseModel): + name: str + + class SubModel2(BaseModel): + foo: str + + class Model(BaseModel): + data: Union[Dict[str, SubModel1], Dict[str, SubModel2]] + + m = Model.construct(data={"hello": {"name": "there"}, "foo": {"foo": "bar"}}) + assert len(list(m.data.keys())) == 2 + assert isinstance(m.data["hello"], SubModel1) + assert m.data["hello"].name == "there" + assert isinstance(m.data["foo"], SubModel1) + assert cast(Any, m.data["foo"]).foo == "bar" + + +def test_iso8601_datetime() -> None: + class Model(BaseModel): + created_at: datetime + + expected = datetime(2019, 12, 27, 18, 11, 19, 117000, tzinfo=timezone.utc) + + if PYDANTIC_V2: + expected_json = '{"created_at":"2019-12-27T18:11:19.117000Z"}' + else: + expected_json = '{"created_at": "2019-12-27T18:11:19.117000+00:00"}' + + model = Model.construct(created_at="2019-12-27T18:11:19.117Z") + assert model.created_at == expected + assert model_json(model) == expected_json + + model = parse_obj(Model, dict(created_at="2019-12-27T18:11:19.117Z")) + assert model.created_at == expected + assert model_json(model) == expected_json + + +def test_does_not_coerce_int() -> None: + class Model(BaseModel): + bar: int + + assert Model.construct(bar=1).bar == 1 + assert Model.construct(bar=10.9).bar == 10.9 + assert Model.construct(bar="19").bar == "19" # type: ignore[comparison-overlap] + assert Model.construct(bar=False).bar is False + + +def test_int_to_float_safe_conversion() -> None: + class Model(BaseModel): + float_field: float + + m = Model.construct(float_field=10) + assert m.float_field == 10.0 + assert isinstance(m.float_field, float) + + m = Model.construct(float_field=10.12) + assert m.float_field == 10.12 + assert isinstance(m.float_field, float) + + # number too big + m = Model.construct(float_field=2**53 + 1) + assert m.float_field == 2**53 + 1 + assert isinstance(m.float_field, int) + + +def test_deprecated_alias() -> None: + class Model(BaseModel): + resource_id: str = Field(alias="model_id") + + @property + def model_id(self) -> str: + return self.resource_id + + m = Model.construct(model_id="id") + assert m.model_id == "id" + assert m.resource_id == "id" + assert m.resource_id is m.model_id + + m = parse_obj(Model, {"model_id": "id"}) + assert m.model_id == "id" + assert m.resource_id == "id" + assert m.resource_id is m.model_id + + +def test_omitted_fields() -> None: + class Model(BaseModel): + resource_id: Optional[str] = None + + m = Model.construct() + assert m.resource_id is None + assert "resource_id" not in m.model_fields_set + + m = Model.construct(resource_id=None) + assert m.resource_id is None + assert "resource_id" in m.model_fields_set + + m = Model.construct(resource_id="foo") + assert m.resource_id == "foo" + assert "resource_id" in m.model_fields_set + + +def test_to_dict() -> None: + class Model(BaseModel): + foo: Optional[str] = Field(alias="FOO", default=None) + + m = Model(FOO="hello") + assert m.to_dict() == {"FOO": "hello"} + assert m.to_dict(use_api_names=False) == {"foo": "hello"} + + m2 = Model() + assert m2.to_dict() == {} + assert m2.to_dict(exclude_unset=False) == {"FOO": None} + assert m2.to_dict(exclude_unset=False, exclude_none=True) == {} + assert m2.to_dict(exclude_unset=False, exclude_defaults=True) == {} + + m3 = Model(FOO=None) + assert m3.to_dict() == {"FOO": None} + assert m3.to_dict(exclude_none=True) == {} + assert m3.to_dict(exclude_defaults=True) == {} + + class Model2(BaseModel): + created_at: datetime + + time_str = "2024-03-21T11:39:01.275859" + m4 = Model2.construct(created_at=time_str) + assert m4.to_dict(mode="python") == {"created_at": datetime.fromisoformat(time_str)} + assert m4.to_dict(mode="json") == {"created_at": time_str} + + if not PYDANTIC_V2: + with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): + m.to_dict(warnings=False) + + +def test_forwards_compat_model_dump_method() -> None: + class Model(BaseModel): + foo: Optional[str] = Field(alias="FOO", default=None) + + m = Model(FOO="hello") + assert m.model_dump() == {"foo": "hello"} + assert m.model_dump(include={"bar"}) == {} + assert m.model_dump(exclude={"foo"}) == {} + assert m.model_dump(by_alias=True) == {"FOO": "hello"} + + m2 = Model() + assert m2.model_dump() == {"foo": None} + assert m2.model_dump(exclude_unset=True) == {} + assert m2.model_dump(exclude_none=True) == {} + assert m2.model_dump(exclude_defaults=True) == {} + + m3 = Model(FOO=None) + assert m3.model_dump() == {"foo": None} + assert m3.model_dump(exclude_none=True) == {} + + if not PYDANTIC_V2: + with pytest.raises(ValueError, match="round_trip is only supported in Pydantic v2"): + m.model_dump(round_trip=True) + + with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): + m.model_dump(warnings=False) + + +def test_compat_method_no_error_for_warnings() -> None: + class Model(BaseModel): + foo: Optional[str] + + m = Model(foo="hello") + assert isinstance(model_dump(m, warnings=False), dict) + + +def test_to_json() -> None: + class Model(BaseModel): + foo: Optional[str] = Field(alias="FOO", default=None) + + m = Model(FOO="hello") + assert json.loads(m.to_json()) == {"FOO": "hello"} + assert json.loads(m.to_json(use_api_names=False)) == {"foo": "hello"} + + if PYDANTIC_V2: + assert m.to_json(indent=None) == '{"FOO":"hello"}' + else: + assert m.to_json(indent=None) == '{"FOO": "hello"}' + + m2 = Model() + assert json.loads(m2.to_json()) == {} + assert json.loads(m2.to_json(exclude_unset=False)) == {"FOO": None} + assert json.loads(m2.to_json(exclude_unset=False, exclude_none=True)) == {} + assert json.loads(m2.to_json(exclude_unset=False, exclude_defaults=True)) == {} + + m3 = Model(FOO=None) + assert json.loads(m3.to_json()) == {"FOO": None} + assert json.loads(m3.to_json(exclude_none=True)) == {} + + if not PYDANTIC_V2: + with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): + m.to_json(warnings=False) + + +def test_forwards_compat_model_dump_json_method() -> None: + class Model(BaseModel): + foo: Optional[str] = Field(alias="FOO", default=None) + + m = Model(FOO="hello") + assert json.loads(m.model_dump_json()) == {"foo": "hello"} + assert json.loads(m.model_dump_json(include={"bar"})) == {} + assert json.loads(m.model_dump_json(include={"foo"})) == {"foo": "hello"} + assert json.loads(m.model_dump_json(by_alias=True)) == {"FOO": "hello"} + + assert m.model_dump_json(indent=2) == '{\n "foo": "hello"\n}' + + m2 = Model() + assert json.loads(m2.model_dump_json()) == {"foo": None} + assert json.loads(m2.model_dump_json(exclude_unset=True)) == {} + assert json.loads(m2.model_dump_json(exclude_none=True)) == {} + assert json.loads(m2.model_dump_json(exclude_defaults=True)) == {} + + m3 = Model(FOO=None) + assert json.loads(m3.model_dump_json()) == {"foo": None} + assert json.loads(m3.model_dump_json(exclude_none=True)) == {} + + if not PYDANTIC_V2: + with pytest.raises(ValueError, match="round_trip is only supported in Pydantic v2"): + m.model_dump_json(round_trip=True) + + with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): + m.model_dump_json(warnings=False) + + +def test_type_compat() -> None: + # our model type can be assigned to Pydantic's model type + + def takes_pydantic(model: pydantic.BaseModel) -> None: # noqa: ARG001 + ... + + class OurModel(BaseModel): + foo: Optional[str] = None + + takes_pydantic(OurModel()) + + +def test_annotated_types() -> None: + class Model(BaseModel): + value: str + + m = construct_type( + value={"value": "foo"}, + type_=cast(Any, Annotated[Model, "random metadata"]), + ) + assert isinstance(m, Model) + assert m.value == "foo" + + +def test_discriminated_unions_invalid_data() -> None: + class A(BaseModel): + type: Literal["a"] + + data: str + + class B(BaseModel): + type: Literal["b"] + + data: int + + m = construct_type( + value={"type": "b", "data": "foo"}, + type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), + ) + assert isinstance(m, B) + assert m.type == "b" + assert m.data == "foo" # type: ignore[comparison-overlap] + + m = construct_type( + value={"type": "a", "data": 100}, + type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), + ) + assert isinstance(m, A) + assert m.type == "a" + if PYDANTIC_V2: + assert m.data == 100 # type: ignore[comparison-overlap] + else: + # pydantic v1 automatically converts inputs to strings + # if the expected type is a str + assert m.data == "100" + + +def test_discriminated_unions_unknown_variant() -> None: + class A(BaseModel): + type: Literal["a"] + + data: str + + class B(BaseModel): + type: Literal["b"] + + data: int + + m = construct_type( + value={"type": "c", "data": None, "new_thing": "bar"}, + type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), + ) + + # just chooses the first variant + assert isinstance(m, A) + assert m.type == "c" # type: ignore[comparison-overlap] + assert m.data == None # type: ignore[unreachable] + assert m.new_thing == "bar" + + +def test_discriminated_unions_invalid_data_nested_unions() -> None: + class A(BaseModel): + type: Literal["a"] + + data: str + + class B(BaseModel): + type: Literal["b"] + + data: int + + class C(BaseModel): + type: Literal["c"] + + data: bool + + m = construct_type( + value={"type": "b", "data": "foo"}, + type_=cast(Any, Annotated[Union[Union[A, B], C], PropertyInfo(discriminator="type")]), + ) + assert isinstance(m, B) + assert m.type == "b" + assert m.data == "foo" # type: ignore[comparison-overlap] + + m = construct_type( + value={"type": "c", "data": "foo"}, + type_=cast(Any, Annotated[Union[Union[A, B], C], PropertyInfo(discriminator="type")]), + ) + assert isinstance(m, C) + assert m.type == "c" + assert m.data == "foo" # type: ignore[comparison-overlap] + + +def test_discriminated_unions_with_aliases_invalid_data() -> None: + class A(BaseModel): + foo_type: Literal["a"] = Field(alias="type") + + data: str + + class B(BaseModel): + foo_type: Literal["b"] = Field(alias="type") + + data: int + + m = construct_type( + value={"type": "b", "data": "foo"}, + type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="foo_type")]), + ) + assert isinstance(m, B) + assert m.foo_type == "b" + assert m.data == "foo" # type: ignore[comparison-overlap] + + m = construct_type( + value={"type": "a", "data": 100}, + type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="foo_type")]), + ) + assert isinstance(m, A) + assert m.foo_type == "a" + if PYDANTIC_V2: + assert m.data == 100 # type: ignore[comparison-overlap] + else: + # pydantic v1 automatically converts inputs to strings + # if the expected type is a str + assert m.data == "100" + + +def test_discriminated_unions_overlapping_discriminators_invalid_data() -> None: + class A(BaseModel): + type: Literal["a"] + + data: bool + + class B(BaseModel): + type: Literal["a"] + + data: int + + m = construct_type( + value={"type": "a", "data": "foo"}, + type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), + ) + assert isinstance(m, B) + assert m.type == "a" + assert m.data == "foo" # type: ignore[comparison-overlap] + + +def test_discriminated_unions_invalid_data_uses_cache() -> None: + class A(BaseModel): + type: Literal["a"] + + data: str + + class B(BaseModel): + type: Literal["b"] + + data: int + + UnionType = cast(Any, Union[A, B]) + + assert not hasattr(UnionType, "__discriminator__") + + m = construct_type( + value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[UnionType, PropertyInfo(discriminator="type")]) + ) + assert isinstance(m, B) + assert m.type == "b" + assert m.data == "foo" # type: ignore[comparison-overlap] + + discriminator = UnionType.__discriminator__ + assert discriminator is not None + + m = construct_type( + value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[UnionType, PropertyInfo(discriminator="type")]) + ) + assert isinstance(m, B) + assert m.type == "b" + assert m.data == "foo" # type: ignore[comparison-overlap] + + # if the discriminator details object stays the same between invocations then + # we hit the cache + assert UnionType.__discriminator__ is discriminator + + +@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1") +def test_type_alias_type() -> None: + Alias = TypeAliasType("Alias", str) # pyright: ignore + + class Model(BaseModel): + alias: Alias + union: Union[int, Alias] + + m = construct_type(value={"alias": "foo", "union": "bar"}, type_=Model) + assert isinstance(m, Model) + assert isinstance(m.alias, str) + assert m.alias == "foo" + assert isinstance(m.union, str) + assert m.union == "bar" + + +@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1") +def test_field_named_cls() -> None: + class Model(BaseModel): + cls: str + + m = construct_type(value={"cls": "foo"}, type_=Model) + assert isinstance(m, Model) + assert isinstance(m.cls, str) + + +def test_discriminated_union_case() -> None: + class A(BaseModel): + type: Literal["a"] + + data: bool + + class B(BaseModel): + type: Literal["b"] + + data: List[Union[A, object]] + + class ModelA(BaseModel): + type: Literal["modelA"] + + data: int + + class ModelB(BaseModel): + type: Literal["modelB"] + + required: str + + data: Union[A, B] + + # when constructing ModelA | ModelB, value data doesn't match ModelB exactly - missing `required` + m = construct_type( + value={"type": "modelB", "data": {"type": "a", "data": True}}, + type_=cast(Any, Annotated[Union[ModelA, ModelB], PropertyInfo(discriminator="type")]), + ) + + assert isinstance(m, ModelB) + + +def test_nested_discriminated_union() -> None: + class InnerType1(BaseModel): + type: Literal["type_1"] + + class InnerModel(BaseModel): + inner_value: str + + class InnerType2(BaseModel): + type: Literal["type_2"] + some_inner_model: InnerModel + + class Type1(BaseModel): + base_type: Literal["base_type_1"] + value: Annotated[ + Union[ + InnerType1, + InnerType2, + ], + PropertyInfo(discriminator="type"), + ] + + class Type2(BaseModel): + base_type: Literal["base_type_2"] + + T = Annotated[ + Union[ + Type1, + Type2, + ], + PropertyInfo(discriminator="base_type"), + ] + + model = construct_type( + type_=T, + value={ + "base_type": "base_type_1", + "value": { + "type": "type_2", + }, + }, + ) + assert isinstance(model, Type1) + assert isinstance(model.value, InnerType2) + + +@pytest.mark.skipif(not PYDANTIC_V2, reason="this is only supported in pydantic v2 for now") +def test_extra_properties() -> None: + class Item(BaseModel): + prop: int + + class Model(BaseModel): + __pydantic_extra__: Dict[str, Item] = Field(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + other: str + + if TYPE_CHECKING: + + def __getattr__(self, attr: str) -> Item: ... + + model = construct_type( + type_=Model, + value={ + "a": {"prop": 1}, + "other": "foo", + }, + ) + assert isinstance(model, Model) + assert model.a.prop == 1 + assert isinstance(model.a, Item) + assert model.other == "foo" diff --git a/tests/test_qs.py b/tests/test_qs.py new file mode 100644 index 0000000..4e08d86 --- /dev/null +++ b/tests/test_qs.py @@ -0,0 +1,78 @@ +from typing import Any, cast +from functools import partial +from urllib.parse import unquote + +import pytest + +from imagekit._qs import Querystring, stringify + + +def test_empty() -> None: + assert stringify({}) == "" + assert stringify({"a": {}}) == "" + assert stringify({"a": {"b": {"c": {}}}}) == "" + + +def test_basic() -> None: + assert stringify({"a": 1}) == "a=1" + assert stringify({"a": "b"}) == "a=b" + assert stringify({"a": True}) == "a=true" + assert stringify({"a": False}) == "a=false" + assert stringify({"a": 1.23456}) == "a=1.23456" + assert stringify({"a": None}) == "" + + +@pytest.mark.parametrize("method", ["class", "function"]) +def test_nested_dotted(method: str) -> None: + if method == "class": + serialise = Querystring(nested_format="dots").stringify + else: + serialise = partial(stringify, nested_format="dots") + + assert unquote(serialise({"a": {"b": "c"}})) == "a.b=c" + assert unquote(serialise({"a": {"b": "c", "d": "e", "f": "g"}})) == "a.b=c&a.d=e&a.f=g" + assert unquote(serialise({"a": {"b": {"c": {"d": "e"}}}})) == "a.b.c.d=e" + assert unquote(serialise({"a": {"b": True}})) == "a.b=true" + + +def test_nested_brackets() -> None: + assert unquote(stringify({"a": {"b": "c"}})) == "a[b]=c" + assert unquote(stringify({"a": {"b": "c", "d": "e", "f": "g"}})) == "a[b]=c&a[d]=e&a[f]=g" + assert unquote(stringify({"a": {"b": {"c": {"d": "e"}}}})) == "a[b][c][d]=e" + assert unquote(stringify({"a": {"b": True}})) == "a[b]=true" + + +@pytest.mark.parametrize("method", ["class", "function"]) +def test_array_comma(method: str) -> None: + if method == "class": + serialise = Querystring(array_format="comma").stringify + else: + serialise = partial(stringify, array_format="comma") + + assert unquote(serialise({"in": ["foo", "bar"]})) == "in=foo,bar" + assert unquote(serialise({"a": {"b": [True, False]}})) == "a[b]=true,false" + assert unquote(serialise({"a": {"b": [True, False, None, True]}})) == "a[b]=true,false,true" + + +def test_array_repeat() -> None: + assert unquote(stringify({"in": ["foo", "bar"]})) == "in=foo&in=bar" + assert unquote(stringify({"a": {"b": [True, False]}})) == "a[b]=true&a[b]=false" + assert unquote(stringify({"a": {"b": [True, False, None, True]}})) == "a[b]=true&a[b]=false&a[b]=true" + assert unquote(stringify({"in": ["foo", {"b": {"c": ["d", "e"]}}]})) == "in=foo&in[b][c]=d&in[b][c]=e" + + +@pytest.mark.parametrize("method", ["class", "function"]) +def test_array_brackets(method: str) -> None: + if method == "class": + serialise = Querystring(array_format="brackets").stringify + else: + serialise = partial(stringify, array_format="brackets") + + assert unquote(serialise({"in": ["foo", "bar"]})) == "in[]=foo&in[]=bar" + assert unquote(serialise({"a": {"b": [True, False]}})) == "a[b][]=true&a[b][]=false" + assert unquote(serialise({"a": {"b": [True, False, None, True]}})) == "a[b][]=true&a[b][]=false&a[b][]=true" + + +def test_unknown_array_format() -> None: + with pytest.raises(NotImplementedError, match="Unknown array_format value: foo, choose from comma, repeat"): + stringify({"a": ["foo", "bar"]}, array_format=cast(Any, "foo")) diff --git a/tests/test_required_args.py b/tests/test_required_args.py new file mode 100644 index 0000000..e066b2a --- /dev/null +++ b/tests/test_required_args.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +import pytest + +from imagekit._utils import required_args + + +def test_too_many_positional_params() -> None: + @required_args(["a"]) + def foo(a: str | None = None) -> str | None: + return a + + with pytest.raises(TypeError, match=r"foo\(\) takes 1 argument\(s\) but 2 were given"): + foo("a", "b") # type: ignore + + +def test_positional_param() -> None: + @required_args(["a"]) + def foo(a: str | None = None) -> str | None: + return a + + assert foo("a") == "a" + assert foo(None) is None + assert foo(a="b") == "b" + + with pytest.raises(TypeError, match="Missing required argument: 'a'"): + foo() + + +def test_keyword_only_param() -> None: + @required_args(["a"]) + def foo(*, a: str | None = None) -> str | None: + return a + + assert foo(a="a") == "a" + assert foo(a=None) is None + assert foo(a="b") == "b" + + with pytest.raises(TypeError, match="Missing required argument: 'a'"): + foo() + + +def test_multiple_params() -> None: + @required_args(["a", "b", "c"]) + def foo(a: str = "", *, b: str = "", c: str = "") -> str | None: + return f"{a} {b} {c}" + + assert foo(a="a", b="b", c="c") == "a b c" + + error_message = r"Missing required arguments.*" + + with pytest.raises(TypeError, match=error_message): + foo() + + with pytest.raises(TypeError, match=error_message): + foo(a="a") + + with pytest.raises(TypeError, match=error_message): + foo(b="b") + + with pytest.raises(TypeError, match=error_message): + foo(c="c") + + with pytest.raises(TypeError, match=r"Missing required argument: 'a'"): + foo(b="a", c="c") + + with pytest.raises(TypeError, match=r"Missing required argument: 'b'"): + foo("a", c="c") + + +def test_multiple_variants() -> None: + @required_args(["a"], ["b"]) + def foo(*, a: str | None = None, b: str | None = None) -> str | None: + return a if a is not None else b + + assert foo(a="foo") == "foo" + assert foo(b="bar") == "bar" + assert foo(a=None) is None + assert foo(b=None) is None + + # TODO: this error message could probably be improved + with pytest.raises( + TypeError, + match=r"Missing required arguments; Expected either \('a'\) or \('b'\) arguments to be given", + ): + foo() + + +def test_multiple_params_multiple_variants() -> None: + @required_args(["a", "b"], ["c"]) + def foo(*, a: str | None = None, b: str | None = None, c: str | None = None) -> str | None: + if a is not None: + return a + if b is not None: + return b + return c + + error_message = r"Missing required arguments; Expected either \('a' and 'b'\) or \('c'\) arguments to be given" + + with pytest.raises(TypeError, match=error_message): + foo(a="foo") + + with pytest.raises(TypeError, match=error_message): + foo(b="bar") + + with pytest.raises(TypeError, match=error_message): + foo() + + assert foo(a=None, b="bar") == "bar" + assert foo(c=None) is None + assert foo(c="foo") == "foo" diff --git a/tests/test_response.py b/tests/test_response.py new file mode 100644 index 0000000..0a41606 --- /dev/null +++ b/tests/test_response.py @@ -0,0 +1,277 @@ +import json +from typing import Any, List, Union, cast +from typing_extensions import Annotated + +import httpx +import pytest +import pydantic + +from imagekit import ImageKit, BaseModel, AsyncImageKit +from imagekit._response import ( + APIResponse, + BaseAPIResponse, + AsyncAPIResponse, + BinaryAPIResponse, + AsyncBinaryAPIResponse, + extract_response_type, +) +from imagekit._streaming import Stream +from imagekit._base_client import FinalRequestOptions + + +class ConcreteBaseAPIResponse(APIResponse[bytes]): ... + + +class ConcreteAPIResponse(APIResponse[List[str]]): ... + + +class ConcreteAsyncAPIResponse(APIResponse[httpx.Response]): ... + + +def test_extract_response_type_direct_classes() -> None: + assert extract_response_type(BaseAPIResponse[str]) == str + assert extract_response_type(APIResponse[str]) == str + assert extract_response_type(AsyncAPIResponse[str]) == str + + +def test_extract_response_type_direct_class_missing_type_arg() -> None: + with pytest.raises( + RuntimeError, + match="Expected type to have a type argument at index 0 but it did not", + ): + extract_response_type(AsyncAPIResponse) + + +def test_extract_response_type_concrete_subclasses() -> None: + assert extract_response_type(ConcreteBaseAPIResponse) == bytes + assert extract_response_type(ConcreteAPIResponse) == List[str] + assert extract_response_type(ConcreteAsyncAPIResponse) == httpx.Response + + +def test_extract_response_type_binary_response() -> None: + assert extract_response_type(BinaryAPIResponse) == bytes + assert extract_response_type(AsyncBinaryAPIResponse) == bytes + + +class PydanticModel(pydantic.BaseModel): ... + + +def test_response_parse_mismatched_basemodel(client: ImageKit) -> None: + response = APIResponse( + raw=httpx.Response(200, content=b"foo"), + client=client, + stream=False, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + with pytest.raises( + TypeError, + match="Pydantic models must subclass our base model type, e.g. `from imagekit import BaseModel`", + ): + response.parse(to=PydanticModel) + + +@pytest.mark.asyncio +async def test_async_response_parse_mismatched_basemodel(async_client: AsyncImageKit) -> None: + response = AsyncAPIResponse( + raw=httpx.Response(200, content=b"foo"), + client=async_client, + stream=False, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + with pytest.raises( + TypeError, + match="Pydantic models must subclass our base model type, e.g. `from imagekit import BaseModel`", + ): + await response.parse(to=PydanticModel) + + +def test_response_parse_custom_stream(client: ImageKit) -> None: + response = APIResponse( + raw=httpx.Response(200, content=b"foo"), + client=client, + stream=True, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + stream = response.parse(to=Stream[int]) + assert stream._cast_to == int + + +@pytest.mark.asyncio +async def test_async_response_parse_custom_stream(async_client: AsyncImageKit) -> None: + response = AsyncAPIResponse( + raw=httpx.Response(200, content=b"foo"), + client=async_client, + stream=True, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + stream = await response.parse(to=Stream[int]) + assert stream._cast_to == int + + +class CustomModel(BaseModel): + foo: str + bar: int + + +def test_response_parse_custom_model(client: ImageKit) -> None: + response = APIResponse( + raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), + client=client, + stream=False, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + obj = response.parse(to=CustomModel) + assert obj.foo == "hello!" + assert obj.bar == 2 + + +@pytest.mark.asyncio +async def test_async_response_parse_custom_model(async_client: AsyncImageKit) -> None: + response = AsyncAPIResponse( + raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), + client=async_client, + stream=False, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + obj = await response.parse(to=CustomModel) + assert obj.foo == "hello!" + assert obj.bar == 2 + + +def test_response_parse_annotated_type(client: ImageKit) -> None: + response = APIResponse( + raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), + client=client, + stream=False, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + obj = response.parse( + to=cast("type[CustomModel]", Annotated[CustomModel, "random metadata"]), + ) + assert obj.foo == "hello!" + assert obj.bar == 2 + + +async def test_async_response_parse_annotated_type(async_client: AsyncImageKit) -> None: + response = AsyncAPIResponse( + raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), + client=async_client, + stream=False, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + obj = await response.parse( + to=cast("type[CustomModel]", Annotated[CustomModel, "random metadata"]), + ) + assert obj.foo == "hello!" + assert obj.bar == 2 + + +@pytest.mark.parametrize( + "content, expected", + [ + ("false", False), + ("true", True), + ("False", False), + ("True", True), + ("TrUe", True), + ("FalSe", False), + ], +) +def test_response_parse_bool(client: ImageKit, content: str, expected: bool) -> None: + response = APIResponse( + raw=httpx.Response(200, content=content), + client=client, + stream=False, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + result = response.parse(to=bool) + assert result is expected + + +@pytest.mark.parametrize( + "content, expected", + [ + ("false", False), + ("true", True), + ("False", False), + ("True", True), + ("TrUe", True), + ("FalSe", False), + ], +) +async def test_async_response_parse_bool(client: AsyncImageKit, content: str, expected: bool) -> None: + response = AsyncAPIResponse( + raw=httpx.Response(200, content=content), + client=client, + stream=False, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + result = await response.parse(to=bool) + assert result is expected + + +class OtherModel(BaseModel): + a: str + + +@pytest.mark.parametrize("client", [False], indirect=True) # loose validation +def test_response_parse_expect_model_union_non_json_content(client: ImageKit) -> None: + response = APIResponse( + raw=httpx.Response(200, content=b"foo", headers={"Content-Type": "application/text"}), + client=client, + stream=False, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + obj = response.parse(to=cast(Any, Union[CustomModel, OtherModel])) + assert isinstance(obj, str) + assert obj == "foo" + + +@pytest.mark.asyncio +@pytest.mark.parametrize("async_client", [False], indirect=True) # loose validation +async def test_async_response_parse_expect_model_union_non_json_content(async_client: AsyncImageKit) -> None: + response = AsyncAPIResponse( + raw=httpx.Response(200, content=b"foo", headers={"Content-Type": "application/text"}), + client=async_client, + stream=False, + stream_cls=None, + cast_to=str, + options=FinalRequestOptions.construct(method="get", url="/foo"), + ) + + obj = await response.parse(to=cast(Any, Union[CustomModel, OtherModel])) + assert isinstance(obj, str) + assert obj == "foo" diff --git a/tests/test_streaming.py b/tests/test_streaming.py new file mode 100644 index 0000000..fa1795d --- /dev/null +++ b/tests/test_streaming.py @@ -0,0 +1,248 @@ +from __future__ import annotations + +from typing import Iterator, AsyncIterator + +import httpx +import pytest + +from imagekit import ImageKit, AsyncImageKit +from imagekit._streaming import Stream, AsyncStream, ServerSentEvent + + +@pytest.mark.asyncio +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +async def test_basic(sync: bool, client: ImageKit, async_client: AsyncImageKit) -> None: + def body() -> Iterator[bytes]: + yield b"event: completion\n" + yield b'data: {"foo":true}\n' + yield b"\n" + + iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) + + sse = await iter_next(iterator) + assert sse.event == "completion" + assert sse.json() == {"foo": True} + + await assert_empty_iter(iterator) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +async def test_data_missing_event(sync: bool, client: ImageKit, async_client: AsyncImageKit) -> None: + def body() -> Iterator[bytes]: + yield b'data: {"foo":true}\n' + yield b"\n" + + iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) + + sse = await iter_next(iterator) + assert sse.event is None + assert sse.json() == {"foo": True} + + await assert_empty_iter(iterator) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +async def test_event_missing_data(sync: bool, client: ImageKit, async_client: AsyncImageKit) -> None: + def body() -> Iterator[bytes]: + yield b"event: ping\n" + yield b"\n" + + iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) + + sse = await iter_next(iterator) + assert sse.event == "ping" + assert sse.data == "" + + await assert_empty_iter(iterator) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +async def test_multiple_events(sync: bool, client: ImageKit, async_client: AsyncImageKit) -> None: + def body() -> Iterator[bytes]: + yield b"event: ping\n" + yield b"\n" + yield b"event: completion\n" + yield b"\n" + + iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) + + sse = await iter_next(iterator) + assert sse.event == "ping" + assert sse.data == "" + + sse = await iter_next(iterator) + assert sse.event == "completion" + assert sse.data == "" + + await assert_empty_iter(iterator) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +async def test_multiple_events_with_data(sync: bool, client: ImageKit, async_client: AsyncImageKit) -> None: + def body() -> Iterator[bytes]: + yield b"event: ping\n" + yield b'data: {"foo":true}\n' + yield b"\n" + yield b"event: completion\n" + yield b'data: {"bar":false}\n' + yield b"\n" + + iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) + + sse = await iter_next(iterator) + assert sse.event == "ping" + assert sse.json() == {"foo": True} + + sse = await iter_next(iterator) + assert sse.event == "completion" + assert sse.json() == {"bar": False} + + await assert_empty_iter(iterator) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +async def test_multiple_data_lines_with_empty_line(sync: bool, client: ImageKit, async_client: AsyncImageKit) -> None: + def body() -> Iterator[bytes]: + yield b"event: ping\n" + yield b"data: {\n" + yield b'data: "foo":\n' + yield b"data: \n" + yield b"data:\n" + yield b"data: true}\n" + yield b"\n\n" + + iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) + + sse = await iter_next(iterator) + assert sse.event == "ping" + assert sse.json() == {"foo": True} + assert sse.data == '{\n"foo":\n\n\ntrue}' + + await assert_empty_iter(iterator) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +async def test_data_json_escaped_double_new_line(sync: bool, client: ImageKit, async_client: AsyncImageKit) -> None: + def body() -> Iterator[bytes]: + yield b"event: ping\n" + yield b'data: {"foo": "my long\\n\\ncontent"}' + yield b"\n\n" + + iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) + + sse = await iter_next(iterator) + assert sse.event == "ping" + assert sse.json() == {"foo": "my long\n\ncontent"} + + await assert_empty_iter(iterator) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +async def test_multiple_data_lines(sync: bool, client: ImageKit, async_client: AsyncImageKit) -> None: + def body() -> Iterator[bytes]: + yield b"event: ping\n" + yield b"data: {\n" + yield b'data: "foo":\n' + yield b"data: true}\n" + yield b"\n\n" + + iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) + + sse = await iter_next(iterator) + assert sse.event == "ping" + assert sse.json() == {"foo": True} + + await assert_empty_iter(iterator) + + +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +async def test_special_new_line_character( + sync: bool, + client: ImageKit, + async_client: AsyncImageKit, +) -> None: + def body() -> Iterator[bytes]: + yield b'data: {"content":" culpa"}\n' + yield b"\n" + yield b'data: {"content":" \xe2\x80\xa8"}\n' + yield b"\n" + yield b'data: {"content":"foo"}\n' + yield b"\n" + + iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) + + sse = await iter_next(iterator) + assert sse.event is None + assert sse.json() == {"content": " culpa"} + + sse = await iter_next(iterator) + assert sse.event is None + assert sse.json() == {"content": " 
"} + + sse = await iter_next(iterator) + assert sse.event is None + assert sse.json() == {"content": "foo"} + + await assert_empty_iter(iterator) + + +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +async def test_multi_byte_character_multiple_chunks( + sync: bool, + client: ImageKit, + async_client: AsyncImageKit, +) -> None: + def body() -> Iterator[bytes]: + yield b'data: {"content":"' + # bytes taken from the string 'известни' and arbitrarily split + # so that some multi-byte characters span multiple chunks + yield b"\xd0" + yield b"\xb8\xd0\xb7\xd0" + yield b"\xb2\xd0\xb5\xd1\x81\xd1\x82\xd0\xbd\xd0\xb8" + yield b'"}\n' + yield b"\n" + + iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) + + sse = await iter_next(iterator) + assert sse.event is None + assert sse.json() == {"content": "известни"} + + +async def to_aiter(iter: Iterator[bytes]) -> AsyncIterator[bytes]: + for chunk in iter: + yield chunk + + +async def iter_next(iter: Iterator[ServerSentEvent] | AsyncIterator[ServerSentEvent]) -> ServerSentEvent: + if isinstance(iter, AsyncIterator): + return await iter.__anext__() + + return next(iter) + + +async def assert_empty_iter(iter: Iterator[ServerSentEvent] | AsyncIterator[ServerSentEvent]) -> None: + with pytest.raises((StopAsyncIteration, RuntimeError)): + await iter_next(iter) + + +def make_event_iterator( + content: Iterator[bytes], + *, + sync: bool, + client: ImageKit, + async_client: AsyncImageKit, +) -> Iterator[ServerSentEvent] | AsyncIterator[ServerSentEvent]: + if sync: + return Stream(cast_to=object, client=client, response=httpx.Response(200, content=content))._iter_events() + + return AsyncStream( + cast_to=object, client=async_client, response=httpx.Response(200, content=to_aiter(content)) + )._iter_events() diff --git a/tests/test_transform.py b/tests/test_transform.py new file mode 100644 index 0000000..0d9defb --- /dev/null +++ b/tests/test_transform.py @@ -0,0 +1,453 @@ +from __future__ import annotations + +import io +import pathlib +from typing import Any, Dict, List, Union, TypeVar, Iterable, Optional, cast +from datetime import date, datetime +from typing_extensions import Required, Annotated, TypedDict + +import pytest + +from imagekit._types import NOT_GIVEN, Base64FileInput +from imagekit._utils import ( + PropertyInfo, + transform as _transform, + parse_datetime, + async_transform as _async_transform, +) +from imagekit._compat import PYDANTIC_V2 +from imagekit._models import BaseModel + +_T = TypeVar("_T") + +SAMPLE_FILE_PATH = pathlib.Path(__file__).parent.joinpath("sample_file.txt") + + +async def transform( + data: _T, + expected_type: object, + use_async: bool, +) -> _T: + if use_async: + return await _async_transform(data, expected_type=expected_type) + + return _transform(data, expected_type=expected_type) + + +parametrize = pytest.mark.parametrize("use_async", [False, True], ids=["sync", "async"]) + + +class Foo1(TypedDict): + foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] + + +@parametrize +@pytest.mark.asyncio +async def test_top_level_alias(use_async: bool) -> None: + assert await transform({"foo_bar": "hello"}, expected_type=Foo1, use_async=use_async) == {"fooBar": "hello"} + + +class Foo2(TypedDict): + bar: Bar2 + + +class Bar2(TypedDict): + this_thing: Annotated[int, PropertyInfo(alias="this__thing")] + baz: Annotated[Baz2, PropertyInfo(alias="Baz")] + + +class Baz2(TypedDict): + my_baz: Annotated[str, PropertyInfo(alias="myBaz")] + + +@parametrize +@pytest.mark.asyncio +async def test_recursive_typeddict(use_async: bool) -> None: + assert await transform({"bar": {"this_thing": 1}}, Foo2, use_async) == {"bar": {"this__thing": 1}} + assert await transform({"bar": {"baz": {"my_baz": "foo"}}}, Foo2, use_async) == {"bar": {"Baz": {"myBaz": "foo"}}} + + +class Foo3(TypedDict): + things: List[Bar3] + + +class Bar3(TypedDict): + my_field: Annotated[str, PropertyInfo(alias="myField")] + + +@parametrize +@pytest.mark.asyncio +async def test_list_of_typeddict(use_async: bool) -> None: + result = await transform({"things": [{"my_field": "foo"}, {"my_field": "foo2"}]}, Foo3, use_async) + assert result == {"things": [{"myField": "foo"}, {"myField": "foo2"}]} + + +class Foo4(TypedDict): + foo: Union[Bar4, Baz4] + + +class Bar4(TypedDict): + foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] + + +class Baz4(TypedDict): + foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] + + +@parametrize +@pytest.mark.asyncio +async def test_union_of_typeddict(use_async: bool) -> None: + assert await transform({"foo": {"foo_bar": "bar"}}, Foo4, use_async) == {"foo": {"fooBar": "bar"}} + assert await transform({"foo": {"foo_baz": "baz"}}, Foo4, use_async) == {"foo": {"fooBaz": "baz"}} + assert await transform({"foo": {"foo_baz": "baz", "foo_bar": "bar"}}, Foo4, use_async) == { + "foo": {"fooBaz": "baz", "fooBar": "bar"} + } + + +class Foo5(TypedDict): + foo: Annotated[Union[Bar4, List[Baz4]], PropertyInfo(alias="FOO")] + + +class Bar5(TypedDict): + foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] + + +class Baz5(TypedDict): + foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] + + +@parametrize +@pytest.mark.asyncio +async def test_union_of_list(use_async: bool) -> None: + assert await transform({"foo": {"foo_bar": "bar"}}, Foo5, use_async) == {"FOO": {"fooBar": "bar"}} + assert await transform( + { + "foo": [ + {"foo_baz": "baz"}, + {"foo_baz": "baz"}, + ] + }, + Foo5, + use_async, + ) == {"FOO": [{"fooBaz": "baz"}, {"fooBaz": "baz"}]} + + +class Foo6(TypedDict): + bar: Annotated[str, PropertyInfo(alias="Bar")] + + +@parametrize +@pytest.mark.asyncio +async def test_includes_unknown_keys(use_async: bool) -> None: + assert await transform({"bar": "bar", "baz_": {"FOO": 1}}, Foo6, use_async) == { + "Bar": "bar", + "baz_": {"FOO": 1}, + } + + +class Foo7(TypedDict): + bar: Annotated[List[Bar7], PropertyInfo(alias="bAr")] + foo: Bar7 + + +class Bar7(TypedDict): + foo: str + + +@parametrize +@pytest.mark.asyncio +async def test_ignores_invalid_input(use_async: bool) -> None: + assert await transform({"bar": ""}, Foo7, use_async) == {"bAr": ""} + assert await transform({"foo": ""}, Foo7, use_async) == {"foo": ""} + + +class DatetimeDict(TypedDict, total=False): + foo: Annotated[datetime, PropertyInfo(format="iso8601")] + + bar: Annotated[Optional[datetime], PropertyInfo(format="iso8601")] + + required: Required[Annotated[Optional[datetime], PropertyInfo(format="iso8601")]] + + list_: Required[Annotated[Optional[List[datetime]], PropertyInfo(format="iso8601")]] + + union: Annotated[Union[int, datetime], PropertyInfo(format="iso8601")] + + +class DateDict(TypedDict, total=False): + foo: Annotated[date, PropertyInfo(format="iso8601")] + + +class DatetimeModel(BaseModel): + foo: datetime + + +class DateModel(BaseModel): + foo: Optional[date] + + +@parametrize +@pytest.mark.asyncio +async def test_iso8601_format(use_async: bool) -> None: + dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") + tz = "Z" if PYDANTIC_V2 else "+00:00" + assert await transform({"foo": dt}, DatetimeDict, use_async) == {"foo": "2023-02-23T14:16:36.337692+00:00"} # type: ignore[comparison-overlap] + assert await transform(DatetimeModel(foo=dt), Any, use_async) == {"foo": "2023-02-23T14:16:36.337692" + tz} # type: ignore[comparison-overlap] + + dt = dt.replace(tzinfo=None) + assert await transform({"foo": dt}, DatetimeDict, use_async) == {"foo": "2023-02-23T14:16:36.337692"} # type: ignore[comparison-overlap] + assert await transform(DatetimeModel(foo=dt), Any, use_async) == {"foo": "2023-02-23T14:16:36.337692"} # type: ignore[comparison-overlap] + + assert await transform({"foo": None}, DateDict, use_async) == {"foo": None} # type: ignore[comparison-overlap] + assert await transform(DateModel(foo=None), Any, use_async) == {"foo": None} # type: ignore + assert await transform({"foo": date.fromisoformat("2023-02-23")}, DateDict, use_async) == {"foo": "2023-02-23"} # type: ignore[comparison-overlap] + assert await transform(DateModel(foo=date.fromisoformat("2023-02-23")), DateDict, use_async) == { + "foo": "2023-02-23" + } # type: ignore[comparison-overlap] + + +@parametrize +@pytest.mark.asyncio +async def test_optional_iso8601_format(use_async: bool) -> None: + dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") + assert await transform({"bar": dt}, DatetimeDict, use_async) == {"bar": "2023-02-23T14:16:36.337692+00:00"} # type: ignore[comparison-overlap] + + assert await transform({"bar": None}, DatetimeDict, use_async) == {"bar": None} + + +@parametrize +@pytest.mark.asyncio +async def test_required_iso8601_format(use_async: bool) -> None: + dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") + assert await transform({"required": dt}, DatetimeDict, use_async) == { + "required": "2023-02-23T14:16:36.337692+00:00" + } # type: ignore[comparison-overlap] + + assert await transform({"required": None}, DatetimeDict, use_async) == {"required": None} + + +@parametrize +@pytest.mark.asyncio +async def test_union_datetime(use_async: bool) -> None: + dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") + assert await transform({"union": dt}, DatetimeDict, use_async) == { # type: ignore[comparison-overlap] + "union": "2023-02-23T14:16:36.337692+00:00" + } + + assert await transform({"union": "foo"}, DatetimeDict, use_async) == {"union": "foo"} + + +@parametrize +@pytest.mark.asyncio +async def test_nested_list_iso6801_format(use_async: bool) -> None: + dt1 = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") + dt2 = parse_datetime("2022-01-15T06:34:23Z") + assert await transform({"list_": [dt1, dt2]}, DatetimeDict, use_async) == { # type: ignore[comparison-overlap] + "list_": ["2023-02-23T14:16:36.337692+00:00", "2022-01-15T06:34:23+00:00"] + } + + +@parametrize +@pytest.mark.asyncio +async def test_datetime_custom_format(use_async: bool) -> None: + dt = parse_datetime("2022-01-15T06:34:23Z") + + result = await transform(dt, Annotated[datetime, PropertyInfo(format="custom", format_template="%H")], use_async) + assert result == "06" # type: ignore[comparison-overlap] + + +class DateDictWithRequiredAlias(TypedDict, total=False): + required_prop: Required[Annotated[date, PropertyInfo(format="iso8601", alias="prop")]] + + +@parametrize +@pytest.mark.asyncio +async def test_datetime_with_alias(use_async: bool) -> None: + assert await transform({"required_prop": None}, DateDictWithRequiredAlias, use_async) == {"prop": None} # type: ignore[comparison-overlap] + assert await transform( + {"required_prop": date.fromisoformat("2023-02-23")}, DateDictWithRequiredAlias, use_async + ) == {"prop": "2023-02-23"} # type: ignore[comparison-overlap] + + +class MyModel(BaseModel): + foo: str + + +@parametrize +@pytest.mark.asyncio +async def test_pydantic_model_to_dictionary(use_async: bool) -> None: + assert cast(Any, await transform(MyModel(foo="hi!"), Any, use_async)) == {"foo": "hi!"} + assert cast(Any, await transform(MyModel.construct(foo="hi!"), Any, use_async)) == {"foo": "hi!"} + + +@parametrize +@pytest.mark.asyncio +async def test_pydantic_empty_model(use_async: bool) -> None: + assert cast(Any, await transform(MyModel.construct(), Any, use_async)) == {} + + +@parametrize +@pytest.mark.asyncio +async def test_pydantic_unknown_field(use_async: bool) -> None: + assert cast(Any, await transform(MyModel.construct(my_untyped_field=True), Any, use_async)) == { + "my_untyped_field": True + } + + +@parametrize +@pytest.mark.asyncio +async def test_pydantic_mismatched_types(use_async: bool) -> None: + model = MyModel.construct(foo=True) + if PYDANTIC_V2: + with pytest.warns(UserWarning): + params = await transform(model, Any, use_async) + else: + params = await transform(model, Any, use_async) + assert cast(Any, params) == {"foo": True} + + +@parametrize +@pytest.mark.asyncio +async def test_pydantic_mismatched_object_type(use_async: bool) -> None: + model = MyModel.construct(foo=MyModel.construct(hello="world")) + if PYDANTIC_V2: + with pytest.warns(UserWarning): + params = await transform(model, Any, use_async) + else: + params = await transform(model, Any, use_async) + assert cast(Any, params) == {"foo": {"hello": "world"}} + + +class ModelNestedObjects(BaseModel): + nested: MyModel + + +@parametrize +@pytest.mark.asyncio +async def test_pydantic_nested_objects(use_async: bool) -> None: + model = ModelNestedObjects.construct(nested={"foo": "stainless"}) + assert isinstance(model.nested, MyModel) + assert cast(Any, await transform(model, Any, use_async)) == {"nested": {"foo": "stainless"}} + + +class ModelWithDefaultField(BaseModel): + foo: str + with_none_default: Union[str, None] = None + with_str_default: str = "foo" + + +@parametrize +@pytest.mark.asyncio +async def test_pydantic_default_field(use_async: bool) -> None: + # should be excluded when defaults are used + model = ModelWithDefaultField.construct() + assert model.with_none_default is None + assert model.with_str_default == "foo" + assert cast(Any, await transform(model, Any, use_async)) == {} + + # should be included when the default value is explicitly given + model = ModelWithDefaultField.construct(with_none_default=None, with_str_default="foo") + assert model.with_none_default is None + assert model.with_str_default == "foo" + assert cast(Any, await transform(model, Any, use_async)) == {"with_none_default": None, "with_str_default": "foo"} + + # should be included when a non-default value is explicitly given + model = ModelWithDefaultField.construct(with_none_default="bar", with_str_default="baz") + assert model.with_none_default == "bar" + assert model.with_str_default == "baz" + assert cast(Any, await transform(model, Any, use_async)) == {"with_none_default": "bar", "with_str_default": "baz"} + + +class TypedDictIterableUnion(TypedDict): + foo: Annotated[Union[Bar8, Iterable[Baz8]], PropertyInfo(alias="FOO")] + + +class Bar8(TypedDict): + foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] + + +class Baz8(TypedDict): + foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] + + +@parametrize +@pytest.mark.asyncio +async def test_iterable_of_dictionaries(use_async: bool) -> None: + assert await transform({"foo": [{"foo_baz": "bar"}]}, TypedDictIterableUnion, use_async) == { + "FOO": [{"fooBaz": "bar"}] + } + assert cast(Any, await transform({"foo": ({"foo_baz": "bar"},)}, TypedDictIterableUnion, use_async)) == { + "FOO": [{"fooBaz": "bar"}] + } + + def my_iter() -> Iterable[Baz8]: + yield {"foo_baz": "hello"} + yield {"foo_baz": "world"} + + assert await transform({"foo": my_iter()}, TypedDictIterableUnion, use_async) == { + "FOO": [{"fooBaz": "hello"}, {"fooBaz": "world"}] + } + + +@parametrize +@pytest.mark.asyncio +async def test_dictionary_items(use_async: bool) -> None: + class DictItems(TypedDict): + foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] + + assert await transform({"foo": {"foo_baz": "bar"}}, Dict[str, DictItems], use_async) == {"foo": {"fooBaz": "bar"}} + + +class TypedDictIterableUnionStr(TypedDict): + foo: Annotated[Union[str, Iterable[Baz8]], PropertyInfo(alias="FOO")] + + +@parametrize +@pytest.mark.asyncio +async def test_iterable_union_str(use_async: bool) -> None: + assert await transform({"foo": "bar"}, TypedDictIterableUnionStr, use_async) == {"FOO": "bar"} + assert cast(Any, await transform(iter([{"foo_baz": "bar"}]), Union[str, Iterable[Baz8]], use_async)) == [ + {"fooBaz": "bar"} + ] + + +class TypedDictBase64Input(TypedDict): + foo: Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")] + + +@parametrize +@pytest.mark.asyncio +async def test_base64_file_input(use_async: bool) -> None: + # strings are left as-is + assert await transform({"foo": "bar"}, TypedDictBase64Input, use_async) == {"foo": "bar"} + + # pathlib.Path is automatically converted to base64 + assert await transform({"foo": SAMPLE_FILE_PATH}, TypedDictBase64Input, use_async) == { + "foo": "SGVsbG8sIHdvcmxkIQo=" + } # type: ignore[comparison-overlap] + + # io instances are automatically converted to base64 + assert await transform({"foo": io.StringIO("Hello, world!")}, TypedDictBase64Input, use_async) == { + "foo": "SGVsbG8sIHdvcmxkIQ==" + } # type: ignore[comparison-overlap] + assert await transform({"foo": io.BytesIO(b"Hello, world!")}, TypedDictBase64Input, use_async) == { + "foo": "SGVsbG8sIHdvcmxkIQ==" + } # type: ignore[comparison-overlap] + + +@parametrize +@pytest.mark.asyncio +async def test_transform_skipping(use_async: bool) -> None: + # lists of ints are left as-is + data = [1, 2, 3] + assert await transform(data, List[int], use_async) is data + + # iterables of ints are converted to a list + data = iter([1, 2, 3]) + assert await transform(data, Iterable[int], use_async) == [1, 2, 3] + + +@parametrize +@pytest.mark.asyncio +async def test_strips_notgiven(use_async: bool) -> None: + assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} + assert await transform({"foo_bar": NOT_GIVEN}, Foo1, use_async) == {} diff --git a/tests/test_utils/test_proxy.py b/tests/test_utils/test_proxy.py new file mode 100644 index 0000000..f6fec33 --- /dev/null +++ b/tests/test_utils/test_proxy.py @@ -0,0 +1,34 @@ +import operator +from typing import Any +from typing_extensions import override + +from imagekit._utils import LazyProxy + + +class RecursiveLazyProxy(LazyProxy[Any]): + @override + def __load__(self) -> Any: + return self + + def __call__(self, *_args: Any, **_kwds: Any) -> Any: + raise RuntimeError("This should never be called!") + + +def test_recursive_proxy() -> None: + proxy = RecursiveLazyProxy() + assert repr(proxy) == "RecursiveLazyProxy" + assert str(proxy) == "RecursiveLazyProxy" + assert dir(proxy) == [] + assert type(proxy).__name__ == "RecursiveLazyProxy" + assert type(operator.attrgetter("name.foo.bar.baz")(proxy)).__name__ == "RecursiveLazyProxy" + + +def test_isinstance_does_not_error() -> None: + class AlwaysErrorProxy(LazyProxy[Any]): + @override + def __load__(self) -> Any: + raise RuntimeError("Mocking missing dependency") + + proxy = AlwaysErrorProxy() + assert not isinstance(proxy, dict) + assert isinstance(proxy, LazyProxy) diff --git a/tests/test_utils/test_typing.py b/tests/test_utils/test_typing.py new file mode 100644 index 0000000..3d41f5d --- /dev/null +++ b/tests/test_utils/test_typing.py @@ -0,0 +1,73 @@ +from __future__ import annotations + +from typing import Generic, TypeVar, cast + +from imagekit._utils import extract_type_var_from_base + +_T = TypeVar("_T") +_T2 = TypeVar("_T2") +_T3 = TypeVar("_T3") + + +class BaseGeneric(Generic[_T]): ... + + +class SubclassGeneric(BaseGeneric[_T]): ... + + +class BaseGenericMultipleTypeArgs(Generic[_T, _T2, _T3]): ... + + +class SubclassGenericMultipleTypeArgs(BaseGenericMultipleTypeArgs[_T, _T2, _T3]): ... + + +class SubclassDifferentOrderGenericMultipleTypeArgs(BaseGenericMultipleTypeArgs[_T2, _T, _T3]): ... + + +def test_extract_type_var() -> None: + assert ( + extract_type_var_from_base( + BaseGeneric[int], + index=0, + generic_bases=cast("tuple[type, ...]", (BaseGeneric,)), + ) + == int + ) + + +def test_extract_type_var_generic_subclass() -> None: + assert ( + extract_type_var_from_base( + SubclassGeneric[int], + index=0, + generic_bases=cast("tuple[type, ...]", (BaseGeneric,)), + ) + == int + ) + + +def test_extract_type_var_multiple() -> None: + typ = BaseGenericMultipleTypeArgs[int, str, None] + + generic_bases = cast("tuple[type, ...]", (BaseGenericMultipleTypeArgs,)) + assert extract_type_var_from_base(typ, index=0, generic_bases=generic_bases) == int + assert extract_type_var_from_base(typ, index=1, generic_bases=generic_bases) == str + assert extract_type_var_from_base(typ, index=2, generic_bases=generic_bases) == type(None) + + +def test_extract_type_var_generic_subclass_multiple() -> None: + typ = SubclassGenericMultipleTypeArgs[int, str, None] + + generic_bases = cast("tuple[type, ...]", (BaseGenericMultipleTypeArgs,)) + assert extract_type_var_from_base(typ, index=0, generic_bases=generic_bases) == int + assert extract_type_var_from_base(typ, index=1, generic_bases=generic_bases) == str + assert extract_type_var_from_base(typ, index=2, generic_bases=generic_bases) == type(None) + + +def test_extract_type_var_generic_subclass_different_ordering_multiple() -> None: + typ = SubclassDifferentOrderGenericMultipleTypeArgs[int, str, None] + + generic_bases = cast("tuple[type, ...]", (BaseGenericMultipleTypeArgs,)) + assert extract_type_var_from_base(typ, index=0, generic_bases=generic_bases) == int + assert extract_type_var_from_base(typ, index=1, generic_bases=generic_bases) == str + assert extract_type_var_from_base(typ, index=2, generic_bases=generic_bases) == type(None) diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..53d5897 --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,159 @@ +from __future__ import annotations + +import os +import inspect +import traceback +import contextlib +from typing import Any, TypeVar, Iterator, cast +from datetime import date, datetime +from typing_extensions import Literal, get_args, get_origin, assert_type + +from imagekit._types import Omit, NoneType +from imagekit._utils import ( + is_dict, + is_list, + is_list_type, + is_union_type, + extract_type_arg, + is_annotated_type, + is_type_alias_type, +) +from imagekit._compat import PYDANTIC_V2, field_outer_type, get_model_fields +from imagekit._models import BaseModel + +BaseModelT = TypeVar("BaseModelT", bound=BaseModel) + + +def assert_matches_model(model: type[BaseModelT], value: BaseModelT, *, path: list[str]) -> bool: + for name, field in get_model_fields(model).items(): + field_value = getattr(value, name) + if PYDANTIC_V2: + allow_none = False + else: + # in v1 nullability was structured differently + # https://docs.pydantic.dev/2.0/migration/#required-optional-and-nullable-fields + allow_none = getattr(field, "allow_none", False) + + assert_matches_type( + field_outer_type(field), + field_value, + path=[*path, name], + allow_none=allow_none, + ) + + return True + + +# Note: the `path` argument is only used to improve error messages when `--showlocals` is used +def assert_matches_type( + type_: Any, + value: object, + *, + path: list[str], + allow_none: bool = False, +) -> None: + if is_type_alias_type(type_): + type_ = type_.__value__ + + # unwrap `Annotated[T, ...]` -> `T` + if is_annotated_type(type_): + type_ = extract_type_arg(type_, 0) + + if allow_none and value is None: + return + + if type_ is None or type_ is NoneType: + assert value is None + return + + origin = get_origin(type_) or type_ + + if is_list_type(type_): + return _assert_list_type(type_, value) + + if origin == str: + assert isinstance(value, str) + elif origin == int: + assert isinstance(value, int) + elif origin == bool: + assert isinstance(value, bool) + elif origin == float: + assert isinstance(value, float) + elif origin == bytes: + assert isinstance(value, bytes) + elif origin == datetime: + assert isinstance(value, datetime) + elif origin == date: + assert isinstance(value, date) + elif origin == object: + # nothing to do here, the expected type is unknown + pass + elif origin == Literal: + assert value in get_args(type_) + elif origin == dict: + assert is_dict(value) + + args = get_args(type_) + key_type = args[0] + items_type = args[1] + + for key, item in value.items(): + assert_matches_type(key_type, key, path=[*path, ""]) + assert_matches_type(items_type, item, path=[*path, ""]) + elif is_union_type(type_): + variants = get_args(type_) + + try: + none_index = variants.index(type(None)) + except ValueError: + pass + else: + # special case Optional[T] for better error messages + if len(variants) == 2: + if value is None: + # valid + return + + return assert_matches_type(type_=variants[not none_index], value=value, path=path) + + for i, variant in enumerate(variants): + try: + assert_matches_type(variant, value, path=[*path, f"variant {i}"]) + return + except AssertionError: + traceback.print_exc() + continue + + raise AssertionError("Did not match any variants") + elif issubclass(origin, BaseModel): + assert isinstance(value, type_) + assert assert_matches_model(type_, cast(Any, value), path=path) + elif inspect.isclass(origin) and origin.__name__ == "HttpxBinaryResponseContent": + assert value.__class__.__name__ == "HttpxBinaryResponseContent" + else: + assert None, f"Unhandled field type: {type_}" + + +def _assert_list_type(type_: type[object], value: object) -> None: + assert is_list(value) + + inner_type = get_args(type_)[0] + for entry in value: + assert_type(inner_type, entry) # type: ignore + + +@contextlib.contextmanager +def update_env(**new_env: str | Omit) -> Iterator[None]: + old = os.environ.copy() + + try: + for name, value in new_env.items(): + if isinstance(value, Omit): + os.environ.pop(name, None) + else: + os.environ[name] = value + + yield None + finally: + os.environ.clear() + os.environ.update(old) From ccb7301be8a02a59e272b1ff6b30922616ea8a01 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 12:20:18 +0000 Subject: [PATCH 003/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 5 + src/imagekit/types/__init__.py | 5 + src/imagekit/types/exif_details.py | 63 +++++++++ src/imagekit/types/exif_image.py | 33 +++++ src/imagekit/types/file_upload_v1_response.py | 122 ++--------------- src/imagekit/types/file_upload_v2_response.py | 122 ++--------------- .../types/files/metadata_from_url_response.py | 127 ++---------------- .../types/files/metadata_retrieve_response.py | 127 ++---------------- src/imagekit/types/gps.py | 13 ++ src/imagekit/types/interoperability.py | 15 +++ src/imagekit/types/thumbnail.py | 23 ++++ 12 files changed, 200 insertions(+), 457 deletions(-) create mode 100644 src/imagekit/types/exif_details.py create mode 100644 src/imagekit/types/exif_image.py create mode 100644 src/imagekit/types/gps.py create mode 100644 src/imagekit/types/interoperability.py create mode 100644 src/imagekit/types/thumbnail.py diff --git a/.stats.yml b/.stats.yml index 3f0734c..4e127b9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 31 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0ffd73f83f6d2c3ad75d943fab8f4511847a7b1f8db10fb26a08f075ec814cc9.yml openapi_spec_hash: afa5d5b601dc01949e9b9acff127ae0d -config_hash: 0076af6656b570a0e67dfbae986295d3 +config_hash: 17c14924113c1d069a05659b7a3e7c1d diff --git a/api.md b/api.md index 8e75811..f71b3f9 100644 --- a/api.md +++ b/api.md @@ -23,6 +23,11 @@ Types: ```python from imagekit.types import ( + ExifDetails, + ExifImage, + Gps, + Interoperability, + Thumbnail, FileListResponse, FileAddTagsResponse, FileRemoveAITagsResponse, diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index ce57f06..7081896 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -2,9 +2,14 @@ from __future__ import annotations +from .gps import Gps as Gps +from .thumbnail import Thumbnail as Thumbnail +from .exif_image import ExifImage as ExifImage +from .exif_details import ExifDetails as ExifDetails from .file_copy_params import FileCopyParams as FileCopyParams from .file_list_params import FileListParams as FileListParams from .file_move_params import FileMoveParams as FileMoveParams +from .interoperability import Interoperability as Interoperability from .file_list_response import FileListResponse as FileListResponse from .file_rename_params import FileRenameParams as FileRenameParams from .file_add_tags_params import FileAddTagsParams as FileAddTagsParams diff --git a/src/imagekit/types/exif_details.py b/src/imagekit/types/exif_details.py new file mode 100644 index 0000000..080717a --- /dev/null +++ b/src/imagekit/types/exif_details.py @@ -0,0 +1,63 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["ExifDetails"] + + +class ExifDetails(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) diff --git a/src/imagekit/types/exif_image.py b/src/imagekit/types/exif_image.py new file mode 100644 index 0000000..fcd316e --- /dev/null +++ b/src/imagekit/types/exif_image.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["ExifImage"] + + +class ExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) diff --git a/src/imagekit/types/file_upload_v1_response.py b/src/imagekit/types/file_upload_v1_response.py index cb428ec..b5edecc 100644 --- a/src/imagekit/types/file_upload_v1_response.py +++ b/src/imagekit/types/file_upload_v1_response.py @@ -6,7 +6,12 @@ from pydantic import Field as FieldInfo +from .gps import Gps from .._models import BaseModel +from .thumbnail import Thumbnail +from .exif_image import ExifImage +from .exif_details import ExifDetails +from .interoperability import Interoperability __all__ = [ "FileUploadV1Response", @@ -15,11 +20,6 @@ "ExtensionStatus", "Metadata", "MetadataExif", - "MetadataExifExif", - "MetadataExifGps", - "MetadataExifImage", - "MetadataExifInteroperability", - "MetadataExifThumbnail", "VersionInfo", ] @@ -423,124 +423,22 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) -class MetadataExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class MetadataExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class MetadataExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class MetadataExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class MetadataExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - class MetadataExif(BaseModel): - exif: Optional[MetadataExifExif] = None + exif: Optional[ExifDetails] = None """Object containing Exif details.""" - gps: Optional[MetadataExifGps] = None + gps: Optional[Gps] = None """Object containing GPS information.""" - image: Optional[MetadataExifImage] = None + image: Optional[ExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[MetadataExifInteroperability] = None + interoperability: Optional[Interoperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[MetadataExifThumbnail] = None + thumbnail: Optional[Thumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/file_upload_v2_response.py b/src/imagekit/types/file_upload_v2_response.py index 27d44da..25cd734 100644 --- a/src/imagekit/types/file_upload_v2_response.py +++ b/src/imagekit/types/file_upload_v2_response.py @@ -6,7 +6,12 @@ from pydantic import Field as FieldInfo +from .gps import Gps from .._models import BaseModel +from .thumbnail import Thumbnail +from .exif_image import ExifImage +from .exif_details import ExifDetails +from .interoperability import Interoperability __all__ = [ "FileUploadV2Response", @@ -15,11 +20,6 @@ "ExtensionStatus", "Metadata", "MetadataExif", - "MetadataExifExif", - "MetadataExifGps", - "MetadataExifImage", - "MetadataExifInteroperability", - "MetadataExifThumbnail", "VersionInfo", ] @@ -423,124 +423,22 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) -class MetadataExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class MetadataExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class MetadataExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class MetadataExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class MetadataExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - class MetadataExif(BaseModel): - exif: Optional[MetadataExifExif] = None + exif: Optional[ExifDetails] = None """Object containing Exif details.""" - gps: Optional[MetadataExifGps] = None + gps: Optional[Gps] = None """Object containing GPS information.""" - image: Optional[MetadataExifImage] = None + image: Optional[ExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[MetadataExifInteroperability] = None + interoperability: Optional[Interoperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[MetadataExifThumbnail] = None + thumbnail: Optional[Thumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/files/metadata_from_url_response.py b/src/imagekit/types/files/metadata_from_url_response.py index 4d48455..66225ef 100644 --- a/src/imagekit/types/files/metadata_from_url_response.py +++ b/src/imagekit/types/files/metadata_from_url_response.py @@ -1,140 +1,35 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional +from typing import Dict, Optional from pydantic import Field as FieldInfo +from ..gps import Gps from ..._models import BaseModel +from ..thumbnail import Thumbnail +from ..exif_image import ExifImage +from ..exif_details import ExifDetails +from ..interoperability import Interoperability -__all__ = [ - "MetadataFromURLResponse", - "Exif", - "ExifExif", - "ExifGps", - "ExifImage", - "ExifInteroperability", - "ExifThumbnail", -] - - -class ExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class ExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class ExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class ExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class ExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) +__all__ = ["MetadataFromURLResponse", "Exif"] class Exif(BaseModel): - exif: Optional[ExifExif] = None + exif: Optional[ExifDetails] = None """Object containing Exif details.""" - gps: Optional[ExifGps] = None + gps: Optional[Gps] = None """Object containing GPS information.""" image: Optional[ExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[ExifInteroperability] = None + interoperability: Optional[Interoperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[ExifThumbnail] = None + thumbnail: Optional[Thumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/files/metadata_retrieve_response.py b/src/imagekit/types/files/metadata_retrieve_response.py index a6c7a25..26e96f7 100644 --- a/src/imagekit/types/files/metadata_retrieve_response.py +++ b/src/imagekit/types/files/metadata_retrieve_response.py @@ -1,140 +1,35 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional +from typing import Dict, Optional from pydantic import Field as FieldInfo +from ..gps import Gps from ..._models import BaseModel +from ..thumbnail import Thumbnail +from ..exif_image import ExifImage +from ..exif_details import ExifDetails +from ..interoperability import Interoperability -__all__ = [ - "MetadataRetrieveResponse", - "Exif", - "ExifExif", - "ExifGps", - "ExifImage", - "ExifInteroperability", - "ExifThumbnail", -] - - -class ExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class ExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class ExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class ExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class ExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) +__all__ = ["MetadataRetrieveResponse", "Exif"] class Exif(BaseModel): - exif: Optional[ExifExif] = None + exif: Optional[ExifDetails] = None """Object containing Exif details.""" - gps: Optional[ExifGps] = None + gps: Optional[Gps] = None """Object containing GPS information.""" image: Optional[ExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[ExifInteroperability] = None + interoperability: Optional[Interoperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[ExifThumbnail] = None + thumbnail: Optional[Thumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/gps.py b/src/imagekit/types/gps.py new file mode 100644 index 0000000..db7024b --- /dev/null +++ b/src/imagekit/types/gps.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["Gps"] + + +class Gps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) diff --git a/src/imagekit/types/interoperability.py b/src/imagekit/types/interoperability.py new file mode 100644 index 0000000..244734d --- /dev/null +++ b/src/imagekit/types/interoperability.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["Interoperability"] + + +class Interoperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) diff --git a/src/imagekit/types/thumbnail.py b/src/imagekit/types/thumbnail.py new file mode 100644 index 0000000..b5a913a --- /dev/null +++ b/src/imagekit/types/thumbnail.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["Thumbnail"] + + +class Thumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) From 27cb955398eec5f7e1a952dc930983c8b526ba8b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 17:05:12 +0000 Subject: [PATCH 004/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 4e127b9..10267c5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 31 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0ffd73f83f6d2c3ad75d943fab8f4511847a7b1f8db10fb26a08f075ec814cc9.yml openapi_spec_hash: afa5d5b601dc01949e9b9acff127ae0d -config_hash: 17c14924113c1d069a05659b7a3e7c1d +config_hash: 60867d5949f11b2d6f699ff644525af2 From d8bedf1ba55ba118ae9621625a087b33e2549995 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 17:05:32 +0000 Subject: [PATCH 005/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 10267c5..eed320b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 31 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0ffd73f83f6d2c3ad75d943fab8f4511847a7b1f8db10fb26a08f075ec814cc9.yml openapi_spec_hash: afa5d5b601dc01949e9b9acff127ae0d -config_hash: 60867d5949f11b2d6f699ff644525af2 +config_hash: a1e8435842b619cd75c7718d86640d26 From 72d40baa7f76b4379c5fafa33341dddcd6bfa07e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 17 Aug 2025 05:59:41 +0000 Subject: [PATCH 006/177] feat(api): manual updates --- .stats.yml | 8 +- README.md | 76 +- api.md | 169 +- src/imagekit/_client.py | 54 +- src/imagekit/_files.py | 2 +- src/imagekit/resources/__init__.py | 82 +- src/imagekit/resources/accounts/__init__.py | 61 + src/imagekit/resources/accounts/accounts.py | 166 ++ src/imagekit/resources/accounts/origins.py | 2243 +++++++++++++++ .../resources/accounts/url_endpoints.py | 598 ++++ .../{accounts.py => accounts/usage.py} | 94 +- src/imagekit/resources/assets.py | 325 +++ src/imagekit/resources/beta/__init__.py | 33 + src/imagekit/resources/beta/beta.py | 102 + src/imagekit/resources/beta/v2/__init__.py | 33 + src/imagekit/resources/beta/v2/files.py | 564 ++++ src/imagekit/resources/beta/v2/v2.py | 102 + src/imagekit/resources/bulk_jobs.py | 397 --- src/imagekit/resources/cache/__init__.py | 33 + src/imagekit/resources/cache/cache.py | 102 + .../{files/purge.py => cache/invalidation.py} | 112 +- .../resources/custom_metadata_fields.py | 6 +- src/imagekit/resources/files/__init__.py | 54 +- src/imagekit/resources/files/bulk.py | 490 ++++ src/imagekit/resources/files/details.py | 447 --- src/imagekit/resources/files/files.py | 1703 ++++-------- src/imagekit/resources/files/metadata.py | 66 +- src/imagekit/resources/files/versions.py | 134 +- src/imagekit/resources/folder.py | 292 -- src/imagekit/resources/folders/__init__.py | 33 + src/imagekit/resources/folders/folders.py | 711 +++++ .../{files/batch.py => folders/job.py} | 118 +- src/imagekit/types/__init__.py | 37 +- src/imagekit/types/accounts/__init__.py | 18 + .../types/accounts/origin_create_params.py | 208 ++ .../types/accounts/origin_create_response.py | 222 ++ .../types/accounts/origin_get_response.py | 222 ++ .../types/accounts/origin_list_response.py | 232 ++ .../types/accounts/origin_update_params.py | 208 ++ .../types/accounts/origin_update_response.py | 222 ++ .../accounts/url_endpoint_create_params.py | 57 + .../accounts/url_endpoint_create_response.py | 64 + .../accounts/url_endpoint_get_response.py | 64 + .../accounts/url_endpoint_list_response.py | 70 + .../accounts/url_endpoint_update_params.py | 57 + .../accounts/url_endpoint_update_response.py | 64 + .../usage_get_params.py} | 6 +- .../usage_get_response.py} | 6 +- src/imagekit/types/asset_list_params.py | 81 + ...ist_response.py => asset_list_response.py} | 58 +- src/imagekit/types/beta/__init__.py | 3 + src/imagekit/types/beta/v2/__init__.py | 6 + .../types/beta/v2/file_upload_params.py | 325 +++ .../types/beta/v2/file_upload_response.py | 341 +++ .../bulk_job_retrieve_status_response.py | 20 - src/imagekit/types/cache/__init__.py | 7 + .../invalidation_create_params.py} | 4 +- .../invalidation_create_response.py} | 4 +- .../invalidation_get_response.py} | 4 +- .../custom_metadata_field_create_params.py | 2 +- .../custom_metadata_field_create_response.py | 2 +- .../custom_metadata_field_list_params.py | 5 +- .../custom_metadata_field_list_response.py | 2 +- .../custom_metadata_field_update_response.py | 2 +- src/imagekit/types/exif_details.py | 63 - src/imagekit/types/exif_image.py | 33 - ...rieve_response.py => file_get_response.py} | 6 +- src/imagekit/types/file_list_params.py | 81 - ...update_params.py => file_update_params.py} | 19 +- ...te_response.py => file_update_response.py} | 10 +- src/imagekit/types/file_upload_params.py | 357 +++ src/imagekit/types/file_upload_response.py | 341 +++ src/imagekit/types/file_upload_v1_params.py | 211 -- src/imagekit/types/file_upload_v1_response.py | 613 ----- src/imagekit/types/file_upload_v2_params.py | 179 -- src/imagekit/types/file_upload_v2_response.py | 613 ----- src/imagekit/types/files/__init__.py | 24 +- .../bulk_add_tags_params.py} | 6 +- .../bulk_add_tags_response.py} | 6 +- ...delete_params.py => bulk_delete_params.py} | 4 +- ...te_response.py => bulk_delete_response.py} | 4 +- .../bulk_remove_ai_tags_params.py} | 6 +- .../bulk_remove_ai_tags_response.py} | 6 +- .../bulk_remove_tags_params.py} | 6 +- .../bulk_remove_tags_response.py} | 6 +- .../types/files/metadata_from_url_response.py | 76 - ...ams.py => metadata_get_from_url_params.py} | 4 +- .../files/metadata_get_from_url_response.py | 181 ++ .../types/files/metadata_get_response.py | 173 ++ .../types/files/metadata_retrieve_response.py | 76 - ...ve_response.py => version_get_response.py} | 4 +- ...folder_params.py => folder_copy_params.py} | 4 +- ...er_response.py => folder_copy_response.py} | 4 +- ...folder_params.py => folder_move_params.py} | 4 +- ...er_response.py => folder_move_response.py} | 4 +- src/imagekit/types/folder_rename_params.py | 40 + src/imagekit/types/folder_rename_response.py | 17 + src/imagekit/types/folders/__init__.py | 5 + .../types/folders/job_get_response.py | 30 + src/imagekit/types/gps.py | 13 - src/imagekit/types/interoperability.py | 15 - src/imagekit/types/thumbnail.py | 23 - tests/api_resources/accounts/__init__.py | 1 + tests/api_resources/accounts/test_origins.py | 2437 +++++++++++++++++ .../accounts/test_url_endpoints.py | 471 ++++ .../test_usage.py} | 50 +- tests/api_resources/beta/__init__.py | 1 + tests/api_resources/beta/v2/__init__.py | 1 + tests/api_resources/beta/v2/test_files.py | 214 ++ tests/api_resources/cache/__init__.py | 1 + .../test_invalidation.py} | 102 +- tests/api_resources/files/test_batch.py | 92 - tests/api_resources/files/test_bulk.py | 319 +++ tests/api_resources/files/test_details.py | 348 --- tests/api_resources/files/test_metadata.py | 94 +- tests/api_resources/files/test_versions.py | 170 +- tests/api_resources/folders/__init__.py | 1 + tests/api_resources/folders/test_job.py | 108 + tests/api_resources/test_assets.py | 108 + tests/api_resources/test_bulk_jobs.py | 280 -- tests/api_resources/test_files.py | 781 +++--- tests/api_resources/test_folder.py | 165 -- tests/api_resources/test_folders.py | 432 +++ tests/test_client.py | 48 +- 124 files changed, 15073 insertions(+), 6451 deletions(-) create mode 100644 src/imagekit/resources/accounts/__init__.py create mode 100644 src/imagekit/resources/accounts/accounts.py create mode 100644 src/imagekit/resources/accounts/origins.py create mode 100644 src/imagekit/resources/accounts/url_endpoints.py rename src/imagekit/resources/{accounts.py => accounts/usage.py} (70%) create mode 100644 src/imagekit/resources/assets.py create mode 100644 src/imagekit/resources/beta/__init__.py create mode 100644 src/imagekit/resources/beta/beta.py create mode 100644 src/imagekit/resources/beta/v2/__init__.py create mode 100644 src/imagekit/resources/beta/v2/files.py create mode 100644 src/imagekit/resources/beta/v2/v2.py delete mode 100644 src/imagekit/resources/bulk_jobs.py create mode 100644 src/imagekit/resources/cache/__init__.py create mode 100644 src/imagekit/resources/cache/cache.py rename src/imagekit/resources/{files/purge.py => cache/invalidation.py} (70%) create mode 100644 src/imagekit/resources/files/bulk.py delete mode 100644 src/imagekit/resources/files/details.py delete mode 100644 src/imagekit/resources/folder.py create mode 100644 src/imagekit/resources/folders/__init__.py create mode 100644 src/imagekit/resources/folders/folders.py rename src/imagekit/resources/{files/batch.py => folders/job.py} (53%) create mode 100644 src/imagekit/types/accounts/__init__.py create mode 100644 src/imagekit/types/accounts/origin_create_params.py create mode 100644 src/imagekit/types/accounts/origin_create_response.py create mode 100644 src/imagekit/types/accounts/origin_get_response.py create mode 100644 src/imagekit/types/accounts/origin_list_response.py create mode 100644 src/imagekit/types/accounts/origin_update_params.py create mode 100644 src/imagekit/types/accounts/origin_update_response.py create mode 100644 src/imagekit/types/accounts/url_endpoint_create_params.py create mode 100644 src/imagekit/types/accounts/url_endpoint_create_response.py create mode 100644 src/imagekit/types/accounts/url_endpoint_get_response.py create mode 100644 src/imagekit/types/accounts/url_endpoint_list_response.py create mode 100644 src/imagekit/types/accounts/url_endpoint_update_params.py create mode 100644 src/imagekit/types/accounts/url_endpoint_update_response.py rename src/imagekit/types/{account_get_usage_params.py => accounts/usage_get_params.py} (86%) rename src/imagekit/types/{account_get_usage_response.py => accounts/usage_get_response.py} (89%) create mode 100644 src/imagekit/types/asset_list_params.py rename src/imagekit/types/{file_list_response.py => asset_list_response.py} (61%) create mode 100644 src/imagekit/types/beta/__init__.py create mode 100644 src/imagekit/types/beta/v2/__init__.py create mode 100644 src/imagekit/types/beta/v2/file_upload_params.py create mode 100644 src/imagekit/types/beta/v2/file_upload_response.py delete mode 100644 src/imagekit/types/bulk_job_retrieve_status_response.py create mode 100644 src/imagekit/types/cache/__init__.py rename src/imagekit/types/{files/purge_execute_params.py => cache/invalidation_create_params.py} (72%) rename src/imagekit/types/{files/purge_execute_response.py => cache/invalidation_create_response.py} (81%) rename src/imagekit/types/{files/purge_status_response.py => cache/invalidation_get_response.py} (78%) delete mode 100644 src/imagekit/types/exif_details.py delete mode 100644 src/imagekit/types/exif_image.py rename src/imagekit/types/{files/version_retrieve_response.py => file_get_response.py} (96%) delete mode 100644 src/imagekit/types/file_list_params.py rename src/imagekit/types/{files/detail_update_params.py => file_update_params.py} (87%) rename src/imagekit/types/{files/detail_update_response.py => file_update_response.py} (93%) create mode 100644 src/imagekit/types/file_upload_params.py create mode 100644 src/imagekit/types/file_upload_response.py delete mode 100644 src/imagekit/types/file_upload_v1_params.py delete mode 100644 src/imagekit/types/file_upload_v1_response.py delete mode 100644 src/imagekit/types/file_upload_v2_params.py delete mode 100644 src/imagekit/types/file_upload_v2_response.py rename src/imagekit/types/{file_add_tags_params.py => files/bulk_add_tags_params.py} (79%) rename src/imagekit/types/{file_add_tags_response.py => files/bulk_add_tags_response.py} (77%) rename src/imagekit/types/files/{batch_delete_params.py => bulk_delete_params.py} (82%) rename src/imagekit/types/files/{batch_delete_response.py => bulk_delete_response.py} (84%) rename src/imagekit/types/{file_remove_ai_tags_params.py => files/bulk_remove_ai_tags_params.py} (79%) rename src/imagekit/types/{file_remove_ai_tags_response.py => files/bulk_remove_ai_tags_response.py} (75%) rename src/imagekit/types/{file_remove_tags_params.py => files/bulk_remove_tags_params.py} (78%) rename src/imagekit/types/{file_remove_tags_response.py => files/bulk_remove_tags_response.py} (76%) delete mode 100644 src/imagekit/types/files/metadata_from_url_response.py rename src/imagekit/types/files/{metadata_from_url_params.py => metadata_get_from_url_params.py} (76%) create mode 100644 src/imagekit/types/files/metadata_get_from_url_response.py create mode 100644 src/imagekit/types/files/metadata_get_response.py delete mode 100644 src/imagekit/types/files/metadata_retrieve_response.py rename src/imagekit/types/files/{detail_retrieve_response.py => version_get_response.py} (97%) rename src/imagekit/types/{bulk_job_copy_folder_params.py => folder_copy_params.py} (90%) rename src/imagekit/types/{bulk_job_copy_folder_response.py => folder_copy_response.py} (81%) rename src/imagekit/types/{bulk_job_move_folder_params.py => folder_move_params.py} (85%) rename src/imagekit/types/{bulk_job_move_folder_response.py => folder_move_response.py} (81%) create mode 100644 src/imagekit/types/folder_rename_params.py create mode 100644 src/imagekit/types/folder_rename_response.py create mode 100644 src/imagekit/types/folders/__init__.py create mode 100644 src/imagekit/types/folders/job_get_response.py delete mode 100644 src/imagekit/types/gps.py delete mode 100644 src/imagekit/types/interoperability.py delete mode 100644 src/imagekit/types/thumbnail.py create mode 100644 tests/api_resources/accounts/__init__.py create mode 100644 tests/api_resources/accounts/test_origins.py create mode 100644 tests/api_resources/accounts/test_url_endpoints.py rename tests/api_resources/{test_accounts.py => accounts/test_usage.py} (60%) create mode 100644 tests/api_resources/beta/__init__.py create mode 100644 tests/api_resources/beta/v2/__init__.py create mode 100644 tests/api_resources/beta/v2/test_files.py create mode 100644 tests/api_resources/cache/__init__.py rename tests/api_resources/{files/test_purge.py => cache/test_invalidation.py} (53%) delete mode 100644 tests/api_resources/files/test_batch.py create mode 100644 tests/api_resources/files/test_bulk.py delete mode 100644 tests/api_resources/files/test_details.py create mode 100644 tests/api_resources/folders/__init__.py create mode 100644 tests/api_resources/folders/test_job.py create mode 100644 tests/api_resources/test_assets.py delete mode 100644 tests/api_resources/test_bulk_jobs.py delete mode 100644 tests/api_resources/test_folder.py create mode 100644 tests/api_resources/test_folders.py diff --git a/.stats.yml b/.stats.yml index eed320b..ee7ab85 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 31 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0ffd73f83f6d2c3ad75d943fab8f4511847a7b1f8db10fb26a08f075ec814cc9.yml -openapi_spec_hash: afa5d5b601dc01949e9b9acff127ae0d -config_hash: a1e8435842b619cd75c7718d86640d26 +configured_endpoints: 42 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-c01164d5dc8f8c9ab2b7c1a1c793ac522d565f96e569b0e56a4e9353e39bab85.yml +openapi_spec_hash: ac7b3a2b968fe86bf7bb81192209123f +config_hash: 8a4138f8d02720b4736ab63effb7fa2d diff --git a/README.md b/README.md index 204ede0..0f28441 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ client = ImageKit( password=os.environ.get("ORG_MY_PASSWORD_TOKEN"), # This is the default and can be omitted ) -response = client.files.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", +response = client.files.upload( + file=b"raw file contents", file_name="fileName", ) print(response.video_codec) @@ -68,8 +68,8 @@ client = AsyncImageKit( async def main() -> None: - response = await client.files.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", + response = await client.files.upload( + file=b"raw file contents", file_name="fileName", ) print(response.video_codec) @@ -105,8 +105,8 @@ async def main() -> None: password="My Password", http_client=DefaultAioHttpClient(), ) as client: - response = await client.files.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", + response = await client.files.upload( + file=b"raw file contents", file_name="fileName", ) print(response.video_codec) @@ -133,18 +133,44 @@ from imagekit import ImageKit client = ImageKit() -custom_metadata_field = client.custom_metadata_fields.create( - label="price", - name="price", - schema={ - "type": "Number", - "max_value": 3000, - "min_value": 1000, +response = client.files.upload( + file=b"raw file contents", + file_name="fileName", + transformation={ + "post": [ + { + "type": "thumbnail", + "value": "w-150,h-150", + }, + { + "protocol": "dash", + "type": "abs", + "value": "sr-240_360_480_720_1080", + }, + ] }, ) -print(custom_metadata_field.schema) +print(response.transformation) ``` +## File uploads + +Request parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`. + +```python +from pathlib import Path +from imagekit import ImageKit + +client = ImageKit() + +client.files.upload( + file=Path("/path/to/file"), + file_name="fileName", +) +``` + +The async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically. + ## Handling errors When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `imagekit.APIConnectionError` is raised. @@ -161,8 +187,8 @@ from imagekit import ImageKit client = ImageKit() try: - client.files.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", + client.files.upload( + file=b"raw file contents", file_name="fileName", ) except imagekit.APIConnectionError as e: @@ -207,8 +233,8 @@ client = ImageKit( ) # Or, configure per-request: -client.with_options(max_retries=5).files.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", +client.with_options(max_retries=5).files.upload( + file=b"raw file contents", file_name="fileName", ) ``` @@ -233,8 +259,8 @@ client = ImageKit( ) # Override per-request: -client.with_options(timeout=5.0).files.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", +client.with_options(timeout=5.0).files.upload( + file=b"raw file contents", file_name="fileName", ) ``` @@ -277,13 +303,13 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to from imagekit import ImageKit client = ImageKit() -response = client.files.with_raw_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", +response = client.files.with_raw_response.upload( + file=b"raw file contents", file_name="fileName", ) print(response.headers.get('X-My-Header')) -file = response.parse() # get the object that `files.upload_v1()` would have returned +file = response.parse() # get the object that `files.upload()` would have returned print(file.video_codec) ``` @@ -298,8 +324,8 @@ The above interface eagerly reads the full response body when you make the reque To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods. ```python -with client.files.with_streaming_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", +with client.files.with_streaming_response.upload( + file=b"raw file contents", file_name="fileName", ) as response: print(response.headers.get("X-My-Header")) diff --git a/api.md b/api.md index f71b3f9..859942b 100644 --- a/api.md +++ b/api.md @@ -23,137 +23,194 @@ Types: ```python from imagekit.types import ( - ExifDetails, - ExifImage, - Gps, - Interoperability, - Thumbnail, - FileListResponse, - FileAddTagsResponse, - FileRemoveAITagsResponse, - FileRemoveTagsResponse, + FileUpdateResponse, + FileGetResponse, FileRenameResponse, - FileUploadV1Response, - FileUploadV2Response, + FileUploadResponse, ) ``` Methods: -- client.files.list(\*\*params) -> FileListResponse +- client.files.update(file_id, \*\*params) -> FileUpdateResponse - client.files.delete(file_id) -> None -- client.files.add_tags(\*\*params) -> FileAddTagsResponse - client.files.copy(\*\*params) -> object +- client.files.get(file_id) -> FileGetResponse - client.files.move(\*\*params) -> object -- client.files.remove_ai_tags(\*\*params) -> FileRemoveAITagsResponse -- client.files.remove_tags(\*\*params) -> FileRemoveTagsResponse - client.files.rename(\*\*params) -> FileRenameResponse -- client.files.upload_v1(\*\*params) -> FileUploadV1Response -- client.files.upload_v2(\*\*params) -> FileUploadV2Response +- client.files.upload(\*\*params) -> FileUploadResponse -## Details +## Bulk Types: ```python -from imagekit.types.files import DetailRetrieveResponse, DetailUpdateResponse +from imagekit.types.files import ( + BulkDeleteResponse, + BulkAddTagsResponse, + BulkRemoveAITagsResponse, + BulkRemoveTagsResponse, +) ``` Methods: -- client.files.details.retrieve(file_id) -> DetailRetrieveResponse -- client.files.details.update(file_id, \*\*params) -> DetailUpdateResponse +- client.files.bulk.delete(\*\*params) -> BulkDeleteResponse +- client.files.bulk.add_tags(\*\*params) -> BulkAddTagsResponse +- client.files.bulk.remove_ai_tags(\*\*params) -> BulkRemoveAITagsResponse +- client.files.bulk.remove_tags(\*\*params) -> BulkRemoveTagsResponse -## Batch +## Versions Types: ```python -from imagekit.types.files import BatchDeleteResponse +from imagekit.types.files import VersionListResponse, VersionGetResponse, VersionRestoreResponse ``` Methods: -- client.files.batch.delete(\*\*params) -> BatchDeleteResponse +- client.files.versions.list(file_id) -> VersionListResponse +- client.files.versions.delete(version_id, \*, file_id) -> object +- client.files.versions.get(version_id, \*, file_id) -> VersionGetResponse +- client.files.versions.restore(version_id, \*, file_id) -> VersionRestoreResponse -## Versions +## Metadata Types: ```python -from imagekit.types.files import ( - VersionRetrieveResponse, - VersionListResponse, - VersionRestoreResponse, -) +from imagekit.types.files import MetadataGetResponse, MetadataGetFromURLResponse ``` Methods: -- client.files.versions.retrieve(version_id, \*, file_id) -> VersionRetrieveResponse -- client.files.versions.list(file_id) -> VersionListResponse -- client.files.versions.delete(version_id, \*, file_id) -> object -- client.files.versions.restore(version_id, \*, file_id) -> VersionRestoreResponse +- client.files.metadata.get(file_id) -> MetadataGetResponse +- client.files.metadata.get_from_url(\*\*params) -> MetadataGetFromURLResponse -## Purge +# Assets Types: ```python -from imagekit.types.files import PurgeExecuteResponse, PurgeStatusResponse +from imagekit.types import AssetListResponse ``` Methods: -- client.files.purge.execute(\*\*params) -> PurgeExecuteResponse -- client.files.purge.status(request_id) -> PurgeStatusResponse +- client.assets.list(\*\*params) -> AssetListResponse -## Metadata +# Cache + +## Invalidation Types: ```python -from imagekit.types.files import MetadataRetrieveResponse, MetadataFromURLResponse +from imagekit.types.cache import InvalidationCreateResponse, InvalidationGetResponse ``` Methods: -- client.files.metadata.retrieve(file_id) -> MetadataRetrieveResponse -- client.files.metadata.from_url(\*\*params) -> MetadataFromURLResponse +- client.cache.invalidation.create(\*\*params) -> InvalidationCreateResponse +- client.cache.invalidation.get(request_id) -> InvalidationGetResponse + +# Folders -# Folder +Types: + +```python +from imagekit.types import FolderCopyResponse, FolderMoveResponse, FolderRenameResponse +``` Methods: -- client.folder.create(\*\*params) -> object -- client.folder.delete(\*\*params) -> object +- client.folders.create(\*\*params) -> object +- client.folders.delete(\*\*params) -> object +- client.folders.copy(\*\*params) -> FolderCopyResponse +- client.folders.move(\*\*params) -> FolderMoveResponse +- client.folders.rename(\*\*params) -> FolderRenameResponse -# BulkJobs +## Job Types: ```python -from imagekit.types import ( - BulkJobCopyFolderResponse, - BulkJobMoveFolderResponse, - BulkJobRetrieveStatusResponse, -) +from imagekit.types.folders import JobGetResponse ``` Methods: -- client.bulk_jobs.copy_folder(\*\*params) -> BulkJobCopyFolderResponse -- client.bulk_jobs.move_folder(\*\*params) -> BulkJobMoveFolderResponse -- client.bulk_jobs.retrieve_status(job_id) -> BulkJobRetrieveStatusResponse +- client.folders.job.get(job_id) -> JobGetResponse # Accounts +## Usage + +Types: + +```python +from imagekit.types.accounts import UsageGetResponse +``` + +Methods: + +- client.accounts.usage.get(\*\*params) -> UsageGetResponse + +## Origins + +Types: + +```python +from imagekit.types.accounts import ( + OriginCreateResponse, + OriginUpdateResponse, + OriginListResponse, + OriginGetResponse, +) +``` + +Methods: + +- client.accounts.origins.create(\*\*params) -> OriginCreateResponse +- client.accounts.origins.update(id, \*\*params) -> OriginUpdateResponse +- client.accounts.origins.list() -> OriginListResponse +- client.accounts.origins.delete(id) -> None +- client.accounts.origins.get(id) -> OriginGetResponse + +## URLEndpoints + +Types: + +```python +from imagekit.types.accounts import ( + URLEndpointCreateResponse, + URLEndpointUpdateResponse, + URLEndpointListResponse, + URLEndpointGetResponse, +) +``` + +Methods: + +- client.accounts.url_endpoints.create(\*\*params) -> URLEndpointCreateResponse +- client.accounts.url_endpoints.update(id, \*\*params) -> URLEndpointUpdateResponse +- client.accounts.url_endpoints.list() -> URLEndpointListResponse +- client.accounts.url_endpoints.delete(id) -> None +- client.accounts.url_endpoints.get(id) -> URLEndpointGetResponse + +# Beta + +## V2 + +### Files + Types: ```python -from imagekit.types import AccountGetUsageResponse +from imagekit.types.beta.v2 import FileUploadResponse ``` Methods: -- client.accounts.get_usage(\*\*params) -> AccountGetUsageResponse +- client.beta.v2.files.upload(\*\*params) -> FileUploadResponse diff --git a/src/imagekit/_client.py b/src/imagekit/_client.py index 6c5a255..e672ca9 100644 --- a/src/imagekit/_client.py +++ b/src/imagekit/_client.py @@ -23,7 +23,7 @@ ) from ._utils import is_given, get_async_library from ._version import __version__ -from .resources import folder, accounts, bulk_jobs, custom_metadata_fields +from .resources import assets, custom_metadata_fields from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import ImageKitError, APIStatusError from ._base_client import ( @@ -31,7 +31,11 @@ SyncAPIClient, AsyncAPIClient, ) +from .resources.beta import beta +from .resources.cache import cache from .resources.files import files +from .resources.folders import folders +from .resources.accounts import accounts __all__ = [ "Timeout", @@ -48,9 +52,11 @@ class ImageKit(SyncAPIClient): custom_metadata_fields: custom_metadata_fields.CustomMetadataFieldsResource files: files.FilesResource - folder: folder.FolderResource - bulk_jobs: bulk_jobs.BulkJobsResource + assets: assets.AssetsResource + cache: cache.CacheResource + folders: folders.FoldersResource accounts: accounts.AccountsResource + beta: beta.BetaResource with_raw_response: ImageKitWithRawResponse with_streaming_response: ImageKitWithStreamedResponse @@ -119,9 +125,11 @@ def __init__( self.custom_metadata_fields = custom_metadata_fields.CustomMetadataFieldsResource(self) self.files = files.FilesResource(self) - self.folder = folder.FolderResource(self) - self.bulk_jobs = bulk_jobs.BulkJobsResource(self) + self.assets = assets.AssetsResource(self) + self.cache = cache.CacheResource(self) + self.folders = folders.FoldersResource(self) self.accounts = accounts.AccountsResource(self) + self.beta = beta.BetaResource(self) self.with_raw_response = ImageKitWithRawResponse(self) self.with_streaming_response = ImageKitWithStreamedResponse(self) @@ -251,9 +259,11 @@ def _make_status_error( class AsyncImageKit(AsyncAPIClient): custom_metadata_fields: custom_metadata_fields.AsyncCustomMetadataFieldsResource files: files.AsyncFilesResource - folder: folder.AsyncFolderResource - bulk_jobs: bulk_jobs.AsyncBulkJobsResource + assets: assets.AsyncAssetsResource + cache: cache.AsyncCacheResource + folders: folders.AsyncFoldersResource accounts: accounts.AsyncAccountsResource + beta: beta.AsyncBetaResource with_raw_response: AsyncImageKitWithRawResponse with_streaming_response: AsyncImageKitWithStreamedResponse @@ -322,9 +332,11 @@ def __init__( self.custom_metadata_fields = custom_metadata_fields.AsyncCustomMetadataFieldsResource(self) self.files = files.AsyncFilesResource(self) - self.folder = folder.AsyncFolderResource(self) - self.bulk_jobs = bulk_jobs.AsyncBulkJobsResource(self) + self.assets = assets.AsyncAssetsResource(self) + self.cache = cache.AsyncCacheResource(self) + self.folders = folders.AsyncFoldersResource(self) self.accounts = accounts.AsyncAccountsResource(self) + self.beta = beta.AsyncBetaResource(self) self.with_raw_response = AsyncImageKitWithRawResponse(self) self.with_streaming_response = AsyncImageKitWithStreamedResponse(self) @@ -457,9 +469,11 @@ def __init__(self, client: ImageKit) -> None: client.custom_metadata_fields ) self.files = files.FilesResourceWithRawResponse(client.files) - self.folder = folder.FolderResourceWithRawResponse(client.folder) - self.bulk_jobs = bulk_jobs.BulkJobsResourceWithRawResponse(client.bulk_jobs) + self.assets = assets.AssetsResourceWithRawResponse(client.assets) + self.cache = cache.CacheResourceWithRawResponse(client.cache) + self.folders = folders.FoldersResourceWithRawResponse(client.folders) self.accounts = accounts.AccountsResourceWithRawResponse(client.accounts) + self.beta = beta.BetaResourceWithRawResponse(client.beta) class AsyncImageKitWithRawResponse: @@ -468,9 +482,11 @@ def __init__(self, client: AsyncImageKit) -> None: client.custom_metadata_fields ) self.files = files.AsyncFilesResourceWithRawResponse(client.files) - self.folder = folder.AsyncFolderResourceWithRawResponse(client.folder) - self.bulk_jobs = bulk_jobs.AsyncBulkJobsResourceWithRawResponse(client.bulk_jobs) + self.assets = assets.AsyncAssetsResourceWithRawResponse(client.assets) + self.cache = cache.AsyncCacheResourceWithRawResponse(client.cache) + self.folders = folders.AsyncFoldersResourceWithRawResponse(client.folders) self.accounts = accounts.AsyncAccountsResourceWithRawResponse(client.accounts) + self.beta = beta.AsyncBetaResourceWithRawResponse(client.beta) class ImageKitWithStreamedResponse: @@ -479,9 +495,11 @@ def __init__(self, client: ImageKit) -> None: client.custom_metadata_fields ) self.files = files.FilesResourceWithStreamingResponse(client.files) - self.folder = folder.FolderResourceWithStreamingResponse(client.folder) - self.bulk_jobs = bulk_jobs.BulkJobsResourceWithStreamingResponse(client.bulk_jobs) + self.assets = assets.AssetsResourceWithStreamingResponse(client.assets) + self.cache = cache.CacheResourceWithStreamingResponse(client.cache) + self.folders = folders.FoldersResourceWithStreamingResponse(client.folders) self.accounts = accounts.AccountsResourceWithStreamingResponse(client.accounts) + self.beta = beta.BetaResourceWithStreamingResponse(client.beta) class AsyncImageKitWithStreamedResponse: @@ -490,9 +508,11 @@ def __init__(self, client: AsyncImageKit) -> None: client.custom_metadata_fields ) self.files = files.AsyncFilesResourceWithStreamingResponse(client.files) - self.folder = folder.AsyncFolderResourceWithStreamingResponse(client.folder) - self.bulk_jobs = bulk_jobs.AsyncBulkJobsResourceWithStreamingResponse(client.bulk_jobs) + self.assets = assets.AsyncAssetsResourceWithStreamingResponse(client.assets) + self.cache = cache.AsyncCacheResourceWithStreamingResponse(client.cache) + self.folders = folders.AsyncFoldersResourceWithStreamingResponse(client.folders) self.accounts = accounts.AsyncAccountsResourceWithStreamingResponse(client.accounts) + self.beta = beta.AsyncBetaResourceWithStreamingResponse(client.beta) Client = ImageKit diff --git a/src/imagekit/_files.py b/src/imagekit/_files.py index cc14c14..3cf7941 100644 --- a/src/imagekit/_files.py +++ b/src/imagekit/_files.py @@ -34,7 +34,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None: if not is_file_content(obj): prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" raise RuntimeError( - f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead." + f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/stainless-sdks/imagekit-python/tree/main#file-uploads" ) from None diff --git a/src/imagekit/resources/__init__.py b/src/imagekit/resources/__init__.py index b53b5b0..6c6a8b6 100644 --- a/src/imagekit/resources/__init__.py +++ b/src/imagekit/resources/__init__.py @@ -1,5 +1,21 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .beta import ( + BetaResource, + AsyncBetaResource, + BetaResourceWithRawResponse, + AsyncBetaResourceWithRawResponse, + BetaResourceWithStreamingResponse, + AsyncBetaResourceWithStreamingResponse, +) +from .cache import ( + CacheResource, + AsyncCacheResource, + CacheResourceWithRawResponse, + AsyncCacheResourceWithRawResponse, + CacheResourceWithStreamingResponse, + AsyncCacheResourceWithStreamingResponse, +) from .files import ( FilesResource, AsyncFilesResource, @@ -8,13 +24,21 @@ FilesResourceWithStreamingResponse, AsyncFilesResourceWithStreamingResponse, ) -from .folder import ( - FolderResource, - AsyncFolderResource, - FolderResourceWithRawResponse, - AsyncFolderResourceWithRawResponse, - FolderResourceWithStreamingResponse, - AsyncFolderResourceWithStreamingResponse, +from .assets import ( + AssetsResource, + AsyncAssetsResource, + AssetsResourceWithRawResponse, + AsyncAssetsResourceWithRawResponse, + AssetsResourceWithStreamingResponse, + AsyncAssetsResourceWithStreamingResponse, +) +from .folders import ( + FoldersResource, + AsyncFoldersResource, + FoldersResourceWithRawResponse, + AsyncFoldersResourceWithRawResponse, + FoldersResourceWithStreamingResponse, + AsyncFoldersResourceWithStreamingResponse, ) from .accounts import ( AccountsResource, @@ -24,14 +48,6 @@ AccountsResourceWithStreamingResponse, AsyncAccountsResourceWithStreamingResponse, ) -from .bulk_jobs import ( - BulkJobsResource, - AsyncBulkJobsResource, - BulkJobsResourceWithRawResponse, - AsyncBulkJobsResourceWithRawResponse, - BulkJobsResourceWithStreamingResponse, - AsyncBulkJobsResourceWithStreamingResponse, -) from .custom_metadata_fields import ( CustomMetadataFieldsResource, AsyncCustomMetadataFieldsResource, @@ -54,22 +70,34 @@ "AsyncFilesResourceWithRawResponse", "FilesResourceWithStreamingResponse", "AsyncFilesResourceWithStreamingResponse", - "FolderResource", - "AsyncFolderResource", - "FolderResourceWithRawResponse", - "AsyncFolderResourceWithRawResponse", - "FolderResourceWithStreamingResponse", - "AsyncFolderResourceWithStreamingResponse", - "BulkJobsResource", - "AsyncBulkJobsResource", - "BulkJobsResourceWithRawResponse", - "AsyncBulkJobsResourceWithRawResponse", - "BulkJobsResourceWithStreamingResponse", - "AsyncBulkJobsResourceWithStreamingResponse", + "AssetsResource", + "AsyncAssetsResource", + "AssetsResourceWithRawResponse", + "AsyncAssetsResourceWithRawResponse", + "AssetsResourceWithStreamingResponse", + "AsyncAssetsResourceWithStreamingResponse", + "CacheResource", + "AsyncCacheResource", + "CacheResourceWithRawResponse", + "AsyncCacheResourceWithRawResponse", + "CacheResourceWithStreamingResponse", + "AsyncCacheResourceWithStreamingResponse", + "FoldersResource", + "AsyncFoldersResource", + "FoldersResourceWithRawResponse", + "AsyncFoldersResourceWithRawResponse", + "FoldersResourceWithStreamingResponse", + "AsyncFoldersResourceWithStreamingResponse", "AccountsResource", "AsyncAccountsResource", "AccountsResourceWithRawResponse", "AsyncAccountsResourceWithRawResponse", "AccountsResourceWithStreamingResponse", "AsyncAccountsResourceWithStreamingResponse", + "BetaResource", + "AsyncBetaResource", + "BetaResourceWithRawResponse", + "AsyncBetaResourceWithRawResponse", + "BetaResourceWithStreamingResponse", + "AsyncBetaResourceWithStreamingResponse", ] diff --git a/src/imagekit/resources/accounts/__init__.py b/src/imagekit/resources/accounts/__init__.py new file mode 100644 index 0000000..fc56413 --- /dev/null +++ b/src/imagekit/resources/accounts/__init__.py @@ -0,0 +1,61 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .usage import ( + UsageResource, + AsyncUsageResource, + UsageResourceWithRawResponse, + AsyncUsageResourceWithRawResponse, + UsageResourceWithStreamingResponse, + AsyncUsageResourceWithStreamingResponse, +) +from .origins import ( + OriginsResource, + AsyncOriginsResource, + OriginsResourceWithRawResponse, + AsyncOriginsResourceWithRawResponse, + OriginsResourceWithStreamingResponse, + AsyncOriginsResourceWithStreamingResponse, +) +from .accounts import ( + AccountsResource, + AsyncAccountsResource, + AccountsResourceWithRawResponse, + AsyncAccountsResourceWithRawResponse, + AccountsResourceWithStreamingResponse, + AsyncAccountsResourceWithStreamingResponse, +) +from .url_endpoints import ( + URLEndpointsResource, + AsyncURLEndpointsResource, + URLEndpointsResourceWithRawResponse, + AsyncURLEndpointsResourceWithRawResponse, + URLEndpointsResourceWithStreamingResponse, + AsyncURLEndpointsResourceWithStreamingResponse, +) + +__all__ = [ + "UsageResource", + "AsyncUsageResource", + "UsageResourceWithRawResponse", + "AsyncUsageResourceWithRawResponse", + "UsageResourceWithStreamingResponse", + "AsyncUsageResourceWithStreamingResponse", + "OriginsResource", + "AsyncOriginsResource", + "OriginsResourceWithRawResponse", + "AsyncOriginsResourceWithRawResponse", + "OriginsResourceWithStreamingResponse", + "AsyncOriginsResourceWithStreamingResponse", + "URLEndpointsResource", + "AsyncURLEndpointsResource", + "URLEndpointsResourceWithRawResponse", + "AsyncURLEndpointsResourceWithRawResponse", + "URLEndpointsResourceWithStreamingResponse", + "AsyncURLEndpointsResourceWithStreamingResponse", + "AccountsResource", + "AsyncAccountsResource", + "AccountsResourceWithRawResponse", + "AsyncAccountsResourceWithRawResponse", + "AccountsResourceWithStreamingResponse", + "AsyncAccountsResourceWithStreamingResponse", +] diff --git a/src/imagekit/resources/accounts/accounts.py b/src/imagekit/resources/accounts/accounts.py new file mode 100644 index 0000000..dba376c --- /dev/null +++ b/src/imagekit/resources/accounts/accounts.py @@ -0,0 +1,166 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .usage import ( + UsageResource, + AsyncUsageResource, + UsageResourceWithRawResponse, + AsyncUsageResourceWithRawResponse, + UsageResourceWithStreamingResponse, + AsyncUsageResourceWithStreamingResponse, +) +from .origins import ( + OriginsResource, + AsyncOriginsResource, + OriginsResourceWithRawResponse, + AsyncOriginsResourceWithRawResponse, + OriginsResourceWithStreamingResponse, + AsyncOriginsResourceWithStreamingResponse, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from .url_endpoints import ( + URLEndpointsResource, + AsyncURLEndpointsResource, + URLEndpointsResourceWithRawResponse, + AsyncURLEndpointsResourceWithRawResponse, + URLEndpointsResourceWithStreamingResponse, + AsyncURLEndpointsResourceWithStreamingResponse, +) + +__all__ = ["AccountsResource", "AsyncAccountsResource"] + + +class AccountsResource(SyncAPIResource): + @cached_property + def usage(self) -> UsageResource: + return UsageResource(self._client) + + @cached_property + def origins(self) -> OriginsResource: + return OriginsResource(self._client) + + @cached_property + def url_endpoints(self) -> URLEndpointsResource: + return URLEndpointsResource(self._client) + + @cached_property + def with_raw_response(self) -> AccountsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AccountsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AccountsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AccountsResourceWithStreamingResponse(self) + + +class AsyncAccountsResource(AsyncAPIResource): + @cached_property + def usage(self) -> AsyncUsageResource: + return AsyncUsageResource(self._client) + + @cached_property + def origins(self) -> AsyncOriginsResource: + return AsyncOriginsResource(self._client) + + @cached_property + def url_endpoints(self) -> AsyncURLEndpointsResource: + return AsyncURLEndpointsResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncAccountsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncAccountsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAccountsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncAccountsResourceWithStreamingResponse(self) + + +class AccountsResourceWithRawResponse: + def __init__(self, accounts: AccountsResource) -> None: + self._accounts = accounts + + @cached_property + def usage(self) -> UsageResourceWithRawResponse: + return UsageResourceWithRawResponse(self._accounts.usage) + + @cached_property + def origins(self) -> OriginsResourceWithRawResponse: + return OriginsResourceWithRawResponse(self._accounts.origins) + + @cached_property + def url_endpoints(self) -> URLEndpointsResourceWithRawResponse: + return URLEndpointsResourceWithRawResponse(self._accounts.url_endpoints) + + +class AsyncAccountsResourceWithRawResponse: + def __init__(self, accounts: AsyncAccountsResource) -> None: + self._accounts = accounts + + @cached_property + def usage(self) -> AsyncUsageResourceWithRawResponse: + return AsyncUsageResourceWithRawResponse(self._accounts.usage) + + @cached_property + def origins(self) -> AsyncOriginsResourceWithRawResponse: + return AsyncOriginsResourceWithRawResponse(self._accounts.origins) + + @cached_property + def url_endpoints(self) -> AsyncURLEndpointsResourceWithRawResponse: + return AsyncURLEndpointsResourceWithRawResponse(self._accounts.url_endpoints) + + +class AccountsResourceWithStreamingResponse: + def __init__(self, accounts: AccountsResource) -> None: + self._accounts = accounts + + @cached_property + def usage(self) -> UsageResourceWithStreamingResponse: + return UsageResourceWithStreamingResponse(self._accounts.usage) + + @cached_property + def origins(self) -> OriginsResourceWithStreamingResponse: + return OriginsResourceWithStreamingResponse(self._accounts.origins) + + @cached_property + def url_endpoints(self) -> URLEndpointsResourceWithStreamingResponse: + return URLEndpointsResourceWithStreamingResponse(self._accounts.url_endpoints) + + +class AsyncAccountsResourceWithStreamingResponse: + def __init__(self, accounts: AsyncAccountsResource) -> None: + self._accounts = accounts + + @cached_property + def usage(self) -> AsyncUsageResourceWithStreamingResponse: + return AsyncUsageResourceWithStreamingResponse(self._accounts.usage) + + @cached_property + def origins(self) -> AsyncOriginsResourceWithStreamingResponse: + return AsyncOriginsResourceWithStreamingResponse(self._accounts.origins) + + @cached_property + def url_endpoints(self) -> AsyncURLEndpointsResourceWithStreamingResponse: + return AsyncURLEndpointsResourceWithStreamingResponse(self._accounts.url_endpoints) diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py new file mode 100644 index 0000000..13c8d75 --- /dev/null +++ b/src/imagekit/resources/accounts/origins.py @@ -0,0 +1,2243 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Any, cast +from typing_extensions import Literal, overload + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +from ..._utils import required_args, maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.accounts import origin_create_params, origin_update_params +from ...types.accounts.origin_get_response import OriginGetResponse +from ...types.accounts.origin_list_response import OriginListResponse +from ...types.accounts.origin_create_response import OriginCreateResponse +from ...types.accounts.origin_update_response import OriginUpdateResponse + +__all__ = ["OriginsResource", "AsyncOriginsResource"] + + +class OriginsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> OriginsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return OriginsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return OriginsResourceWithStreamingResponse(self) + + @overload + def create( + self, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["S3"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + access_key: str, + bucket: str, + endpoint: str, + name: str, + secret_key: str, + type: Literal["S3_COMPATIBLE"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + endpoint: Custom S3-compatible endpoint. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + s3_force_path_style: Use path-style S3 URLs? + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["CLOUDINARY_BACKUP"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + base_url: str, + name: str, + type: Literal["WEB_FOLDER"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + base_url: Root URL for the web folder origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + forward_host_header_to_origin: Forward the Host header to origin? + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + name: str, + type: Literal["WEB_PROXY"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + bucket: str, + client_email: str, + name: str, + private_key: str, + type: Literal["GCS"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + account_name: str, + container: str, + name: str, + sas_token: str, + type: Literal["AZURE_BLOB"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + base_url: str, + client_id: str, + client_secret: str, + name: str, + password: str, + type: Literal["AKENEO_PIM"], + username: str, + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + base_url: Akeneo instance base URL. + + client_id: Akeneo API client ID. + + client_secret: Akeneo API client secret. + + name: Display name of the origin. + + password: Akeneo API password. + + username: Akeneo API username. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args( + ["access_key", "bucket", "name", "secret_key", "type"], + ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], + ["base_url", "name", "type"], + ["name", "type"], + ["bucket", "client_email", "name", "private_key", "type"], + ["account_name", "container", "name", "sas_token", "type"], + ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], + ) + def create( + self, + *, + access_key: str | NotGiven = NOT_GIVEN, + bucket: str | NotGiven = NOT_GIVEN, + name: str, + secret_key: str | NotGiven = NOT_GIVEN, + type: Literal["S3"] + | Literal["S3_COMPATIBLE"] + | Literal["CLOUDINARY_BACKUP"] + | Literal["WEB_FOLDER"] + | Literal["WEB_PROXY"] + | Literal["GCS"] + | Literal["AZURE_BLOB"] + | Literal["AKENEO_PIM"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + endpoint: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + client_email: str | NotGiven = NOT_GIVEN, + private_key: str | NotGiven = NOT_GIVEN, + account_name: str | NotGiven = NOT_GIVEN, + container: str | NotGiven = NOT_GIVEN, + sas_token: str | NotGiven = NOT_GIVEN, + client_id: str | NotGiven = NOT_GIVEN, + client_secret: str | NotGiven = NOT_GIVEN, + password: str | NotGiven = NOT_GIVEN, + username: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + return cast( + OriginCreateResponse, + self._post( + "/v1/accounts/origins", + body=maybe_transform( + { + "access_key": access_key, + "bucket": bucket, + "name": name, + "secret_key": secret_key, + "type": type, + "base_url_for_canonical_header": base_url_for_canonical_header, + "include_canonical_header": include_canonical_header, + "prefix": prefix, + "endpoint": endpoint, + "s3_force_path_style": s3_force_path_style, + "base_url": base_url, + "forward_host_header_to_origin": forward_host_header_to_origin, + "client_email": client_email, + "private_key": private_key, + "account_name": account_name, + "container": container, + "sas_token": sas_token, + "client_id": client_id, + "client_secret": client_secret, + "password": password, + "username": username, + }, + origin_create_params.OriginCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, OriginCreateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + @overload + def update( + self, + id: str, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["S3"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + access_key: str, + bucket: str, + endpoint: str, + name: str, + secret_key: str, + type: Literal["S3_COMPATIBLE"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + endpoint: Custom S3-compatible endpoint. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + s3_force_path_style: Use path-style S3 URLs? + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["CLOUDINARY_BACKUP"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + base_url: str, + name: str, + type: Literal["WEB_FOLDER"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + base_url: Root URL for the web folder origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + forward_host_header_to_origin: Forward the Host header to origin? + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + name: str, + type: Literal["WEB_PROXY"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + bucket: str, + client_email: str, + name: str, + private_key: str, + type: Literal["GCS"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + account_name: str, + container: str, + name: str, + sas_token: str, + type: Literal["AZURE_BLOB"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + base_url: str, + client_id: str, + client_secret: str, + name: str, + password: str, + type: Literal["AKENEO_PIM"], + username: str, + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + base_url: Akeneo instance base URL. + + client_id: Akeneo API client ID. + + client_secret: Akeneo API client secret. + + name: Display name of the origin. + + password: Akeneo API password. + + username: Akeneo API username. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args( + ["access_key", "bucket", "name", "secret_key", "type"], + ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], + ["base_url", "name", "type"], + ["name", "type"], + ["bucket", "client_email", "name", "private_key", "type"], + ["account_name", "container", "name", "sas_token", "type"], + ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], + ) + def update( + self, + id: str, + *, + access_key: str | NotGiven = NOT_GIVEN, + bucket: str | NotGiven = NOT_GIVEN, + name: str, + secret_key: str | NotGiven = NOT_GIVEN, + type: Literal["S3"] + | Literal["S3_COMPATIBLE"] + | Literal["CLOUDINARY_BACKUP"] + | Literal["WEB_FOLDER"] + | Literal["WEB_PROXY"] + | Literal["GCS"] + | Literal["AZURE_BLOB"] + | Literal["AKENEO_PIM"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + endpoint: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + client_email: str | NotGiven = NOT_GIVEN, + private_key: str | NotGiven = NOT_GIVEN, + account_name: str | NotGiven = NOT_GIVEN, + container: str | NotGiven = NOT_GIVEN, + sas_token: str | NotGiven = NOT_GIVEN, + client_id: str | NotGiven = NOT_GIVEN, + client_secret: str | NotGiven = NOT_GIVEN, + password: str | NotGiven = NOT_GIVEN, + username: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginUpdateResponse, + self._put( + f"/v1/accounts/origins/{id}", + body=maybe_transform( + { + "access_key": access_key, + "bucket": bucket, + "name": name, + "secret_key": secret_key, + "type": type, + "base_url_for_canonical_header": base_url_for_canonical_header, + "include_canonical_header": include_canonical_header, + "prefix": prefix, + "endpoint": endpoint, + "s3_force_path_style": s3_force_path_style, + "base_url": base_url, + "forward_host_header_to_origin": forward_host_header_to_origin, + "client_email": client_email, + "private_key": private_key, + "account_name": account_name, + "container": container, + "sas_token": sas_token, + "client_id": client_id, + "client_secret": client_secret, + "password": password, + "username": username, + }, + origin_update_params.OriginUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, OriginUpdateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginListResponse: + """**Note:** This API is currently in beta. + + + Returns an array of all configured origins for the current account. + """ + return self._get( + "/v1/accounts/origins", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=OriginListResponse, + ) + + def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """**Note:** This API is currently in beta. + + + Permanently removes the origin identified by `id`. If the origin is in use by + any URL‑endpoints, the API will return an error. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def get( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginGetResponse: + """**Note:** This API is currently in beta. + + + Retrieves the origin identified by `id`. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginGetResponse, + self._get( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast(Any, OriginGetResponse), # Union types cannot be passed in as arguments in the type system + ), + ) + + +class AsyncOriginsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncOriginsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncOriginsResourceWithStreamingResponse(self) + + @overload + async def create( + self, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["S3"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + access_key: str, + bucket: str, + endpoint: str, + name: str, + secret_key: str, + type: Literal["S3_COMPATIBLE"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + endpoint: Custom S3-compatible endpoint. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + s3_force_path_style: Use path-style S3 URLs? + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["CLOUDINARY_BACKUP"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + base_url: str, + name: str, + type: Literal["WEB_FOLDER"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + base_url: Root URL for the web folder origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + forward_host_header_to_origin: Forward the Host header to origin? + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + name: str, + type: Literal["WEB_PROXY"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + bucket: str, + client_email: str, + name: str, + private_key: str, + type: Literal["GCS"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + account_name: str, + container: str, + name: str, + sas_token: str, + type: Literal["AZURE_BLOB"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + base_url: str, + client_id: str, + client_secret: str, + name: str, + password: str, + type: Literal["AKENEO_PIM"], + username: str, + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + base_url: Akeneo instance base URL. + + client_id: Akeneo API client ID. + + client_secret: Akeneo API client secret. + + name: Display name of the origin. + + password: Akeneo API password. + + username: Akeneo API username. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args( + ["access_key", "bucket", "name", "secret_key", "type"], + ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], + ["base_url", "name", "type"], + ["name", "type"], + ["bucket", "client_email", "name", "private_key", "type"], + ["account_name", "container", "name", "sas_token", "type"], + ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], + ) + async def create( + self, + *, + access_key: str | NotGiven = NOT_GIVEN, + bucket: str | NotGiven = NOT_GIVEN, + name: str, + secret_key: str | NotGiven = NOT_GIVEN, + type: Literal["S3"] + | Literal["S3_COMPATIBLE"] + | Literal["CLOUDINARY_BACKUP"] + | Literal["WEB_FOLDER"] + | Literal["WEB_PROXY"] + | Literal["GCS"] + | Literal["AZURE_BLOB"] + | Literal["AKENEO_PIM"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + endpoint: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + client_email: str | NotGiven = NOT_GIVEN, + private_key: str | NotGiven = NOT_GIVEN, + account_name: str | NotGiven = NOT_GIVEN, + container: str | NotGiven = NOT_GIVEN, + sas_token: str | NotGiven = NOT_GIVEN, + client_id: str | NotGiven = NOT_GIVEN, + client_secret: str | NotGiven = NOT_GIVEN, + password: str | NotGiven = NOT_GIVEN, + username: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + return cast( + OriginCreateResponse, + await self._post( + "/v1/accounts/origins", + body=await async_maybe_transform( + { + "access_key": access_key, + "bucket": bucket, + "name": name, + "secret_key": secret_key, + "type": type, + "base_url_for_canonical_header": base_url_for_canonical_header, + "include_canonical_header": include_canonical_header, + "prefix": prefix, + "endpoint": endpoint, + "s3_force_path_style": s3_force_path_style, + "base_url": base_url, + "forward_host_header_to_origin": forward_host_header_to_origin, + "client_email": client_email, + "private_key": private_key, + "account_name": account_name, + "container": container, + "sas_token": sas_token, + "client_id": client_id, + "client_secret": client_secret, + "password": password, + "username": username, + }, + origin_create_params.OriginCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, OriginCreateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + @overload + async def update( + self, + id: str, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["S3"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def update( + self, + id: str, + *, + access_key: str, + bucket: str, + endpoint: str, + name: str, + secret_key: str, + type: Literal["S3_COMPATIBLE"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + endpoint: Custom S3-compatible endpoint. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + s3_force_path_style: Use path-style S3 URLs? + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def update( + self, + id: str, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["CLOUDINARY_BACKUP"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def update( + self, + id: str, + *, + base_url: str, + name: str, + type: Literal["WEB_FOLDER"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + base_url: Root URL for the web folder origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + forward_host_header_to_origin: Forward the Host header to origin? + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def update( + self, + id: str, + *, + name: str, + type: Literal["WEB_PROXY"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def update( + self, + id: str, + *, + bucket: str, + client_email: str, + name: str, + private_key: str, + type: Literal["GCS"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def update( + self, + id: str, + *, + account_name: str, + container: str, + name: str, + sas_token: str, + type: Literal["AZURE_BLOB"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def update( + self, + id: str, + *, + base_url: str, + client_id: str, + client_secret: str, + name: str, + password: str, + type: Literal["AKENEO_PIM"], + username: str, + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + base_url: Akeneo instance base URL. + + client_id: Akeneo API client ID. + + client_secret: Akeneo API client secret. + + name: Display name of the origin. + + password: Akeneo API password. + + username: Akeneo API username. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args( + ["access_key", "bucket", "name", "secret_key", "type"], + ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], + ["base_url", "name", "type"], + ["name", "type"], + ["bucket", "client_email", "name", "private_key", "type"], + ["account_name", "container", "name", "sas_token", "type"], + ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], + ) + async def update( + self, + id: str, + *, + access_key: str | NotGiven = NOT_GIVEN, + bucket: str | NotGiven = NOT_GIVEN, + name: str, + secret_key: str | NotGiven = NOT_GIVEN, + type: Literal["S3"] + | Literal["S3_COMPATIBLE"] + | Literal["CLOUDINARY_BACKUP"] + | Literal["WEB_FOLDER"] + | Literal["WEB_PROXY"] + | Literal["GCS"] + | Literal["AZURE_BLOB"] + | Literal["AKENEO_PIM"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + endpoint: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + client_email: str | NotGiven = NOT_GIVEN, + private_key: str | NotGiven = NOT_GIVEN, + account_name: str | NotGiven = NOT_GIVEN, + container: str | NotGiven = NOT_GIVEN, + sas_token: str | NotGiven = NOT_GIVEN, + client_id: str | NotGiven = NOT_GIVEN, + client_secret: str | NotGiven = NOT_GIVEN, + password: str | NotGiven = NOT_GIVEN, + username: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginUpdateResponse, + await self._put( + f"/v1/accounts/origins/{id}", + body=await async_maybe_transform( + { + "access_key": access_key, + "bucket": bucket, + "name": name, + "secret_key": secret_key, + "type": type, + "base_url_for_canonical_header": base_url_for_canonical_header, + "include_canonical_header": include_canonical_header, + "prefix": prefix, + "endpoint": endpoint, + "s3_force_path_style": s3_force_path_style, + "base_url": base_url, + "forward_host_header_to_origin": forward_host_header_to_origin, + "client_email": client_email, + "private_key": private_key, + "account_name": account_name, + "container": container, + "sas_token": sas_token, + "client_id": client_id, + "client_secret": client_secret, + "password": password, + "username": username, + }, + origin_update_params.OriginUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, OriginUpdateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + async def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginListResponse: + """**Note:** This API is currently in beta. + + + Returns an array of all configured origins for the current account. + """ + return await self._get( + "/v1/accounts/origins", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=OriginListResponse, + ) + + async def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """**Note:** This API is currently in beta. + + + Permanently removes the origin identified by `id`. If the origin is in use by + any URL‑endpoints, the API will return an error. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def get( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginGetResponse: + """**Note:** This API is currently in beta. + + + Retrieves the origin identified by `id`. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginGetResponse, + await self._get( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast(Any, OriginGetResponse), # Union types cannot be passed in as arguments in the type system + ), + ) + + +class OriginsResourceWithRawResponse: + def __init__(self, origins: OriginsResource) -> None: + self._origins = origins + + self.create = to_raw_response_wrapper( + origins.create, + ) + self.update = to_raw_response_wrapper( + origins.update, + ) + self.list = to_raw_response_wrapper( + origins.list, + ) + self.delete = to_raw_response_wrapper( + origins.delete, + ) + self.get = to_raw_response_wrapper( + origins.get, + ) + + +class AsyncOriginsResourceWithRawResponse: + def __init__(self, origins: AsyncOriginsResource) -> None: + self._origins = origins + + self.create = async_to_raw_response_wrapper( + origins.create, + ) + self.update = async_to_raw_response_wrapper( + origins.update, + ) + self.list = async_to_raw_response_wrapper( + origins.list, + ) + self.delete = async_to_raw_response_wrapper( + origins.delete, + ) + self.get = async_to_raw_response_wrapper( + origins.get, + ) + + +class OriginsResourceWithStreamingResponse: + def __init__(self, origins: OriginsResource) -> None: + self._origins = origins + + self.create = to_streamed_response_wrapper( + origins.create, + ) + self.update = to_streamed_response_wrapper( + origins.update, + ) + self.list = to_streamed_response_wrapper( + origins.list, + ) + self.delete = to_streamed_response_wrapper( + origins.delete, + ) + self.get = to_streamed_response_wrapper( + origins.get, + ) + + +class AsyncOriginsResourceWithStreamingResponse: + def __init__(self, origins: AsyncOriginsResource) -> None: + self._origins = origins + + self.create = async_to_streamed_response_wrapper( + origins.create, + ) + self.update = async_to_streamed_response_wrapper( + origins.update, + ) + self.list = async_to_streamed_response_wrapper( + origins.list, + ) + self.delete = async_to_streamed_response_wrapper( + origins.delete, + ) + self.get = async_to_streamed_response_wrapper( + origins.get, + ) diff --git a/src/imagekit/resources/accounts/url_endpoints.py b/src/imagekit/resources/accounts/url_endpoints.py new file mode 100644 index 0000000..ce20a62 --- /dev/null +++ b/src/imagekit/resources/accounts/url_endpoints.py @@ -0,0 +1,598 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.accounts import url_endpoint_create_params, url_endpoint_update_params +from ...types.accounts.url_endpoint_get_response import URLEndpointGetResponse +from ...types.accounts.url_endpoint_list_response import URLEndpointListResponse +from ...types.accounts.url_endpoint_create_response import URLEndpointCreateResponse +from ...types.accounts.url_endpoint_update_response import URLEndpointUpdateResponse + +__all__ = ["URLEndpointsResource", "AsyncURLEndpointsResource"] + + +class URLEndpointsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> URLEndpointsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return URLEndpointsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> URLEndpointsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return URLEndpointsResourceWithStreamingResponse(self) + + def create( + self, + *, + description: str, + origins: List[str] | NotGiven = NOT_GIVEN, + url_prefix: str | NotGiven = NOT_GIVEN, + url_rewriter: url_endpoint_create_params.URLRewriter | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> URLEndpointCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new URL‑endpoint and returns the resulting object. + + Args: + description: Description of the URL endpoint. + + origins: Ordered list of origin IDs to try when the file isn’t in the Media Library; + ImageKit checks them in the sequence provided. Origin must be created before it + can be used in a URL endpoint. + + url_prefix: Path segment appended to your base URL to form the endpoint (letters, digits, + and hyphens only — or empty for the default endpoint). + + url_rewriter: Configuration for third-party URL rewriting. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/accounts/url-endpoints", + body=maybe_transform( + { + "description": description, + "origins": origins, + "url_prefix": url_prefix, + "url_rewriter": url_rewriter, + }, + url_endpoint_create_params.URLEndpointCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=URLEndpointCreateResponse, + ) + + def update( + self, + id: str, + *, + description: str, + origins: List[str] | NotGiven = NOT_GIVEN, + url_prefix: str | NotGiven = NOT_GIVEN, + url_rewriter: url_endpoint_update_params.URLRewriter | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> URLEndpointUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the URL‑endpoint identified by `id` and returns the updated object. + + Args: + id: Unique identifier for the URL-endpoint. This is generated by ImageKit when you + create a new URL-endpoint. For the default URL-endpoint, this is always + `default`. + + description: Description of the URL endpoint. + + origins: Ordered list of origin IDs to try when the file isn’t in the Media Library; + ImageKit checks them in the sequence provided. Origin must be created before it + can be used in a URL endpoint. + + url_prefix: Path segment appended to your base URL to form the endpoint (letters, digits, + and hyphens only — or empty for the default endpoint). + + url_rewriter: Configuration for third-party URL rewriting. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._put( + f"/v1/accounts/url-endpoints/{id}", + body=maybe_transform( + { + "description": description, + "origins": origins, + "url_prefix": url_prefix, + "url_rewriter": url_rewriter, + }, + url_endpoint_update_params.URLEndpointUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=URLEndpointUpdateResponse, + ) + + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> URLEndpointListResponse: + """**Note:** This API is currently in beta. + + + Returns an array of all URL‑endpoints configured including the default + URL-endpoint generated by ImageKit during account creation. + """ + return self._get( + "/v1/accounts/url-endpoints", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=URLEndpointListResponse, + ) + + def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """**Note:** This API is currently in beta. + + + Deletes the URL‑endpoint identified by `id`. You cannot delete the default + URL‑endpoint created by ImageKit during account creation. + + Args: + id: Unique identifier for the URL-endpoint. This is generated by ImageKit when you + create a new URL-endpoint. For the default URL-endpoint, this is always + `default`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/v1/accounts/url-endpoints/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def get( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> URLEndpointGetResponse: + """**Note:** This API is currently in beta. + + + Retrieves the URL‑endpoint identified by `id`. + + Args: + id: Unique identifier for the URL-endpoint. This is generated by ImageKit when you + create a new URL-endpoint. For the default URL-endpoint, this is always + `default`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + f"/v1/accounts/url-endpoints/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=URLEndpointGetResponse, + ) + + +class AsyncURLEndpointsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncURLEndpointsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncURLEndpointsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncURLEndpointsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncURLEndpointsResourceWithStreamingResponse(self) + + async def create( + self, + *, + description: str, + origins: List[str] | NotGiven = NOT_GIVEN, + url_prefix: str | NotGiven = NOT_GIVEN, + url_rewriter: url_endpoint_create_params.URLRewriter | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> URLEndpointCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new URL‑endpoint and returns the resulting object. + + Args: + description: Description of the URL endpoint. + + origins: Ordered list of origin IDs to try when the file isn’t in the Media Library; + ImageKit checks them in the sequence provided. Origin must be created before it + can be used in a URL endpoint. + + url_prefix: Path segment appended to your base URL to form the endpoint (letters, digits, + and hyphens only — or empty for the default endpoint). + + url_rewriter: Configuration for third-party URL rewriting. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/accounts/url-endpoints", + body=await async_maybe_transform( + { + "description": description, + "origins": origins, + "url_prefix": url_prefix, + "url_rewriter": url_rewriter, + }, + url_endpoint_create_params.URLEndpointCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=URLEndpointCreateResponse, + ) + + async def update( + self, + id: str, + *, + description: str, + origins: List[str] | NotGiven = NOT_GIVEN, + url_prefix: str | NotGiven = NOT_GIVEN, + url_rewriter: url_endpoint_update_params.URLRewriter | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> URLEndpointUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the URL‑endpoint identified by `id` and returns the updated object. + + Args: + id: Unique identifier for the URL-endpoint. This is generated by ImageKit when you + create a new URL-endpoint. For the default URL-endpoint, this is always + `default`. + + description: Description of the URL endpoint. + + origins: Ordered list of origin IDs to try when the file isn’t in the Media Library; + ImageKit checks them in the sequence provided. Origin must be created before it + can be used in a URL endpoint. + + url_prefix: Path segment appended to your base URL to form the endpoint (letters, digits, + and hyphens only — or empty for the default endpoint). + + url_rewriter: Configuration for third-party URL rewriting. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._put( + f"/v1/accounts/url-endpoints/{id}", + body=await async_maybe_transform( + { + "description": description, + "origins": origins, + "url_prefix": url_prefix, + "url_rewriter": url_rewriter, + }, + url_endpoint_update_params.URLEndpointUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=URLEndpointUpdateResponse, + ) + + async def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> URLEndpointListResponse: + """**Note:** This API is currently in beta. + + + Returns an array of all URL‑endpoints configured including the default + URL-endpoint generated by ImageKit during account creation. + """ + return await self._get( + "/v1/accounts/url-endpoints", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=URLEndpointListResponse, + ) + + async def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """**Note:** This API is currently in beta. + + + Deletes the URL‑endpoint identified by `id`. You cannot delete the default + URL‑endpoint created by ImageKit during account creation. + + Args: + id: Unique identifier for the URL-endpoint. This is generated by ImageKit when you + create a new URL-endpoint. For the default URL-endpoint, this is always + `default`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + f"/v1/accounts/url-endpoints/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def get( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> URLEndpointGetResponse: + """**Note:** This API is currently in beta. + + + Retrieves the URL‑endpoint identified by `id`. + + Args: + id: Unique identifier for the URL-endpoint. This is generated by ImageKit when you + create a new URL-endpoint. For the default URL-endpoint, this is always + `default`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + f"/v1/accounts/url-endpoints/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=URLEndpointGetResponse, + ) + + +class URLEndpointsResourceWithRawResponse: + def __init__(self, url_endpoints: URLEndpointsResource) -> None: + self._url_endpoints = url_endpoints + + self.create = to_raw_response_wrapper( + url_endpoints.create, + ) + self.update = to_raw_response_wrapper( + url_endpoints.update, + ) + self.list = to_raw_response_wrapper( + url_endpoints.list, + ) + self.delete = to_raw_response_wrapper( + url_endpoints.delete, + ) + self.get = to_raw_response_wrapper( + url_endpoints.get, + ) + + +class AsyncURLEndpointsResourceWithRawResponse: + def __init__(self, url_endpoints: AsyncURLEndpointsResource) -> None: + self._url_endpoints = url_endpoints + + self.create = async_to_raw_response_wrapper( + url_endpoints.create, + ) + self.update = async_to_raw_response_wrapper( + url_endpoints.update, + ) + self.list = async_to_raw_response_wrapper( + url_endpoints.list, + ) + self.delete = async_to_raw_response_wrapper( + url_endpoints.delete, + ) + self.get = async_to_raw_response_wrapper( + url_endpoints.get, + ) + + +class URLEndpointsResourceWithStreamingResponse: + def __init__(self, url_endpoints: URLEndpointsResource) -> None: + self._url_endpoints = url_endpoints + + self.create = to_streamed_response_wrapper( + url_endpoints.create, + ) + self.update = to_streamed_response_wrapper( + url_endpoints.update, + ) + self.list = to_streamed_response_wrapper( + url_endpoints.list, + ) + self.delete = to_streamed_response_wrapper( + url_endpoints.delete, + ) + self.get = to_streamed_response_wrapper( + url_endpoints.get, + ) + + +class AsyncURLEndpointsResourceWithStreamingResponse: + def __init__(self, url_endpoints: AsyncURLEndpointsResource) -> None: + self._url_endpoints = url_endpoints + + self.create = async_to_streamed_response_wrapper( + url_endpoints.create, + ) + self.update = async_to_streamed_response_wrapper( + url_endpoints.update, + ) + self.list = async_to_streamed_response_wrapper( + url_endpoints.list, + ) + self.delete = async_to_streamed_response_wrapper( + url_endpoints.delete, + ) + self.get = async_to_streamed_response_wrapper( + url_endpoints.get, + ) diff --git a/src/imagekit/resources/accounts.py b/src/imagekit/resources/accounts/usage.py similarity index 70% rename from src/imagekit/resources/accounts.py rename to src/imagekit/resources/accounts/usage.py index b63e01b..0b9b9de 100644 --- a/src/imagekit/resources/accounts.py +++ b/src/imagekit/resources/accounts/usage.py @@ -7,44 +7,44 @@ import httpx -from ..types import account_get_usage_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import maybe_transform, async_maybe_transform -from .._compat import cached_property -from .._resource import SyncAPIResource, AsyncAPIResource -from .._response import ( +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( to_raw_response_wrapper, to_streamed_response_wrapper, async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from .._base_client import make_request_options -from ..types.account_get_usage_response import AccountGetUsageResponse +from ..._base_client import make_request_options +from ...types.accounts import usage_get_params +from ...types.accounts.usage_get_response import UsageGetResponse -__all__ = ["AccountsResource", "AsyncAccountsResource"] +__all__ = ["UsageResource", "AsyncUsageResource"] -class AccountsResource(SyncAPIResource): +class UsageResource(SyncAPIResource): @cached_property - def with_raw_response(self) -> AccountsResourceWithRawResponse: + def with_raw_response(self) -> UsageResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ - return AccountsResourceWithRawResponse(self) + return UsageResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AccountsResourceWithStreamingResponse: + def with_streaming_response(self) -> UsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ - return AccountsResourceWithStreamingResponse(self) + return UsageResourceWithStreamingResponse(self) - def get_usage( + def get( self, *, end_date: Union[str, date], @@ -55,7 +55,7 @@ def get_usage( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AccountGetUsageResponse: + ) -> UsageGetResponse: """Get the account usage information between two dates. Note that the API response @@ -90,34 +90,34 @@ def get_usage( "end_date": end_date, "start_date": start_date, }, - account_get_usage_params.AccountGetUsageParams, + usage_get_params.UsageGetParams, ), ), - cast_to=AccountGetUsageResponse, + cast_to=UsageGetResponse, ) -class AsyncAccountsResource(AsyncAPIResource): +class AsyncUsageResource(AsyncAPIResource): @cached_property - def with_raw_response(self) -> AsyncAccountsResourceWithRawResponse: + def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ - return AsyncAccountsResourceWithRawResponse(self) + return AsyncUsageResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AsyncAccountsResourceWithStreamingResponse: + def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ - return AsyncAccountsResourceWithStreamingResponse(self) + return AsyncUsageResourceWithStreamingResponse(self) - async def get_usage( + async def get( self, *, end_date: Union[str, date], @@ -128,7 +128,7 @@ async def get_usage( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AccountGetUsageResponse: + ) -> UsageGetResponse: """Get the account usage information between two dates. Note that the API response @@ -163,44 +163,44 @@ async def get_usage( "end_date": end_date, "start_date": start_date, }, - account_get_usage_params.AccountGetUsageParams, + usage_get_params.UsageGetParams, ), ), - cast_to=AccountGetUsageResponse, + cast_to=UsageGetResponse, ) -class AccountsResourceWithRawResponse: - def __init__(self, accounts: AccountsResource) -> None: - self._accounts = accounts +class UsageResourceWithRawResponse: + def __init__(self, usage: UsageResource) -> None: + self._usage = usage - self.get_usage = to_raw_response_wrapper( - accounts.get_usage, + self.get = to_raw_response_wrapper( + usage.get, ) -class AsyncAccountsResourceWithRawResponse: - def __init__(self, accounts: AsyncAccountsResource) -> None: - self._accounts = accounts +class AsyncUsageResourceWithRawResponse: + def __init__(self, usage: AsyncUsageResource) -> None: + self._usage = usage - self.get_usage = async_to_raw_response_wrapper( - accounts.get_usage, + self.get = async_to_raw_response_wrapper( + usage.get, ) -class AccountsResourceWithStreamingResponse: - def __init__(self, accounts: AccountsResource) -> None: - self._accounts = accounts +class UsageResourceWithStreamingResponse: + def __init__(self, usage: UsageResource) -> None: + self._usage = usage - self.get_usage = to_streamed_response_wrapper( - accounts.get_usage, + self.get = to_streamed_response_wrapper( + usage.get, ) -class AsyncAccountsResourceWithStreamingResponse: - def __init__(self, accounts: AsyncAccountsResource) -> None: - self._accounts = accounts +class AsyncUsageResourceWithStreamingResponse: + def __init__(self, usage: AsyncUsageResource) -> None: + self._usage = usage - self.get_usage = async_to_streamed_response_wrapper( - accounts.get_usage, + self.get = async_to_streamed_response_wrapper( + usage.get, ) diff --git a/src/imagekit/resources/assets.py b/src/imagekit/resources/assets.py new file mode 100644 index 0000000..f2b124c --- /dev/null +++ b/src/imagekit/resources/assets.py @@ -0,0 +1,325 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +import httpx + +from ..types import asset_list_params +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.asset_list_response import AssetListResponse + +__all__ = ["AssetsResource", "AsyncAssetsResource"] + + +class AssetsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> AssetsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AssetsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AssetsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AssetsResourceWithStreamingResponse(self) + + def list( + self, + *, + file_type: Literal["all", "image", "non-image"] | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + path: str | NotGiven = NOT_GIVEN, + search_query: str | NotGiven = NOT_GIVEN, + skip: int | NotGiven = NOT_GIVEN, + sort: Literal[ + "ASC_NAME", + "DESC_NAME", + "ASC_CREATED", + "DESC_CREATED", + "ASC_UPDATED", + "DESC_UPDATED", + "ASC_HEIGHT", + "DESC_HEIGHT", + "ASC_WIDTH", + "DESC_WIDTH", + "ASC_SIZE", + "DESC_SIZE", + "ASC_RELEVANCE", + "DESC_RELEVANCE", + ] + | NotGiven = NOT_GIVEN, + type: Literal["file", "file-version", "folder", "all"] | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> AssetListResponse: + """ + This API can list all the uploaded files and folders in your ImageKit.io media + library. In addition, you can fine-tune your query by specifying various filters + by generating a query string in a Lucene-like syntax and provide this generated + string as the value of the `searchQuery`. + + Args: + file_type: Filter results by file type. + + - `all` — include all file types + - `image` — include only image files + - `non-image` — include only non-image files (e.g., JS, CSS, video) + + limit: The maximum number of results to return in response. + + path: Folder path if you want to limit the search within a specific folder. For + example, `/sales-banner/` will only search in folder sales-banner. + + Note : If your use case involves searching within a folder as well as its + subfolders, you can use `path` parameter in `searchQuery` with appropriate + operator. Checkout + [Supported parameters](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#supported-parameters) + for more information. + + search_query: Query string in a Lucene-like query language e.g. `createdAt > "7d"`. + + Note : When the searchQuery parameter is present, the following query parameters + will have no effect on the result: + + 1. `tags` + 2. `type` + 3. `name` + + [Learn more](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#advanced-search-queries) + from examples. + + skip: The number of results to skip before returning results. + + sort: Sort the results by one of the supported fields in ascending or descending + order. + + type: Filter results by asset type. + + - `file` — returns only files + - `file-version` — returns specific file versions + - `folder` — returns only folders + - `all` — returns both files and folders (excludes `file-version`) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/v1/files", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "file_type": file_type, + "limit": limit, + "path": path, + "search_query": search_query, + "skip": skip, + "sort": sort, + "type": type, + }, + asset_list_params.AssetListParams, + ), + ), + cast_to=AssetListResponse, + ) + + +class AsyncAssetsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncAssetsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncAssetsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAssetsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncAssetsResourceWithStreamingResponse(self) + + async def list( + self, + *, + file_type: Literal["all", "image", "non-image"] | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + path: str | NotGiven = NOT_GIVEN, + search_query: str | NotGiven = NOT_GIVEN, + skip: int | NotGiven = NOT_GIVEN, + sort: Literal[ + "ASC_NAME", + "DESC_NAME", + "ASC_CREATED", + "DESC_CREATED", + "ASC_UPDATED", + "DESC_UPDATED", + "ASC_HEIGHT", + "DESC_HEIGHT", + "ASC_WIDTH", + "DESC_WIDTH", + "ASC_SIZE", + "DESC_SIZE", + "ASC_RELEVANCE", + "DESC_RELEVANCE", + ] + | NotGiven = NOT_GIVEN, + type: Literal["file", "file-version", "folder", "all"] | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> AssetListResponse: + """ + This API can list all the uploaded files and folders in your ImageKit.io media + library. In addition, you can fine-tune your query by specifying various filters + by generating a query string in a Lucene-like syntax and provide this generated + string as the value of the `searchQuery`. + + Args: + file_type: Filter results by file type. + + - `all` — include all file types + - `image` — include only image files + - `non-image` — include only non-image files (e.g., JS, CSS, video) + + limit: The maximum number of results to return in response. + + path: Folder path if you want to limit the search within a specific folder. For + example, `/sales-banner/` will only search in folder sales-banner. + + Note : If your use case involves searching within a folder as well as its + subfolders, you can use `path` parameter in `searchQuery` with appropriate + operator. Checkout + [Supported parameters](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#supported-parameters) + for more information. + + search_query: Query string in a Lucene-like query language e.g. `createdAt > "7d"`. + + Note : When the searchQuery parameter is present, the following query parameters + will have no effect on the result: + + 1. `tags` + 2. `type` + 3. `name` + + [Learn more](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#advanced-search-queries) + from examples. + + skip: The number of results to skip before returning results. + + sort: Sort the results by one of the supported fields in ascending or descending + order. + + type: Filter results by asset type. + + - `file` — returns only files + - `file-version` — returns specific file versions + - `folder` — returns only folders + - `all` — returns both files and folders (excludes `file-version`) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/v1/files", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "file_type": file_type, + "limit": limit, + "path": path, + "search_query": search_query, + "skip": skip, + "sort": sort, + "type": type, + }, + asset_list_params.AssetListParams, + ), + ), + cast_to=AssetListResponse, + ) + + +class AssetsResourceWithRawResponse: + def __init__(self, assets: AssetsResource) -> None: + self._assets = assets + + self.list = to_raw_response_wrapper( + assets.list, + ) + + +class AsyncAssetsResourceWithRawResponse: + def __init__(self, assets: AsyncAssetsResource) -> None: + self._assets = assets + + self.list = async_to_raw_response_wrapper( + assets.list, + ) + + +class AssetsResourceWithStreamingResponse: + def __init__(self, assets: AssetsResource) -> None: + self._assets = assets + + self.list = to_streamed_response_wrapper( + assets.list, + ) + + +class AsyncAssetsResourceWithStreamingResponse: + def __init__(self, assets: AsyncAssetsResource) -> None: + self._assets = assets + + self.list = async_to_streamed_response_wrapper( + assets.list, + ) diff --git a/src/imagekit/resources/beta/__init__.py b/src/imagekit/resources/beta/__init__.py new file mode 100644 index 0000000..08cb3fb --- /dev/null +++ b/src/imagekit/resources/beta/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .v2 import ( + V2Resource, + AsyncV2Resource, + V2ResourceWithRawResponse, + AsyncV2ResourceWithRawResponse, + V2ResourceWithStreamingResponse, + AsyncV2ResourceWithStreamingResponse, +) +from .beta import ( + BetaResource, + AsyncBetaResource, + BetaResourceWithRawResponse, + AsyncBetaResourceWithRawResponse, + BetaResourceWithStreamingResponse, + AsyncBetaResourceWithStreamingResponse, +) + +__all__ = [ + "V2Resource", + "AsyncV2Resource", + "V2ResourceWithRawResponse", + "AsyncV2ResourceWithRawResponse", + "V2ResourceWithStreamingResponse", + "AsyncV2ResourceWithStreamingResponse", + "BetaResource", + "AsyncBetaResource", + "BetaResourceWithRawResponse", + "AsyncBetaResourceWithRawResponse", + "BetaResourceWithStreamingResponse", + "AsyncBetaResourceWithStreamingResponse", +] diff --git a/src/imagekit/resources/beta/beta.py b/src/imagekit/resources/beta/beta.py new file mode 100644 index 0000000..e37c117 --- /dev/null +++ b/src/imagekit/resources/beta/beta.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .v2.v2 import ( + V2Resource, + AsyncV2Resource, + V2ResourceWithRawResponse, + AsyncV2ResourceWithRawResponse, + V2ResourceWithStreamingResponse, + AsyncV2ResourceWithStreamingResponse, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource + +__all__ = ["BetaResource", "AsyncBetaResource"] + + +class BetaResource(SyncAPIResource): + @cached_property + def v2(self) -> V2Resource: + return V2Resource(self._client) + + @cached_property + def with_raw_response(self) -> BetaResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return BetaResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> BetaResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return BetaResourceWithStreamingResponse(self) + + +class AsyncBetaResource(AsyncAPIResource): + @cached_property + def v2(self) -> AsyncV2Resource: + return AsyncV2Resource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncBetaResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncBetaResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncBetaResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncBetaResourceWithStreamingResponse(self) + + +class BetaResourceWithRawResponse: + def __init__(self, beta: BetaResource) -> None: + self._beta = beta + + @cached_property + def v2(self) -> V2ResourceWithRawResponse: + return V2ResourceWithRawResponse(self._beta.v2) + + +class AsyncBetaResourceWithRawResponse: + def __init__(self, beta: AsyncBetaResource) -> None: + self._beta = beta + + @cached_property + def v2(self) -> AsyncV2ResourceWithRawResponse: + return AsyncV2ResourceWithRawResponse(self._beta.v2) + + +class BetaResourceWithStreamingResponse: + def __init__(self, beta: BetaResource) -> None: + self._beta = beta + + @cached_property + def v2(self) -> V2ResourceWithStreamingResponse: + return V2ResourceWithStreamingResponse(self._beta.v2) + + +class AsyncBetaResourceWithStreamingResponse: + def __init__(self, beta: AsyncBetaResource) -> None: + self._beta = beta + + @cached_property + def v2(self) -> AsyncV2ResourceWithStreamingResponse: + return AsyncV2ResourceWithStreamingResponse(self._beta.v2) diff --git a/src/imagekit/resources/beta/v2/__init__.py b/src/imagekit/resources/beta/v2/__init__.py new file mode 100644 index 0000000..6f4e8f3 --- /dev/null +++ b/src/imagekit/resources/beta/v2/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .v2 import ( + V2Resource, + AsyncV2Resource, + V2ResourceWithRawResponse, + AsyncV2ResourceWithRawResponse, + V2ResourceWithStreamingResponse, + AsyncV2ResourceWithStreamingResponse, +) +from .files import ( + FilesResource, + AsyncFilesResource, + FilesResourceWithRawResponse, + AsyncFilesResourceWithRawResponse, + FilesResourceWithStreamingResponse, + AsyncFilesResourceWithStreamingResponse, +) + +__all__ = [ + "FilesResource", + "AsyncFilesResource", + "FilesResourceWithRawResponse", + "AsyncFilesResourceWithRawResponse", + "FilesResourceWithStreamingResponse", + "AsyncFilesResourceWithStreamingResponse", + "V2Resource", + "AsyncV2Resource", + "V2ResourceWithRawResponse", + "AsyncV2ResourceWithRawResponse", + "V2ResourceWithStreamingResponse", + "AsyncV2ResourceWithStreamingResponse", +] diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py new file mode 100644 index 0000000..7d5074a --- /dev/null +++ b/src/imagekit/resources/beta/v2/files.py @@ -0,0 +1,564 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List, Mapping, Iterable, cast +from typing_extensions import Literal + +import httpx + +from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes +from ...._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._base_client import make_request_options +from ....types.beta.v2 import file_upload_params +from ....types.beta.v2.file_upload_response import FileUploadResponse + +__all__ = ["FilesResource", "AsyncFilesResource"] + + +class FilesResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> FilesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return FilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FilesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return FilesResourceWithStreamingResponse(self) + + def upload( + self, + *, + file: FileTypes, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, + tags: List[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadResponse: + """The V2 API enhances security by verifying the entire payload using JWT. + + This API + is in beta. + + ImageKit.io allows you to upload files directly from both the server and client + sides. For server-side uploads, private API key authentication is used. For + client-side uploads, generate a one-time `token` from your secure backend using + private API. + [Learn more](/docs/api-reference/upload-file/upload-file-v2#how-to-implement-secure-client-side-file-upload) + about how to implement secure client-side file upload. + + **File size limit** \\ + On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw + files, and 100MB for videos. On the paid plan, these limits increase to 40MB for + images, audio, and raw files, and 2GB for videos. These limits can be further increased + with higher-tier plans. + + **Version limit** \\ + A file can have a maximum of 100 versions. + + **Demo applications** + + - A full-fledged + [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + supporting file selections from local storage, URL, Dropbox, Google Drive, + Instagram, and more. + - [Quick start guides](/docs/quick-start-guides) for various frameworks and + technologies. + + Args: + file: + The API accepts any of the following: + + - **Binary data** – send the raw bytes as `multipart/form-data`. + - **HTTP / HTTPS URL** – a publicly reachable URL that ImageKit’s servers can + fetch. + - **Base64 string** – the file encoded as a Base64 data URI or plain Base64. + + When supplying a URL, the server must receive the response headers within 8 + seconds; otherwise the request fails with 400 Bad Request. + + file_name: The name with which the file has to be uploaded. + + token: This is the client-generated JSON Web Token (JWT). The ImageKit.io server uses + it to authenticate and check that the upload request parameters have not been + tampered with after the token has been generated. Learn how to create the token + on the page below. This field is only required for authentication when uploading + a file from the client side. + + **Note**: Sending a JWT that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new token. + + **⚠️Warning**: JWT must be generated on the server-side because it is generated + using your account's private API key. This field is required for authentication + when uploading a file from the client-side. + + checks: Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file-v2#upload-api-checks). + + custom_coordinates: Define an important area in the image. This is only relevant for image type + files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + + custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata + fields before setting these values. + + description: Optional text to describe the contents of the file. + + extensions: Array of extensions to be applied to the image. Each extension can be configured + with specific parameters based on the extension type. + + folder: The folder path in which the image has to be uploaded. If the folder(s) didn't + exist before, a new folder(s) is created. Using multiple `/` creates a nested + folder. + + is_private_file: Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + + is_published: Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + + overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + + overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + + overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + + overwrite_tags: If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + + response_fields: Array of response field keys to include in the API response body. + + tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. + + transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + + use_unique_file_name: Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + body = deepcopy_minimal( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "response_fields": response_fields, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + } + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return self._post( + "/api/v2/files/upload" + if self._client._base_url_overridden + else "https://upload.imagekit.io/api/v2/files/upload", + body=maybe_transform(body, file_upload_params.FileUploadParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileUploadResponse, + ) + + +class AsyncFilesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncFilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncFilesResourceWithStreamingResponse(self) + + async def upload( + self, + *, + file: FileTypes, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, + tags: List[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadResponse: + """The V2 API enhances security by verifying the entire payload using JWT. + + This API + is in beta. + + ImageKit.io allows you to upload files directly from both the server and client + sides. For server-side uploads, private API key authentication is used. For + client-side uploads, generate a one-time `token` from your secure backend using + private API. + [Learn more](/docs/api-reference/upload-file/upload-file-v2#how-to-implement-secure-client-side-file-upload) + about how to implement secure client-side file upload. + + **File size limit** \\ + On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw + files, and 100MB for videos. On the paid plan, these limits increase to 40MB for + images, audio, and raw files, and 2GB for videos. These limits can be further increased + with higher-tier plans. + + **Version limit** \\ + A file can have a maximum of 100 versions. + + **Demo applications** + + - A full-fledged + [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + supporting file selections from local storage, URL, Dropbox, Google Drive, + Instagram, and more. + - [Quick start guides](/docs/quick-start-guides) for various frameworks and + technologies. + + Args: + file: + The API accepts any of the following: + + - **Binary data** – send the raw bytes as `multipart/form-data`. + - **HTTP / HTTPS URL** – a publicly reachable URL that ImageKit’s servers can + fetch. + - **Base64 string** – the file encoded as a Base64 data URI or plain Base64. + + When supplying a URL, the server must receive the response headers within 8 + seconds; otherwise the request fails with 400 Bad Request. + + file_name: The name with which the file has to be uploaded. + + token: This is the client-generated JSON Web Token (JWT). The ImageKit.io server uses + it to authenticate and check that the upload request parameters have not been + tampered with after the token has been generated. Learn how to create the token + on the page below. This field is only required for authentication when uploading + a file from the client side. + + **Note**: Sending a JWT that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new token. + + **⚠️Warning**: JWT must be generated on the server-side because it is generated + using your account's private API key. This field is required for authentication + when uploading a file from the client-side. + + checks: Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file-v2#upload-api-checks). + + custom_coordinates: Define an important area in the image. This is only relevant for image type + files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + + custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata + fields before setting these values. + + description: Optional text to describe the contents of the file. + + extensions: Array of extensions to be applied to the image. Each extension can be configured + with specific parameters based on the extension type. + + folder: The folder path in which the image has to be uploaded. If the folder(s) didn't + exist before, a new folder(s) is created. Using multiple `/` creates a nested + folder. + + is_private_file: Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + + is_published: Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + + overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + + overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + + overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + + overwrite_tags: If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + + response_fields: Array of response field keys to include in the API response body. + + tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. + + transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + + use_unique_file_name: Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + body = deepcopy_minimal( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "response_fields": response_fields, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + } + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return await self._post( + "/api/v2/files/upload" + if self._client._base_url_overridden + else "https://upload.imagekit.io/api/v2/files/upload", + body=await async_maybe_transform(body, file_upload_params.FileUploadParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileUploadResponse, + ) + + +class FilesResourceWithRawResponse: + def __init__(self, files: FilesResource) -> None: + self._files = files + + self.upload = to_raw_response_wrapper( + files.upload, + ) + + +class AsyncFilesResourceWithRawResponse: + def __init__(self, files: AsyncFilesResource) -> None: + self._files = files + + self.upload = async_to_raw_response_wrapper( + files.upload, + ) + + +class FilesResourceWithStreamingResponse: + def __init__(self, files: FilesResource) -> None: + self._files = files + + self.upload = to_streamed_response_wrapper( + files.upload, + ) + + +class AsyncFilesResourceWithStreamingResponse: + def __init__(self, files: AsyncFilesResource) -> None: + self._files = files + + self.upload = async_to_streamed_response_wrapper( + files.upload, + ) diff --git a/src/imagekit/resources/beta/v2/v2.py b/src/imagekit/resources/beta/v2/v2.py new file mode 100644 index 0000000..f552e26 --- /dev/null +++ b/src/imagekit/resources/beta/v2/v2.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .files import ( + FilesResource, + AsyncFilesResource, + FilesResourceWithRawResponse, + AsyncFilesResourceWithRawResponse, + FilesResourceWithStreamingResponse, + AsyncFilesResourceWithStreamingResponse, +) +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource + +__all__ = ["V2Resource", "AsyncV2Resource"] + + +class V2Resource(SyncAPIResource): + @cached_property + def files(self) -> FilesResource: + return FilesResource(self._client) + + @cached_property + def with_raw_response(self) -> V2ResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return V2ResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> V2ResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return V2ResourceWithStreamingResponse(self) + + +class AsyncV2Resource(AsyncAPIResource): + @cached_property + def files(self) -> AsyncFilesResource: + return AsyncFilesResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncV2ResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncV2ResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncV2ResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncV2ResourceWithStreamingResponse(self) + + +class V2ResourceWithRawResponse: + def __init__(self, v2: V2Resource) -> None: + self._v2 = v2 + + @cached_property + def files(self) -> FilesResourceWithRawResponse: + return FilesResourceWithRawResponse(self._v2.files) + + +class AsyncV2ResourceWithRawResponse: + def __init__(self, v2: AsyncV2Resource) -> None: + self._v2 = v2 + + @cached_property + def files(self) -> AsyncFilesResourceWithRawResponse: + return AsyncFilesResourceWithRawResponse(self._v2.files) + + +class V2ResourceWithStreamingResponse: + def __init__(self, v2: V2Resource) -> None: + self._v2 = v2 + + @cached_property + def files(self) -> FilesResourceWithStreamingResponse: + return FilesResourceWithStreamingResponse(self._v2.files) + + +class AsyncV2ResourceWithStreamingResponse: + def __init__(self, v2: AsyncV2Resource) -> None: + self._v2 = v2 + + @cached_property + def files(self) -> AsyncFilesResourceWithStreamingResponse: + return AsyncFilesResourceWithStreamingResponse(self._v2.files) diff --git a/src/imagekit/resources/bulk_jobs.py b/src/imagekit/resources/bulk_jobs.py deleted file mode 100644 index 6ba9632..0000000 --- a/src/imagekit/resources/bulk_jobs.py +++ /dev/null @@ -1,397 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import httpx - -from ..types import bulk_job_copy_folder_params, bulk_job_move_folder_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import maybe_transform, async_maybe_transform -from .._compat import cached_property -from .._resource import SyncAPIResource, AsyncAPIResource -from .._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from .._base_client import make_request_options -from ..types.bulk_job_copy_folder_response import BulkJobCopyFolderResponse -from ..types.bulk_job_move_folder_response import BulkJobMoveFolderResponse -from ..types.bulk_job_retrieve_status_response import BulkJobRetrieveStatusResponse - -__all__ = ["BulkJobsResource", "AsyncBulkJobsResource"] - - -class BulkJobsResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> BulkJobsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers - """ - return BulkJobsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> BulkJobsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response - """ - return BulkJobsResourceWithStreamingResponse(self) - - def copy_folder( - self, - *, - destination_path: str, - source_folder_path: str, - include_versions: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> BulkJobCopyFolderResponse: - """This will copy one folder into another. - - The selected folder, its nested folders, - files, and their versions (in `includeVersions` is set to true) are copied in - this operation. Note: If any file at the destination has the same name as the - source file, then the source file and its versions will be appended to the - destination file version history. - - Args: - destination_path: Full path to the destination folder where you want to copy the source folder - into. - - source_folder_path: The full path to the source folder you want to copy. - - include_versions: Option to copy all versions of files that are nested inside the selected folder. - By default, only the current version of each file will be copied. When set to - true, all versions of each file will be copied. Default value - `false`. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/v1/bulkJobs/copyFolder", - body=maybe_transform( - { - "destination_path": destination_path, - "source_folder_path": source_folder_path, - "include_versions": include_versions, - }, - bulk_job_copy_folder_params.BulkJobCopyFolderParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=BulkJobCopyFolderResponse, - ) - - def move_folder( - self, - *, - destination_path: str, - source_folder_path: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> BulkJobMoveFolderResponse: - """This will move one folder into another. - - The selected folder, its nested folders, - files, and their versions are moved in this operation. Note: If any file at the - destination has the same name as the source file, then the source file and its - versions will be appended to the destination file version history. - - Args: - destination_path: Full path to the destination folder where you want to move the source folder - into. - - source_folder_path: The full path to the source folder you want to move. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/v1/bulkJobs/moveFolder", - body=maybe_transform( - { - "destination_path": destination_path, - "source_folder_path": source_folder_path, - }, - bulk_job_move_folder_params.BulkJobMoveFolderParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=BulkJobMoveFolderResponse, - ) - - def retrieve_status( - self, - job_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> BulkJobRetrieveStatusResponse: - """ - This API returns the status of a bulk job like copy and move folder operations. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not job_id: - raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}") - return self._get( - f"/v1/bulkJobs/{job_id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=BulkJobRetrieveStatusResponse, - ) - - -class AsyncBulkJobsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncBulkJobsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers - """ - return AsyncBulkJobsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncBulkJobsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response - """ - return AsyncBulkJobsResourceWithStreamingResponse(self) - - async def copy_folder( - self, - *, - destination_path: str, - source_folder_path: str, - include_versions: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> BulkJobCopyFolderResponse: - """This will copy one folder into another. - - The selected folder, its nested folders, - files, and their versions (in `includeVersions` is set to true) are copied in - this operation. Note: If any file at the destination has the same name as the - source file, then the source file and its versions will be appended to the - destination file version history. - - Args: - destination_path: Full path to the destination folder where you want to copy the source folder - into. - - source_folder_path: The full path to the source folder you want to copy. - - include_versions: Option to copy all versions of files that are nested inside the selected folder. - By default, only the current version of each file will be copied. When set to - true, all versions of each file will be copied. Default value - `false`. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/v1/bulkJobs/copyFolder", - body=await async_maybe_transform( - { - "destination_path": destination_path, - "source_folder_path": source_folder_path, - "include_versions": include_versions, - }, - bulk_job_copy_folder_params.BulkJobCopyFolderParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=BulkJobCopyFolderResponse, - ) - - async def move_folder( - self, - *, - destination_path: str, - source_folder_path: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> BulkJobMoveFolderResponse: - """This will move one folder into another. - - The selected folder, its nested folders, - files, and their versions are moved in this operation. Note: If any file at the - destination has the same name as the source file, then the source file and its - versions will be appended to the destination file version history. - - Args: - destination_path: Full path to the destination folder where you want to move the source folder - into. - - source_folder_path: The full path to the source folder you want to move. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/v1/bulkJobs/moveFolder", - body=await async_maybe_transform( - { - "destination_path": destination_path, - "source_folder_path": source_folder_path, - }, - bulk_job_move_folder_params.BulkJobMoveFolderParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=BulkJobMoveFolderResponse, - ) - - async def retrieve_status( - self, - job_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> BulkJobRetrieveStatusResponse: - """ - This API returns the status of a bulk job like copy and move folder operations. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not job_id: - raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}") - return await self._get( - f"/v1/bulkJobs/{job_id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=BulkJobRetrieveStatusResponse, - ) - - -class BulkJobsResourceWithRawResponse: - def __init__(self, bulk_jobs: BulkJobsResource) -> None: - self._bulk_jobs = bulk_jobs - - self.copy_folder = to_raw_response_wrapper( - bulk_jobs.copy_folder, - ) - self.move_folder = to_raw_response_wrapper( - bulk_jobs.move_folder, - ) - self.retrieve_status = to_raw_response_wrapper( - bulk_jobs.retrieve_status, - ) - - -class AsyncBulkJobsResourceWithRawResponse: - def __init__(self, bulk_jobs: AsyncBulkJobsResource) -> None: - self._bulk_jobs = bulk_jobs - - self.copy_folder = async_to_raw_response_wrapper( - bulk_jobs.copy_folder, - ) - self.move_folder = async_to_raw_response_wrapper( - bulk_jobs.move_folder, - ) - self.retrieve_status = async_to_raw_response_wrapper( - bulk_jobs.retrieve_status, - ) - - -class BulkJobsResourceWithStreamingResponse: - def __init__(self, bulk_jobs: BulkJobsResource) -> None: - self._bulk_jobs = bulk_jobs - - self.copy_folder = to_streamed_response_wrapper( - bulk_jobs.copy_folder, - ) - self.move_folder = to_streamed_response_wrapper( - bulk_jobs.move_folder, - ) - self.retrieve_status = to_streamed_response_wrapper( - bulk_jobs.retrieve_status, - ) - - -class AsyncBulkJobsResourceWithStreamingResponse: - def __init__(self, bulk_jobs: AsyncBulkJobsResource) -> None: - self._bulk_jobs = bulk_jobs - - self.copy_folder = async_to_streamed_response_wrapper( - bulk_jobs.copy_folder, - ) - self.move_folder = async_to_streamed_response_wrapper( - bulk_jobs.move_folder, - ) - self.retrieve_status = async_to_streamed_response_wrapper( - bulk_jobs.retrieve_status, - ) diff --git a/src/imagekit/resources/cache/__init__.py b/src/imagekit/resources/cache/__init__.py new file mode 100644 index 0000000..f7e5a70 --- /dev/null +++ b/src/imagekit/resources/cache/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .cache import ( + CacheResource, + AsyncCacheResource, + CacheResourceWithRawResponse, + AsyncCacheResourceWithRawResponse, + CacheResourceWithStreamingResponse, + AsyncCacheResourceWithStreamingResponse, +) +from .invalidation import ( + InvalidationResource, + AsyncInvalidationResource, + InvalidationResourceWithRawResponse, + AsyncInvalidationResourceWithRawResponse, + InvalidationResourceWithStreamingResponse, + AsyncInvalidationResourceWithStreamingResponse, +) + +__all__ = [ + "InvalidationResource", + "AsyncInvalidationResource", + "InvalidationResourceWithRawResponse", + "AsyncInvalidationResourceWithRawResponse", + "InvalidationResourceWithStreamingResponse", + "AsyncInvalidationResourceWithStreamingResponse", + "CacheResource", + "AsyncCacheResource", + "CacheResourceWithRawResponse", + "AsyncCacheResourceWithRawResponse", + "CacheResourceWithStreamingResponse", + "AsyncCacheResourceWithStreamingResponse", +] diff --git a/src/imagekit/resources/cache/cache.py b/src/imagekit/resources/cache/cache.py new file mode 100644 index 0000000..47016b0 --- /dev/null +++ b/src/imagekit/resources/cache/cache.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from .invalidation import ( + InvalidationResource, + AsyncInvalidationResource, + InvalidationResourceWithRawResponse, + AsyncInvalidationResourceWithRawResponse, + InvalidationResourceWithStreamingResponse, + AsyncInvalidationResourceWithStreamingResponse, +) + +__all__ = ["CacheResource", "AsyncCacheResource"] + + +class CacheResource(SyncAPIResource): + @cached_property + def invalidation(self) -> InvalidationResource: + return InvalidationResource(self._client) + + @cached_property + def with_raw_response(self) -> CacheResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return CacheResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CacheResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return CacheResourceWithStreamingResponse(self) + + +class AsyncCacheResource(AsyncAPIResource): + @cached_property + def invalidation(self) -> AsyncInvalidationResource: + return AsyncInvalidationResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncCacheResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncCacheResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCacheResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncCacheResourceWithStreamingResponse(self) + + +class CacheResourceWithRawResponse: + def __init__(self, cache: CacheResource) -> None: + self._cache = cache + + @cached_property + def invalidation(self) -> InvalidationResourceWithRawResponse: + return InvalidationResourceWithRawResponse(self._cache.invalidation) + + +class AsyncCacheResourceWithRawResponse: + def __init__(self, cache: AsyncCacheResource) -> None: + self._cache = cache + + @cached_property + def invalidation(self) -> AsyncInvalidationResourceWithRawResponse: + return AsyncInvalidationResourceWithRawResponse(self._cache.invalidation) + + +class CacheResourceWithStreamingResponse: + def __init__(self, cache: CacheResource) -> None: + self._cache = cache + + @cached_property + def invalidation(self) -> InvalidationResourceWithStreamingResponse: + return InvalidationResourceWithStreamingResponse(self._cache.invalidation) + + +class AsyncCacheResourceWithStreamingResponse: + def __init__(self, cache: AsyncCacheResource) -> None: + self._cache = cache + + @cached_property + def invalidation(self) -> AsyncInvalidationResourceWithStreamingResponse: + return AsyncInvalidationResourceWithStreamingResponse(self._cache.invalidation) diff --git a/src/imagekit/resources/files/purge.py b/src/imagekit/resources/cache/invalidation.py similarity index 70% rename from src/imagekit/resources/files/purge.py rename to src/imagekit/resources/cache/invalidation.py index 6282979..48d9a2c 100644 --- a/src/imagekit/resources/files/purge.py +++ b/src/imagekit/resources/cache/invalidation.py @@ -14,35 +14,35 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ...types.files import purge_execute_params +from ...types.cache import invalidation_create_params from ..._base_client import make_request_options -from ...types.files.purge_status_response import PurgeStatusResponse -from ...types.files.purge_execute_response import PurgeExecuteResponse +from ...types.cache.invalidation_get_response import InvalidationGetResponse +from ...types.cache.invalidation_create_response import InvalidationCreateResponse -__all__ = ["PurgeResource", "AsyncPurgeResource"] +__all__ = ["InvalidationResource", "AsyncInvalidationResource"] -class PurgeResource(SyncAPIResource): +class InvalidationResource(SyncAPIResource): @cached_property - def with_raw_response(self) -> PurgeResourceWithRawResponse: + def with_raw_response(self) -> InvalidationResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ - return PurgeResourceWithRawResponse(self) + return InvalidationResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> PurgeResourceWithStreamingResponse: + def with_streaming_response(self) -> InvalidationResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ - return PurgeResourceWithStreamingResponse(self) + return InvalidationResourceWithStreamingResponse(self) - def execute( + def create( self, *, url: str, @@ -52,7 +52,7 @@ def execute( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> PurgeExecuteResponse: + ) -> InvalidationCreateResponse: """This API will purge CDN cache and ImageKit.io's internal cache for a file. Note: @@ -72,14 +72,14 @@ def execute( """ return self._post( "/v1/files/purge", - body=maybe_transform({"url": url}, purge_execute_params.PurgeExecuteParams), + body=maybe_transform({"url": url}, invalidation_create_params.InvalidationCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=PurgeExecuteResponse, + cast_to=InvalidationCreateResponse, ) - def status( + def get( self, request_id: str, *, @@ -89,7 +89,7 @@ def status( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> PurgeStatusResponse: + ) -> InvalidationGetResponse: """ This API returns the status of a purge cache request. @@ -109,31 +109,31 @@ def status( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=PurgeStatusResponse, + cast_to=InvalidationGetResponse, ) -class AsyncPurgeResource(AsyncAPIResource): +class AsyncInvalidationResource(AsyncAPIResource): @cached_property - def with_raw_response(self) -> AsyncPurgeResourceWithRawResponse: + def with_raw_response(self) -> AsyncInvalidationResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ - return AsyncPurgeResourceWithRawResponse(self) + return AsyncInvalidationResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AsyncPurgeResourceWithStreamingResponse: + def with_streaming_response(self) -> AsyncInvalidationResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ - return AsyncPurgeResourceWithStreamingResponse(self) + return AsyncInvalidationResourceWithStreamingResponse(self) - async def execute( + async def create( self, *, url: str, @@ -143,7 +143,7 @@ async def execute( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> PurgeExecuteResponse: + ) -> InvalidationCreateResponse: """This API will purge CDN cache and ImageKit.io's internal cache for a file. Note: @@ -163,14 +163,14 @@ async def execute( """ return await self._post( "/v1/files/purge", - body=await async_maybe_transform({"url": url}, purge_execute_params.PurgeExecuteParams), + body=await async_maybe_transform({"url": url}, invalidation_create_params.InvalidationCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=PurgeExecuteResponse, + cast_to=InvalidationCreateResponse, ) - async def status( + async def get( self, request_id: str, *, @@ -180,7 +180,7 @@ async def status( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> PurgeStatusResponse: + ) -> InvalidationGetResponse: """ This API returns the status of a purge cache request. @@ -200,53 +200,53 @@ async def status( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=PurgeStatusResponse, + cast_to=InvalidationGetResponse, ) -class PurgeResourceWithRawResponse: - def __init__(self, purge: PurgeResource) -> None: - self._purge = purge +class InvalidationResourceWithRawResponse: + def __init__(self, invalidation: InvalidationResource) -> None: + self._invalidation = invalidation - self.execute = to_raw_response_wrapper( - purge.execute, + self.create = to_raw_response_wrapper( + invalidation.create, ) - self.status = to_raw_response_wrapper( - purge.status, + self.get = to_raw_response_wrapper( + invalidation.get, ) -class AsyncPurgeResourceWithRawResponse: - def __init__(self, purge: AsyncPurgeResource) -> None: - self._purge = purge +class AsyncInvalidationResourceWithRawResponse: + def __init__(self, invalidation: AsyncInvalidationResource) -> None: + self._invalidation = invalidation - self.execute = async_to_raw_response_wrapper( - purge.execute, + self.create = async_to_raw_response_wrapper( + invalidation.create, ) - self.status = async_to_raw_response_wrapper( - purge.status, + self.get = async_to_raw_response_wrapper( + invalidation.get, ) -class PurgeResourceWithStreamingResponse: - def __init__(self, purge: PurgeResource) -> None: - self._purge = purge +class InvalidationResourceWithStreamingResponse: + def __init__(self, invalidation: InvalidationResource) -> None: + self._invalidation = invalidation - self.execute = to_streamed_response_wrapper( - purge.execute, + self.create = to_streamed_response_wrapper( + invalidation.create, ) - self.status = to_streamed_response_wrapper( - purge.status, + self.get = to_streamed_response_wrapper( + invalidation.get, ) -class AsyncPurgeResourceWithStreamingResponse: - def __init__(self, purge: AsyncPurgeResource) -> None: - self._purge = purge +class AsyncInvalidationResourceWithStreamingResponse: + def __init__(self, invalidation: AsyncInvalidationResource) -> None: + self._invalidation = invalidation - self.execute = async_to_streamed_response_wrapper( - purge.execute, + self.create = async_to_streamed_response_wrapper( + invalidation.create, ) - self.status = async_to_streamed_response_wrapper( - purge.status, + self.get = async_to_streamed_response_wrapper( + invalidation.get, ) diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py index acdbc6b..ce4e096 100644 --- a/src/imagekit/resources/custom_metadata_fields.py +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -170,8 +170,7 @@ def list( fields in the API response. Args: - include_deleted: Set it to `true` to include deleted field objects in the API response. Default - value is `false`. + include_deleted: Set it to `true` to include deleted field objects in the API response. extra_headers: Send extra headers @@ -375,8 +374,7 @@ async def list( fields in the API response. Args: - include_deleted: Set it to `true` to include deleted field objects in the API response. Default - value is `false`. + include_deleted: Set it to `true` to include deleted field objects in the API response. extra_headers: Send extra headers diff --git a/src/imagekit/resources/files/__init__.py b/src/imagekit/resources/files/__init__.py index 55cfc51..7fdf519 100644 --- a/src/imagekit/resources/files/__init__.py +++ b/src/imagekit/resources/files/__init__.py @@ -1,12 +1,12 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .batch import ( - BatchResource, - AsyncBatchResource, - BatchResourceWithRawResponse, - AsyncBatchResourceWithRawResponse, - BatchResourceWithStreamingResponse, - AsyncBatchResourceWithStreamingResponse, +from .bulk import ( + BulkResource, + AsyncBulkResource, + BulkResourceWithRawResponse, + AsyncBulkResourceWithRawResponse, + BulkResourceWithStreamingResponse, + AsyncBulkResourceWithStreamingResponse, ) from .files import ( FilesResource, @@ -16,22 +16,6 @@ FilesResourceWithStreamingResponse, AsyncFilesResourceWithStreamingResponse, ) -from .purge import ( - PurgeResource, - AsyncPurgeResource, - PurgeResourceWithRawResponse, - AsyncPurgeResourceWithRawResponse, - PurgeResourceWithStreamingResponse, - AsyncPurgeResourceWithStreamingResponse, -) -from .details import ( - DetailsResource, - AsyncDetailsResource, - DetailsResourceWithRawResponse, - AsyncDetailsResourceWithRawResponse, - DetailsResourceWithStreamingResponse, - AsyncDetailsResourceWithStreamingResponse, -) from .metadata import ( MetadataResource, AsyncMetadataResource, @@ -50,30 +34,18 @@ ) __all__ = [ - "DetailsResource", - "AsyncDetailsResource", - "DetailsResourceWithRawResponse", - "AsyncDetailsResourceWithRawResponse", - "DetailsResourceWithStreamingResponse", - "AsyncDetailsResourceWithStreamingResponse", - "BatchResource", - "AsyncBatchResource", - "BatchResourceWithRawResponse", - "AsyncBatchResourceWithRawResponse", - "BatchResourceWithStreamingResponse", - "AsyncBatchResourceWithStreamingResponse", + "BulkResource", + "AsyncBulkResource", + "BulkResourceWithRawResponse", + "AsyncBulkResourceWithRawResponse", + "BulkResourceWithStreamingResponse", + "AsyncBulkResourceWithStreamingResponse", "VersionsResource", "AsyncVersionsResource", "VersionsResourceWithRawResponse", "AsyncVersionsResourceWithRawResponse", "VersionsResourceWithStreamingResponse", "AsyncVersionsResourceWithStreamingResponse", - "PurgeResource", - "AsyncPurgeResource", - "PurgeResourceWithRawResponse", - "AsyncPurgeResourceWithRawResponse", - "PurgeResourceWithStreamingResponse", - "AsyncPurgeResourceWithStreamingResponse", "MetadataResource", "AsyncMetadataResource", "MetadataResourceWithRawResponse", diff --git a/src/imagekit/resources/files/bulk.py b/src/imagekit/resources/files/bulk.py new file mode 100644 index 0000000..1ba19cf --- /dev/null +++ b/src/imagekit/resources/files/bulk.py @@ -0,0 +1,490 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.files import bulk_delete_params, bulk_add_tags_params, bulk_remove_tags_params, bulk_remove_ai_tags_params +from ..._base_client import make_request_options +from ...types.files.bulk_delete_response import BulkDeleteResponse +from ...types.files.bulk_add_tags_response import BulkAddTagsResponse +from ...types.files.bulk_remove_tags_response import BulkRemoveTagsResponse +from ...types.files.bulk_remove_ai_tags_response import BulkRemoveAITagsResponse + +__all__ = ["BulkResource", "AsyncBulkResource"] + + +class BulkResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> BulkResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return BulkResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> BulkResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return BulkResourceWithStreamingResponse(self) + + def delete( + self, + *, + file_ids: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkDeleteResponse: + """ + This API deletes multiple files and all their file versions permanently. + + Note: If a file or specific transformation has been requested in the past, then + the response is cached. Deleting a file does not purge the cache. You can purge + the cache using purge cache API. + + A maximum of 100 files can be deleted at a time. + + Args: + file_ids: An array of fileIds which you want to delete. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/batch/deleteByFileIds", + body=maybe_transform({"file_ids": file_ids}, bulk_delete_params.BulkDeleteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkDeleteResponse, + ) + + def add_tags( + self, + *, + file_ids: List[str], + tags: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkAddTagsResponse: + """This API adds tags to multiple files in bulk. + + A maximum of 50 files can be + specified at a time. + + Args: + file_ids: An array of fileIds to which you want to add tags. + + tags: An array of tags that you want to add to the files. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/addTags", + body=maybe_transform( + { + "file_ids": file_ids, + "tags": tags, + }, + bulk_add_tags_params.BulkAddTagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkAddTagsResponse, + ) + + def remove_ai_tags( + self, + *, + ai_tags: List[str], + file_ids: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkRemoveAITagsResponse: + """This API removes AITags from multiple files in bulk. + + A maximum of 50 files can + be specified at a time. + + Args: + ai_tags: An array of AITags that you want to remove from the files. + + file_ids: An array of fileIds from which you want to remove AITags. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/removeAITags", + body=maybe_transform( + { + "ai_tags": ai_tags, + "file_ids": file_ids, + }, + bulk_remove_ai_tags_params.BulkRemoveAITagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkRemoveAITagsResponse, + ) + + def remove_tags( + self, + *, + file_ids: List[str], + tags: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkRemoveTagsResponse: + """This API removes tags from multiple files in bulk. + + A maximum of 50 files can be + specified at a time. + + Args: + file_ids: An array of fileIds from which you want to remove tags. + + tags: An array of tags that you want to remove from the files. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/files/removeTags", + body=maybe_transform( + { + "file_ids": file_ids, + "tags": tags, + }, + bulk_remove_tags_params.BulkRemoveTagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkRemoveTagsResponse, + ) + + +class AsyncBulkResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncBulkResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncBulkResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncBulkResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncBulkResourceWithStreamingResponse(self) + + async def delete( + self, + *, + file_ids: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkDeleteResponse: + """ + This API deletes multiple files and all their file versions permanently. + + Note: If a file or specific transformation has been requested in the past, then + the response is cached. Deleting a file does not purge the cache. You can purge + the cache using purge cache API. + + A maximum of 100 files can be deleted at a time. + + Args: + file_ids: An array of fileIds which you want to delete. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/batch/deleteByFileIds", + body=await async_maybe_transform({"file_ids": file_ids}, bulk_delete_params.BulkDeleteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkDeleteResponse, + ) + + async def add_tags( + self, + *, + file_ids: List[str], + tags: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkAddTagsResponse: + """This API adds tags to multiple files in bulk. + + A maximum of 50 files can be + specified at a time. + + Args: + file_ids: An array of fileIds to which you want to add tags. + + tags: An array of tags that you want to add to the files. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/addTags", + body=await async_maybe_transform( + { + "file_ids": file_ids, + "tags": tags, + }, + bulk_add_tags_params.BulkAddTagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkAddTagsResponse, + ) + + async def remove_ai_tags( + self, + *, + ai_tags: List[str], + file_ids: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkRemoveAITagsResponse: + """This API removes AITags from multiple files in bulk. + + A maximum of 50 files can + be specified at a time. + + Args: + ai_tags: An array of AITags that you want to remove from the files. + + file_ids: An array of fileIds from which you want to remove AITags. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/removeAITags", + body=await async_maybe_transform( + { + "ai_tags": ai_tags, + "file_ids": file_ids, + }, + bulk_remove_ai_tags_params.BulkRemoveAITagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkRemoveAITagsResponse, + ) + + async def remove_tags( + self, + *, + file_ids: List[str], + tags: List[str], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> BulkRemoveTagsResponse: + """This API removes tags from multiple files in bulk. + + A maximum of 50 files can be + specified at a time. + + Args: + file_ids: An array of fileIds from which you want to remove tags. + + tags: An array of tags that you want to remove from the files. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/files/removeTags", + body=await async_maybe_transform( + { + "file_ids": file_ids, + "tags": tags, + }, + bulk_remove_tags_params.BulkRemoveTagsParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkRemoveTagsResponse, + ) + + +class BulkResourceWithRawResponse: + def __init__(self, bulk: BulkResource) -> None: + self._bulk = bulk + + self.delete = to_raw_response_wrapper( + bulk.delete, + ) + self.add_tags = to_raw_response_wrapper( + bulk.add_tags, + ) + self.remove_ai_tags = to_raw_response_wrapper( + bulk.remove_ai_tags, + ) + self.remove_tags = to_raw_response_wrapper( + bulk.remove_tags, + ) + + +class AsyncBulkResourceWithRawResponse: + def __init__(self, bulk: AsyncBulkResource) -> None: + self._bulk = bulk + + self.delete = async_to_raw_response_wrapper( + bulk.delete, + ) + self.add_tags = async_to_raw_response_wrapper( + bulk.add_tags, + ) + self.remove_ai_tags = async_to_raw_response_wrapper( + bulk.remove_ai_tags, + ) + self.remove_tags = async_to_raw_response_wrapper( + bulk.remove_tags, + ) + + +class BulkResourceWithStreamingResponse: + def __init__(self, bulk: BulkResource) -> None: + self._bulk = bulk + + self.delete = to_streamed_response_wrapper( + bulk.delete, + ) + self.add_tags = to_streamed_response_wrapper( + bulk.add_tags, + ) + self.remove_ai_tags = to_streamed_response_wrapper( + bulk.remove_ai_tags, + ) + self.remove_tags = to_streamed_response_wrapper( + bulk.remove_tags, + ) + + +class AsyncBulkResourceWithStreamingResponse: + def __init__(self, bulk: AsyncBulkResource) -> None: + self._bulk = bulk + + self.delete = async_to_streamed_response_wrapper( + bulk.delete, + ) + self.add_tags = async_to_streamed_response_wrapper( + bulk.add_tags, + ) + self.remove_ai_tags = async_to_streamed_response_wrapper( + bulk.remove_ai_tags, + ) + self.remove_tags = async_to_streamed_response_wrapper( + bulk.remove_tags, + ) diff --git a/src/imagekit/resources/files/details.py b/src/imagekit/resources/files/details.py deleted file mode 100644 index 234d2ab..0000000 --- a/src/imagekit/resources/files/details.py +++ /dev/null @@ -1,447 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import List, Union, Iterable, Optional -from typing_extensions import Literal, overload - -import httpx - -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ..._utils import maybe_transform, async_maybe_transform -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...types.files import detail_update_params -from ..._base_client import make_request_options -from ...types.files.detail_update_response import DetailUpdateResponse -from ...types.files.detail_retrieve_response import DetailRetrieveResponse - -__all__ = ["DetailsResource", "AsyncDetailsResource"] - - -class DetailsResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> DetailsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers - """ - return DetailsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> DetailsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response - """ - return DetailsResourceWithStreamingResponse(self) - - def retrieve( - self, - file_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> DetailRetrieveResponse: - """ - This API returns an object with details or attributes about the current version - of the file. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not file_id: - raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - return self._get( - f"/v1/files/{file_id}/details", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=DetailRetrieveResponse, - ) - - @overload - def update( - self, - file_id: str, - *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: object | NotGiven = NOT_GIVEN, - extensions: Iterable[detail_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> DetailUpdateResponse: - """ - This API updates the details or attributes of the current version of the file. - You can update `tags`, `customCoordinates`, `customMetadata`, publication - status, remove existing `AITags` and apply extensions using this API. - - Args: - custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. - `10,10,100,100`. Send `null` to unset this value. - - custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` - value for that key. Before setting any custom metadata on an asset you have to - create the field using custom metadata fields API. - - extensions: Array of extensions to be applied to the asset. Each extension can be configured - with specific parameters based on the extension type. - - remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. - `["car", "vehicle", "motorsports"]`. - - If you want to remove all AITags associated with the file, send a string - - "all". - - Note: The remove operation for `AITags` executes before any of the `extensions` - are processed. - - tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send - `null` to unset all tags associated with the file. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - file_id: str, - *, - publish: detail_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> DetailUpdateResponse: - """ - This API updates the details or attributes of the current version of the file. - You can update `tags`, `customCoordinates`, `customMetadata`, publication - status, remove existing `AITags` and apply extensions using this API. - - Args: - publish: Configure the publication status of a file and its versions. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - def update( - self, - file_id: str, - *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: object | NotGiven = NOT_GIVEN, - extensions: Iterable[detail_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - publish: detail_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> DetailUpdateResponse: - if not file_id: - raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - return self._patch( - f"/v1/files/{file_id}/details", - body=maybe_transform( - { - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "extensions": extensions, - "remove_ai_tags": remove_ai_tags, - "tags": tags, - "webhook_url": webhook_url, - "publish": publish, - }, - detail_update_params.DetailUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=DetailUpdateResponse, - ) - - -class AsyncDetailsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncDetailsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers - """ - return AsyncDetailsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncDetailsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response - """ - return AsyncDetailsResourceWithStreamingResponse(self) - - async def retrieve( - self, - file_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> DetailRetrieveResponse: - """ - This API returns an object with details or attributes about the current version - of the file. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not file_id: - raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - return await self._get( - f"/v1/files/{file_id}/details", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=DetailRetrieveResponse, - ) - - @overload - async def update( - self, - file_id: str, - *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: object | NotGiven = NOT_GIVEN, - extensions: Iterable[detail_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> DetailUpdateResponse: - """ - This API updates the details or attributes of the current version of the file. - You can update `tags`, `customCoordinates`, `customMetadata`, publication - status, remove existing `AITags` and apply extensions using this API. - - Args: - custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. - `10,10,100,100`. Send `null` to unset this value. - - custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` - value for that key. Before setting any custom metadata on an asset you have to - create the field using custom metadata fields API. - - extensions: Array of extensions to be applied to the asset. Each extension can be configured - with specific parameters based on the extension type. - - remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. - `["car", "vehicle", "motorsports"]`. - - If you want to remove all AITags associated with the file, send a string - - "all". - - Note: The remove operation for `AITags` executes before any of the `extensions` - are processed. - - tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send - `null` to unset all tags associated with the file. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def update( - self, - file_id: str, - *, - publish: detail_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> DetailUpdateResponse: - """ - This API updates the details or attributes of the current version of the file. - You can update `tags`, `customCoordinates`, `customMetadata`, publication - status, remove existing `AITags` and apply extensions using this API. - - Args: - publish: Configure the publication status of a file and its versions. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - async def update( - self, - file_id: str, - *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: object | NotGiven = NOT_GIVEN, - extensions: Iterable[detail_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - publish: detail_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> DetailUpdateResponse: - if not file_id: - raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - return await self._patch( - f"/v1/files/{file_id}/details", - body=await async_maybe_transform( - { - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "extensions": extensions, - "remove_ai_tags": remove_ai_tags, - "tags": tags, - "webhook_url": webhook_url, - "publish": publish, - }, - detail_update_params.DetailUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=DetailUpdateResponse, - ) - - -class DetailsResourceWithRawResponse: - def __init__(self, details: DetailsResource) -> None: - self._details = details - - self.retrieve = to_raw_response_wrapper( - details.retrieve, - ) - self.update = to_raw_response_wrapper( - details.update, - ) - - -class AsyncDetailsResourceWithRawResponse: - def __init__(self, details: AsyncDetailsResource) -> None: - self._details = details - - self.retrieve = async_to_raw_response_wrapper( - details.retrieve, - ) - self.update = async_to_raw_response_wrapper( - details.update, - ) - - -class DetailsResourceWithStreamingResponse: - def __init__(self, details: DetailsResource) -> None: - self._details = details - - self.retrieve = to_streamed_response_wrapper( - details.retrieve, - ) - self.update = to_streamed_response_wrapper( - details.update, - ) - - -class AsyncDetailsResourceWithStreamingResponse: - def __init__(self, details: AsyncDetailsResource) -> None: - self._details = details - - self.retrieve = async_to_streamed_response_wrapper( - details.retrieve, - ) - self.update = async_to_streamed_response_wrapper( - details.update, - ) diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 52db743..8e3a2a2 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -2,48 +2,22 @@ from __future__ import annotations -from typing import List -from typing_extensions import Literal +from typing import Dict, List, Union, Mapping, Iterable, Optional, cast +from typing_extensions import Literal, overload import httpx -from .batch import ( - BatchResource, - AsyncBatchResource, - BatchResourceWithRawResponse, - AsyncBatchResourceWithRawResponse, - BatchResourceWithStreamingResponse, - AsyncBatchResourceWithStreamingResponse, +from .bulk import ( + BulkResource, + AsyncBulkResource, + BulkResourceWithRawResponse, + AsyncBulkResourceWithRawResponse, + BulkResourceWithStreamingResponse, + AsyncBulkResourceWithStreamingResponse, ) -from .purge import ( - PurgeResource, - AsyncPurgeResource, - PurgeResourceWithRawResponse, - AsyncPurgeResourceWithRawResponse, - PurgeResourceWithStreamingResponse, - AsyncPurgeResourceWithStreamingResponse, -) -from ...types import ( - file_copy_params, - file_list_params, - file_move_params, - file_rename_params, - file_add_tags_params, - file_upload_v1_params, - file_upload_v2_params, - file_remove_tags_params, - file_remove_ai_tags_params, -) -from .details import ( - DetailsResource, - AsyncDetailsResource, - DetailsResourceWithRawResponse, - AsyncDetailsResourceWithRawResponse, - DetailsResourceWithStreamingResponse, - AsyncDetailsResourceWithStreamingResponse, -) -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from ..._utils import maybe_transform, async_maybe_transform +from ...types import file_copy_params, file_move_params, file_rename_params, file_update_params, file_upload_params +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes +from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from .metadata import ( MetadataResource, AsyncMetadataResource, @@ -69,34 +43,23 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options -from ...types.file_list_response import FileListResponse +from ...types.file_get_response import FileGetResponse from ...types.file_rename_response import FileRenameResponse -from ...types.file_add_tags_response import FileAddTagsResponse -from ...types.file_upload_v1_response import FileUploadV1Response -from ...types.file_upload_v2_response import FileUploadV2Response -from ...types.file_remove_tags_response import FileRemoveTagsResponse -from ...types.file_remove_ai_tags_response import FileRemoveAITagsResponse +from ...types.file_update_response import FileUpdateResponse +from ...types.file_upload_response import FileUploadResponse __all__ = ["FilesResource", "AsyncFilesResource"] class FilesResource(SyncAPIResource): @cached_property - def details(self) -> DetailsResource: - return DetailsResource(self._client) - - @cached_property - def batch(self) -> BatchResource: - return BatchResource(self._client) + def bulk(self) -> BulkResource: + return BulkResource(self._client) @cached_property def versions(self) -> VersionsResource: return VersionsResource(self._client) - @cached_property - def purge(self) -> PurgeResource: - return PurgeResource(self._client) - @cached_property def metadata(self) -> MetadataResource: return MetadataResource(self._client) @@ -120,87 +83,59 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ return FilesResourceWithStreamingResponse(self) - def list( + @overload + def update( self, + file_id: str, *, - file_type: str | NotGiven = NOT_GIVEN, - limit: str | NotGiven = NOT_GIVEN, - path: str | NotGiven = NOT_GIVEN, - search_query: str | NotGiven = NOT_GIVEN, - skip: str | NotGiven = NOT_GIVEN, - sort: str | NotGiven = NOT_GIVEN, - type: Literal["file", "file-version", "folder", "all"] | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: object | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileListResponse: + ) -> FileUpdateResponse: """ - This API can list all the uploaded files and folders in your ImageKit.io media - library. In addition, you can fine-tune your query by specifying various filters - by generating a query string in a Lucene-like syntax and provide this generated - string as the value of the `searchQuery`. + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. Args: - file_type: - Type of files to include in the result set. Accepts three values: - - `all` - include all types of files in the result set. `image` - only search in - image type files. `non-image` - only search in files that are not images, e.g., - JS or CSS or video files. - - Default value - `all` - - limit: - The maximum number of results to return in response: - - Minimum value - 1 - - Maximum value - 1000 - - Default value - 1000 - - path: Folder path if you want to limit the search within a specific folder. For - example, `/sales-banner/` will only search in folder sales-banner. + custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. + `10,10,100,100`. Send `null` to unset this value. - search_query: Query string in a Lucene-like query language e.g. `createdAt > "7d"`. + custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` + value for that key. Before setting any custom metadata on an asset you have to + create the field using custom metadata fields API. - Note : When the searchQuery parameter is present, the following query parameters - will have no effect on the result: + description: Optional text to describe the contents of the file. - 1. `tags` - 2. `type` - 3. `name` + extensions: Array of extensions to be applied to the asset. Each extension can be configured + with specific parameters based on the extension type. - [Learn more](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#advanced-search-queries) - from examples. + remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. + `["car", "vehicle", "motorsports"]`. - skip: - The number of results to skip before returning results: + If you want to remove all AITags associated with the file, send a string - + "all". - Minimum value - 0 + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. - Default value - 0 + tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send + `null` to unset all tags associated with the file. - sort: - You can sort based on the following fields: - - 1. name - `ASC_NAME` or `DESC_NAME` - 2. createdAt - `ASC_CREATED` or `DESC_CREATED` - 3. updatedAt - `ASC_UPDATED` or `DESC_UPDATED` - 4. height - `ASC_HEIGHT` or `DESC_HEIGHT` - 5. width - `ASC_WIDTH` or `DESC_WIDTH` - 6. size - `ASC_SIZE` or `DESC_SIZE` - - Default value - `ASC_CREATED` - - type: Limit search to one of `file`, `file-version`, or `folder`. Pass `all` to - include `files` and `folders` in search results (`file-version` will not be - included in this case). - - Default value - `file` + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. extra_headers: Send extra headers @@ -210,48 +145,29 @@ def list( timeout: Override the client-level default timeout for this request, in seconds """ - return self._get( - "/v1/files", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "file_type": file_type, - "limit": limit, - "path": path, - "search_query": search_query, - "skip": skip, - "sort": sort, - "type": type, - }, - file_list_params.FileListParams, - ), - ), - cast_to=FileListResponse, - ) + ... - def delete( + @overload + def update( self, file_id: str, *, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> None: + ) -> FileUpdateResponse: """ - This API deletes the file and all its file versions permanently. - - Note: If a file or specific transformation has been requested in the past, then - the response is cached. Deleting a file does not purge the cache. You can purge - the cache using purge cache API. + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. Args: + publish: Configure the publication status of a file and its versions. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -260,39 +176,69 @@ def delete( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + def update( + self, + file_id: str, + *, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: object | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - f"/v1/files/{file_id}", + return self._patch( + f"/v1/files/{file_id}/details", + body=maybe_transform( + { + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "extensions": extensions, + "remove_ai_tags": remove_ai_tags, + "tags": tags, + "webhook_url": webhook_url, + "publish": publish, + }, + file_update_params.FileUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=NoneType, + cast_to=FileUpdateResponse, ) - def add_tags( + def delete( self, + file_id: str, *, - file_ids: List[str], - tags: List[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileAddTagsResponse: - """This API adds tags to multiple files in bulk. + ) -> None: + """ + This API deletes the file and all its file versions permanently. - A maximum of 50 files can be - specified at a time. + Note: If a file or specific transformation has been requested in the past, then + the response is cached. Deleting a file does not purge the cache. You can purge + the cache using purge cache API. Args: - file_ids: An array of fileIds to which you want to add tags. - - tags: An array of tags that you want to add to the files. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -301,19 +247,15 @@ def add_tags( timeout: Override the client-level default timeout for this request, in seconds """ - return self._post( - "/v1/files/addTags", - body=maybe_transform( - { - "file_ids": file_ids, - "tags": tags, - }, - file_add_tags_params.FileAddTagsParams, - ), + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/v1/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FileAddTagsResponse, + cast_to=NoneType, ) def copy( @@ -369,29 +311,22 @@ def copy( cast_to=object, ) - def move( + def get( self, + file_id: str, *, - destination_path: str, - source_file_path: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> FileGetResponse: """ - This will move a file and all its versions from one folder to another. - - Note: If any file at the destination has the same name as the source file, then - the source file and its versions will be appended to the destination file. + This API returns an object with details or attributes about the current version + of the file. Args: - destination_path: Full path to the folder you want to move the above file into. - - source_file_path: The full path of the file you want to move. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -400,87 +335,38 @@ def move( timeout: Override the client-level default timeout for this request, in seconds """ - return self._post( - "/v1/files/move", - body=maybe_transform( - { - "destination_path": destination_path, - "source_file_path": source_file_path, - }, - file_move_params.FileMoveParams, - ), + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return self._get( + f"/v1/files/{file_id}/details", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=FileGetResponse, ) - def remove_ai_tags( + def move( self, *, - ai_tags: List[str], - file_ids: List[str], + destination_path: str, + source_file_path: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileRemoveAITagsResponse: - """This API removes AITags from multiple files in bulk. - - A maximum of 50 files can - be specified at a time. - - Args: - ai_tags: An array of AITags that you want to remove from the files. - - file_ids: An array of fileIds from which you want to remove AITags. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + ) -> object: """ - return self._post( - "/v1/files/removeAITags", - body=maybe_transform( - { - "ai_tags": ai_tags, - "file_ids": file_ids, - }, - file_remove_ai_tags_params.FileRemoveAITagsParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=FileRemoveAITagsResponse, - ) - - def remove_tags( - self, - *, - file_ids: List[str], - tags: List[str], - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileRemoveTagsResponse: - """This API removes tags from multiple files in bulk. + This will move a file and all its versions from one folder to another. - A maximum of 50 files can be - specified at a time. + Note: If any file at the destination has the same name as the source file, then + the source file and its versions will be appended to the destination file. Args: - file_ids: An array of fileIds from which you want to remove tags. + destination_path: Full path to the folder you want to move the above file into. - tags: An array of tags that you want to remove from the files. + source_file_path: The full path of the file you want to move. extra_headers: Send extra headers @@ -491,18 +377,18 @@ def remove_tags( timeout: Override the client-level default timeout for this request, in seconds """ return self._post( - "/v1/files/removeTags", + "/v1/files/move", body=maybe_transform( { - "file_ids": file_ids, - "tags": tags, + "destination_path": destination_path, + "source_file_path": source_file_path, }, - file_remove_tags_params.FileRemoveTagsParams, + file_move_params.FileMoveParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FileRemoveTagsResponse, + cast_to=object, ) def rename( @@ -577,30 +463,42 @@ def rename( cast_to=FileRenameResponse, ) - def upload_v1( + def upload( self, *, - file: str, + file: FileTypes, file_name: str, token: str | NotGiven = NOT_GIVEN, checks: str | NotGiven = NOT_GIVEN, custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: str | NotGiven = NOT_GIVEN, - expire: str | NotGiven = NOT_GIVEN, - extensions: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + expire: int | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, - is_private_file: Literal["true", "false"] | NotGiven = NOT_GIVEN, - is_published: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_ai_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_file: str | NotGiven = NOT_GIVEN, - overwrite_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, public_key: str | NotGiven = NOT_GIVEN, - response_fields: str | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, - tags: str | NotGiven = NOT_GIVEN, - transformation: str | NotGiven = NOT_GIVEN, - use_unique_file_name: Literal["true", "false"] | NotGiven = NOT_GIVEN, + tags: List[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -608,7 +506,7 @@ def upload_v1( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadV1Response: + ) -> FileUploadResponse: """ ImageKit.io allows you to upload files directly from both the server and client sides. For server-side uploads, private API key authentication is used. For @@ -639,11 +537,16 @@ def upload_v1( technologies. Args: - file: Pass the HTTP URL or base64 string. When passing a URL in the file parameter, - please ensure that our servers can access the URL. In case ImageKit is unable to - download the file from the specified URL, a `400` error response is returned. - This will also result in a `400` error if the file download request is aborted - if response headers are not received in 8 seconds. + file: + The API accepts any of the following: + + - **Binary data** – send the raw bytes as `multipart/form-data`. + - **HTTP / HTTPS URL** – a publicly reachable URL that ImageKit’s servers can + fetch. + - **Base64 string** – the file encoded as a Base64 data URI or plain Base64. + + When supplying a URL, the server must receive the response headers within 8 + seconds; otherwise the request fails with 400 Bad Request. file_name: The name with which the file has to be uploaded. The file name can contain: @@ -675,16 +578,18 @@ def upload_v1( - If this field is not specified and the file is overwritten, then customCoordinates will be removed. - custom_metadata: Stringified JSON key-value data to be associated with the asset. + custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata + fields before setting these values. + + description: Optional text to describe the contents of the file. expire: The time until your signature is valid. It must be a [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into the future. It should be in seconds. This field is only required for authentication when uploading a file from the client side. - extensions: Stringified JSON object with an array of extensions to be applied to the image. - Refer to extensions schema in - [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). + extensions: Array of extensions to be applied to the image. Each extension can be configured + with specific parameters based on the extension type. folder: The folder path in which the image has to be uploaded. If the folder(s) didn't exist before, a new folder(s) is created. @@ -725,15 +630,7 @@ def upload_v1( public_key: Your ImageKit.io public key. This field is only required for authentication when uploading a file from the client side. - response_fields: Comma-separated values of the fields that you want the API to return in the - response. - - For example, set the value of this field to - `tags,customCoordinates,isPrivateFile` to get the value of `tags`, - `customCoordinates`, and `isPrivateFile` in the response. - - Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, - `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. + response_fields: Array of response field keys to include in the API response body. signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a key. Learn how to create a signature on the page below. This should be in @@ -742,31 +639,22 @@ def upload_v1( Signature must be calculated on the server-side. This field is only required for authentication when uploading a file from the client side. - tags: Set the tags while uploading the file. - - Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length - of all characters should not exceed 500. `%` is not allowed. - - If this field is not specified and the file is overwritten then the tags will be - removed. + tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. - transformation: - Stringified JSON object with properties for pre and post transformations: + transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. - `pre` - Accepts a "string" containing a valid transformation used for requesting - a pre-transformation for an image or a video file. + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). - `post` - Accepts an array of objects with properties: + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. - - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` - (Adaptive bitrate streaming). - - `value`: A "string" corresponding to the required transformation. Required if - `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or - `thumbnail`. - - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. - - Read more about - [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). + You can mix and match any combination of post-processing types. use_unique_file_name: Whether to use a unique filename for this file or not. @@ -789,6 +677,34 @@ def upload_v1( timeout: Override the client-level default timeout for this request, in seconds """ + body = deepcopy_minimal( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "expire": expire, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "public_key": public_key, + "response_fields": response_fields, + "signature": signature, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + } + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- @@ -797,60 +713,58 @@ def upload_v1( "/api/v1/files/upload" if self._client._base_url_overridden else "https://upload.imagekit.io/api/v1/files/upload", - body=maybe_transform( - { - "file": file, - "file_name": file_name, - "token": token, - "checks": checks, - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "expire": expire, - "extensions": extensions, - "folder": folder, - "is_private_file": is_private_file, - "is_published": is_published, - "overwrite_ai_tags": overwrite_ai_tags, - "overwrite_custom_metadata": overwrite_custom_metadata, - "overwrite_file": overwrite_file, - "overwrite_tags": overwrite_tags, - "public_key": public_key, - "response_fields": response_fields, - "signature": signature, - "tags": tags, - "transformation": transformation, - "use_unique_file_name": use_unique_file_name, - "webhook_url": webhook_url, - }, - file_upload_v1_params.FileUploadV1Params, - ), + body=maybe_transform(body, file_upload_params.FileUploadParams), + files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FileUploadV1Response, + cast_to=FileUploadResponse, ) - def upload_v2( + +class AsyncFilesResource(AsyncAPIResource): + @cached_property + def bulk(self) -> AsyncBulkResource: + return AsyncBulkResource(self._client) + + @cached_property + def versions(self) -> AsyncVersionsResource: + return AsyncVersionsResource(self._client) + + @cached_property + def metadata(self) -> AsyncMetadataResource: + return AsyncMetadataResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncFilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncFilesResourceWithStreamingResponse(self) + + @overload + async def update( self, + file_id: str, *, - file: str, - file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: str | NotGiven = NOT_GIVEN, - extensions: str | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: Literal["true", "false"] | NotGiven = NOT_GIVEN, - is_published: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_ai_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_file: str | NotGiven = NOT_GIVEN, - overwrite_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, - response_fields: str | NotGiven = NOT_GIVEN, - tags: str | NotGiven = NOT_GIVEN, - transformation: str | NotGiven = NOT_GIVEN, - use_unique_file_name: Literal["true", "false"] | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: object | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -858,159 +772,74 @@ def upload_v2( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadV2Response: - """The V2 API enhances security by verifying the entire payload using JWT. + ) -> FileUpdateResponse: + """ + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. - This API - is in beta. + Args: + custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. + `10,10,100,100`. Send `null` to unset this value. - ImageKit.io allows you to upload files directly from both the server and client - sides. For server-side uploads, private API key authentication is used. For - client-side uploads, generate a one-time `token` from your secure backend using - private API. - [Learn more](/docs/api-reference/upload-file/upload-file-v2#how-to-implement-secure-client-side-file-upload) - about how to implement secure client-side file upload. + custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` + value for that key. Before setting any custom metadata on an asset you have to + create the field using custom metadata fields API. - **File size limit** \\ - On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw - files, and 100MB for videos. On the paid plan, these limits increase to 40MB for - images, audio, and raw files, and 2GB for videos. These limits can be further increased - with higher-tier plans. + description: Optional text to describe the contents of the file. - **Version limit** \\ - A file can have a maximum of 100 versions. + extensions: Array of extensions to be applied to the asset. Each extension can be configured + with specific parameters based on the extension type. - **Demo applications** + remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. + `["car", "vehicle", "motorsports"]`. - - A full-fledged - [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), - supporting file selections from local storage, URL, Dropbox, Google Drive, - Instagram, and more. - - [Quick start guides](/docs/quick-start-guides) for various frameworks and - technologies. + If you want to remove all AITags associated with the file, send a string - + "all". - Args: - file: Pass the HTTP URL or base64 string. When passing a URL in the file parameter, - please ensure that our servers can access the URL. In case ImageKit is unable to - download the file from the specified URL, a `400` error response is returned. - This will also result in a `400` error if the file download request is aborted - if response headers are not received in 8 seconds. + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. - file_name: The name with which the file has to be uploaded. + tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send + `null` to unset all tags associated with the file. - token: This is the client-generated JSON Web Token (JWT). The ImageKit.io server uses - it to authenticate and check that the upload request parameters have not been - tampered with after the token has been generated. Learn how to create the token - on the page below. This field is only required for authentication when uploading - a file from the client side. + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. - **Note**: Sending a JWT that has been used in the past will result in a - validation error. Even if your previous request resulted in an error, you should - always send a new token. + extra_headers: Send extra headers - **⚠️Warning**: JWT must be generated on the server-side because it is generated - using your account's private API key. This field is required for authentication - when uploading a file from the client-side. + extra_query: Add additional query parameters to the request - checks: Server-side checks to run on the asset. Read more about - [Upload API checks](/docs/api-reference/upload-file/upload-file-v2#upload-api-checks). + extra_body: Add additional JSON properties to the request - custom_coordinates: Define an important area in the image. This is only relevant for image type - files. + timeout: Override the client-level default timeout for this request, in seconds + """ + ... - - To be passed as a string with the x and y coordinates of the top-left corner, - and width and height of the area of interest in the format `x,y,width,height`. - For example - `10,10,100,100` - - Can be used with fo-customtransformation. - - If this field is not specified and the file is overwritten, then - customCoordinates will be removed. + @overload + async def update( + self, + file_id: str, + *, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUpdateResponse: + """ + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. - custom_metadata: Stringified JSON key-value data to be associated with the asset. + Args: + publish: Configure the publication status of a file and its versions. - extensions: Stringified JSON object with an array of extensions to be applied to the image. - Refer to extensions schema in - [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). - - folder: The folder path in which the image has to be uploaded. If the folder(s) didn't - exist before, a new folder(s) is created. Using multiple `/` creates a nested - folder. - - is_private_file: Whether to mark the file as private or not. - - If `true`, the file is marked as private and is accessible only using named - transformation or signed URL. - - is_published: Whether to upload file as published or not. - - If `false`, the file is marked as unpublished, which restricts access to the - file only via the media library. Files in draft or unpublished state can only be - publicly accessed after being published. - - The option to upload in draft state is only available in custom enterprise - pricing plans. - - overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags - will be removed. Set `overwriteAITags` to `false` to preserve AITags. - - overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the - exact location, existing customMetadata will be removed. - - overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at - the exact location, upload API will return an error immediately. - - overwrite_tags: If the request does not have `tags`, and a file already exists at the exact - location, existing tags will be removed. - - response_fields: Comma-separated values of the fields that you want the API to return in the - response. - - For example, set the value of this field to - `tags,customCoordinates,isPrivateFile` to get the value of `tags`, - `customCoordinates`, and `isPrivateFile` in the response. - - Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, - `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. - - tags: Set the tags while uploading the file. - - Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length - of all characters should not exceed 500. `%` is not allowed. - - If this field is not specified and the file is overwritten then the tags will be - removed. - - transformation: - Stringified JSON object with properties for pre and post transformations: - - `pre` - Accepts a "string" containing a valid transformation used for requesting - a pre-transformation for an image or a video file. - - `post` - Accepts an array of objects with properties: - - - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` - (Adaptive bitrate streaming). - - `value`: A "string" corresponding to the required transformation. Required if - `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or - `thumbnail`. - - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. - - Read more about - [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). - - use_unique_file_name: Whether to use a unique filename for this file or not. - - If `true`, ImageKit.io will add a unique suffix to the filename parameter to get - a unique filename. - - If `false`, then the image is uploaded with the provided filename parameter, and - any existing file with the same name is replaced. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1018,196 +847,48 @@ def upload_v2( timeout: Override the client-level default timeout for this request, in seconds """ - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} - return self._post( - "/api/v2/files/upload" - if self._client._base_url_overridden - else "https://upload.imagekit.io/api/v2/files/upload", - body=maybe_transform( - { - "file": file, - "file_name": file_name, - "token": token, - "checks": checks, - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "extensions": extensions, - "folder": folder, - "is_private_file": is_private_file, - "is_published": is_published, - "overwrite_ai_tags": overwrite_ai_tags, - "overwrite_custom_metadata": overwrite_custom_metadata, - "overwrite_file": overwrite_file, - "overwrite_tags": overwrite_tags, - "response_fields": response_fields, - "tags": tags, - "transformation": transformation, - "use_unique_file_name": use_unique_file_name, - "webhook_url": webhook_url, - }, - file_upload_v2_params.FileUploadV2Params, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=FileUploadV2Response, - ) - - -class AsyncFilesResource(AsyncAPIResource): - @cached_property - def details(self) -> AsyncDetailsResource: - return AsyncDetailsResource(self._client) - - @cached_property - def batch(self) -> AsyncBatchResource: - return AsyncBatchResource(self._client) - - @cached_property - def versions(self) -> AsyncVersionsResource: - return AsyncVersionsResource(self._client) - - @cached_property - def purge(self) -> AsyncPurgeResource: - return AsyncPurgeResource(self._client) - - @cached_property - def metadata(self) -> AsyncMetadataResource: - return AsyncMetadataResource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers - """ - return AsyncFilesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response - """ - return AsyncFilesResourceWithStreamingResponse(self) + ... - async def list( + async def update( self, + file_id: str, *, - file_type: str | NotGiven = NOT_GIVEN, - limit: str | NotGiven = NOT_GIVEN, - path: str | NotGiven = NOT_GIVEN, - search_query: str | NotGiven = NOT_GIVEN, - skip: str | NotGiven = NOT_GIVEN, - sort: str | NotGiven = NOT_GIVEN, - type: Literal["file", "file-version", "folder", "all"] | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: object | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileListResponse: - """ - This API can list all the uploaded files and folders in your ImageKit.io media - library. In addition, you can fine-tune your query by specifying various filters - by generating a query string in a Lucene-like syntax and provide this generated - string as the value of the `searchQuery`. - - Args: - file_type: - Type of files to include in the result set. Accepts three values: - - `all` - include all types of files in the result set. `image` - only search in - image type files. `non-image` - only search in files that are not images, e.g., - JS or CSS or video files. - - Default value - `all` - - limit: - The maximum number of results to return in response: - - Minimum value - 1 - - Maximum value - 1000 - - Default value - 1000 - - path: Folder path if you want to limit the search within a specific folder. For - example, `/sales-banner/` will only search in folder sales-banner. - - search_query: Query string in a Lucene-like query language e.g. `createdAt > "7d"`. - - Note : When the searchQuery parameter is present, the following query parameters - will have no effect on the result: - - 1. `tags` - 2. `type` - 3. `name` - - [Learn more](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#advanced-search-queries) - from examples. - - skip: - The number of results to skip before returning results: - - Minimum value - 0 - - Default value - 0 - - sort: - You can sort based on the following fields: - - 1. name - `ASC_NAME` or `DESC_NAME` - 2. createdAt - `ASC_CREATED` or `DESC_CREATED` - 3. updatedAt - `ASC_UPDATED` or `DESC_UPDATED` - 4. height - `ASC_HEIGHT` or `DESC_HEIGHT` - 5. width - `ASC_WIDTH` or `DESC_WIDTH` - 6. size - `ASC_SIZE` or `DESC_SIZE` - - Default value - `ASC_CREATED` - - type: Limit search to one of `file`, `file-version`, or `folder`. Pass `all` to - include `files` and `folders` in search results (`file-version` will not be - included in this case). - - Default value - `file` - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._get( - "/v1/files", + ) -> FileUpdateResponse: + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return await self._patch( + f"/v1/files/{file_id}/details", + body=await async_maybe_transform( + { + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "extensions": extensions, + "remove_ai_tags": remove_ai_tags, + "tags": tags, + "webhook_url": webhook_url, + "publish": publish, + }, + file_update_params.FileUpdateParams, + ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "file_type": file_type, - "limit": limit, - "path": path, - "search_query": search_query, - "skip": skip, - "sort": sort, - "type": type, - }, - file_list_params.FileListParams, - ), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FileListResponse, + cast_to=FileUpdateResponse, ) async def delete( @@ -1248,51 +929,6 @@ async def delete( cast_to=NoneType, ) - async def add_tags( - self, - *, - file_ids: List[str], - tags: List[str], - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileAddTagsResponse: - """This API adds tags to multiple files in bulk. - - A maximum of 50 files can be - specified at a time. - - Args: - file_ids: An array of fileIds to which you want to add tags. - - tags: An array of tags that you want to add to the files. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/v1/files/addTags", - body=await async_maybe_transform( - { - "file_ids": file_ids, - "tags": tags, - }, - file_add_tags_params.FileAddTagsParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=FileAddTagsResponse, - ) - async def copy( self, *, @@ -1346,29 +982,22 @@ async def copy( cast_to=object, ) - async def move( + async def get( self, + file_id: str, *, - destination_path: str, - source_file_path: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> FileGetResponse: """ - This will move a file and all its versions from one folder to another. - - Note: If any file at the destination has the same name as the source file, then - the source file and its versions will be appended to the destination file. + This API returns an object with details or attributes about the current version + of the file. Args: - destination_path: Full path to the folder you want to move the above file into. - - source_file_path: The full path of the file you want to move. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1377,87 +1006,38 @@ async def move( timeout: Override the client-level default timeout for this request, in seconds """ - return await self._post( - "/v1/files/move", - body=await async_maybe_transform( - { - "destination_path": destination_path, - "source_file_path": source_file_path, - }, - file_move_params.FileMoveParams, - ), + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return await self._get( + f"/v1/files/{file_id}/details", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=FileGetResponse, ) - async def remove_ai_tags( + async def move( self, *, - ai_tags: List[str], - file_ids: List[str], + destination_path: str, + source_file_path: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileRemoveAITagsResponse: - """This API removes AITags from multiple files in bulk. - - A maximum of 50 files can - be specified at a time. - - Args: - ai_tags: An array of AITags that you want to remove from the files. - - file_ids: An array of fileIds from which you want to remove AITags. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + ) -> object: """ - return await self._post( - "/v1/files/removeAITags", - body=await async_maybe_transform( - { - "ai_tags": ai_tags, - "file_ids": file_ids, - }, - file_remove_ai_tags_params.FileRemoveAITagsParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=FileRemoveAITagsResponse, - ) - - async def remove_tags( - self, - *, - file_ids: List[str], - tags: List[str], - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileRemoveTagsResponse: - """This API removes tags from multiple files in bulk. + This will move a file and all its versions from one folder to another. - A maximum of 50 files can be - specified at a time. + Note: If any file at the destination has the same name as the source file, then + the source file and its versions will be appended to the destination file. Args: - file_ids: An array of fileIds from which you want to remove tags. + destination_path: Full path to the folder you want to move the above file into. - tags: An array of tags that you want to remove from the files. + source_file_path: The full path of the file you want to move. extra_headers: Send extra headers @@ -1468,18 +1048,18 @@ async def remove_tags( timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( - "/v1/files/removeTags", + "/v1/files/move", body=await async_maybe_transform( { - "file_ids": file_ids, - "tags": tags, + "destination_path": destination_path, + "source_file_path": source_file_path, }, - file_remove_tags_params.FileRemoveTagsParams, + file_move_params.FileMoveParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FileRemoveTagsResponse, + cast_to=object, ) async def rename( @@ -1554,30 +1134,42 @@ async def rename( cast_to=FileRenameResponse, ) - async def upload_v1( + async def upload( self, *, - file: str, + file: FileTypes, file_name: str, token: str | NotGiven = NOT_GIVEN, checks: str | NotGiven = NOT_GIVEN, custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: str | NotGiven = NOT_GIVEN, - expire: str | NotGiven = NOT_GIVEN, - extensions: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + expire: int | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, - is_private_file: Literal["true", "false"] | NotGiven = NOT_GIVEN, - is_published: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_ai_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_file: str | NotGiven = NOT_GIVEN, - overwrite_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, public_key: str | NotGiven = NOT_GIVEN, - response_fields: str | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, - tags: str | NotGiven = NOT_GIVEN, - transformation: str | NotGiven = NOT_GIVEN, - use_unique_file_name: Literal["true", "false"] | NotGiven = NOT_GIVEN, + tags: List[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -1585,7 +1177,7 @@ async def upload_v1( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadV1Response: + ) -> FileUploadResponse: """ ImageKit.io allows you to upload files directly from both the server and client sides. For server-side uploads, private API key authentication is used. For @@ -1616,11 +1208,16 @@ async def upload_v1( technologies. Args: - file: Pass the HTTP URL or base64 string. When passing a URL in the file parameter, - please ensure that our servers can access the URL. In case ImageKit is unable to - download the file from the specified URL, a `400` error response is returned. - This will also result in a `400` error if the file download request is aborted - if response headers are not received in 8 seconds. + file: + The API accepts any of the following: + + - **Binary data** – send the raw bytes as `multipart/form-data`. + - **HTTP / HTTPS URL** – a publicly reachable URL that ImageKit’s servers can + fetch. + - **Base64 string** – the file encoded as a Base64 data URI or plain Base64. + + When supplying a URL, the server must receive the response headers within 8 + seconds; otherwise the request fails with 400 Bad Request. file_name: The name with which the file has to be uploaded. The file name can contain: @@ -1652,16 +1249,18 @@ async def upload_v1( - If this field is not specified and the file is overwritten, then customCoordinates will be removed. - custom_metadata: Stringified JSON key-value data to be associated with the asset. + custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata + fields before setting these values. + + description: Optional text to describe the contents of the file. expire: The time until your signature is valid. It must be a [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into the future. It should be in seconds. This field is only required for authentication when uploading a file from the client side. - extensions: Stringified JSON object with an array of extensions to be applied to the image. - Refer to extensions schema in - [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). + extensions: Array of extensions to be applied to the image. Each extension can be configured + with specific parameters based on the extension type. folder: The folder path in which the image has to be uploaded. If the folder(s) didn't exist before, a new folder(s) is created. @@ -1702,15 +1301,7 @@ async def upload_v1( public_key: Your ImageKit.io public key. This field is only required for authentication when uploading a file from the client side. - response_fields: Comma-separated values of the fields that you want the API to return in the - response. - - For example, set the value of this field to - `tags,customCoordinates,isPrivateFile` to get the value of `tags`, - `customCoordinates`, and `isPrivateFile` in the response. - - Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, - `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. + response_fields: Array of response field keys to include in the API response body. signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a key. Learn how to create a signature on the page below. This should be in @@ -1719,31 +1310,22 @@ async def upload_v1( Signature must be calculated on the server-side. This field is only required for authentication when uploading a file from the client side. - tags: Set the tags while uploading the file. - - Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length - of all characters should not exceed 500. `%` is not allowed. + tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. - If this field is not specified and the file is overwritten then the tags will be - removed. + transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. - transformation: - Stringified JSON object with properties for pre and post transformations: + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). - `pre` - Accepts a "string" containing a valid transformation used for requesting - a pre-transformation for an image or a video file. + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. - `post` - Accepts an array of objects with properties: - - - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` - (Adaptive bitrate streaming). - - `value`: A "string" corresponding to the required transformation. Required if - `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or - `thumbnail`. - - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. - - Read more about - [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). + You can mix and match any combination of post-processing types. use_unique_file_name: Whether to use a unique filename for this file or not. @@ -1766,6 +1348,34 @@ async def upload_v1( timeout: Override the client-level default timeout for this request, in seconds """ + body = deepcopy_minimal( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "expire": expire, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "public_key": public_key, + "response_fields": response_fields, + "signature": signature, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + } + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- @@ -1774,263 +1384,12 @@ async def upload_v1( "/api/v1/files/upload" if self._client._base_url_overridden else "https://upload.imagekit.io/api/v1/files/upload", - body=await async_maybe_transform( - { - "file": file, - "file_name": file_name, - "token": token, - "checks": checks, - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "expire": expire, - "extensions": extensions, - "folder": folder, - "is_private_file": is_private_file, - "is_published": is_published, - "overwrite_ai_tags": overwrite_ai_tags, - "overwrite_custom_metadata": overwrite_custom_metadata, - "overwrite_file": overwrite_file, - "overwrite_tags": overwrite_tags, - "public_key": public_key, - "response_fields": response_fields, - "signature": signature, - "tags": tags, - "transformation": transformation, - "use_unique_file_name": use_unique_file_name, - "webhook_url": webhook_url, - }, - file_upload_v1_params.FileUploadV1Params, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=FileUploadV1Response, - ) - - async def upload_v2( - self, - *, - file: str, - file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: str | NotGiven = NOT_GIVEN, - extensions: str | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: Literal["true", "false"] | NotGiven = NOT_GIVEN, - is_published: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_ai_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: Literal["true", "false"] | NotGiven = NOT_GIVEN, - overwrite_file: str | NotGiven = NOT_GIVEN, - overwrite_tags: Literal["true", "false"] | NotGiven = NOT_GIVEN, - response_fields: str | NotGiven = NOT_GIVEN, - tags: str | NotGiven = NOT_GIVEN, - transformation: str | NotGiven = NOT_GIVEN, - use_unique_file_name: Literal["true", "false"] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadV2Response: - """The V2 API enhances security by verifying the entire payload using JWT. - - This API - is in beta. - - ImageKit.io allows you to upload files directly from both the server and client - sides. For server-side uploads, private API key authentication is used. For - client-side uploads, generate a one-time `token` from your secure backend using - private API. - [Learn more](/docs/api-reference/upload-file/upload-file-v2#how-to-implement-secure-client-side-file-upload) - about how to implement secure client-side file upload. - - **File size limit** \\ - On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw - files, and 100MB for videos. On the paid plan, these limits increase to 40MB for - images, audio, and raw files, and 2GB for videos. These limits can be further increased - with higher-tier plans. - - **Version limit** \\ - A file can have a maximum of 100 versions. - - **Demo applications** - - - A full-fledged - [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), - supporting file selections from local storage, URL, Dropbox, Google Drive, - Instagram, and more. - - [Quick start guides](/docs/quick-start-guides) for various frameworks and - technologies. - - Args: - file: Pass the HTTP URL or base64 string. When passing a URL in the file parameter, - please ensure that our servers can access the URL. In case ImageKit is unable to - download the file from the specified URL, a `400` error response is returned. - This will also result in a `400` error if the file download request is aborted - if response headers are not received in 8 seconds. - - file_name: The name with which the file has to be uploaded. - - token: This is the client-generated JSON Web Token (JWT). The ImageKit.io server uses - it to authenticate and check that the upload request parameters have not been - tampered with after the token has been generated. Learn how to create the token - on the page below. This field is only required for authentication when uploading - a file from the client side. - - **Note**: Sending a JWT that has been used in the past will result in a - validation error. Even if your previous request resulted in an error, you should - always send a new token. - - **⚠️Warning**: JWT must be generated on the server-side because it is generated - using your account's private API key. This field is required for authentication - when uploading a file from the client-side. - - checks: Server-side checks to run on the asset. Read more about - [Upload API checks](/docs/api-reference/upload-file/upload-file-v2#upload-api-checks). - - custom_coordinates: Define an important area in the image. This is only relevant for image type - files. - - - To be passed as a string with the x and y coordinates of the top-left corner, - and width and height of the area of interest in the format `x,y,width,height`. - For example - `10,10,100,100` - - Can be used with fo-customtransformation. - - If this field is not specified and the file is overwritten, then - customCoordinates will be removed. - - custom_metadata: Stringified JSON key-value data to be associated with the asset. - - extensions: Stringified JSON object with an array of extensions to be applied to the image. - Refer to extensions schema in - [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). - - folder: The folder path in which the image has to be uploaded. If the folder(s) didn't - exist before, a new folder(s) is created. Using multiple `/` creates a nested - folder. - - is_private_file: Whether to mark the file as private or not. - - If `true`, the file is marked as private and is accessible only using named - transformation or signed URL. - - is_published: Whether to upload file as published or not. - - If `false`, the file is marked as unpublished, which restricts access to the - file only via the media library. Files in draft or unpublished state can only be - publicly accessed after being published. - - The option to upload in draft state is only available in custom enterprise - pricing plans. - - overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags - will be removed. Set `overwriteAITags` to `false` to preserve AITags. - - overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the - exact location, existing customMetadata will be removed. - - overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at - the exact location, upload API will return an error immediately. - - overwrite_tags: If the request does not have `tags`, and a file already exists at the exact - location, existing tags will be removed. - - response_fields: Comma-separated values of the fields that you want the API to return in the - response. - - For example, set the value of this field to - `tags,customCoordinates,isPrivateFile` to get the value of `tags`, - `customCoordinates`, and `isPrivateFile` in the response. - - Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, - `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. - - tags: Set the tags while uploading the file. - - Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length - of all characters should not exceed 500. `%` is not allowed. - - If this field is not specified and the file is overwritten then the tags will be - removed. - - transformation: - Stringified JSON object with properties for pre and post transformations: - - `pre` - Accepts a "string" containing a valid transformation used for requesting - a pre-transformation for an image or a video file. - - `post` - Accepts an array of objects with properties: - - - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` - (Adaptive bitrate streaming). - - `value`: A "string" corresponding to the required transformation. Required if - `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or - `thumbnail`. - - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. - - Read more about - [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). - - use_unique_file_name: Whether to use a unique filename for this file or not. - - If `true`, ImageKit.io will add a unique suffix to the filename parameter to get - a unique filename. - - If `false`, then the image is uploaded with the provided filename parameter, and - any existing file with the same name is replaced. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} - return await self._post( - "/api/v2/files/upload" - if self._client._base_url_overridden - else "https://upload.imagekit.io/api/v2/files/upload", - body=await async_maybe_transform( - { - "file": file, - "file_name": file_name, - "token": token, - "checks": checks, - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "extensions": extensions, - "folder": folder, - "is_private_file": is_private_file, - "is_published": is_published, - "overwrite_ai_tags": overwrite_ai_tags, - "overwrite_custom_metadata": overwrite_custom_metadata, - "overwrite_file": overwrite_file, - "overwrite_tags": overwrite_tags, - "response_fields": response_fields, - "tags": tags, - "transformation": transformation, - "use_unique_file_name": use_unique_file_name, - "webhook_url": webhook_url, - }, - file_upload_v2_params.FileUploadV2Params, - ), + body=await async_maybe_transform(body, file_upload_params.FileUploadParams), + files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FileUploadV2Response, + cast_to=FileUploadResponse, ) @@ -2038,53 +1397,36 @@ class FilesResourceWithRawResponse: def __init__(self, files: FilesResource) -> None: self._files = files - self.list = to_raw_response_wrapper( - files.list, + self.update = to_raw_response_wrapper( + files.update, ) self.delete = to_raw_response_wrapper( files.delete, ) - self.add_tags = to_raw_response_wrapper( - files.add_tags, - ) self.copy = to_raw_response_wrapper( files.copy, ) + self.get = to_raw_response_wrapper( + files.get, + ) self.move = to_raw_response_wrapper( files.move, ) - self.remove_ai_tags = to_raw_response_wrapper( - files.remove_ai_tags, - ) - self.remove_tags = to_raw_response_wrapper( - files.remove_tags, - ) self.rename = to_raw_response_wrapper( files.rename, ) - self.upload_v1 = to_raw_response_wrapper( - files.upload_v1, - ) - self.upload_v2 = to_raw_response_wrapper( - files.upload_v2, + self.upload = to_raw_response_wrapper( + files.upload, ) @cached_property - def details(self) -> DetailsResourceWithRawResponse: - return DetailsResourceWithRawResponse(self._files.details) - - @cached_property - def batch(self) -> BatchResourceWithRawResponse: - return BatchResourceWithRawResponse(self._files.batch) + def bulk(self) -> BulkResourceWithRawResponse: + return BulkResourceWithRawResponse(self._files.bulk) @cached_property def versions(self) -> VersionsResourceWithRawResponse: return VersionsResourceWithRawResponse(self._files.versions) - @cached_property - def purge(self) -> PurgeResourceWithRawResponse: - return PurgeResourceWithRawResponse(self._files.purge) - @cached_property def metadata(self) -> MetadataResourceWithRawResponse: return MetadataResourceWithRawResponse(self._files.metadata) @@ -2094,53 +1436,36 @@ class AsyncFilesResourceWithRawResponse: def __init__(self, files: AsyncFilesResource) -> None: self._files = files - self.list = async_to_raw_response_wrapper( - files.list, + self.update = async_to_raw_response_wrapper( + files.update, ) self.delete = async_to_raw_response_wrapper( files.delete, ) - self.add_tags = async_to_raw_response_wrapper( - files.add_tags, - ) self.copy = async_to_raw_response_wrapper( files.copy, ) + self.get = async_to_raw_response_wrapper( + files.get, + ) self.move = async_to_raw_response_wrapper( files.move, ) - self.remove_ai_tags = async_to_raw_response_wrapper( - files.remove_ai_tags, - ) - self.remove_tags = async_to_raw_response_wrapper( - files.remove_tags, - ) self.rename = async_to_raw_response_wrapper( files.rename, ) - self.upload_v1 = async_to_raw_response_wrapper( - files.upload_v1, + self.upload = async_to_raw_response_wrapper( + files.upload, ) - self.upload_v2 = async_to_raw_response_wrapper( - files.upload_v2, - ) - - @cached_property - def details(self) -> AsyncDetailsResourceWithRawResponse: - return AsyncDetailsResourceWithRawResponse(self._files.details) @cached_property - def batch(self) -> AsyncBatchResourceWithRawResponse: - return AsyncBatchResourceWithRawResponse(self._files.batch) + def bulk(self) -> AsyncBulkResourceWithRawResponse: + return AsyncBulkResourceWithRawResponse(self._files.bulk) @cached_property def versions(self) -> AsyncVersionsResourceWithRawResponse: return AsyncVersionsResourceWithRawResponse(self._files.versions) - @cached_property - def purge(self) -> AsyncPurgeResourceWithRawResponse: - return AsyncPurgeResourceWithRawResponse(self._files.purge) - @cached_property def metadata(self) -> AsyncMetadataResourceWithRawResponse: return AsyncMetadataResourceWithRawResponse(self._files.metadata) @@ -2150,53 +1475,36 @@ class FilesResourceWithStreamingResponse: def __init__(self, files: FilesResource) -> None: self._files = files - self.list = to_streamed_response_wrapper( - files.list, + self.update = to_streamed_response_wrapper( + files.update, ) self.delete = to_streamed_response_wrapper( files.delete, ) - self.add_tags = to_streamed_response_wrapper( - files.add_tags, - ) self.copy = to_streamed_response_wrapper( files.copy, ) + self.get = to_streamed_response_wrapper( + files.get, + ) self.move = to_streamed_response_wrapper( files.move, ) - self.remove_ai_tags = to_streamed_response_wrapper( - files.remove_ai_tags, - ) - self.remove_tags = to_streamed_response_wrapper( - files.remove_tags, - ) self.rename = to_streamed_response_wrapper( files.rename, ) - self.upload_v1 = to_streamed_response_wrapper( - files.upload_v1, - ) - self.upload_v2 = to_streamed_response_wrapper( - files.upload_v2, + self.upload = to_streamed_response_wrapper( + files.upload, ) @cached_property - def details(self) -> DetailsResourceWithStreamingResponse: - return DetailsResourceWithStreamingResponse(self._files.details) - - @cached_property - def batch(self) -> BatchResourceWithStreamingResponse: - return BatchResourceWithStreamingResponse(self._files.batch) + def bulk(self) -> BulkResourceWithStreamingResponse: + return BulkResourceWithStreamingResponse(self._files.bulk) @cached_property def versions(self) -> VersionsResourceWithStreamingResponse: return VersionsResourceWithStreamingResponse(self._files.versions) - @cached_property - def purge(self) -> PurgeResourceWithStreamingResponse: - return PurgeResourceWithStreamingResponse(self._files.purge) - @cached_property def metadata(self) -> MetadataResourceWithStreamingResponse: return MetadataResourceWithStreamingResponse(self._files.metadata) @@ -2206,53 +1514,36 @@ class AsyncFilesResourceWithStreamingResponse: def __init__(self, files: AsyncFilesResource) -> None: self._files = files - self.list = async_to_streamed_response_wrapper( - files.list, + self.update = async_to_streamed_response_wrapper( + files.update, ) self.delete = async_to_streamed_response_wrapper( files.delete, ) - self.add_tags = async_to_streamed_response_wrapper( - files.add_tags, - ) self.copy = async_to_streamed_response_wrapper( files.copy, ) + self.get = async_to_streamed_response_wrapper( + files.get, + ) self.move = async_to_streamed_response_wrapper( files.move, ) - self.remove_ai_tags = async_to_streamed_response_wrapper( - files.remove_ai_tags, - ) - self.remove_tags = async_to_streamed_response_wrapper( - files.remove_tags, - ) self.rename = async_to_streamed_response_wrapper( files.rename, ) - self.upload_v1 = async_to_streamed_response_wrapper( - files.upload_v1, - ) - self.upload_v2 = async_to_streamed_response_wrapper( - files.upload_v2, + self.upload = async_to_streamed_response_wrapper( + files.upload, ) @cached_property - def details(self) -> AsyncDetailsResourceWithStreamingResponse: - return AsyncDetailsResourceWithStreamingResponse(self._files.details) - - @cached_property - def batch(self) -> AsyncBatchResourceWithStreamingResponse: - return AsyncBatchResourceWithStreamingResponse(self._files.batch) + def bulk(self) -> AsyncBulkResourceWithStreamingResponse: + return AsyncBulkResourceWithStreamingResponse(self._files.bulk) @cached_property def versions(self) -> AsyncVersionsResourceWithStreamingResponse: return AsyncVersionsResourceWithStreamingResponse(self._files.versions) - @cached_property - def purge(self) -> AsyncPurgeResourceWithStreamingResponse: - return AsyncPurgeResourceWithStreamingResponse(self._files.purge) - @cached_property def metadata(self) -> AsyncMetadataResourceWithStreamingResponse: return AsyncMetadataResourceWithStreamingResponse(self._files.metadata) diff --git a/src/imagekit/resources/files/metadata.py b/src/imagekit/resources/files/metadata.py index 7a019cd..c6e5035 100644 --- a/src/imagekit/resources/files/metadata.py +++ b/src/imagekit/resources/files/metadata.py @@ -14,10 +14,10 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ...types.files import metadata_from_url_params +from ...types.files import metadata_get_from_url_params from ..._base_client import make_request_options -from ...types.files.metadata_from_url_response import MetadataFromURLResponse -from ...types.files.metadata_retrieve_response import MetadataRetrieveResponse +from ...types.files.metadata_get_response import MetadataGetResponse +from ...types.files.metadata_get_from_url_response import MetadataGetFromURLResponse __all__ = ["MetadataResource", "AsyncMetadataResource"] @@ -42,7 +42,7 @@ def with_streaming_response(self) -> MetadataResourceWithStreamingResponse: """ return MetadataResourceWithStreamingResponse(self) - def retrieve( + def get( self, file_id: str, *, @@ -52,7 +52,7 @@ def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> MetadataRetrieveResponse: + ) -> MetadataGetResponse: """ You can programmatically get image EXIF, pHash, and other metadata for uploaded files in the ImageKit.io media library using this API. @@ -76,10 +76,10 @@ def retrieve( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=MetadataRetrieveResponse, + cast_to=MetadataGetResponse, ) - def from_url( + def get_from_url( self, *, url: str, @@ -89,7 +89,7 @@ def from_url( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> MetadataFromURLResponse: + ) -> MetadataGetFromURLResponse: """ Get image EXIF, pHash, and other metadata from ImageKit.io powered remote URL using this API. @@ -113,9 +113,9 @@ def from_url( extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=maybe_transform({"url": url}, metadata_from_url_params.MetadataFromURLParams), + query=maybe_transform({"url": url}, metadata_get_from_url_params.MetadataGetFromURLParams), ), - cast_to=MetadataFromURLResponse, + cast_to=MetadataGetFromURLResponse, ) @@ -139,7 +139,7 @@ def with_streaming_response(self) -> AsyncMetadataResourceWithStreamingResponse: """ return AsyncMetadataResourceWithStreamingResponse(self) - async def retrieve( + async def get( self, file_id: str, *, @@ -149,7 +149,7 @@ async def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> MetadataRetrieveResponse: + ) -> MetadataGetResponse: """ You can programmatically get image EXIF, pHash, and other metadata for uploaded files in the ImageKit.io media library using this API. @@ -173,10 +173,10 @@ async def retrieve( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=MetadataRetrieveResponse, + cast_to=MetadataGetResponse, ) - async def from_url( + async def get_from_url( self, *, url: str, @@ -186,7 +186,7 @@ async def from_url( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> MetadataFromURLResponse: + ) -> MetadataGetFromURLResponse: """ Get image EXIF, pHash, and other metadata from ImageKit.io powered remote URL using this API. @@ -210,9 +210,9 @@ async def from_url( extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=await async_maybe_transform({"url": url}, metadata_from_url_params.MetadataFromURLParams), + query=await async_maybe_transform({"url": url}, metadata_get_from_url_params.MetadataGetFromURLParams), ), - cast_to=MetadataFromURLResponse, + cast_to=MetadataGetFromURLResponse, ) @@ -220,11 +220,11 @@ class MetadataResourceWithRawResponse: def __init__(self, metadata: MetadataResource) -> None: self._metadata = metadata - self.retrieve = to_raw_response_wrapper( - metadata.retrieve, + self.get = to_raw_response_wrapper( + metadata.get, ) - self.from_url = to_raw_response_wrapper( - metadata.from_url, + self.get_from_url = to_raw_response_wrapper( + metadata.get_from_url, ) @@ -232,11 +232,11 @@ class AsyncMetadataResourceWithRawResponse: def __init__(self, metadata: AsyncMetadataResource) -> None: self._metadata = metadata - self.retrieve = async_to_raw_response_wrapper( - metadata.retrieve, + self.get = async_to_raw_response_wrapper( + metadata.get, ) - self.from_url = async_to_raw_response_wrapper( - metadata.from_url, + self.get_from_url = async_to_raw_response_wrapper( + metadata.get_from_url, ) @@ -244,11 +244,11 @@ class MetadataResourceWithStreamingResponse: def __init__(self, metadata: MetadataResource) -> None: self._metadata = metadata - self.retrieve = to_streamed_response_wrapper( - metadata.retrieve, + self.get = to_streamed_response_wrapper( + metadata.get, ) - self.from_url = to_streamed_response_wrapper( - metadata.from_url, + self.get_from_url = to_streamed_response_wrapper( + metadata.get_from_url, ) @@ -256,9 +256,9 @@ class AsyncMetadataResourceWithStreamingResponse: def __init__(self, metadata: AsyncMetadataResource) -> None: self._metadata = metadata - self.retrieve = async_to_streamed_response_wrapper( - metadata.retrieve, + self.get = async_to_streamed_response_wrapper( + metadata.get, ) - self.from_url = async_to_streamed_response_wrapper( - metadata.from_url, + self.get_from_url = async_to_streamed_response_wrapper( + metadata.get_from_url, ) diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py index c99c590..dd50640 100644 --- a/src/imagekit/resources/files/versions.py +++ b/src/imagekit/resources/files/versions.py @@ -14,9 +14,9 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options +from ...types.files.version_get_response import VersionGetResponse from ...types.files.version_list_response import VersionListResponse from ...types.files.version_restore_response import VersionRestoreResponse -from ...types.files.version_retrieve_response import VersionRetrieveResponse __all__ = ["VersionsResource", "AsyncVersionsResource"] @@ -41,20 +41,19 @@ def with_streaming_response(self) -> VersionsResourceWithStreamingResponse: """ return VersionsResourceWithStreamingResponse(self) - def retrieve( + def list( self, - version_id: str, - *, file_id: str, + *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> VersionRetrieveResponse: + ) -> VersionListResponse: """ - This API returns an object with details or attributes of a file version. + This API returns details of all versions of a file. Args: extra_headers: Send extra headers @@ -67,29 +66,32 @@ def retrieve( """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - if not version_id: - raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") return self._get( - f"/v1/files/{file_id}/versions/{version_id}", + f"/v1/files/{file_id}/versions", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=VersionRetrieveResponse, + cast_to=VersionListResponse, ) - def list( + def delete( self, - file_id: str, + version_id: str, *, + file_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> VersionListResponse: - """ - This API returns details of all versions of a file. + ) -> object: + """This API deletes a non-current file version permanently. + + The API returns an + empty response. + + Note: If you want to delete all versions of a file, use the delete file API. Args: extra_headers: Send extra headers @@ -102,15 +104,17 @@ def list( """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - return self._get( - f"/v1/files/{file_id}/versions", + if not version_id: + raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") + return self._delete( + f"/v1/files/{file_id}/versions/{version_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=VersionListResponse, + cast_to=object, ) - def delete( + def get( self, version_id: str, *, @@ -121,13 +125,9 @@ def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: - """This API deletes a non-current file version permanently. - - The API returns an - empty response. - - Note: If you want to delete all versions of a file, use the delete file API. + ) -> VersionGetResponse: + """ + This API returns an object with details or attributes of a file version. Args: extra_headers: Send extra headers @@ -142,12 +142,12 @@ def delete( raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") if not version_id: raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") - return self._delete( + return self._get( f"/v1/files/{file_id}/versions/{version_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=VersionGetResponse, ) def restore( @@ -207,20 +207,19 @@ def with_streaming_response(self) -> AsyncVersionsResourceWithStreamingResponse: """ return AsyncVersionsResourceWithStreamingResponse(self) - async def retrieve( + async def list( self, - version_id: str, - *, file_id: str, + *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> VersionRetrieveResponse: + ) -> VersionListResponse: """ - This API returns an object with details or attributes of a file version. + This API returns details of all versions of a file. Args: extra_headers: Send extra headers @@ -233,29 +232,32 @@ async def retrieve( """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - if not version_id: - raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") return await self._get( - f"/v1/files/{file_id}/versions/{version_id}", + f"/v1/files/{file_id}/versions", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=VersionRetrieveResponse, + cast_to=VersionListResponse, ) - async def list( + async def delete( self, - file_id: str, + version_id: str, *, + file_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> VersionListResponse: - """ - This API returns details of all versions of a file. + ) -> object: + """This API deletes a non-current file version permanently. + + The API returns an + empty response. + + Note: If you want to delete all versions of a file, use the delete file API. Args: extra_headers: Send extra headers @@ -268,15 +270,17 @@ async def list( """ if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - return await self._get( - f"/v1/files/{file_id}/versions", + if not version_id: + raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") + return await self._delete( + f"/v1/files/{file_id}/versions/{version_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=VersionListResponse, + cast_to=object, ) - async def delete( + async def get( self, version_id: str, *, @@ -287,13 +291,9 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: - """This API deletes a non-current file version permanently. - - The API returns an - empty response. - - Note: If you want to delete all versions of a file, use the delete file API. + ) -> VersionGetResponse: + """ + This API returns an object with details or attributes of a file version. Args: extra_headers: Send extra headers @@ -308,12 +308,12 @@ async def delete( raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") if not version_id: raise ValueError(f"Expected a non-empty value for `version_id` but received {version_id!r}") - return await self._delete( + return await self._get( f"/v1/files/{file_id}/versions/{version_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=VersionGetResponse, ) async def restore( @@ -357,15 +357,15 @@ class VersionsResourceWithRawResponse: def __init__(self, versions: VersionsResource) -> None: self._versions = versions - self.retrieve = to_raw_response_wrapper( - versions.retrieve, - ) self.list = to_raw_response_wrapper( versions.list, ) self.delete = to_raw_response_wrapper( versions.delete, ) + self.get = to_raw_response_wrapper( + versions.get, + ) self.restore = to_raw_response_wrapper( versions.restore, ) @@ -375,15 +375,15 @@ class AsyncVersionsResourceWithRawResponse: def __init__(self, versions: AsyncVersionsResource) -> None: self._versions = versions - self.retrieve = async_to_raw_response_wrapper( - versions.retrieve, - ) self.list = async_to_raw_response_wrapper( versions.list, ) self.delete = async_to_raw_response_wrapper( versions.delete, ) + self.get = async_to_raw_response_wrapper( + versions.get, + ) self.restore = async_to_raw_response_wrapper( versions.restore, ) @@ -393,15 +393,15 @@ class VersionsResourceWithStreamingResponse: def __init__(self, versions: VersionsResource) -> None: self._versions = versions - self.retrieve = to_streamed_response_wrapper( - versions.retrieve, - ) self.list = to_streamed_response_wrapper( versions.list, ) self.delete = to_streamed_response_wrapper( versions.delete, ) + self.get = to_streamed_response_wrapper( + versions.get, + ) self.restore = to_streamed_response_wrapper( versions.restore, ) @@ -411,15 +411,15 @@ class AsyncVersionsResourceWithStreamingResponse: def __init__(self, versions: AsyncVersionsResource) -> None: self._versions = versions - self.retrieve = async_to_streamed_response_wrapper( - versions.retrieve, - ) self.list = async_to_streamed_response_wrapper( versions.list, ) self.delete = async_to_streamed_response_wrapper( versions.delete, ) + self.get = async_to_streamed_response_wrapper( + versions.get, + ) self.restore = async_to_streamed_response_wrapper( versions.restore, ) diff --git a/src/imagekit/resources/folder.py b/src/imagekit/resources/folder.py deleted file mode 100644 index 15c5aa3..0000000 --- a/src/imagekit/resources/folder.py +++ /dev/null @@ -1,292 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import httpx - -from ..types import folder_create_params, folder_delete_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import maybe_transform, async_maybe_transform -from .._compat import cached_property -from .._resource import SyncAPIResource, AsyncAPIResource -from .._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from .._base_client import make_request_options - -__all__ = ["FolderResource", "AsyncFolderResource"] - - -class FolderResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> FolderResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers - """ - return FolderResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> FolderResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response - """ - return FolderResourceWithStreamingResponse(self) - - def create( - self, - *, - folder_name: str, - parent_folder_path: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: - """This will create a new folder. - - You can specify the folder name and location of - the parent folder where this new folder should be created. - - Args: - folder_name: The folder will be created with this name. - - All characters except alphabets and numbers (inclusive of unicode letters, - marks, and numerals in other languages) will be replaced by an underscore i.e. - `_`. - - parent_folder_path: The folder where the new folder should be created, for root use `/` else the - path e.g. `containing/folder/`. - - Note: If any folder(s) is not present in the parentFolderPath parameter, it will - be automatically created. For example, if you pass `/product/images/summer`, - then `product`, `images`, and `summer` folders will be created if they don't - already exist. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/v1/folder", - body=maybe_transform( - { - "folder_name": folder_name, - "parent_folder_path": parent_folder_path, - }, - folder_create_params.FolderCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=object, - ) - - def delete( - self, - *, - folder_path: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: - """This will delete a folder and all its contents permanently. - - The API returns an - empty response. - - Args: - folder_path: Full path to the folder you want to delete. For example `/folder/to/delete/`. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._delete( - "/v1/folder", - body=maybe_transform({"folder_path": folder_path}, folder_delete_params.FolderDeleteParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=object, - ) - - -class AsyncFolderResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncFolderResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers - """ - return AsyncFolderResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncFolderResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response - """ - return AsyncFolderResourceWithStreamingResponse(self) - - async def create( - self, - *, - folder_name: str, - parent_folder_path: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: - """This will create a new folder. - - You can specify the folder name and location of - the parent folder where this new folder should be created. - - Args: - folder_name: The folder will be created with this name. - - All characters except alphabets and numbers (inclusive of unicode letters, - marks, and numerals in other languages) will be replaced by an underscore i.e. - `_`. - - parent_folder_path: The folder where the new folder should be created, for root use `/` else the - path e.g. `containing/folder/`. - - Note: If any folder(s) is not present in the parentFolderPath parameter, it will - be automatically created. For example, if you pass `/product/images/summer`, - then `product`, `images`, and `summer` folders will be created if they don't - already exist. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/v1/folder", - body=await async_maybe_transform( - { - "folder_name": folder_name, - "parent_folder_path": parent_folder_path, - }, - folder_create_params.FolderCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=object, - ) - - async def delete( - self, - *, - folder_path: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: - """This will delete a folder and all its contents permanently. - - The API returns an - empty response. - - Args: - folder_path: Full path to the folder you want to delete. For example `/folder/to/delete/`. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._delete( - "/v1/folder", - body=await async_maybe_transform({"folder_path": folder_path}, folder_delete_params.FolderDeleteParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=object, - ) - - -class FolderResourceWithRawResponse: - def __init__(self, folder: FolderResource) -> None: - self._folder = folder - - self.create = to_raw_response_wrapper( - folder.create, - ) - self.delete = to_raw_response_wrapper( - folder.delete, - ) - - -class AsyncFolderResourceWithRawResponse: - def __init__(self, folder: AsyncFolderResource) -> None: - self._folder = folder - - self.create = async_to_raw_response_wrapper( - folder.create, - ) - self.delete = async_to_raw_response_wrapper( - folder.delete, - ) - - -class FolderResourceWithStreamingResponse: - def __init__(self, folder: FolderResource) -> None: - self._folder = folder - - self.create = to_streamed_response_wrapper( - folder.create, - ) - self.delete = to_streamed_response_wrapper( - folder.delete, - ) - - -class AsyncFolderResourceWithStreamingResponse: - def __init__(self, folder: AsyncFolderResource) -> None: - self._folder = folder - - self.create = async_to_streamed_response_wrapper( - folder.create, - ) - self.delete = async_to_streamed_response_wrapper( - folder.delete, - ) diff --git a/src/imagekit/resources/folders/__init__.py b/src/imagekit/resources/folders/__init__.py new file mode 100644 index 0000000..a88720f --- /dev/null +++ b/src/imagekit/resources/folders/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .job import ( + JobResource, + AsyncJobResource, + JobResourceWithRawResponse, + AsyncJobResourceWithRawResponse, + JobResourceWithStreamingResponse, + AsyncJobResourceWithStreamingResponse, +) +from .folders import ( + FoldersResource, + AsyncFoldersResource, + FoldersResourceWithRawResponse, + AsyncFoldersResourceWithRawResponse, + FoldersResourceWithStreamingResponse, + AsyncFoldersResourceWithStreamingResponse, +) + +__all__ = [ + "JobResource", + "AsyncJobResource", + "JobResourceWithRawResponse", + "AsyncJobResourceWithRawResponse", + "JobResourceWithStreamingResponse", + "AsyncJobResourceWithStreamingResponse", + "FoldersResource", + "AsyncFoldersResource", + "FoldersResourceWithRawResponse", + "AsyncFoldersResourceWithRawResponse", + "FoldersResourceWithStreamingResponse", + "AsyncFoldersResourceWithStreamingResponse", +] diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekit/resources/folders/folders.py new file mode 100644 index 0000000..0e193ef --- /dev/null +++ b/src/imagekit/resources/folders/folders.py @@ -0,0 +1,711 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from .job import ( + JobResource, + AsyncJobResource, + JobResourceWithRawResponse, + AsyncJobResourceWithRawResponse, + JobResourceWithStreamingResponse, + AsyncJobResourceWithStreamingResponse, +) +from ...types import ( + folder_copy_params, + folder_move_params, + folder_create_params, + folder_delete_params, + folder_rename_params, +) +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.folder_copy_response import FolderCopyResponse +from ...types.folder_move_response import FolderMoveResponse +from ...types.folder_rename_response import FolderRenameResponse + +__all__ = ["FoldersResource", "AsyncFoldersResource"] + + +class FoldersResource(SyncAPIResource): + @cached_property + def job(self) -> JobResource: + return JobResource(self._client) + + @cached_property + def with_raw_response(self) -> FoldersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return FoldersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FoldersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return FoldersResourceWithStreamingResponse(self) + + def create( + self, + *, + folder_name: str, + parent_folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This will create a new folder. + + You can specify the folder name and location of + the parent folder where this new folder should be created. + + Args: + folder_name: The folder will be created with this name. + + All characters except alphabets and numbers (inclusive of unicode letters, + marks, and numerals in other languages) will be replaced by an underscore i.e. + `_`. + + parent_folder_path: The folder where the new folder should be created, for root use `/` else the + path e.g. `containing/folder/`. + + Note: If any folder(s) is not present in the parentFolderPath parameter, it will + be automatically created. For example, if you pass `/product/images/summer`, + then `product`, `images`, and `summer` folders will be created if they don't + already exist. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/folder", + body=maybe_transform( + { + "folder_name": folder_name, + "parent_folder_path": parent_folder_path, + }, + folder_create_params.FolderCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + def delete( + self, + *, + folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This will delete a folder and all its contents permanently. + + The API returns an + empty response. + + Args: + folder_path: Full path to the folder you want to delete. For example `/folder/to/delete/`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._delete( + "/v1/folder", + body=maybe_transform({"folder_path": folder_path}, folder_delete_params.FolderDeleteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + def copy( + self, + *, + destination_path: str, + source_folder_path: str, + include_versions: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FolderCopyResponse: + """This will copy one folder into another. + + The selected folder, its nested folders, + files, and their versions (in `includeVersions` is set to true) are copied in + this operation. Note: If any file at the destination has the same name as the + source file, then the source file and its versions will be appended to the + destination file version history. + + Args: + destination_path: Full path to the destination folder where you want to copy the source folder + into. + + source_folder_path: The full path to the source folder you want to copy. + + include_versions: Option to copy all versions of files that are nested inside the selected folder. + By default, only the current version of each file will be copied. When set to + true, all versions of each file will be copied. Default value - `false`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/bulkJobs/copyFolder", + body=maybe_transform( + { + "destination_path": destination_path, + "source_folder_path": source_folder_path, + "include_versions": include_versions, + }, + folder_copy_params.FolderCopyParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FolderCopyResponse, + ) + + def move( + self, + *, + destination_path: str, + source_folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FolderMoveResponse: + """This will move one folder into another. + + The selected folder, its nested folders, + files, and their versions are moved in this operation. Note: If any file at the + destination has the same name as the source file, then the source file and its + versions will be appended to the destination file version history. + + Args: + destination_path: Full path to the destination folder where you want to move the source folder + into. + + source_folder_path: The full path to the source folder you want to move. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/bulkJobs/moveFolder", + body=maybe_transform( + { + "destination_path": destination_path, + "source_folder_path": source_folder_path, + }, + folder_move_params.FolderMoveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FolderMoveResponse, + ) + + def rename( + self, + *, + folder_path: str, + new_folder_name: str, + purge_cache: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FolderRenameResponse: + """This API allows you to rename an existing folder. + + The folder and all its nested + assets and sub-folders will remain unchanged, but their paths will be updated to + reflect the new folder name. + + Args: + folder_path: The full path to the folder you want to rename. + + new_folder_name: The new name for the folder. + + All characters except alphabets and numbers (inclusive of unicode letters, + marks, and numerals in other languages) and `-` will be replaced by an + underscore i.e. `_`. + + purge_cache: Option to purge cache for the old nested files and their versions' URLs. + + When set to true, it will internally issue a purge cache request on CDN to + remove the cached content of the old nested files and their versions. There will + only be one purge request for all the nested files, which will be counted + against your monthly purge quota. + + Note: A purge cache request will be issued against + `https://ik.imagekit.io/old/folder/path*` (with a wildcard at the end). This + will remove all nested files, their versions' URLs, and any transformations made + using query parameters on these files or their versions. However, the cache for + file transformations made using path parameters will persist. You can purge them + using the purge API. For more details, refer to the purge API documentation. + + Default value - `false` + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/bulkJobs/renameFolder", + body=maybe_transform( + { + "folder_path": folder_path, + "new_folder_name": new_folder_name, + "purge_cache": purge_cache, + }, + folder_rename_params.FolderRenameParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FolderRenameResponse, + ) + + +class AsyncFoldersResource(AsyncAPIResource): + @cached_property + def job(self) -> AsyncJobResource: + return AsyncJobResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncFoldersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncFoldersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFoldersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncFoldersResourceWithStreamingResponse(self) + + async def create( + self, + *, + folder_name: str, + parent_folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This will create a new folder. + + You can specify the folder name and location of + the parent folder where this new folder should be created. + + Args: + folder_name: The folder will be created with this name. + + All characters except alphabets and numbers (inclusive of unicode letters, + marks, and numerals in other languages) will be replaced by an underscore i.e. + `_`. + + parent_folder_path: The folder where the new folder should be created, for root use `/` else the + path e.g. `containing/folder/`. + + Note: If any folder(s) is not present in the parentFolderPath parameter, it will + be automatically created. For example, if you pass `/product/images/summer`, + then `product`, `images`, and `summer` folders will be created if they don't + already exist. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/folder", + body=await async_maybe_transform( + { + "folder_name": folder_name, + "parent_folder_path": parent_folder_path, + }, + folder_create_params.FolderCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + async def delete( + self, + *, + folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> object: + """This will delete a folder and all its contents permanently. + + The API returns an + empty response. + + Args: + folder_path: Full path to the folder you want to delete. For example `/folder/to/delete/`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._delete( + "/v1/folder", + body=await async_maybe_transform({"folder_path": folder_path}, folder_delete_params.FolderDeleteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + async def copy( + self, + *, + destination_path: str, + source_folder_path: str, + include_versions: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FolderCopyResponse: + """This will copy one folder into another. + + The selected folder, its nested folders, + files, and their versions (in `includeVersions` is set to true) are copied in + this operation. Note: If any file at the destination has the same name as the + source file, then the source file and its versions will be appended to the + destination file version history. + + Args: + destination_path: Full path to the destination folder where you want to copy the source folder + into. + + source_folder_path: The full path to the source folder you want to copy. + + include_versions: Option to copy all versions of files that are nested inside the selected folder. + By default, only the current version of each file will be copied. When set to + true, all versions of each file will be copied. Default value - `false`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/bulkJobs/copyFolder", + body=await async_maybe_transform( + { + "destination_path": destination_path, + "source_folder_path": source_folder_path, + "include_versions": include_versions, + }, + folder_copy_params.FolderCopyParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FolderCopyResponse, + ) + + async def move( + self, + *, + destination_path: str, + source_folder_path: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FolderMoveResponse: + """This will move one folder into another. + + The selected folder, its nested folders, + files, and their versions are moved in this operation. Note: If any file at the + destination has the same name as the source file, then the source file and its + versions will be appended to the destination file version history. + + Args: + destination_path: Full path to the destination folder where you want to move the source folder + into. + + source_folder_path: The full path to the source folder you want to move. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/bulkJobs/moveFolder", + body=await async_maybe_transform( + { + "destination_path": destination_path, + "source_folder_path": source_folder_path, + }, + folder_move_params.FolderMoveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FolderMoveResponse, + ) + + async def rename( + self, + *, + folder_path: str, + new_folder_name: str, + purge_cache: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FolderRenameResponse: + """This API allows you to rename an existing folder. + + The folder and all its nested + assets and sub-folders will remain unchanged, but their paths will be updated to + reflect the new folder name. + + Args: + folder_path: The full path to the folder you want to rename. + + new_folder_name: The new name for the folder. + + All characters except alphabets and numbers (inclusive of unicode letters, + marks, and numerals in other languages) and `-` will be replaced by an + underscore i.e. `_`. + + purge_cache: Option to purge cache for the old nested files and their versions' URLs. + + When set to true, it will internally issue a purge cache request on CDN to + remove the cached content of the old nested files and their versions. There will + only be one purge request for all the nested files, which will be counted + against your monthly purge quota. + + Note: A purge cache request will be issued against + `https://ik.imagekit.io/old/folder/path*` (with a wildcard at the end). This + will remove all nested files, their versions' URLs, and any transformations made + using query parameters on these files or their versions. However, the cache for + file transformations made using path parameters will persist. You can purge them + using the purge API. For more details, refer to the purge API documentation. + + Default value - `false` + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/bulkJobs/renameFolder", + body=await async_maybe_transform( + { + "folder_path": folder_path, + "new_folder_name": new_folder_name, + "purge_cache": purge_cache, + }, + folder_rename_params.FolderRenameParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FolderRenameResponse, + ) + + +class FoldersResourceWithRawResponse: + def __init__(self, folders: FoldersResource) -> None: + self._folders = folders + + self.create = to_raw_response_wrapper( + folders.create, + ) + self.delete = to_raw_response_wrapper( + folders.delete, + ) + self.copy = to_raw_response_wrapper( + folders.copy, + ) + self.move = to_raw_response_wrapper( + folders.move, + ) + self.rename = to_raw_response_wrapper( + folders.rename, + ) + + @cached_property + def job(self) -> JobResourceWithRawResponse: + return JobResourceWithRawResponse(self._folders.job) + + +class AsyncFoldersResourceWithRawResponse: + def __init__(self, folders: AsyncFoldersResource) -> None: + self._folders = folders + + self.create = async_to_raw_response_wrapper( + folders.create, + ) + self.delete = async_to_raw_response_wrapper( + folders.delete, + ) + self.copy = async_to_raw_response_wrapper( + folders.copy, + ) + self.move = async_to_raw_response_wrapper( + folders.move, + ) + self.rename = async_to_raw_response_wrapper( + folders.rename, + ) + + @cached_property + def job(self) -> AsyncJobResourceWithRawResponse: + return AsyncJobResourceWithRawResponse(self._folders.job) + + +class FoldersResourceWithStreamingResponse: + def __init__(self, folders: FoldersResource) -> None: + self._folders = folders + + self.create = to_streamed_response_wrapper( + folders.create, + ) + self.delete = to_streamed_response_wrapper( + folders.delete, + ) + self.copy = to_streamed_response_wrapper( + folders.copy, + ) + self.move = to_streamed_response_wrapper( + folders.move, + ) + self.rename = to_streamed_response_wrapper( + folders.rename, + ) + + @cached_property + def job(self) -> JobResourceWithStreamingResponse: + return JobResourceWithStreamingResponse(self._folders.job) + + +class AsyncFoldersResourceWithStreamingResponse: + def __init__(self, folders: AsyncFoldersResource) -> None: + self._folders = folders + + self.create = async_to_streamed_response_wrapper( + folders.create, + ) + self.delete = async_to_streamed_response_wrapper( + folders.delete, + ) + self.copy = async_to_streamed_response_wrapper( + folders.copy, + ) + self.move = async_to_streamed_response_wrapper( + folders.move, + ) + self.rename = async_to_streamed_response_wrapper( + folders.rename, + ) + + @cached_property + def job(self) -> AsyncJobResourceWithStreamingResponse: + return AsyncJobResourceWithStreamingResponse(self._folders.job) diff --git a/src/imagekit/resources/files/batch.py b/src/imagekit/resources/folders/job.py similarity index 53% rename from src/imagekit/resources/files/batch.py rename to src/imagekit/resources/folders/job.py index 7c5e14b..d051b7f 100644 --- a/src/imagekit/resources/files/batch.py +++ b/src/imagekit/resources/folders/job.py @@ -2,12 +2,9 @@ from __future__ import annotations -from typing import List - import httpx from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -16,56 +13,47 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ...types.files import batch_delete_params from ..._base_client import make_request_options -from ...types.files.batch_delete_response import BatchDeleteResponse +from ...types.folders.job_get_response import JobGetResponse -__all__ = ["BatchResource", "AsyncBatchResource"] +__all__ = ["JobResource", "AsyncJobResource"] -class BatchResource(SyncAPIResource): +class JobResource(SyncAPIResource): @cached_property - def with_raw_response(self) -> BatchResourceWithRawResponse: + def with_raw_response(self) -> JobResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ - return BatchResourceWithRawResponse(self) + return JobResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> BatchResourceWithStreamingResponse: + def with_streaming_response(self) -> JobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ - return BatchResourceWithStreamingResponse(self) + return JobResourceWithStreamingResponse(self) - def delete( + def get( self, + job_id: str, *, - file_ids: List[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> BatchDeleteResponse: + ) -> JobGetResponse: """ - This API deletes multiple files and all their file versions permanently. - - Note: If a file or specific transformation has been requested in the past, then - the response is cached. Deleting a file does not purge the cache. You can purge - the cache using purge cache API. - - A maximum of 100 files can be deleted at a time. + This API returns the status of a bulk job like copy and move folder operations. Args: - file_ids: An array of fileIds which you want to delete. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -74,59 +62,52 @@ def delete( timeout: Override the client-level default timeout for this request, in seconds """ - return self._post( - "/v1/files/batch/deleteByFileIds", - body=maybe_transform({"file_ids": file_ids}, batch_delete_params.BatchDeleteParams), + if not job_id: + raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}") + return self._get( + f"/v1/bulkJobs/{job_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=BatchDeleteResponse, + cast_to=JobGetResponse, ) -class AsyncBatchResource(AsyncAPIResource): +class AsyncJobResource(AsyncAPIResource): @cached_property - def with_raw_response(self) -> AsyncBatchResourceWithRawResponse: + def with_raw_response(self) -> AsyncJobResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ - return AsyncBatchResourceWithRawResponse(self) + return AsyncJobResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AsyncBatchResourceWithStreamingResponse: + def with_streaming_response(self) -> AsyncJobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ - return AsyncBatchResourceWithStreamingResponse(self) + return AsyncJobResourceWithStreamingResponse(self) - async def delete( + async def get( self, + job_id: str, *, - file_ids: List[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> BatchDeleteResponse: + ) -> JobGetResponse: """ - This API deletes multiple files and all their file versions permanently. - - Note: If a file or specific transformation has been requested in the past, then - the response is cached. Deleting a file does not purge the cache. You can purge - the cache using purge cache API. - - A maximum of 100 files can be deleted at a time. + This API returns the status of a bulk job like copy and move folder operations. Args: - file_ids: An array of fileIds which you want to delete. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -135,47 +116,48 @@ async def delete( timeout: Override the client-level default timeout for this request, in seconds """ - return await self._post( - "/v1/files/batch/deleteByFileIds", - body=await async_maybe_transform({"file_ids": file_ids}, batch_delete_params.BatchDeleteParams), + if not job_id: + raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}") + return await self._get( + f"/v1/bulkJobs/{job_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=BatchDeleteResponse, + cast_to=JobGetResponse, ) -class BatchResourceWithRawResponse: - def __init__(self, batch: BatchResource) -> None: - self._batch = batch +class JobResourceWithRawResponse: + def __init__(self, job: JobResource) -> None: + self._job = job - self.delete = to_raw_response_wrapper( - batch.delete, + self.get = to_raw_response_wrapper( + job.get, ) -class AsyncBatchResourceWithRawResponse: - def __init__(self, batch: AsyncBatchResource) -> None: - self._batch = batch +class AsyncJobResourceWithRawResponse: + def __init__(self, job: AsyncJobResource) -> None: + self._job = job - self.delete = async_to_raw_response_wrapper( - batch.delete, + self.get = async_to_raw_response_wrapper( + job.get, ) -class BatchResourceWithStreamingResponse: - def __init__(self, batch: BatchResource) -> None: - self._batch = batch +class JobResourceWithStreamingResponse: + def __init__(self, job: JobResource) -> None: + self._job = job - self.delete = to_streamed_response_wrapper( - batch.delete, + self.get = to_streamed_response_wrapper( + job.get, ) -class AsyncBatchResourceWithStreamingResponse: - def __init__(self, batch: AsyncBatchResource) -> None: - self._batch = batch +class AsyncJobResourceWithStreamingResponse: + def __init__(self, job: AsyncJobResource) -> None: + self._job = job - self.delete = async_to_streamed_response_wrapper( - batch.delete, + self.get = async_to_streamed_response_wrapper( + job.get, ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 7081896..2c5b94c 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -2,36 +2,25 @@ from __future__ import annotations -from .gps import Gps as Gps -from .thumbnail import Thumbnail as Thumbnail -from .exif_image import ExifImage as ExifImage -from .exif_details import ExifDetails as ExifDetails from .file_copy_params import FileCopyParams as FileCopyParams -from .file_list_params import FileListParams as FileListParams from .file_move_params import FileMoveParams as FileMoveParams -from .interoperability import Interoperability as Interoperability -from .file_list_response import FileListResponse as FileListResponse +from .asset_list_params import AssetListParams as AssetListParams +from .file_get_response import FileGetResponse as FileGetResponse from .file_rename_params import FileRenameParams as FileRenameParams -from .file_add_tags_params import FileAddTagsParams as FileAddTagsParams +from .file_update_params import FileUpdateParams as FileUpdateParams +from .file_upload_params import FileUploadParams as FileUploadParams +from .folder_copy_params import FolderCopyParams as FolderCopyParams +from .folder_move_params import FolderMoveParams as FolderMoveParams +from .asset_list_response import AssetListResponse as AssetListResponse from .file_rename_response import FileRenameResponse as FileRenameResponse +from .file_update_response import FileUpdateResponse as FileUpdateResponse +from .file_upload_response import FileUploadResponse as FileUploadResponse +from .folder_copy_response import FolderCopyResponse as FolderCopyResponse from .folder_create_params import FolderCreateParams as FolderCreateParams from .folder_delete_params import FolderDeleteParams as FolderDeleteParams -from .file_upload_v1_params import FileUploadV1Params as FileUploadV1Params -from .file_upload_v2_params import FileUploadV2Params as FileUploadV2Params -from .file_add_tags_response import FileAddTagsResponse as FileAddTagsResponse -from .file_remove_tags_params import FileRemoveTagsParams as FileRemoveTagsParams -from .file_upload_v1_response import FileUploadV1Response as FileUploadV1Response -from .file_upload_v2_response import FileUploadV2Response as FileUploadV2Response -from .account_get_usage_params import AccountGetUsageParams as AccountGetUsageParams -from .file_remove_tags_response import FileRemoveTagsResponse as FileRemoveTagsResponse -from .account_get_usage_response import AccountGetUsageResponse as AccountGetUsageResponse -from .file_remove_ai_tags_params import FileRemoveAITagsParams as FileRemoveAITagsParams -from .bulk_job_copy_folder_params import BulkJobCopyFolderParams as BulkJobCopyFolderParams -from .bulk_job_move_folder_params import BulkJobMoveFolderParams as BulkJobMoveFolderParams -from .file_remove_ai_tags_response import FileRemoveAITagsResponse as FileRemoveAITagsResponse -from .bulk_job_copy_folder_response import BulkJobCopyFolderResponse as BulkJobCopyFolderResponse -from .bulk_job_move_folder_response import BulkJobMoveFolderResponse as BulkJobMoveFolderResponse -from .bulk_job_retrieve_status_response import BulkJobRetrieveStatusResponse as BulkJobRetrieveStatusResponse +from .folder_move_response import FolderMoveResponse as FolderMoveResponse +from .folder_rename_params import FolderRenameParams as FolderRenameParams +from .folder_rename_response import FolderRenameResponse as FolderRenameResponse from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams from .custom_metadata_field_list_response import CustomMetadataFieldListResponse as CustomMetadataFieldListResponse diff --git a/src/imagekit/types/accounts/__init__.py b/src/imagekit/types/accounts/__init__.py new file mode 100644 index 0000000..cc6d81c --- /dev/null +++ b/src/imagekit/types/accounts/__init__.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .usage_get_params import UsageGetParams as UsageGetParams +from .usage_get_response import UsageGetResponse as UsageGetResponse +from .origin_get_response import OriginGetResponse as OriginGetResponse +from .origin_create_params import OriginCreateParams as OriginCreateParams +from .origin_list_response import OriginListResponse as OriginListResponse +from .origin_update_params import OriginUpdateParams as OriginUpdateParams +from .origin_create_response import OriginCreateResponse as OriginCreateResponse +from .origin_update_response import OriginUpdateResponse as OriginUpdateResponse +from .url_endpoint_get_response import URLEndpointGetResponse as URLEndpointGetResponse +from .url_endpoint_create_params import URLEndpointCreateParams as URLEndpointCreateParams +from .url_endpoint_list_response import URLEndpointListResponse as URLEndpointListResponse +from .url_endpoint_update_params import URLEndpointUpdateParams as URLEndpointUpdateParams +from .url_endpoint_create_response import URLEndpointCreateResponse as URLEndpointCreateResponse +from .url_endpoint_update_response import URLEndpointUpdateResponse as URLEndpointUpdateResponse diff --git a/src/imagekit/types/accounts/origin_create_params.py b/src/imagekit/types/accounts/origin_create_params.py new file mode 100644 index 0000000..7489a1d --- /dev/null +++ b/src/imagekit/types/accounts/origin_create_params.py @@ -0,0 +1,208 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from ..._utils import PropertyInfo + +__all__ = [ + "OriginCreateParams", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "GoogleCloudStorageGcs", + "AzureBlobStorage", + "AkeneoPim", +] + + +class S3(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class S3Compatible(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + endpoint: Required[str] + """Custom S3-compatible endpoint.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3_COMPATIBLE"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] + """Use path-style S3 URLs?""" + + +class CloudinaryBackup(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["CLOUDINARY_BACKUP"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class WebFolder(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Root URL for the web folder origin.""" + + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_FOLDER"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] + """Forward the Host header to origin?""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class WebProxy(TypedDict, total=False): + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_PROXY"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class GoogleCloudStorageGcs(TypedDict, total=False): + bucket: Required[str] + + client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] + + name: Required[str] + """Display name of the origin.""" + + private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] + + type: Required[Literal["GCS"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AzureBlobStorage(TypedDict, total=False): + account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] + + container: Required[str] + + name: Required[str] + """Display name of the origin.""" + + sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] + + type: Required[Literal["AZURE_BLOB"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AkeneoPim(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Akeneo instance base URL.""" + + client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] + """Akeneo API client ID.""" + + client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] + """Akeneo API client secret.""" + + name: Required[str] + """Display name of the origin.""" + + password: Required[str] + """Akeneo API password.""" + + type: Required[Literal["AKENEO_PIM"]] + + username: Required[str] + """Akeneo API username.""" + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +OriginCreateParams: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +] diff --git a/src/imagekit/types/accounts/origin_create_response.py b/src/imagekit/types/accounts/origin_create_response.py new file mode 100644 index 0000000..f4036d6 --- /dev/null +++ b/src/imagekit/types/accounts/origin_create_response.py @@ -0,0 +1,222 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "OriginCreateResponse", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "GoogleCloudStorageGcs", + "AzureBlobStorage", + "AkeneoPim", +] + + +class S3(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + type: Literal["S3"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class S3Compatible(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + endpoint: str + """Custom S3-compatible endpoint.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") + """Use path-style S3 URLs?""" + + type: Literal["S3_COMPATIBLE"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class CloudinaryBackup(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + type: Literal["CLOUDINARY_BACKUP"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class WebFolder(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + base_url: object = FieldInfo(alias="baseUrl") + """Root URL for the web folder origin.""" + + forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") + """Forward the Host header to origin?""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["WEB_FOLDER"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class WebProxy(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["WEB_PROXY"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class GoogleCloudStorageGcs(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + + client_email: str = FieldInfo(alias="clientEmail") + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + + type: Literal["GCS"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class AzureBlobStorage(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + account_name: str = FieldInfo(alias="accountName") + + container: str + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + + type: Literal["AZURE_BLOB"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class AkeneoPim(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + base_url: object = FieldInfo(alias="baseUrl") + """Akeneo instance base URL.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["AKENEO_PIM"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +OriginCreateResponse: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +] diff --git a/src/imagekit/types/accounts/origin_get_response.py b/src/imagekit/types/accounts/origin_get_response.py new file mode 100644 index 0000000..dc7ddca --- /dev/null +++ b/src/imagekit/types/accounts/origin_get_response.py @@ -0,0 +1,222 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "OriginGetResponse", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "GoogleCloudStorageGcs", + "AzureBlobStorage", + "AkeneoPim", +] + + +class S3(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + type: Literal["S3"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class S3Compatible(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + endpoint: str + """Custom S3-compatible endpoint.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") + """Use path-style S3 URLs?""" + + type: Literal["S3_COMPATIBLE"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class CloudinaryBackup(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + type: Literal["CLOUDINARY_BACKUP"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class WebFolder(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + base_url: object = FieldInfo(alias="baseUrl") + """Root URL for the web folder origin.""" + + forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") + """Forward the Host header to origin?""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["WEB_FOLDER"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class WebProxy(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["WEB_PROXY"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class GoogleCloudStorageGcs(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + + client_email: str = FieldInfo(alias="clientEmail") + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + + type: Literal["GCS"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class AzureBlobStorage(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + account_name: str = FieldInfo(alias="accountName") + + container: str + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + + type: Literal["AZURE_BLOB"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class AkeneoPim(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + base_url: object = FieldInfo(alias="baseUrl") + """Akeneo instance base URL.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["AKENEO_PIM"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +OriginGetResponse: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +] diff --git a/src/imagekit/types/accounts/origin_list_response.py b/src/imagekit/types/accounts/origin_list_response.py new file mode 100644 index 0000000..1108ff6 --- /dev/null +++ b/src/imagekit/types/accounts/origin_list_response.py @@ -0,0 +1,232 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "OriginListResponse", + "OriginListResponseItem", + "OriginListResponseItemS3", + "OriginListResponseItemS3Compatible", + "OriginListResponseItemCloudinaryBackup", + "OriginListResponseItemWebFolder", + "OriginListResponseItemWebProxy", + "OriginListResponseItemGoogleCloudStorageGcs", + "OriginListResponseItemAzureBlobStorage", + "OriginListResponseItemAkeneoPim", +] + + +class OriginListResponseItemS3(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + type: Literal["S3"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class OriginListResponseItemS3Compatible(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + endpoint: str + """Custom S3-compatible endpoint.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") + """Use path-style S3 URLs?""" + + type: Literal["S3_COMPATIBLE"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class OriginListResponseItemCloudinaryBackup(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + type: Literal["CLOUDINARY_BACKUP"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class OriginListResponseItemWebFolder(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + base_url: object = FieldInfo(alias="baseUrl") + """Root URL for the web folder origin.""" + + forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") + """Forward the Host header to origin?""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["WEB_FOLDER"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class OriginListResponseItemWebProxy(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["WEB_PROXY"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class OriginListResponseItemGoogleCloudStorageGcs(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + + client_email: str = FieldInfo(alias="clientEmail") + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + + type: Literal["GCS"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class OriginListResponseItemAzureBlobStorage(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + account_name: str = FieldInfo(alias="accountName") + + container: str + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + + type: Literal["AZURE_BLOB"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class OriginListResponseItemAkeneoPim(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + base_url: object = FieldInfo(alias="baseUrl") + """Akeneo instance base URL.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["AKENEO_PIM"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +OriginListResponseItem: TypeAlias = Union[ + OriginListResponseItemS3, + OriginListResponseItemS3Compatible, + OriginListResponseItemCloudinaryBackup, + OriginListResponseItemWebFolder, + OriginListResponseItemWebProxy, + OriginListResponseItemGoogleCloudStorageGcs, + OriginListResponseItemAzureBlobStorage, + OriginListResponseItemAkeneoPim, +] + +OriginListResponse: TypeAlias = List[OriginListResponseItem] diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekit/types/accounts/origin_update_params.py new file mode 100644 index 0000000..a7b39fb --- /dev/null +++ b/src/imagekit/types/accounts/origin_update_params.py @@ -0,0 +1,208 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from ..._utils import PropertyInfo + +__all__ = [ + "OriginUpdateParams", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "GoogleCloudStorageGcs", + "AzureBlobStorage", + "AkeneoPim", +] + + +class S3(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class S3Compatible(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + endpoint: Required[str] + """Custom S3-compatible endpoint.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3_COMPATIBLE"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] + """Use path-style S3 URLs?""" + + +class CloudinaryBackup(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["CLOUDINARY_BACKUP"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class WebFolder(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Root URL for the web folder origin.""" + + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_FOLDER"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] + """Forward the Host header to origin?""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class WebProxy(TypedDict, total=False): + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_PROXY"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class GoogleCloudStorageGcs(TypedDict, total=False): + bucket: Required[str] + + client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] + + name: Required[str] + """Display name of the origin.""" + + private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] + + type: Required[Literal["GCS"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AzureBlobStorage(TypedDict, total=False): + account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] + + container: Required[str] + + name: Required[str] + """Display name of the origin.""" + + sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] + + type: Required[Literal["AZURE_BLOB"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AkeneoPim(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Akeneo instance base URL.""" + + client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] + """Akeneo API client ID.""" + + client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] + """Akeneo API client secret.""" + + name: Required[str] + """Display name of the origin.""" + + password: Required[str] + """Akeneo API password.""" + + type: Required[Literal["AKENEO_PIM"]] + + username: Required[str] + """Akeneo API username.""" + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +OriginUpdateParams: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +] diff --git a/src/imagekit/types/accounts/origin_update_response.py b/src/imagekit/types/accounts/origin_update_response.py new file mode 100644 index 0000000..a7ec735 --- /dev/null +++ b/src/imagekit/types/accounts/origin_update_response.py @@ -0,0 +1,222 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "OriginUpdateResponse", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "GoogleCloudStorageGcs", + "AzureBlobStorage", + "AkeneoPim", +] + + +class S3(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + type: Literal["S3"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class S3Compatible(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + endpoint: str + """Custom S3-compatible endpoint.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") + """Use path-style S3 URLs?""" + + type: Literal["S3_COMPATIBLE"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class CloudinaryBackup(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + """S3 bucket name.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + """Path prefix inside the bucket.""" + + type: Literal["CLOUDINARY_BACKUP"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class WebFolder(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + base_url: object = FieldInfo(alias="baseUrl") + """Root URL for the web folder origin.""" + + forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") + """Forward the Host header to origin?""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["WEB_FOLDER"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class WebProxy(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["WEB_PROXY"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class GoogleCloudStorageGcs(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + bucket: str + + client_email: str = FieldInfo(alias="clientEmail") + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + + type: Literal["GCS"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class AzureBlobStorage(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + account_name: str = FieldInfo(alias="accountName") + + container: str + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + prefix: object + + type: Literal["AZURE_BLOB"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class AkeneoPim(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + + base_url: object = FieldInfo(alias="baseUrl") + """Akeneo instance base URL.""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + + name: str + """Display name of the origin.""" + + type: Literal["AKENEO_PIM"] + + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +OriginUpdateResponse: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +] diff --git a/src/imagekit/types/accounts/url_endpoint_create_params.py b/src/imagekit/types/accounts/url_endpoint_create_params.py new file mode 100644 index 0000000..e604253 --- /dev/null +++ b/src/imagekit/types/accounts/url_endpoint_create_params.py @@ -0,0 +1,57 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from ..._utils import PropertyInfo + +__all__ = [ + "URLEndpointCreateParams", + "URLRewriter", + "URLRewriterCloudinaryURLRewriter", + "URLRewriterImgixURLRewriter", + "URLRewriterAkamaiURLRewriter", +] + + +class URLEndpointCreateParams(TypedDict, total=False): + description: Required[str] + """Description of the URL endpoint.""" + + origins: List[str] + """ + Ordered list of origin IDs to try when the file isn’t in the Media Library; + ImageKit checks them in the sequence provided. Origin must be created before it + can be used in a URL endpoint. + """ + + url_prefix: Annotated[str, PropertyInfo(alias="urlPrefix")] + """ + Path segment appended to your base URL to form the endpoint (letters, digits, + and hyphens only — or empty for the default endpoint). + """ + + url_rewriter: Annotated[URLRewriter, PropertyInfo(alias="urlRewriter")] + """Configuration for third-party URL rewriting.""" + + +class URLRewriterCloudinaryURLRewriter(TypedDict, total=False): + type: Required[Literal["CLOUDINARY"]] + + preserve_asset_delivery_types: Annotated[bool, PropertyInfo(alias="preserveAssetDeliveryTypes")] + """Whether to preserve `/` in the rewritten URL.""" + + +class URLRewriterImgixURLRewriter(TypedDict, total=False): + type: Required[Literal["IMGIX"]] + + +class URLRewriterAkamaiURLRewriter(TypedDict, total=False): + type: Required[Literal["AKAMAI"]] + + +URLRewriter: TypeAlias = Union[ + URLRewriterCloudinaryURLRewriter, URLRewriterImgixURLRewriter, URLRewriterAkamaiURLRewriter +] diff --git a/src/imagekit/types/accounts/url_endpoint_create_response.py b/src/imagekit/types/accounts/url_endpoint_create_response.py new file mode 100644 index 0000000..e2ddecf --- /dev/null +++ b/src/imagekit/types/accounts/url_endpoint_create_response.py @@ -0,0 +1,64 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "URLEndpointCreateResponse", + "URLRewriter", + "URLRewriterCloudinaryURLRewriter", + "URLRewriterImgixURLRewriter", + "URLRewriterAkamaiURLRewriter", +] + + +class URLRewriterCloudinaryURLRewriter(BaseModel): + preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") + """Whether to preserve `/` in the rewritten URL.""" + + type: Literal["CLOUDINARY"] + + +class URLRewriterImgixURLRewriter(BaseModel): + type: Literal["IMGIX"] + + +class URLRewriterAkamaiURLRewriter(BaseModel): + type: Literal["AKAMAI"] + + +URLRewriter: TypeAlias = Union[ + URLRewriterCloudinaryURLRewriter, URLRewriterImgixURLRewriter, URLRewriterAkamaiURLRewriter +] + + +class URLEndpointCreateResponse(BaseModel): + id: str + """Unique identifier for the URL-endpoint. + + This is generated by ImageKit when you create a new URL-endpoint. For the + default URL-endpoint, this is always `default`. + """ + + description: str + """Description of the URL endpoint.""" + + origins: List[str] + """ + Ordered list of origin IDs to try when the file isn’t in the Media Library; + ImageKit checks them in the sequence provided. Origin must be created before it + can be used in a URL endpoint. + """ + + url_prefix: str = FieldInfo(alias="urlPrefix") + """ + Path segment appended to your base URL to form the endpoint (letters, digits, + and hyphens only — or empty for the default endpoint). + """ + + url_rewriter: Optional[URLRewriter] = FieldInfo(alias="urlRewriter", default=None) + """Configuration for third-party URL rewriting.""" diff --git a/src/imagekit/types/accounts/url_endpoint_get_response.py b/src/imagekit/types/accounts/url_endpoint_get_response.py new file mode 100644 index 0000000..ce5b14b --- /dev/null +++ b/src/imagekit/types/accounts/url_endpoint_get_response.py @@ -0,0 +1,64 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "URLEndpointGetResponse", + "URLRewriter", + "URLRewriterCloudinaryURLRewriter", + "URLRewriterImgixURLRewriter", + "URLRewriterAkamaiURLRewriter", +] + + +class URLRewriterCloudinaryURLRewriter(BaseModel): + preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") + """Whether to preserve `/` in the rewritten URL.""" + + type: Literal["CLOUDINARY"] + + +class URLRewriterImgixURLRewriter(BaseModel): + type: Literal["IMGIX"] + + +class URLRewriterAkamaiURLRewriter(BaseModel): + type: Literal["AKAMAI"] + + +URLRewriter: TypeAlias = Union[ + URLRewriterCloudinaryURLRewriter, URLRewriterImgixURLRewriter, URLRewriterAkamaiURLRewriter +] + + +class URLEndpointGetResponse(BaseModel): + id: str + """Unique identifier for the URL-endpoint. + + This is generated by ImageKit when you create a new URL-endpoint. For the + default URL-endpoint, this is always `default`. + """ + + description: str + """Description of the URL endpoint.""" + + origins: List[str] + """ + Ordered list of origin IDs to try when the file isn’t in the Media Library; + ImageKit checks them in the sequence provided. Origin must be created before it + can be used in a URL endpoint. + """ + + url_prefix: str = FieldInfo(alias="urlPrefix") + """ + Path segment appended to your base URL to form the endpoint (letters, digits, + and hyphens only — or empty for the default endpoint). + """ + + url_rewriter: Optional[URLRewriter] = FieldInfo(alias="urlRewriter", default=None) + """Configuration for third-party URL rewriting.""" diff --git a/src/imagekit/types/accounts/url_endpoint_list_response.py b/src/imagekit/types/accounts/url_endpoint_list_response.py new file mode 100644 index 0000000..2ab3bfd --- /dev/null +++ b/src/imagekit/types/accounts/url_endpoint_list_response.py @@ -0,0 +1,70 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "URLEndpointListResponse", + "URLEndpointListResponseItem", + "URLEndpointListResponseItemURLRewriter", + "URLEndpointListResponseItemURLRewriterCloudinaryURLRewriter", + "URLEndpointListResponseItemURLRewriterImgixURLRewriter", + "URLEndpointListResponseItemURLRewriterAkamaiURLRewriter", +] + + +class URLEndpointListResponseItemURLRewriterCloudinaryURLRewriter(BaseModel): + preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") + """Whether to preserve `/` in the rewritten URL.""" + + type: Literal["CLOUDINARY"] + + +class URLEndpointListResponseItemURLRewriterImgixURLRewriter(BaseModel): + type: Literal["IMGIX"] + + +class URLEndpointListResponseItemURLRewriterAkamaiURLRewriter(BaseModel): + type: Literal["AKAMAI"] + + +URLEndpointListResponseItemURLRewriter: TypeAlias = Union[ + URLEndpointListResponseItemURLRewriterCloudinaryURLRewriter, + URLEndpointListResponseItemURLRewriterImgixURLRewriter, + URLEndpointListResponseItemURLRewriterAkamaiURLRewriter, +] + + +class URLEndpointListResponseItem(BaseModel): + id: str + """Unique identifier for the URL-endpoint. + + This is generated by ImageKit when you create a new URL-endpoint. For the + default URL-endpoint, this is always `default`. + """ + + description: str + """Description of the URL endpoint.""" + + origins: List[str] + """ + Ordered list of origin IDs to try when the file isn’t in the Media Library; + ImageKit checks them in the sequence provided. Origin must be created before it + can be used in a URL endpoint. + """ + + url_prefix: str = FieldInfo(alias="urlPrefix") + """ + Path segment appended to your base URL to form the endpoint (letters, digits, + and hyphens only — or empty for the default endpoint). + """ + + url_rewriter: Optional[URLEndpointListResponseItemURLRewriter] = FieldInfo(alias="urlRewriter", default=None) + """Configuration for third-party URL rewriting.""" + + +URLEndpointListResponse: TypeAlias = List[URLEndpointListResponseItem] diff --git a/src/imagekit/types/accounts/url_endpoint_update_params.py b/src/imagekit/types/accounts/url_endpoint_update_params.py new file mode 100644 index 0000000..d83c39a --- /dev/null +++ b/src/imagekit/types/accounts/url_endpoint_update_params.py @@ -0,0 +1,57 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from ..._utils import PropertyInfo + +__all__ = [ + "URLEndpointUpdateParams", + "URLRewriter", + "URLRewriterCloudinaryURLRewriter", + "URLRewriterImgixURLRewriter", + "URLRewriterAkamaiURLRewriter", +] + + +class URLEndpointUpdateParams(TypedDict, total=False): + description: Required[str] + """Description of the URL endpoint.""" + + origins: List[str] + """ + Ordered list of origin IDs to try when the file isn’t in the Media Library; + ImageKit checks them in the sequence provided. Origin must be created before it + can be used in a URL endpoint. + """ + + url_prefix: Annotated[str, PropertyInfo(alias="urlPrefix")] + """ + Path segment appended to your base URL to form the endpoint (letters, digits, + and hyphens only — or empty for the default endpoint). + """ + + url_rewriter: Annotated[URLRewriter, PropertyInfo(alias="urlRewriter")] + """Configuration for third-party URL rewriting.""" + + +class URLRewriterCloudinaryURLRewriter(TypedDict, total=False): + type: Required[Literal["CLOUDINARY"]] + + preserve_asset_delivery_types: Annotated[bool, PropertyInfo(alias="preserveAssetDeliveryTypes")] + """Whether to preserve `/` in the rewritten URL.""" + + +class URLRewriterImgixURLRewriter(TypedDict, total=False): + type: Required[Literal["IMGIX"]] + + +class URLRewriterAkamaiURLRewriter(TypedDict, total=False): + type: Required[Literal["AKAMAI"]] + + +URLRewriter: TypeAlias = Union[ + URLRewriterCloudinaryURLRewriter, URLRewriterImgixURLRewriter, URLRewriterAkamaiURLRewriter +] diff --git a/src/imagekit/types/accounts/url_endpoint_update_response.py b/src/imagekit/types/accounts/url_endpoint_update_response.py new file mode 100644 index 0000000..1486105 --- /dev/null +++ b/src/imagekit/types/accounts/url_endpoint_update_response.py @@ -0,0 +1,64 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "URLEndpointUpdateResponse", + "URLRewriter", + "URLRewriterCloudinaryURLRewriter", + "URLRewriterImgixURLRewriter", + "URLRewriterAkamaiURLRewriter", +] + + +class URLRewriterCloudinaryURLRewriter(BaseModel): + preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") + """Whether to preserve `/` in the rewritten URL.""" + + type: Literal["CLOUDINARY"] + + +class URLRewriterImgixURLRewriter(BaseModel): + type: Literal["IMGIX"] + + +class URLRewriterAkamaiURLRewriter(BaseModel): + type: Literal["AKAMAI"] + + +URLRewriter: TypeAlias = Union[ + URLRewriterCloudinaryURLRewriter, URLRewriterImgixURLRewriter, URLRewriterAkamaiURLRewriter +] + + +class URLEndpointUpdateResponse(BaseModel): + id: str + """Unique identifier for the URL-endpoint. + + This is generated by ImageKit when you create a new URL-endpoint. For the + default URL-endpoint, this is always `default`. + """ + + description: str + """Description of the URL endpoint.""" + + origins: List[str] + """ + Ordered list of origin IDs to try when the file isn’t in the Media Library; + ImageKit checks them in the sequence provided. Origin must be created before it + can be used in a URL endpoint. + """ + + url_prefix: str = FieldInfo(alias="urlPrefix") + """ + Path segment appended to your base URL to form the endpoint (letters, digits, + and hyphens only — or empty for the default endpoint). + """ + + url_rewriter: Optional[URLRewriter] = FieldInfo(alias="urlRewriter", default=None) + """Configuration for third-party URL rewriting.""" diff --git a/src/imagekit/types/account_get_usage_params.py b/src/imagekit/types/accounts/usage_get_params.py similarity index 86% rename from src/imagekit/types/account_get_usage_params.py rename to src/imagekit/types/accounts/usage_get_params.py index ab07ac0..298a969 100644 --- a/src/imagekit/types/account_get_usage_params.py +++ b/src/imagekit/types/accounts/usage_get_params.py @@ -6,12 +6,12 @@ from datetime import date from typing_extensions import Required, Annotated, TypedDict -from .._utils import PropertyInfo +from ..._utils import PropertyInfo -__all__ = ["AccountGetUsageParams"] +__all__ = ["UsageGetParams"] -class AccountGetUsageParams(TypedDict, total=False): +class UsageGetParams(TypedDict, total=False): end_date: Required[Annotated[Union[str, date], PropertyInfo(alias="endDate", format="iso8601")]] """Specify a `endDate` in `YYYY-MM-DD` format. diff --git a/src/imagekit/types/account_get_usage_response.py b/src/imagekit/types/accounts/usage_get_response.py similarity index 89% rename from src/imagekit/types/account_get_usage_response.py rename to src/imagekit/types/accounts/usage_get_response.py index 524d9f3..651552c 100644 --- a/src/imagekit/types/account_get_usage_response.py +++ b/src/imagekit/types/accounts/usage_get_response.py @@ -4,12 +4,12 @@ from pydantic import Field as FieldInfo -from .._models import BaseModel +from ..._models import BaseModel -__all__ = ["AccountGetUsageResponse"] +__all__ = ["UsageGetResponse"] -class AccountGetUsageResponse(BaseModel): +class UsageGetResponse(BaseModel): bandwidth_bytes: Optional[int] = FieldInfo(alias="bandwidthBytes", default=None) """Amount of bandwidth used in bytes.""" diff --git a/src/imagekit/types/asset_list_params.py b/src/imagekit/types/asset_list_params.py new file mode 100644 index 0000000..ea4024e --- /dev/null +++ b/src/imagekit/types/asset_list_params.py @@ -0,0 +1,81 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["AssetListParams"] + + +class AssetListParams(TypedDict, total=False): + file_type: Annotated[Literal["all", "image", "non-image"], PropertyInfo(alias="fileType")] + """Filter results by file type. + + - `all` — include all file types + - `image` — include only image files + - `non-image` — include only non-image files (e.g., JS, CSS, video) + """ + + limit: int + """The maximum number of results to return in response.""" + + path: str + """Folder path if you want to limit the search within a specific folder. + + For example, `/sales-banner/` will only search in folder sales-banner. + + Note : If your use case involves searching within a folder as well as its + subfolders, you can use `path` parameter in `searchQuery` with appropriate + operator. Checkout + [Supported parameters](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#supported-parameters) + for more information. + """ + + search_query: Annotated[str, PropertyInfo(alias="searchQuery")] + """Query string in a Lucene-like query language e.g. `createdAt > "7d"`. + + Note : When the searchQuery parameter is present, the following query parameters + will have no effect on the result: + + 1. `tags` + 2. `type` + 3. `name` + + [Learn more](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#advanced-search-queries) + from examples. + """ + + skip: int + """The number of results to skip before returning results.""" + + sort: Literal[ + "ASC_NAME", + "DESC_NAME", + "ASC_CREATED", + "DESC_CREATED", + "ASC_UPDATED", + "DESC_UPDATED", + "ASC_HEIGHT", + "DESC_HEIGHT", + "ASC_WIDTH", + "DESC_WIDTH", + "ASC_SIZE", + "DESC_SIZE", + "ASC_RELEVANCE", + "DESC_RELEVANCE", + ] + """ + Sort the results by one of the supported fields in ascending or descending + order. + """ + + type: Literal["file", "file-version", "folder", "all"] + """Filter results by asset type. + + - `file` — returns only files + - `file-version` — returns specific file versions + - `folder` — returns only folders + - `all` — returns both files and folders (excludes `file-version`) + """ diff --git a/src/imagekit/types/file_list_response.py b/src/imagekit/types/asset_list_response.py similarity index 61% rename from src/imagekit/types/file_list_response.py rename to src/imagekit/types/asset_list_response.py index cc6fd58..7a0fdd1 100644 --- a/src/imagekit/types/file_list_response.py +++ b/src/imagekit/types/asset_list_response.py @@ -1,16 +1,23 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional -from typing_extensions import TypeAlias +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias from pydantic import Field as FieldInfo from .._models import BaseModel -__all__ = ["FileListResponse", "FileListResponseItem", "FileListResponseItemAITag", "FileListResponseItemVersionInfo"] +__all__ = [ + "AssetListResponse", + "AssetListResponseItem", + "AssetListResponseItemFileDetails", + "AssetListResponseItemFileDetailsAITag", + "AssetListResponseItemFileDetailsVersionInfo", + "AssetListResponseItemFolderDetails", +] -class FileListResponseItemAITag(BaseModel): +class AssetListResponseItemFileDetailsAITag(BaseModel): confidence: Optional[float] = None """Confidence score of the tag.""" @@ -24,7 +31,7 @@ class FileListResponseItemAITag(BaseModel): """ -class FileListResponseItemVersionInfo(BaseModel): +class AssetListResponseItemFileDetailsVersionInfo(BaseModel): id: Optional[str] = None """Unique identifier of the file version.""" @@ -32,8 +39,8 @@ class FileListResponseItemVersionInfo(BaseModel): """Name of the file version.""" -class FileListResponseItem(BaseModel): - ai_tags: Optional[List[FileListResponseItemAITag]] = FieldInfo(alias="AITags", default=None) +class AssetListResponseItemFileDetails(BaseModel): + ai_tags: Optional[List[AssetListResponseItemFileDetailsAITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) @@ -107,11 +114,44 @@ class FileListResponseItem(BaseModel): url: Optional[str] = None """URL of the file.""" - version_info: Optional[FileListResponseItemVersionInfo] = FieldInfo(alias="versionInfo", default=None) + version_info: Optional[AssetListResponseItemFileDetailsVersionInfo] = FieldInfo(alias="versionInfo", default=None) """An object with details of the file version.""" width: Optional[float] = None """Width of the file.""" -FileListResponse: TypeAlias = List[FileListResponseItem] +class AssetListResponseItemFolderDetails(BaseModel): + created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + """Date and time when the folder was created. + + The date and time is in ISO8601 format. + """ + + folder_id: Optional[str] = FieldInfo(alias="folderId", default=None) + """Unique identifier of the asset.""" + + folder_path: Optional[str] = FieldInfo(alias="folderPath", default=None) + """Path of the folder. + + This is the path you would use in the URL to access the folder. For example, if + the folder is at the root of the media library, the path will be /folder. If the + folder is inside another folder named images, the path will be /images/folder. + """ + + name: Optional[str] = None + """Name of the asset.""" + + type: Optional[Literal["folder"]] = None + """Type of the asset.""" + + updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + """Date and time when the folder was last updated. + + The date and time is in ISO8601 format. + """ + + +AssetListResponseItem: TypeAlias = Union[AssetListResponseItemFileDetails, AssetListResponseItemFolderDetails] + +AssetListResponse: TypeAlias = List[AssetListResponseItem] diff --git a/src/imagekit/types/beta/__init__.py b/src/imagekit/types/beta/__init__.py new file mode 100644 index 0000000..f8ee8b1 --- /dev/null +++ b/src/imagekit/types/beta/__init__.py @@ -0,0 +1,3 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations diff --git a/src/imagekit/types/beta/v2/__init__.py b/src/imagekit/types/beta/v2/__init__.py new file mode 100644 index 0000000..c5c3d83 --- /dev/null +++ b/src/imagekit/types/beta/v2/__init__.py @@ -0,0 +1,6 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .file_upload_params import FileUploadParams as FileUploadParams +from .file_upload_response import FileUploadResponse as FileUploadResponse diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekit/types/beta/v2/file_upload_params.py new file mode 100644 index 0000000..82fa22a --- /dev/null +++ b/src/imagekit/types/beta/v2/file_upload_params.py @@ -0,0 +1,325 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List, Union, Iterable +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from ...._types import FileTypes +from ...._utils import PropertyInfo + +__all__ = [ + "FileUploadParams", + "Extension", + "ExtensionRemovedotBgExtension", + "ExtensionRemovedotBgExtensionOptions", + "ExtensionAutoTaggingExtension", + "ExtensionAutoDescriptionExtension", + "Transformation", + "TransformationPost", + "TransformationPostSimplePostTransformation", + "TransformationPostConvertGifToVideo", + "TransformationPostGenerateAThumbnail", + "TransformationPostAdaptiveBitrateStreaming", +] + + +class FileUploadParams(TypedDict, total=False): + file: Required[FileTypes] + """The API accepts any of the following: + + - **Binary data** – send the raw bytes as `multipart/form-data`. + - **HTTP / HTTPS URL** – a publicly reachable URL that ImageKit’s servers can + fetch. + - **Base64 string** – the file encoded as a Base64 data URI or plain Base64. + + When supplying a URL, the server must receive the response headers within 8 + seconds; otherwise the request fails with 400 Bad Request. + """ + + file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] + """The name with which the file has to be uploaded.""" + + token: str + """This is the client-generated JSON Web Token (JWT). + + The ImageKit.io server uses it to authenticate and check that the upload request + parameters have not been tampered with after the token has been generated. Learn + how to create the token on the page below. This field is only required for + authentication when uploading a file from the client side. + + **Note**: Sending a JWT that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new token. + + **⚠️Warning**: JWT must be generated on the server-side because it is generated + using your account's private API key. This field is required for authentication + when uploading a file from the client-side. + """ + + checks: str + """ + Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file-v2#upload-api-checks). + """ + + custom_coordinates: Annotated[str, PropertyInfo(alias="customCoordinates")] + """Define an important area in the image. + + This is only relevant for image type files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + """ + + custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] + """JSON key-value pairs to associate with the asset. + + Create the custom metadata fields before setting these values. + """ + + description: str + """Optional text to describe the contents of the file.""" + + extensions: Iterable[Extension] + """Array of extensions to be applied to the image. + + Each extension can be configured with specific parameters based on the extension + type. + """ + + folder: str + """The folder path in which the image has to be uploaded. + + If the folder(s) didn't exist before, a new folder(s) is created. Using multiple + `/` creates a nested folder. + """ + + is_private_file: Annotated[bool, PropertyInfo(alias="isPrivateFile")] + """Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + """ + + is_published: Annotated[bool, PropertyInfo(alias="isPublished")] + """Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + """ + + overwrite_ai_tags: Annotated[bool, PropertyInfo(alias="overwriteAITags")] + """ + If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + """ + + overwrite_custom_metadata: Annotated[bool, PropertyInfo(alias="overwriteCustomMetadata")] + """ + If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + """ + + overwrite_file: Annotated[bool, PropertyInfo(alias="overwriteFile")] + """ + If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + """ + + overwrite_tags: Annotated[bool, PropertyInfo(alias="overwriteTags")] + """ + If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + """ + + response_fields: Annotated[ + List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ], + PropertyInfo(alias="responseFields"), + ] + """Array of response field keys to include in the API response body.""" + + tags: List[str] + """Set the tags while uploading the file. Provide an array of tag strings (e.g. + + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. + """ + + transformation: Transformation + """Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + """ + + use_unique_file_name: Annotated[bool, PropertyInfo(alias="useUniqueFileName")] + """Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + """ + + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ + + +class ExtensionRemovedotBgExtensionOptions(TypedDict, total=False): + add_shadow: bool + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: str + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: str + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: bool + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class ExtensionRemovedotBgExtension(TypedDict, total=False): + name: Required[Literal["remove-bg"]] + """Specifies the background removal extension.""" + + options: ExtensionRemovedotBgExtensionOptions + + +class ExtensionAutoTaggingExtension(TypedDict, total=False): + max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] + """Maximum number of tags to attach to the asset.""" + + min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] + """Minimum confidence level for tags to be considered valid.""" + + name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] + """Specifies the auto-tagging extension used.""" + + +class ExtensionAutoDescriptionExtension(TypedDict, total=False): + name: Required[Literal["ai-auto-description"]] + """Specifies the auto description extension.""" + + +Extension: TypeAlias = Union[ + ExtensionRemovedotBgExtension, ExtensionAutoTaggingExtension, ExtensionAutoDescriptionExtension +] + + +class TransformationPostSimplePostTransformation(TypedDict, total=False): + type: Required[Literal["transformation"]] + """Transformation type.""" + + value: Required[str] + """Transformation string (e.g. + + `w-200,h-200`). + Same syntax as ImageKit URL-based transformations. + """ + + +class TransformationPostConvertGifToVideo(TypedDict, total=False): + type: Required[Literal["gif-to-video"]] + """Converts an animated GIF into an MP4.""" + + value: str + """Optional transformation string to apply to the output video. + + **Example**: `q-80` + """ + + +class TransformationPostGenerateAThumbnail(TypedDict, total=False): + type: Required[Literal["thumbnail"]] + """Generates a thumbnail image.""" + + value: str + """Optional transformation string. + + **Example**: `w-150,h-150` + """ + + +class TransformationPostAdaptiveBitrateStreaming(TypedDict, total=False): + protocol: Required[Literal["hls", "dash"]] + """Streaming protocol to use (`hls` or `dash`).""" + + type: Required[Literal["abs"]] + """Adaptive Bitrate Streaming (ABS) setup.""" + + value: Required[str] + """ + List of different representations you want to create separated by an underscore. + """ + + +TransformationPost: TypeAlias = Union[ + TransformationPostSimplePostTransformation, + TransformationPostConvertGifToVideo, + TransformationPostGenerateAThumbnail, + TransformationPostAdaptiveBitrateStreaming, +] + + +class Transformation(TypedDict, total=False): + post: Iterable[TransformationPost] + """List of transformations to apply _after_ the file is uploaded. + + Each item must match one of the following types: `transformation`, + `gif-to-video`, `thumbnail`, `abs`. + """ + + pre: str + """Transformation string to apply before uploading the file to the Media Library. + + Useful for optimizing files at ingestion. + """ diff --git a/src/imagekit/types/beta/v2/file_upload_response.py b/src/imagekit/types/beta/v2/file_upload_response.py new file mode 100644 index 0000000..d719c38 --- /dev/null +++ b/src/imagekit/types/beta/v2/file_upload_response.py @@ -0,0 +1,341 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ...._models import BaseModel + +__all__ = [ + "FileUploadResponse", + "AITag", + "ExtensionStatus", + "Metadata", + "MetadataExif", + "MetadataExifExif", + "MetadataExifGps", + "MetadataExifImage", + "MetadataExifInteroperability", + "MetadataExifThumbnail", + "VersionInfo", +] + + +class AITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Array of `AITags` associated with the image. + + If no `AITags` are set, it will be null. These tags can be added using the + `google-auto-tagging` or `aws-auto-tagging` extensions. + """ + + +class ExtensionStatus(BaseModel): + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="aws-auto-tagging", default=None + ) + + google_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="google-auto-tagging", default=None + ) + + remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) + + +class MetadataExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class MetadataExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class MetadataExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class MetadataExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class MetadataExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class MetadataExif(BaseModel): + exif: Optional[MetadataExifExif] = None + """Object containing Exif details.""" + + gps: Optional[MetadataExifGps] = None + """Object containing GPS information.""" + + image: Optional[MetadataExifImage] = None + """Object containing EXIF image information.""" + + interoperability: Optional[MetadataExifInteroperability] = None + """JSON object.""" + + makernote: Optional[Dict[str, object]] = None + + thumbnail: Optional[MetadataExifThumbnail] = None + """Object containing Thumbnail information.""" + + +class Metadata(BaseModel): + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + density: Optional[int] = None + """The density of the image in DPI.""" + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + exif: Optional[MetadataExif] = None + + format: Optional[str] = None + """The format of the file (e.g., 'jpg', 'mp4').""" + + has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) + """Indicates if the image has a color profile.""" + + has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) + """Indicates if the image contains transparent areas.""" + + height: Optional[int] = None + """The height of the image or video in pixels.""" + + p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) + """Perceptual hash of the image.""" + + quality: Optional[int] = None + """The quality indicator of the image.""" + + size: Optional[int] = None + """The file size in bytes.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[int] = None + """The width of the image or video in pixels.""" + + +class VersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class FileUploadResponse(BaseModel): + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the uploaded file by auto tagging.""" + + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """ + Value of custom coordinates associated with the image in the format + `x,y,width,height`. If `customCoordinates` are not defined, then it is `null`. + Send `customCoordinates` in `responseFields` in API request to get the value of + this field. + """ + + custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + """A key-value data associated with the asset. + + Use `responseField` in API request to get `customMetadata` in the upload API + response. Before setting any custom metadata on an asset, you have to create the + field using custom metadata fields API. Send `customMetadata` in + `responseFields` in API request to get the value of this field. + """ + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + embedded_metadata: Optional[Dict[str, object]] = FieldInfo(alias="embeddedMetadata", default=None) + """Consolidated embedded metadata associated with the file. + + It includes exif, iptc, and xmp data. Send `embeddedMetadata` in + `responseFields` in API request to get embeddedMetadata in the upload API + response. + """ + + extension_status: Optional[ExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) + """ + Extension names with their processing status at the time of completion of the + request. It could have one of the following status values: + + `success`: The extension has been successfully applied. `failed`: The extension + has failed and will not be retried. `pending`: The extension will finish + processing in some time. On completion, the final status (success / failed) will + be sent to the `webhookUrl` provided. + + If no extension was requested, then this parameter is not returned. + """ + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique fileId. + + Store this fileld in your database, as this will be used to perform update + action on this file. + """ + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """The relative path of the file in the media library e.g. + + `/marketing-assets/new-banner.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the uploaded file. Possible values are `image`, `non-image`.""" + + height: Optional[float] = None + """Height of the image in pixels (Only for images)""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Is the file marked as private. + + It can be either `true` or `false`. Send `isPrivateFile` in `responseFields` in + API request to get the value of this field. + """ + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Is the file published or in draft state. + + It can be either `true` or `false`. Send `isPublished` in `responseFields` in + API request to get the value of this field. + """ + + metadata: Optional[Metadata] = None + """Legacy metadata. + + Send `metadata` in `responseFields` in API request to get metadata in the upload + API response. + """ + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the image file in Bytes.""" + + tags: Optional[List[str]] = None + """The array of tags associated with the asset. + + If no tags are set, it will be `null`. Send `tags` in `responseFields` in API + request to get the value of this field. + """ + + thumbnail_url: Optional[str] = FieldInfo(alias="thumbnailUrl", default=None) + """In the case of an image, a small thumbnail URL.""" + + url: Optional[str] = None + """A publicly accessible URL of the file.""" + + version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object containing the file or file version's `id` (versionId) and `name`.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[float] = None + """Width of the image in pixels (Only for Images)""" diff --git a/src/imagekit/types/bulk_job_retrieve_status_response.py b/src/imagekit/types/bulk_job_retrieve_status_response.py deleted file mode 100644 index 5d50476..0000000 --- a/src/imagekit/types/bulk_job_retrieve_status_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["BulkJobRetrieveStatusResponse"] - - -class BulkJobRetrieveStatusResponse(BaseModel): - job_id: Optional[str] = FieldInfo(alias="jobId", default=None) - """Unique identifier of the bulk job.""" - - status: Optional[str] = None - """Status of the bulk job. Possible values - `Pending`, `Completed`.""" - - type: Optional[str] = None - """Type of the bulk job. Possible values - `COPY_FOLDER`, `MOVE_FOLDER`.""" diff --git a/src/imagekit/types/cache/__init__.py b/src/imagekit/types/cache/__init__.py new file mode 100644 index 0000000..76e5283 --- /dev/null +++ b/src/imagekit/types/cache/__init__.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .invalidation_get_response import InvalidationGetResponse as InvalidationGetResponse +from .invalidation_create_params import InvalidationCreateParams as InvalidationCreateParams +from .invalidation_create_response import InvalidationCreateResponse as InvalidationCreateResponse diff --git a/src/imagekit/types/files/purge_execute_params.py b/src/imagekit/types/cache/invalidation_create_params.py similarity index 72% rename from src/imagekit/types/files/purge_execute_params.py rename to src/imagekit/types/cache/invalidation_create_params.py index aa1e93d..55df58f 100644 --- a/src/imagekit/types/files/purge_execute_params.py +++ b/src/imagekit/types/cache/invalidation_create_params.py @@ -4,9 +4,9 @@ from typing_extensions import Required, TypedDict -__all__ = ["PurgeExecuteParams"] +__all__ = ["InvalidationCreateParams"] -class PurgeExecuteParams(TypedDict, total=False): +class InvalidationCreateParams(TypedDict, total=False): url: Required[str] """The full URL of the file to be purged.""" diff --git a/src/imagekit/types/files/purge_execute_response.py b/src/imagekit/types/cache/invalidation_create_response.py similarity index 81% rename from src/imagekit/types/files/purge_execute_response.py rename to src/imagekit/types/cache/invalidation_create_response.py index bba594a..2dfbce8 100644 --- a/src/imagekit/types/files/purge_execute_response.py +++ b/src/imagekit/types/cache/invalidation_create_response.py @@ -6,10 +6,10 @@ from ..._models import BaseModel -__all__ = ["PurgeExecuteResponse"] +__all__ = ["InvalidationCreateResponse"] -class PurgeExecuteResponse(BaseModel): +class InvalidationCreateResponse(BaseModel): request_id: Optional[str] = FieldInfo(alias="requestId", default=None) """Unique identifier of the purge request. diff --git a/src/imagekit/types/files/purge_status_response.py b/src/imagekit/types/cache/invalidation_get_response.py similarity index 78% rename from src/imagekit/types/files/purge_status_response.py rename to src/imagekit/types/cache/invalidation_get_response.py index c80f1d3..96c1304 100644 --- a/src/imagekit/types/files/purge_status_response.py +++ b/src/imagekit/types/cache/invalidation_get_response.py @@ -5,9 +5,9 @@ from ..._models import BaseModel -__all__ = ["PurgeStatusResponse"] +__all__ = ["InvalidationGetResponse"] -class PurgeStatusResponse(BaseModel): +class InvalidationGetResponse(BaseModel): status: Optional[Literal["Pending", "Completed"]] = None """Status of the purge request.""" diff --git a/src/imagekit/types/custom_metadata_field_create_params.py b/src/imagekit/types/custom_metadata_field_create_params.py index a971d1a..1d029fd 100644 --- a/src/imagekit/types/custom_metadata_field_create_params.py +++ b/src/imagekit/types/custom_metadata_field_create_params.py @@ -29,7 +29,7 @@ class CustomMetadataFieldCreateParams(TypedDict, total=False): class Schema(TypedDict, total=False): - type: Required[Literal["Text", "TextArea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"]] + type: Required[Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"]] """Type of the custom metadata field.""" default_value: Annotated[Union[str, float, bool, List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue")] diff --git a/src/imagekit/types/custom_metadata_field_create_response.py b/src/imagekit/types/custom_metadata_field_create_response.py index 7113c1f..dceb4f6 100644 --- a/src/imagekit/types/custom_metadata_field_create_response.py +++ b/src/imagekit/types/custom_metadata_field_create_response.py @@ -11,7 +11,7 @@ class Schema(BaseModel): - type: Literal["Text", "TextArea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] + type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] """Type of the custom metadata field.""" default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( diff --git a/src/imagekit/types/custom_metadata_field_list_params.py b/src/imagekit/types/custom_metadata_field_list_params.py index f6df562..41eb2bd 100644 --- a/src/imagekit/types/custom_metadata_field_list_params.py +++ b/src/imagekit/types/custom_metadata_field_list_params.py @@ -11,7 +11,4 @@ class CustomMetadataFieldListParams(TypedDict, total=False): include_deleted: Annotated[bool, PropertyInfo(alias="includeDeleted")] - """Set it to `true` to include deleted field objects in the API response. - - Default value is `false`. - """ + """Set it to `true` to include deleted field objects in the API response.""" diff --git a/src/imagekit/types/custom_metadata_field_list_response.py b/src/imagekit/types/custom_metadata_field_list_response.py index 90c7bce..03f6c25 100644 --- a/src/imagekit/types/custom_metadata_field_list_response.py +++ b/src/imagekit/types/custom_metadata_field_list_response.py @@ -15,7 +15,7 @@ class CustomMetadataFieldListResponseItemSchema(BaseModel): - type: Literal["Text", "TextArea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] + type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] """Type of the custom metadata field.""" default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( diff --git a/src/imagekit/types/custom_metadata_field_update_response.py b/src/imagekit/types/custom_metadata_field_update_response.py index dd98d10..3789663 100644 --- a/src/imagekit/types/custom_metadata_field_update_response.py +++ b/src/imagekit/types/custom_metadata_field_update_response.py @@ -11,7 +11,7 @@ class Schema(BaseModel): - type: Literal["Text", "TextArea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] + type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] """Type of the custom metadata field.""" default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( diff --git a/src/imagekit/types/exif_details.py b/src/imagekit/types/exif_details.py deleted file mode 100644 index 080717a..0000000 --- a/src/imagekit/types/exif_details.py +++ /dev/null @@ -1,63 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["ExifDetails"] - - -class ExifDetails(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) diff --git a/src/imagekit/types/exif_image.py b/src/imagekit/types/exif_image.py deleted file mode 100644 index fcd316e..0000000 --- a/src/imagekit/types/exif_image.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["ExifImage"] - - -class ExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) diff --git a/src/imagekit/types/files/version_retrieve_response.py b/src/imagekit/types/file_get_response.py similarity index 96% rename from src/imagekit/types/files/version_retrieve_response.py rename to src/imagekit/types/file_get_response.py index 9d7d883..8f229ae 100644 --- a/src/imagekit/types/files/version_retrieve_response.py +++ b/src/imagekit/types/file_get_response.py @@ -4,9 +4,9 @@ from pydantic import Field as FieldInfo -from ..._models import BaseModel +from .._models import BaseModel -__all__ = ["VersionRetrieveResponse", "AITag", "VersionInfo"] +__all__ = ["FileGetResponse", "AITag", "VersionInfo"] class AITag(BaseModel): @@ -31,7 +31,7 @@ class VersionInfo(BaseModel): """Name of the file version.""" -class VersionRetrieveResponse(BaseModel): +class FileGetResponse(BaseModel): ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" diff --git a/src/imagekit/types/file_list_params.py b/src/imagekit/types/file_list_params.py deleted file mode 100644 index 2cfe153..0000000 --- a/src/imagekit/types/file_list_params.py +++ /dev/null @@ -1,81 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["FileListParams"] - - -class FileListParams(TypedDict, total=False): - file_type: Annotated[str, PropertyInfo(alias="fileType")] - """Type of files to include in the result set. Accepts three values: - - `all` - include all types of files in the result set. `image` - only search in - image type files. `non-image` - only search in files that are not images, e.g., - JS or CSS or video files. - - Default value - `all` - """ - - limit: str - """The maximum number of results to return in response: - - Minimum value - 1 - - Maximum value - 1000 - - Default value - 1000 - """ - - path: str - """Folder path if you want to limit the search within a specific folder. - - For example, `/sales-banner/` will only search in folder sales-banner. - """ - - search_query: Annotated[str, PropertyInfo(alias="searchQuery")] - """Query string in a Lucene-like query language e.g. `createdAt > "7d"`. - - Note : When the searchQuery parameter is present, the following query parameters - will have no effect on the result: - - 1. `tags` - 2. `type` - 3. `name` - - [Learn more](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#advanced-search-queries) - from examples. - """ - - skip: str - """The number of results to skip before returning results: - - Minimum value - 0 - - Default value - 0 - """ - - sort: str - """You can sort based on the following fields: - - 1. name - `ASC_NAME` or `DESC_NAME` - 2. createdAt - `ASC_CREATED` or `DESC_CREATED` - 3. updatedAt - `ASC_UPDATED` or `DESC_UPDATED` - 4. height - `ASC_HEIGHT` or `DESC_HEIGHT` - 5. width - `ASC_WIDTH` or `DESC_WIDTH` - 6. size - `ASC_SIZE` or `DESC_SIZE` - - Default value - `ASC_CREATED` - """ - - type: Literal["file", "file-version", "folder", "all"] - """Limit search to one of `file`, `file-version`, or `folder`. - - Pass `all` to include `files` and `folders` in search results (`file-version` - will not be included in this case). - - Default value - `file` - """ diff --git a/src/imagekit/types/files/detail_update_params.py b/src/imagekit/types/file_update_params.py similarity index 87% rename from src/imagekit/types/files/detail_update_params.py rename to src/imagekit/types/file_update_params.py index c524d76..d47ec07 100644 --- a/src/imagekit/types/files/detail_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -5,15 +5,16 @@ from typing import List, Union, Iterable, Optional from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from ..._utils import PropertyInfo +from .._utils import PropertyInfo __all__ = [ - "DetailUpdateParams", + "FileUpdateParams", "UpdateFileDetails", "UpdateFileDetailsExtension", "UpdateFileDetailsExtensionRemovedotBgExtension", "UpdateFileDetailsExtensionRemovedotBgExtensionOptions", "UpdateFileDetailsExtensionAutoTaggingExtension", + "UpdateFileDetailsExtensionAutoDescriptionExtension", "ChangePublicationStatus", "ChangePublicationStatusPublish", ] @@ -34,6 +35,9 @@ class UpdateFileDetails(TypedDict, total=False): API. """ + description: str + """Optional text to describe the contents of the file.""" + extensions: Iterable[UpdateFileDetailsExtension] """Array of extensions to be applied to the asset. @@ -115,8 +119,15 @@ class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): """Specifies the auto-tagging extension used.""" +class UpdateFileDetailsExtensionAutoDescriptionExtension(TypedDict, total=False): + name: Required[Literal["ai-auto-description"]] + """Specifies the auto description extension.""" + + UpdateFileDetailsExtension: TypeAlias = Union[ - UpdateFileDetailsExtensionRemovedotBgExtension, UpdateFileDetailsExtensionAutoTaggingExtension + UpdateFileDetailsExtensionRemovedotBgExtension, + UpdateFileDetailsExtensionAutoTaggingExtension, + UpdateFileDetailsExtensionAutoDescriptionExtension, ] @@ -136,4 +147,4 @@ class ChangePublicationStatusPublish(TypedDict, total=False): """ -DetailUpdateParams: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] +FileUpdateParams: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] diff --git a/src/imagekit/types/files/detail_update_response.py b/src/imagekit/types/file_update_response.py similarity index 93% rename from src/imagekit/types/files/detail_update_response.py rename to src/imagekit/types/file_update_response.py index baaeff9..bd9533f 100644 --- a/src/imagekit/types/files/detail_update_response.py +++ b/src/imagekit/types/file_update_response.py @@ -5,9 +5,9 @@ from pydantic import Field as FieldInfo -from ..._models import BaseModel +from .._models import BaseModel -__all__ = ["DetailUpdateResponse", "AITag", "ExtensionStatus", "VersionInfo"] +__all__ = ["FileUpdateResponse", "AITag", "ExtensionStatus", "VersionInfo"] class AITag(BaseModel): @@ -25,6 +25,10 @@ class AITag(BaseModel): class ExtensionStatus(BaseModel): + ai_auto_description: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="ai-auto-description", default=None + ) + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( alias="aws-auto-tagging", default=None ) @@ -44,7 +48,7 @@ class VersionInfo(BaseModel): """Name of the file version.""" -class DetailUpdateResponse(BaseModel): +class FileUpdateResponse(BaseModel): ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py new file mode 100644 index 0000000..291fbf4 --- /dev/null +++ b/src/imagekit/types/file_upload_params.py @@ -0,0 +1,357 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List, Union, Iterable +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from .._types import FileTypes +from .._utils import PropertyInfo + +__all__ = [ + "FileUploadParams", + "Extension", + "ExtensionRemovedotBgExtension", + "ExtensionRemovedotBgExtensionOptions", + "ExtensionAutoTaggingExtension", + "ExtensionAutoDescriptionExtension", + "Transformation", + "TransformationPost", + "TransformationPostSimplePostTransformation", + "TransformationPostConvertGifToVideo", + "TransformationPostGenerateAThumbnail", + "TransformationPostAdaptiveBitrateStreaming", +] + + +class FileUploadParams(TypedDict, total=False): + file: Required[FileTypes] + """The API accepts any of the following: + + - **Binary data** – send the raw bytes as `multipart/form-data`. + - **HTTP / HTTPS URL** – a publicly reachable URL that ImageKit’s servers can + fetch. + - **Base64 string** – the file encoded as a Base64 data URI or plain Base64. + + When supplying a URL, the server must receive the response headers within 8 + seconds; otherwise the request fails with 400 Bad Request. + """ + + file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] + """The name with which the file has to be uploaded. The file name can contain: + + - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + - Special Characters: `.`, `-` + + Any other character including space will be replaced by `_` + """ + + token: str + """ + A unique value that the ImageKit.io server will use to recognize and prevent + subsequent retries for the same request. We suggest using V4 UUIDs, or another + random string with enough entropy to avoid collisions. This field is only + required for authentication when uploading a file from the client side. + + **Note**: Sending a value that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new value for this field. + """ + + checks: str + """ + Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + """ + + custom_coordinates: Annotated[str, PropertyInfo(alias="customCoordinates")] + """Define an important area in the image. + + This is only relevant for image type files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + """ + + custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] + """JSON key-value pairs to associate with the asset. + + Create the custom metadata fields before setting these values. + """ + + description: str + """Optional text to describe the contents of the file.""" + + expire: int + """The time until your signature is valid. + + It must be a [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 + hour into the future. It should be in seconds. This field is only required for + authentication when uploading a file from the client side. + """ + + extensions: Iterable[Extension] + """Array of extensions to be applied to the image. + + Each extension can be configured with specific parameters based on the extension + type. + """ + + folder: str + """The folder path in which the image has to be uploaded. + + If the folder(s) didn't exist before, a new folder(s) is created. + + The folder name can contain: + + - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + - Special Characters: `/` , `_` , `-` + + Using multiple `/` creates a nested folder. + """ + + is_private_file: Annotated[bool, PropertyInfo(alias="isPrivateFile")] + """Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + """ + + is_published: Annotated[bool, PropertyInfo(alias="isPublished")] + """Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + """ + + overwrite_ai_tags: Annotated[bool, PropertyInfo(alias="overwriteAITags")] + """ + If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + """ + + overwrite_custom_metadata: Annotated[bool, PropertyInfo(alias="overwriteCustomMetadata")] + """ + If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + """ + + overwrite_file: Annotated[bool, PropertyInfo(alias="overwriteFile")] + """ + If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + """ + + overwrite_tags: Annotated[bool, PropertyInfo(alias="overwriteTags")] + """ + If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + """ + + public_key: Annotated[str, PropertyInfo(alias="publicKey")] + """Your ImageKit.io public key. + + This field is only required for authentication when uploading a file from the + client side. + """ + + response_fields: Annotated[ + List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ], + PropertyInfo(alias="responseFields"), + ] + """Array of response field keys to include in the API response body.""" + + signature: str + """ + HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a + key. Learn how to create a signature on the page below. This should be in + lowercase. + + Signature must be calculated on the server-side. This field is only required for + authentication when uploading a file from the client side. + """ + + tags: List[str] + """Set the tags while uploading the file. Provide an array of tag strings (e.g. + + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. + """ + + transformation: Transformation + """Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + """ + + use_unique_file_name: Annotated[bool, PropertyInfo(alias="useUniqueFileName")] + """Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + """ + + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ + + +class ExtensionRemovedotBgExtensionOptions(TypedDict, total=False): + add_shadow: bool + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: str + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: str + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: bool + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class ExtensionRemovedotBgExtension(TypedDict, total=False): + name: Required[Literal["remove-bg"]] + """Specifies the background removal extension.""" + + options: ExtensionRemovedotBgExtensionOptions + + +class ExtensionAutoTaggingExtension(TypedDict, total=False): + max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] + """Maximum number of tags to attach to the asset.""" + + min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] + """Minimum confidence level for tags to be considered valid.""" + + name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] + """Specifies the auto-tagging extension used.""" + + +class ExtensionAutoDescriptionExtension(TypedDict, total=False): + name: Required[Literal["ai-auto-description"]] + """Specifies the auto description extension.""" + + +Extension: TypeAlias = Union[ + ExtensionRemovedotBgExtension, ExtensionAutoTaggingExtension, ExtensionAutoDescriptionExtension +] + + +class TransformationPostSimplePostTransformation(TypedDict, total=False): + type: Required[Literal["transformation"]] + """Transformation type.""" + + value: Required[str] + """Transformation string (e.g. + + `w-200,h-200`). + Same syntax as ImageKit URL-based transformations. + """ + + +class TransformationPostConvertGifToVideo(TypedDict, total=False): + type: Required[Literal["gif-to-video"]] + """Converts an animated GIF into an MP4.""" + + value: str + """Optional transformation string to apply to the output video. + + **Example**: `q-80` + """ + + +class TransformationPostGenerateAThumbnail(TypedDict, total=False): + type: Required[Literal["thumbnail"]] + """Generates a thumbnail image.""" + + value: str + """Optional transformation string. + + **Example**: `w-150,h-150` + """ + + +class TransformationPostAdaptiveBitrateStreaming(TypedDict, total=False): + protocol: Required[Literal["hls", "dash"]] + """Streaming protocol to use (`hls` or `dash`).""" + + type: Required[Literal["abs"]] + """Adaptive Bitrate Streaming (ABS) setup.""" + + value: Required[str] + """ + List of different representations you want to create separated by an underscore. + """ + + +TransformationPost: TypeAlias = Union[ + TransformationPostSimplePostTransformation, + TransformationPostConvertGifToVideo, + TransformationPostGenerateAThumbnail, + TransformationPostAdaptiveBitrateStreaming, +] + + +class Transformation(TypedDict, total=False): + post: Iterable[TransformationPost] + """List of transformations to apply _after_ the file is uploaded. + + Each item must match one of the following types: `transformation`, + `gif-to-video`, `thumbnail`, `abs`. + """ + + pre: str + """Transformation string to apply before uploading the file to the Media Library. + + Useful for optimizing files at ingestion. + """ diff --git a/src/imagekit/types/file_upload_response.py b/src/imagekit/types/file_upload_response.py new file mode 100644 index 0000000..deabddd --- /dev/null +++ b/src/imagekit/types/file_upload_response.py @@ -0,0 +1,341 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = [ + "FileUploadResponse", + "AITag", + "ExtensionStatus", + "Metadata", + "MetadataExif", + "MetadataExifExif", + "MetadataExifGps", + "MetadataExifImage", + "MetadataExifInteroperability", + "MetadataExifThumbnail", + "VersionInfo", +] + + +class AITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Array of `AITags` associated with the image. + + If no `AITags` are set, it will be null. These tags can be added using the + `google-auto-tagging` or `aws-auto-tagging` extensions. + """ + + +class ExtensionStatus(BaseModel): + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="aws-auto-tagging", default=None + ) + + google_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="google-auto-tagging", default=None + ) + + remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) + + +class MetadataExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class MetadataExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class MetadataExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class MetadataExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class MetadataExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class MetadataExif(BaseModel): + exif: Optional[MetadataExifExif] = None + """Object containing Exif details.""" + + gps: Optional[MetadataExifGps] = None + """Object containing GPS information.""" + + image: Optional[MetadataExifImage] = None + """Object containing EXIF image information.""" + + interoperability: Optional[MetadataExifInteroperability] = None + """JSON object.""" + + makernote: Optional[Dict[str, object]] = None + + thumbnail: Optional[MetadataExifThumbnail] = None + """Object containing Thumbnail information.""" + + +class Metadata(BaseModel): + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + density: Optional[int] = None + """The density of the image in DPI.""" + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + exif: Optional[MetadataExif] = None + + format: Optional[str] = None + """The format of the file (e.g., 'jpg', 'mp4').""" + + has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) + """Indicates if the image has a color profile.""" + + has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) + """Indicates if the image contains transparent areas.""" + + height: Optional[int] = None + """The height of the image or video in pixels.""" + + p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) + """Perceptual hash of the image.""" + + quality: Optional[int] = None + """The quality indicator of the image.""" + + size: Optional[int] = None + """The file size in bytes.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[int] = None + """The width of the image or video in pixels.""" + + +class VersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class FileUploadResponse(BaseModel): + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the uploaded file by auto tagging.""" + + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """ + Value of custom coordinates associated with the image in the format + `x,y,width,height`. If `customCoordinates` are not defined, then it is `null`. + Send `customCoordinates` in `responseFields` in API request to get the value of + this field. + """ + + custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + """A key-value data associated with the asset. + + Use `responseField` in API request to get `customMetadata` in the upload API + response. Before setting any custom metadata on an asset, you have to create the + field using custom metadata fields API. Send `customMetadata` in + `responseFields` in API request to get the value of this field. + """ + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + embedded_metadata: Optional[Dict[str, object]] = FieldInfo(alias="embeddedMetadata", default=None) + """Consolidated embedded metadata associated with the file. + + It includes exif, iptc, and xmp data. Send `embeddedMetadata` in + `responseFields` in API request to get embeddedMetadata in the upload API + response. + """ + + extension_status: Optional[ExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) + """ + Extension names with their processing status at the time of completion of the + request. It could have one of the following status values: + + `success`: The extension has been successfully applied. `failed`: The extension + has failed and will not be retried. `pending`: The extension will finish + processing in some time. On completion, the final status (success / failed) will + be sent to the `webhookUrl` provided. + + If no extension was requested, then this parameter is not returned. + """ + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique fileId. + + Store this fileld in your database, as this will be used to perform update + action on this file. + """ + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """The relative path of the file in the media library e.g. + + `/marketing-assets/new-banner.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the uploaded file. Possible values are `image`, `non-image`.""" + + height: Optional[float] = None + """Height of the image in pixels (Only for images)""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Is the file marked as private. + + It can be either `true` or `false`. Send `isPrivateFile` in `responseFields` in + API request to get the value of this field. + """ + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Is the file published or in draft state. + + It can be either `true` or `false`. Send `isPublished` in `responseFields` in + API request to get the value of this field. + """ + + metadata: Optional[Metadata] = None + """Legacy metadata. + + Send `metadata` in `responseFields` in API request to get metadata in the upload + API response. + """ + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the image file in Bytes.""" + + tags: Optional[List[str]] = None + """The array of tags associated with the asset. + + If no tags are set, it will be `null`. Send `tags` in `responseFields` in API + request to get the value of this field. + """ + + thumbnail_url: Optional[str] = FieldInfo(alias="thumbnailUrl", default=None) + """In the case of an image, a small thumbnail URL.""" + + url: Optional[str] = None + """A publicly accessible URL of the file.""" + + version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object containing the file or file version's `id` (versionId) and `name`.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[float] = None + """Width of the image in pixels (Only for Images)""" diff --git a/src/imagekit/types/file_upload_v1_params.py b/src/imagekit/types/file_upload_v1_params.py deleted file mode 100644 index 01b7a31..0000000 --- a/src/imagekit/types/file_upload_v1_params.py +++ /dev/null @@ -1,211 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["FileUploadV1Params"] - - -class FileUploadV1Params(TypedDict, total=False): - file: Required[str] - """Pass the HTTP URL or base64 string. - - When passing a URL in the file parameter, please ensure that our servers can - access the URL. In case ImageKit is unable to download the file from the - specified URL, a `400` error response is returned. This will also result in a - `400` error if the file download request is aborted if response headers are not - received in 8 seconds. - """ - - file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] - """The name with which the file has to be uploaded. The file name can contain: - - - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. - - Special Characters: `.`, `-` - - Any other character including space will be replaced by `_` - """ - - token: str - """ - A unique value that the ImageKit.io server will use to recognize and prevent - subsequent retries for the same request. We suggest using V4 UUIDs, or another - random string with enough entropy to avoid collisions. This field is only - required for authentication when uploading a file from the client side. - - **Note**: Sending a value that has been used in the past will result in a - validation error. Even if your previous request resulted in an error, you should - always send a new value for this field. - """ - - checks: str - """ - Server-side checks to run on the asset. Read more about - [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). - """ - - custom_coordinates: Annotated[str, PropertyInfo(alias="customCoordinates")] - """Define an important area in the image. - - This is only relevant for image type files. - - - To be passed as a string with the x and y coordinates of the top-left corner, - and width and height of the area of interest in the format `x,y,width,height`. - For example - `10,10,100,100` - - Can be used with fo-customtransformation. - - If this field is not specified and the file is overwritten, then - customCoordinates will be removed. - """ - - custom_metadata: Annotated[str, PropertyInfo(alias="customMetadata")] - """Stringified JSON key-value data to be associated with the asset.""" - - expire: str - """The time until your signature is valid. - - It must be a [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 - hour into the future. It should be in seconds. This field is only required for - authentication when uploading a file from the client side. - """ - - extensions: str - """Stringified JSON object with an array of extensions to be applied to the image. - - Refer to extensions schema in - [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). - """ - - folder: str - """The folder path in which the image has to be uploaded. - - If the folder(s) didn't exist before, a new folder(s) is created. - - The folder name can contain: - - - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` - - Special Characters: `/` , `_` , `-` - - Using multiple `/` creates a nested folder. - """ - - is_private_file: Annotated[Literal["true", "false"], PropertyInfo(alias="isPrivateFile")] - """Whether to mark the file as private or not. - - If `true`, the file is marked as private and is accessible only using named - transformation or signed URL. - """ - - is_published: Annotated[Literal["true", "false"], PropertyInfo(alias="isPublished")] - """Whether to upload file as published or not. - - If `false`, the file is marked as unpublished, which restricts access to the - file only via the media library. Files in draft or unpublished state can only be - publicly accessed after being published. - - The option to upload in draft state is only available in custom enterprise - pricing plans. - """ - - overwrite_ai_tags: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteAITags")] - """ - If set to `true` and a file already exists at the exact location, its AITags - will be removed. Set `overwriteAITags` to `false` to preserve AITags. - """ - - overwrite_custom_metadata: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteCustomMetadata")] - """ - If the request does not have `customMetadata`, and a file already exists at the - exact location, existing customMetadata will be removed. - """ - - overwrite_file: Annotated[str, PropertyInfo(alias="overwriteFile")] - """ - If `false` and `useUniqueFileName` is also `false`, and a file already exists at - the exact location, upload API will return an error immediately. - """ - - overwrite_tags: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteTags")] - """ - If the request does not have `tags`, and a file already exists at the exact - location, existing tags will be removed. - """ - - public_key: Annotated[str, PropertyInfo(alias="publicKey")] - """Your ImageKit.io public key. - - This field is only required for authentication when uploading a file from the - client side. - """ - - response_fields: Annotated[str, PropertyInfo(alias="responseFields")] - """ - Comma-separated values of the fields that you want the API to return in the - response. - - For example, set the value of this field to - `tags,customCoordinates,isPrivateFile` to get the value of `tags`, - `customCoordinates`, and `isPrivateFile` in the response. - - Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, - `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. - """ - - signature: str - """ - HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a - key. Learn how to create a signature on the page below. This should be in - lowercase. - - Signature must be calculated on the server-side. This field is only required for - authentication when uploading a file from the client side. - """ - - tags: str - """Set the tags while uploading the file. - - Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length - of all characters should not exceed 500. `%` is not allowed. - - If this field is not specified and the file is overwritten then the tags will be - removed. - """ - - transformation: str - """Stringified JSON object with properties for pre and post transformations: - - `pre` - Accepts a "string" containing a valid transformation used for requesting - a pre-transformation for an image or a video file. - - `post` - Accepts an array of objects with properties: - - - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` - (Adaptive bitrate streaming). - - `value`: A "string" corresponding to the required transformation. Required if - `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or - `thumbnail`. - - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. - - Read more about - [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). - """ - - use_unique_file_name: Annotated[Literal["true", "false"], PropertyInfo(alias="useUniqueFileName")] - """Whether to use a unique filename for this file or not. - - If `true`, ImageKit.io will add a unique suffix to the filename parameter to get - a unique filename. - - If `false`, then the image is uploaded with the provided filename parameter, and - any existing file with the same name is replaced. - """ - - webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] - """ - The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - """ diff --git a/src/imagekit/types/file_upload_v1_response.py b/src/imagekit/types/file_upload_v1_response.py deleted file mode 100644 index b5edecc..0000000 --- a/src/imagekit/types/file_upload_v1_response.py +++ /dev/null @@ -1,613 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .gps import Gps -from .._models import BaseModel -from .thumbnail import Thumbnail -from .exif_image import ExifImage -from .exif_details import ExifDetails -from .interoperability import Interoperability - -__all__ = [ - "FileUploadV1Response", - "AITag", - "EmbeddedMetadata", - "ExtensionStatus", - "Metadata", - "MetadataExif", - "VersionInfo", -] - - -class AITag(BaseModel): - confidence: Optional[float] = None - """Confidence score of the tag.""" - - name: Optional[str] = None - """Name of the tag.""" - - source: Optional[str] = None - """Array of `AITags` associated with the image. - - If no `AITags` are set, it will be null. These tags can be added using the - `google-auto-tagging` or `aws-auto-tagging` extensions. - """ - - -class EmbeddedMetadata(BaseModel): - about_cv_term_cv_id: Optional[str] = FieldInfo(alias="AboutCvTermCvId", default=None) - - about_cv_term_id: Optional[str] = FieldInfo(alias="AboutCvTermId", default=None) - - about_cv_term_name: Optional[str] = FieldInfo(alias="AboutCvTermName", default=None) - - about_cv_term_refined_about: Optional[str] = FieldInfo(alias="AboutCvTermRefinedAbout", default=None) - - additional_model_information: Optional[str] = FieldInfo(alias="AdditionalModelInformation", default=None) - - application_record_version: Optional[int] = FieldInfo(alias="ApplicationRecordVersion", default=None) - - artist: Optional[str] = FieldInfo(alias="Artist", default=None) - - artwork_circa_date_created: Optional[str] = FieldInfo(alias="ArtworkCircaDateCreated", default=None) - - artwork_content_description: Optional[str] = FieldInfo(alias="ArtworkContentDescription", default=None) - - artwork_contribution_description: Optional[str] = FieldInfo(alias="ArtworkContributionDescription", default=None) - - artwork_copyright_notice: Optional[str] = FieldInfo(alias="ArtworkCopyrightNotice", default=None) - - artwork_copyright_owner_id: Optional[str] = FieldInfo(alias="ArtworkCopyrightOwnerID", default=None) - - artwork_copyright_owner_name: Optional[str] = FieldInfo(alias="ArtworkCopyrightOwnerName", default=None) - - artwork_creator: Optional[List[str]] = FieldInfo(alias="ArtworkCreator", default=None) - - artwork_creator_id: Optional[List[str]] = FieldInfo(alias="ArtworkCreatorID", default=None) - - artwork_date_created: Optional[datetime] = FieldInfo(alias="ArtworkDateCreated", default=None) - - artwork_licensor_id: Optional[str] = FieldInfo(alias="ArtworkLicensorID", default=None) - - artwork_licensor_name: Optional[str] = FieldInfo(alias="ArtworkLicensorName", default=None) - - artwork_physical_description: Optional[str] = FieldInfo(alias="ArtworkPhysicalDescription", default=None) - - artwork_source: Optional[str] = FieldInfo(alias="ArtworkSource", default=None) - - artwork_source_inventory_no: Optional[str] = FieldInfo(alias="ArtworkSourceInventoryNo", default=None) - - artwork_source_inv_url: Optional[str] = FieldInfo(alias="ArtworkSourceInvURL", default=None) - - artwork_style_period: Optional[List[str]] = FieldInfo(alias="ArtworkStylePeriod", default=None) - - artwork_title: Optional[str] = FieldInfo(alias="ArtworkTitle", default=None) - - authors_position: Optional[str] = FieldInfo(alias="AuthorsPosition", default=None) - - byline: Optional[str] = FieldInfo(alias="Byline", default=None) - - byline_title: Optional[str] = FieldInfo(alias="BylineTitle", default=None) - - caption: Optional[str] = FieldInfo(alias="Caption", default=None) - - caption_abstract: Optional[str] = FieldInfo(alias="CaptionAbstract", default=None) - - caption_writer: Optional[str] = FieldInfo(alias="CaptionWriter", default=None) - - city: Optional[str] = FieldInfo(alias="City", default=None) - - color_space: Optional[str] = FieldInfo(alias="ColorSpace", default=None) - - components_configuration: Optional[str] = FieldInfo(alias="ComponentsConfiguration", default=None) - - copyright: Optional[str] = FieldInfo(alias="Copyright", default=None) - - copyright_notice: Optional[str] = FieldInfo(alias="CopyrightNotice", default=None) - - copyright_owner_id: Optional[List[str]] = FieldInfo(alias="CopyrightOwnerID", default=None) - - copyright_owner_name: Optional[List[str]] = FieldInfo(alias="CopyrightOwnerName", default=None) - - country: Optional[str] = FieldInfo(alias="Country", default=None) - - country_code: Optional[str] = FieldInfo(alias="CountryCode", default=None) - - country_primary_location_code: Optional[str] = FieldInfo(alias="CountryPrimaryLocationCode", default=None) - - country_primary_location_name: Optional[str] = FieldInfo(alias="CountryPrimaryLocationName", default=None) - - creator: Optional[str] = FieldInfo(alias="Creator", default=None) - - creator_address: Optional[str] = FieldInfo(alias="CreatorAddress", default=None) - - creator_city: Optional[str] = FieldInfo(alias="CreatorCity", default=None) - - creator_country: Optional[str] = FieldInfo(alias="CreatorCountry", default=None) - - creator_postal_code: Optional[str] = FieldInfo(alias="CreatorPostalCode", default=None) - - creator_region: Optional[str] = FieldInfo(alias="CreatorRegion", default=None) - - creator_work_email: Optional[str] = FieldInfo(alias="CreatorWorkEmail", default=None) - - creator_work_telephone: Optional[str] = FieldInfo(alias="CreatorWorkTelephone", default=None) - - creator_work_url: Optional[str] = FieldInfo(alias="CreatorWorkURL", default=None) - - credit: Optional[str] = FieldInfo(alias="Credit", default=None) - - date_created: Optional[datetime] = FieldInfo(alias="DateCreated", default=None) - - date_time_created: Optional[datetime] = FieldInfo(alias="DateTimeCreated", default=None) - - date_time_original: Optional[datetime] = FieldInfo(alias="DateTimeOriginal", default=None) - - description: Optional[str] = FieldInfo(alias="Description", default=None) - - digital_image_guid: Optional[str] = FieldInfo(alias="DigitalImageGUID", default=None) - - digital_source_type: Optional[str] = FieldInfo(alias="DigitalSourceType", default=None) - - embedded_encoded_rights_expr: Optional[str] = FieldInfo(alias="EmbeddedEncodedRightsExpr", default=None) - - embedded_encoded_rights_expr_lang_id: Optional[str] = FieldInfo( - alias="EmbeddedEncodedRightsExprLangID", default=None - ) - - embedded_encoded_rights_expr_type: Optional[str] = FieldInfo(alias="EmbeddedEncodedRightsExprType", default=None) - - event: Optional[str] = FieldInfo(alias="Event", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - genre_cv_id: Optional[str] = FieldInfo(alias="GenreCvId", default=None) - - genre_cv_term_id: Optional[str] = FieldInfo(alias="GenreCvTermId", default=None) - - genre_cv_term_name: Optional[str] = FieldInfo(alias="GenreCvTermName", default=None) - - genre_cv_term_refined_about: Optional[str] = FieldInfo(alias="GenreCvTermRefinedAbout", default=None) - - headline: Optional[str] = FieldInfo(alias="Headline", default=None) - - image_creator_id: Optional[str] = FieldInfo(alias="ImageCreatorID", default=None) - - image_creator_image_id: Optional[str] = FieldInfo(alias="ImageCreatorImageID", default=None) - - image_creator_name: Optional[str] = FieldInfo(alias="ImageCreatorName", default=None) - - image_description: Optional[str] = FieldInfo(alias="ImageDescription", default=None) - - image_region_boundary_h: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryH", default=None) - - image_region_boundary_rx: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryRx", default=None) - - image_region_boundary_shape: Optional[List[str]] = FieldInfo(alias="ImageRegionBoundaryShape", default=None) - - image_region_boundary_unit: Optional[List[str]] = FieldInfo(alias="ImageRegionBoundaryUnit", default=None) - - image_region_boundary_vertices_x: Optional[List[float]] = FieldInfo( - alias="ImageRegionBoundaryVerticesX", default=None - ) - - image_region_boundary_vertices_y: Optional[List[float]] = FieldInfo( - alias="ImageRegionBoundaryVerticesY", default=None - ) - - image_region_boundary_w: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryW", default=None) - - image_region_boundary_x: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryX", default=None) - - image_region_boundary_y: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryY", default=None) - - image_region_ctype_identifier: Optional[List[str]] = FieldInfo(alias="ImageRegionCtypeIdentifier", default=None) - - image_region_ctype_name: Optional[List[str]] = FieldInfo(alias="ImageRegionCtypeName", default=None) - - image_region_id: Optional[List[str]] = FieldInfo(alias="ImageRegionID", default=None) - - image_region_name: Optional[List[str]] = FieldInfo(alias="ImageRegionName", default=None) - - image_region_organisation_in_image_name: Optional[List[str]] = FieldInfo( - alias="ImageRegionOrganisationInImageName", default=None - ) - - image_region_person_in_image: Optional[List[str]] = FieldInfo(alias="ImageRegionPersonInImage", default=None) - - image_region_role_identifier: Optional[List[str]] = FieldInfo(alias="ImageRegionRoleIdentifier", default=None) - - image_region_role_name: Optional[List[str]] = FieldInfo(alias="ImageRegionRoleName", default=None) - - image_supplier_id: Optional[str] = FieldInfo(alias="ImageSupplierID", default=None) - - image_supplier_image_id: Optional[str] = FieldInfo(alias="ImageSupplierImageID", default=None) - - image_supplier_name: Optional[str] = FieldInfo(alias="ImageSupplierName", default=None) - - instructions: Optional[str] = FieldInfo(alias="Instructions", default=None) - - intellectual_genre: Optional[str] = FieldInfo(alias="IntellectualGenre", default=None) - - keywords: Optional[List[str]] = FieldInfo(alias="Keywords", default=None) - - licensor_city: Optional[List[str]] = FieldInfo(alias="LicensorCity", default=None) - - licensor_country: Optional[List[str]] = FieldInfo(alias="LicensorCountry", default=None) - - licensor_email: Optional[List[str]] = FieldInfo(alias="LicensorEmail", default=None) - - licensor_extended_address: Optional[List[str]] = FieldInfo(alias="LicensorExtendedAddress", default=None) - - licensor_id: Optional[List[str]] = FieldInfo(alias="LicensorID", default=None) - - licensor_name: Optional[List[str]] = FieldInfo(alias="LicensorName", default=None) - - licensor_postal_code: Optional[List[str]] = FieldInfo(alias="LicensorPostalCode", default=None) - - licensor_region: Optional[List[str]] = FieldInfo(alias="LicensorRegion", default=None) - - licensor_street_address: Optional[List[str]] = FieldInfo(alias="LicensorStreetAddress", default=None) - - licensor_telephone1: Optional[List[str]] = FieldInfo(alias="LicensorTelephone1", default=None) - - licensor_telephone2: Optional[List[str]] = FieldInfo(alias="LicensorTelephone2", default=None) - - licensor_url: Optional[List[str]] = FieldInfo(alias="LicensorURL", default=None) - - linked_encoded_rights_expr: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExpr", default=None) - - linked_encoded_rights_expr_lang_id: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExprLangID", default=None) - - linked_encoded_rights_expr_type: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExprType", default=None) - - location: Optional[str] = FieldInfo(alias="Location", default=None) - - location_created_city: Optional[str] = FieldInfo(alias="LocationCreatedCity", default=None) - - location_created_country_code: Optional[str] = FieldInfo(alias="LocationCreatedCountryCode", default=None) - - location_created_country_name: Optional[str] = FieldInfo(alias="LocationCreatedCountryName", default=None) - - location_created_gps_altitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSAltitude", default=None) - - location_created_gps_latitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSLatitude", default=None) - - location_created_gps_longitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSLongitude", default=None) - - location_created_location_id: Optional[str] = FieldInfo(alias="LocationCreatedLocationId", default=None) - - location_created_location_name: Optional[str] = FieldInfo(alias="LocationCreatedLocationName", default=None) - - location_created_province_state: Optional[str] = FieldInfo(alias="LocationCreatedProvinceState", default=None) - - location_created_sublocation: Optional[str] = FieldInfo(alias="LocationCreatedSublocation", default=None) - - location_created_world_region: Optional[str] = FieldInfo(alias="LocationCreatedWorldRegion", default=None) - - location_shown_city: Optional[List[str]] = FieldInfo(alias="LocationShownCity", default=None) - - location_shown_country_code: Optional[List[str]] = FieldInfo(alias="LocationShownCountryCode", default=None) - - location_shown_country_name: Optional[List[str]] = FieldInfo(alias="LocationShownCountryName", default=None) - - location_shown_gps_altitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSAltitude", default=None) - - location_shown_gps_latitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSLatitude", default=None) - - location_shown_gps_longitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSLongitude", default=None) - - location_shown_location_id: Optional[List[str]] = FieldInfo(alias="LocationShownLocationId", default=None) - - location_shown_location_name: Optional[List[str]] = FieldInfo(alias="LocationShownLocationName", default=None) - - location_shown_province_state: Optional[List[str]] = FieldInfo(alias="LocationShownProvinceState", default=None) - - location_shown_sublocation: Optional[List[str]] = FieldInfo(alias="LocationShownSublocation", default=None) - - location_shown_world_region: Optional[List[str]] = FieldInfo(alias="LocationShownWorldRegion", default=None) - - max_avail_height: Optional[float] = FieldInfo(alias="MaxAvailHeight", default=None) - - max_avail_width: Optional[float] = FieldInfo(alias="MaxAvailWidth", default=None) - - api_model_age: Optional[List[float]] = FieldInfo(alias="ModelAge", default=None) - - api_model_release_id: Optional[List[str]] = FieldInfo(alias="ModelReleaseID", default=None) - - object_attribute_reference: Optional[str] = FieldInfo(alias="ObjectAttributeReference", default=None) - - object_name: Optional[str] = FieldInfo(alias="ObjectName", default=None) - - offset_time_original: Optional[str] = FieldInfo(alias="OffsetTimeOriginal", default=None) - - organisation_in_image_code: Optional[List[str]] = FieldInfo(alias="OrganisationInImageCode", default=None) - - organisation_in_image_name: Optional[List[str]] = FieldInfo(alias="OrganisationInImageName", default=None) - - orientation: Optional[str] = FieldInfo(alias="Orientation", default=None) - - original_transmission_reference: Optional[str] = FieldInfo(alias="OriginalTransmissionReference", default=None) - - person_in_image: Optional[List[str]] = FieldInfo(alias="PersonInImage", default=None) - - person_in_image_cv_term_cv_id: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermCvId", default=None) - - person_in_image_cv_term_id: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermId", default=None) - - person_in_image_cv_term_name: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermName", default=None) - - person_in_image_cv_term_refined_about: Optional[List[str]] = FieldInfo( - alias="PersonInImageCvTermRefinedAbout", default=None - ) - - person_in_image_description: Optional[List[str]] = FieldInfo(alias="PersonInImageDescription", default=None) - - person_in_image_id: Optional[List[str]] = FieldInfo(alias="PersonInImageId", default=None) - - person_in_image_name: Optional[List[str]] = FieldInfo(alias="PersonInImageName", default=None) - - product_in_image_description: Optional[List[str]] = FieldInfo(alias="ProductInImageDescription", default=None) - - product_in_image_gtin: Optional[List[float]] = FieldInfo(alias="ProductInImageGTIN", default=None) - - product_in_image_name: Optional[List[str]] = FieldInfo(alias="ProductInImageName", default=None) - - property_release_id: Optional[List[str]] = FieldInfo(alias="PropertyReleaseID", default=None) - - province_state: Optional[str] = FieldInfo(alias="ProvinceState", default=None) - - rating: Optional[int] = FieldInfo(alias="Rating", default=None) - - registry_entry_role: Optional[List[str]] = FieldInfo(alias="RegistryEntryRole", default=None) - - registry_item_id: Optional[List[str]] = FieldInfo(alias="RegistryItemID", default=None) - - registry_organisation_id: Optional[List[str]] = FieldInfo(alias="RegistryOrganisationID", default=None) - - resolution_unit: Optional[str] = FieldInfo(alias="ResolutionUnit", default=None) - - rights: Optional[str] = FieldInfo(alias="Rights", default=None) - - scene: Optional[List[str]] = FieldInfo(alias="Scene", default=None) - - source: Optional[str] = FieldInfo(alias="Source", default=None) - - special_instructions: Optional[str] = FieldInfo(alias="SpecialInstructions", default=None) - - state: Optional[str] = FieldInfo(alias="State", default=None) - - subject: Optional[List[str]] = FieldInfo(alias="Subject", default=None) - - subject_code: Optional[List[str]] = FieldInfo(alias="SubjectCode", default=None) - - subject_reference: Optional[List[str]] = FieldInfo(alias="SubjectReference", default=None) - - sublocation: Optional[str] = FieldInfo(alias="Sublocation", default=None) - - time_created: Optional[str] = FieldInfo(alias="TimeCreated", default=None) - - title: Optional[str] = FieldInfo(alias="Title", default=None) - - transmission_reference: Optional[str] = FieldInfo(alias="TransmissionReference", default=None) - - usage_terms: Optional[str] = FieldInfo(alias="UsageTerms", default=None) - - web_statement: Optional[str] = FieldInfo(alias="WebStatement", default=None) - - writer: Optional[str] = FieldInfo(alias="Writer", default=None) - - writer_editor: Optional[str] = FieldInfo(alias="WriterEditor", default=None) - - x_resolution: Optional[float] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[float] = FieldInfo(alias="YResolution", default=None) - - -class ExtensionStatus(BaseModel): - aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( - alias="aws-auto-tagging", default=None - ) - - google_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( - alias="google-auto-tagging", default=None - ) - - remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) - - -class MetadataExif(BaseModel): - exif: Optional[ExifDetails] = None - """Object containing Exif details.""" - - gps: Optional[Gps] = None - """Object containing GPS information.""" - - image: Optional[ExifImage] = None - """Object containing EXIF image information.""" - - interoperability: Optional[Interoperability] = None - """JSON object.""" - - makernote: Optional[Dict[str, object]] = None - - thumbnail: Optional[Thumbnail] = None - """Object containing Thumbnail information.""" - - -class Metadata(BaseModel): - audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) - """The audio codec used in the video (only for video).""" - - bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) - """The bit rate of the video in kbps (only for video).""" - - density: Optional[int] = None - """The density of the image in DPI.""" - - duration: Optional[int] = None - """The duration of the video in seconds (only for video).""" - - exif: Optional[MetadataExif] = None - - format: Optional[str] = None - """The format of the file (e.g., 'jpg', 'mp4').""" - - has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) - """Indicates if the image has a color profile.""" - - has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) - """Indicates if the image contains transparent areas.""" - - height: Optional[int] = None - """The height of the image or video in pixels.""" - - p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) - """Perceptual hash of the image.""" - - quality: Optional[int] = None - """The quality indicator of the image.""" - - size: Optional[int] = None - """The file size in bytes.""" - - video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) - """The video codec used in the video (only for video).""" - - width: Optional[int] = None - """The width of the image or video in pixels.""" - - -class VersionInfo(BaseModel): - id: Optional[str] = None - """Unique identifier of the file version.""" - - name: Optional[str] = None - """Name of the file version.""" - - -class FileUploadV1Response(BaseModel): - ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) - """An array of tags assigned to the uploaded file by auto tagging.""" - - audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) - """The audio codec used in the video (only for video).""" - - bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) - """The bit rate of the video in kbps (only for video).""" - - custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) - """ - Value of custom coordinates associated with the image in the format - `x,y,width,height`. If `customCoordinates` are not defined, then it is `null`. - Send `customCoordinates` in `responseFields` in API request to get the value of - this field. - """ - - custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) - """A key-value data associated with the asset. - - Use `responseField` in API request to get `customMetadata` in the upload API - response. Before setting any custom metadata on an asset, you have to create the - field using custom metadata fields API. Send `customMetadata` in - `responseFields` in API request to get the value of this field. - """ - - duration: Optional[int] = None - """The duration of the video in seconds (only for video).""" - - embedded_metadata: Optional[EmbeddedMetadata] = FieldInfo(alias="embeddedMetadata", default=None) - """Consolidated embedded metadata associated with the file. - - It includes exif, iptc, and xmp data. Send `embeddedMetadata` in - `responseFields` in API request to get embeddedMetadata in the upload API - response. - """ - - extension_status: Optional[ExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) - """ - Extension names with their processing status at the time of completion of the - request. It could have one of the following status values: - - `success`: The extension has been successfully applied. `failed`: The extension - has failed and will not be retried. `pending`: The extension will finish - processing in some time. On completion, the final status (success / failed) will - be sent to the `webhookUrl` provided. - - If no extension was requested, then this parameter is not returned. - """ - - file_id: Optional[str] = FieldInfo(alias="fileId", default=None) - """Unique fileId. - - Store this fileld in your database, as this will be used to perform update - action on this file. - """ - - file_path: Optional[str] = FieldInfo(alias="filePath", default=None) - """The relative path of the file in the media library e.g. - - `/marketing-assets/new-banner.jpg`. - """ - - file_type: Optional[str] = FieldInfo(alias="fileType", default=None) - """Type of the uploaded file. Possible values are `image`, `non-image`.""" - - height: Optional[float] = None - """Height of the image in pixels (Only for images)""" - - is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) - """Is the file marked as private. - - It can be either `true` or `false`. Send `isPrivateFile` in `responseFields` in - API request to get the value of this field. - """ - - is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) - """Is the file published or in draft state. - - It can be either `true` or `false`. Send `isPublished` in `responseFields` in - API request to get the value of this field. - """ - - metadata: Optional[Metadata] = None - """Legacy metadata. - - Send `metadata` in `responseFields` in API request to get metadata in the upload - API response. - """ - - name: Optional[str] = None - """Name of the asset.""" - - size: Optional[float] = None - """Size of the image file in Bytes.""" - - tags: Optional[List[str]] = None - """The array of tags associated with the asset. - - If no tags are set, it will be `null`. Send `tags` in `responseFields` in API - request to get the value of this field. - """ - - thumbnail_url: Optional[str] = FieldInfo(alias="thumbnailUrl", default=None) - """In the case of an image, a small thumbnail URL.""" - - url: Optional[str] = None - """A publicly accessible URL of the file.""" - - version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) - """An object containing the file or file version's `id` (versionId) and `name`.""" - - video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) - """The video codec used in the video (only for video).""" - - width: Optional[float] = None - """Width of the image in pixels (Only for Images)""" diff --git a/src/imagekit/types/file_upload_v2_params.py b/src/imagekit/types/file_upload_v2_params.py deleted file mode 100644 index 92c2c17..0000000 --- a/src/imagekit/types/file_upload_v2_params.py +++ /dev/null @@ -1,179 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["FileUploadV2Params"] - - -class FileUploadV2Params(TypedDict, total=False): - file: Required[str] - """Pass the HTTP URL or base64 string. - - When passing a URL in the file parameter, please ensure that our servers can - access the URL. In case ImageKit is unable to download the file from the - specified URL, a `400` error response is returned. This will also result in a - `400` error if the file download request is aborted if response headers are not - received in 8 seconds. - """ - - file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] - """The name with which the file has to be uploaded.""" - - token: str - """This is the client-generated JSON Web Token (JWT). - - The ImageKit.io server uses it to authenticate and check that the upload request - parameters have not been tampered with after the token has been generated. Learn - how to create the token on the page below. This field is only required for - authentication when uploading a file from the client side. - - **Note**: Sending a JWT that has been used in the past will result in a - validation error. Even if your previous request resulted in an error, you should - always send a new token. - - **⚠️Warning**: JWT must be generated on the server-side because it is generated - using your account's private API key. This field is required for authentication - when uploading a file from the client-side. - """ - - checks: str - """ - Server-side checks to run on the asset. Read more about - [Upload API checks](/docs/api-reference/upload-file/upload-file-v2#upload-api-checks). - """ - - custom_coordinates: Annotated[str, PropertyInfo(alias="customCoordinates")] - """Define an important area in the image. - - This is only relevant for image type files. - - - To be passed as a string with the x and y coordinates of the top-left corner, - and width and height of the area of interest in the format `x,y,width,height`. - For example - `10,10,100,100` - - Can be used with fo-customtransformation. - - If this field is not specified and the file is overwritten, then - customCoordinates will be removed. - """ - - custom_metadata: Annotated[str, PropertyInfo(alias="customMetadata")] - """Stringified JSON key-value data to be associated with the asset.""" - - extensions: str - """Stringified JSON object with an array of extensions to be applied to the image. - - Refer to extensions schema in - [update file API request body](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#request-body). - """ - - folder: str - """The folder path in which the image has to be uploaded. - - If the folder(s) didn't exist before, a new folder(s) is created. Using multiple - `/` creates a nested folder. - """ - - is_private_file: Annotated[Literal["true", "false"], PropertyInfo(alias="isPrivateFile")] - """Whether to mark the file as private or not. - - If `true`, the file is marked as private and is accessible only using named - transformation or signed URL. - """ - - is_published: Annotated[Literal["true", "false"], PropertyInfo(alias="isPublished")] - """Whether to upload file as published or not. - - If `false`, the file is marked as unpublished, which restricts access to the - file only via the media library. Files in draft or unpublished state can only be - publicly accessed after being published. - - The option to upload in draft state is only available in custom enterprise - pricing plans. - """ - - overwrite_ai_tags: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteAITags")] - """ - If set to `true` and a file already exists at the exact location, its AITags - will be removed. Set `overwriteAITags` to `false` to preserve AITags. - """ - - overwrite_custom_metadata: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteCustomMetadata")] - """ - If the request does not have `customMetadata`, and a file already exists at the - exact location, existing customMetadata will be removed. - """ - - overwrite_file: Annotated[str, PropertyInfo(alias="overwriteFile")] - """ - If `false` and `useUniqueFileName` is also `false`, and a file already exists at - the exact location, upload API will return an error immediately. - """ - - overwrite_tags: Annotated[Literal["true", "false"], PropertyInfo(alias="overwriteTags")] - """ - If the request does not have `tags`, and a file already exists at the exact - location, existing tags will be removed. - """ - - response_fields: Annotated[str, PropertyInfo(alias="responseFields")] - """ - Comma-separated values of the fields that you want the API to return in the - response. - - For example, set the value of this field to - `tags,customCoordinates,isPrivateFile` to get the value of `tags`, - `customCoordinates`, and `isPrivateFile` in the response. - - Accepts combination of `tags`, `customCoordinates`, `isPrivateFile`, - `embeddedMetadata`, `isPublished`, `customMetadata`, and `metadata`. - """ - - tags: str - """Set the tags while uploading the file. - - Comma-separated value of tags in the format `tag1,tag2,tag3`. The maximum length - of all characters should not exceed 500. `%` is not allowed. - - If this field is not specified and the file is overwritten then the tags will be - removed. - """ - - transformation: str - """Stringified JSON object with properties for pre and post transformations: - - `pre` - Accepts a "string" containing a valid transformation used for requesting - a pre-transformation for an image or a video file. - - `post` - Accepts an array of objects with properties: - - - `type`: One of `transformation`, `gif-to-video`, `thumbnail`, or `abs` - (Adaptive bitrate streaming). - - `value`: A "string" corresponding to the required transformation. Required if - `type` is `transformation` or `abs`. Optional if `type` is `gif-to-video` or - `thumbnail`. - - `protocol`: Either `hls` or `dash`, applicable only if `type` is `abs`. - - Read more about - [Adaptive bitrate streaming (ABS)](/docs/adaptive-bitrate-streaming). - """ - - use_unique_file_name: Annotated[Literal["true", "false"], PropertyInfo(alias="useUniqueFileName")] - """Whether to use a unique filename for this file or not. - - If `true`, ImageKit.io will add a unique suffix to the filename parameter to get - a unique filename. - - If `false`, then the image is uploaded with the provided filename parameter, and - any existing file with the same name is replaced. - """ - - webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] - """ - The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - """ diff --git a/src/imagekit/types/file_upload_v2_response.py b/src/imagekit/types/file_upload_v2_response.py deleted file mode 100644 index 25cd734..0000000 --- a/src/imagekit/types/file_upload_v2_response.py +++ /dev/null @@ -1,613 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .gps import Gps -from .._models import BaseModel -from .thumbnail import Thumbnail -from .exif_image import ExifImage -from .exif_details import ExifDetails -from .interoperability import Interoperability - -__all__ = [ - "FileUploadV2Response", - "AITag", - "EmbeddedMetadata", - "ExtensionStatus", - "Metadata", - "MetadataExif", - "VersionInfo", -] - - -class AITag(BaseModel): - confidence: Optional[float] = None - """Confidence score of the tag.""" - - name: Optional[str] = None - """Name of the tag.""" - - source: Optional[str] = None - """Array of `AITags` associated with the image. - - If no `AITags` are set, it will be null. These tags can be added using the - `google-auto-tagging` or `aws-auto-tagging` extensions. - """ - - -class EmbeddedMetadata(BaseModel): - about_cv_term_cv_id: Optional[str] = FieldInfo(alias="AboutCvTermCvId", default=None) - - about_cv_term_id: Optional[str] = FieldInfo(alias="AboutCvTermId", default=None) - - about_cv_term_name: Optional[str] = FieldInfo(alias="AboutCvTermName", default=None) - - about_cv_term_refined_about: Optional[str] = FieldInfo(alias="AboutCvTermRefinedAbout", default=None) - - additional_model_information: Optional[str] = FieldInfo(alias="AdditionalModelInformation", default=None) - - application_record_version: Optional[int] = FieldInfo(alias="ApplicationRecordVersion", default=None) - - artist: Optional[str] = FieldInfo(alias="Artist", default=None) - - artwork_circa_date_created: Optional[str] = FieldInfo(alias="ArtworkCircaDateCreated", default=None) - - artwork_content_description: Optional[str] = FieldInfo(alias="ArtworkContentDescription", default=None) - - artwork_contribution_description: Optional[str] = FieldInfo(alias="ArtworkContributionDescription", default=None) - - artwork_copyright_notice: Optional[str] = FieldInfo(alias="ArtworkCopyrightNotice", default=None) - - artwork_copyright_owner_id: Optional[str] = FieldInfo(alias="ArtworkCopyrightOwnerID", default=None) - - artwork_copyright_owner_name: Optional[str] = FieldInfo(alias="ArtworkCopyrightOwnerName", default=None) - - artwork_creator: Optional[List[str]] = FieldInfo(alias="ArtworkCreator", default=None) - - artwork_creator_id: Optional[List[str]] = FieldInfo(alias="ArtworkCreatorID", default=None) - - artwork_date_created: Optional[datetime] = FieldInfo(alias="ArtworkDateCreated", default=None) - - artwork_licensor_id: Optional[str] = FieldInfo(alias="ArtworkLicensorID", default=None) - - artwork_licensor_name: Optional[str] = FieldInfo(alias="ArtworkLicensorName", default=None) - - artwork_physical_description: Optional[str] = FieldInfo(alias="ArtworkPhysicalDescription", default=None) - - artwork_source: Optional[str] = FieldInfo(alias="ArtworkSource", default=None) - - artwork_source_inventory_no: Optional[str] = FieldInfo(alias="ArtworkSourceInventoryNo", default=None) - - artwork_source_inv_url: Optional[str] = FieldInfo(alias="ArtworkSourceInvURL", default=None) - - artwork_style_period: Optional[List[str]] = FieldInfo(alias="ArtworkStylePeriod", default=None) - - artwork_title: Optional[str] = FieldInfo(alias="ArtworkTitle", default=None) - - authors_position: Optional[str] = FieldInfo(alias="AuthorsPosition", default=None) - - byline: Optional[str] = FieldInfo(alias="Byline", default=None) - - byline_title: Optional[str] = FieldInfo(alias="BylineTitle", default=None) - - caption: Optional[str] = FieldInfo(alias="Caption", default=None) - - caption_abstract: Optional[str] = FieldInfo(alias="CaptionAbstract", default=None) - - caption_writer: Optional[str] = FieldInfo(alias="CaptionWriter", default=None) - - city: Optional[str] = FieldInfo(alias="City", default=None) - - color_space: Optional[str] = FieldInfo(alias="ColorSpace", default=None) - - components_configuration: Optional[str] = FieldInfo(alias="ComponentsConfiguration", default=None) - - copyright: Optional[str] = FieldInfo(alias="Copyright", default=None) - - copyright_notice: Optional[str] = FieldInfo(alias="CopyrightNotice", default=None) - - copyright_owner_id: Optional[List[str]] = FieldInfo(alias="CopyrightOwnerID", default=None) - - copyright_owner_name: Optional[List[str]] = FieldInfo(alias="CopyrightOwnerName", default=None) - - country: Optional[str] = FieldInfo(alias="Country", default=None) - - country_code: Optional[str] = FieldInfo(alias="CountryCode", default=None) - - country_primary_location_code: Optional[str] = FieldInfo(alias="CountryPrimaryLocationCode", default=None) - - country_primary_location_name: Optional[str] = FieldInfo(alias="CountryPrimaryLocationName", default=None) - - creator: Optional[str] = FieldInfo(alias="Creator", default=None) - - creator_address: Optional[str] = FieldInfo(alias="CreatorAddress", default=None) - - creator_city: Optional[str] = FieldInfo(alias="CreatorCity", default=None) - - creator_country: Optional[str] = FieldInfo(alias="CreatorCountry", default=None) - - creator_postal_code: Optional[str] = FieldInfo(alias="CreatorPostalCode", default=None) - - creator_region: Optional[str] = FieldInfo(alias="CreatorRegion", default=None) - - creator_work_email: Optional[str] = FieldInfo(alias="CreatorWorkEmail", default=None) - - creator_work_telephone: Optional[str] = FieldInfo(alias="CreatorWorkTelephone", default=None) - - creator_work_url: Optional[str] = FieldInfo(alias="CreatorWorkURL", default=None) - - credit: Optional[str] = FieldInfo(alias="Credit", default=None) - - date_created: Optional[datetime] = FieldInfo(alias="DateCreated", default=None) - - date_time_created: Optional[datetime] = FieldInfo(alias="DateTimeCreated", default=None) - - date_time_original: Optional[datetime] = FieldInfo(alias="DateTimeOriginal", default=None) - - description: Optional[str] = FieldInfo(alias="Description", default=None) - - digital_image_guid: Optional[str] = FieldInfo(alias="DigitalImageGUID", default=None) - - digital_source_type: Optional[str] = FieldInfo(alias="DigitalSourceType", default=None) - - embedded_encoded_rights_expr: Optional[str] = FieldInfo(alias="EmbeddedEncodedRightsExpr", default=None) - - embedded_encoded_rights_expr_lang_id: Optional[str] = FieldInfo( - alias="EmbeddedEncodedRightsExprLangID", default=None - ) - - embedded_encoded_rights_expr_type: Optional[str] = FieldInfo(alias="EmbeddedEncodedRightsExprType", default=None) - - event: Optional[str] = FieldInfo(alias="Event", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - genre_cv_id: Optional[str] = FieldInfo(alias="GenreCvId", default=None) - - genre_cv_term_id: Optional[str] = FieldInfo(alias="GenreCvTermId", default=None) - - genre_cv_term_name: Optional[str] = FieldInfo(alias="GenreCvTermName", default=None) - - genre_cv_term_refined_about: Optional[str] = FieldInfo(alias="GenreCvTermRefinedAbout", default=None) - - headline: Optional[str] = FieldInfo(alias="Headline", default=None) - - image_creator_id: Optional[str] = FieldInfo(alias="ImageCreatorID", default=None) - - image_creator_image_id: Optional[str] = FieldInfo(alias="ImageCreatorImageID", default=None) - - image_creator_name: Optional[str] = FieldInfo(alias="ImageCreatorName", default=None) - - image_description: Optional[str] = FieldInfo(alias="ImageDescription", default=None) - - image_region_boundary_h: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryH", default=None) - - image_region_boundary_rx: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryRx", default=None) - - image_region_boundary_shape: Optional[List[str]] = FieldInfo(alias="ImageRegionBoundaryShape", default=None) - - image_region_boundary_unit: Optional[List[str]] = FieldInfo(alias="ImageRegionBoundaryUnit", default=None) - - image_region_boundary_vertices_x: Optional[List[float]] = FieldInfo( - alias="ImageRegionBoundaryVerticesX", default=None - ) - - image_region_boundary_vertices_y: Optional[List[float]] = FieldInfo( - alias="ImageRegionBoundaryVerticesY", default=None - ) - - image_region_boundary_w: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryW", default=None) - - image_region_boundary_x: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryX", default=None) - - image_region_boundary_y: Optional[List[float]] = FieldInfo(alias="ImageRegionBoundaryY", default=None) - - image_region_ctype_identifier: Optional[List[str]] = FieldInfo(alias="ImageRegionCtypeIdentifier", default=None) - - image_region_ctype_name: Optional[List[str]] = FieldInfo(alias="ImageRegionCtypeName", default=None) - - image_region_id: Optional[List[str]] = FieldInfo(alias="ImageRegionID", default=None) - - image_region_name: Optional[List[str]] = FieldInfo(alias="ImageRegionName", default=None) - - image_region_organisation_in_image_name: Optional[List[str]] = FieldInfo( - alias="ImageRegionOrganisationInImageName", default=None - ) - - image_region_person_in_image: Optional[List[str]] = FieldInfo(alias="ImageRegionPersonInImage", default=None) - - image_region_role_identifier: Optional[List[str]] = FieldInfo(alias="ImageRegionRoleIdentifier", default=None) - - image_region_role_name: Optional[List[str]] = FieldInfo(alias="ImageRegionRoleName", default=None) - - image_supplier_id: Optional[str] = FieldInfo(alias="ImageSupplierID", default=None) - - image_supplier_image_id: Optional[str] = FieldInfo(alias="ImageSupplierImageID", default=None) - - image_supplier_name: Optional[str] = FieldInfo(alias="ImageSupplierName", default=None) - - instructions: Optional[str] = FieldInfo(alias="Instructions", default=None) - - intellectual_genre: Optional[str] = FieldInfo(alias="IntellectualGenre", default=None) - - keywords: Optional[List[str]] = FieldInfo(alias="Keywords", default=None) - - licensor_city: Optional[List[str]] = FieldInfo(alias="LicensorCity", default=None) - - licensor_country: Optional[List[str]] = FieldInfo(alias="LicensorCountry", default=None) - - licensor_email: Optional[List[str]] = FieldInfo(alias="LicensorEmail", default=None) - - licensor_extended_address: Optional[List[str]] = FieldInfo(alias="LicensorExtendedAddress", default=None) - - licensor_id: Optional[List[str]] = FieldInfo(alias="LicensorID", default=None) - - licensor_name: Optional[List[str]] = FieldInfo(alias="LicensorName", default=None) - - licensor_postal_code: Optional[List[str]] = FieldInfo(alias="LicensorPostalCode", default=None) - - licensor_region: Optional[List[str]] = FieldInfo(alias="LicensorRegion", default=None) - - licensor_street_address: Optional[List[str]] = FieldInfo(alias="LicensorStreetAddress", default=None) - - licensor_telephone1: Optional[List[str]] = FieldInfo(alias="LicensorTelephone1", default=None) - - licensor_telephone2: Optional[List[str]] = FieldInfo(alias="LicensorTelephone2", default=None) - - licensor_url: Optional[List[str]] = FieldInfo(alias="LicensorURL", default=None) - - linked_encoded_rights_expr: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExpr", default=None) - - linked_encoded_rights_expr_lang_id: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExprLangID", default=None) - - linked_encoded_rights_expr_type: Optional[str] = FieldInfo(alias="LinkedEncodedRightsExprType", default=None) - - location: Optional[str] = FieldInfo(alias="Location", default=None) - - location_created_city: Optional[str] = FieldInfo(alias="LocationCreatedCity", default=None) - - location_created_country_code: Optional[str] = FieldInfo(alias="LocationCreatedCountryCode", default=None) - - location_created_country_name: Optional[str] = FieldInfo(alias="LocationCreatedCountryName", default=None) - - location_created_gps_altitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSAltitude", default=None) - - location_created_gps_latitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSLatitude", default=None) - - location_created_gps_longitude: Optional[str] = FieldInfo(alias="LocationCreatedGPSLongitude", default=None) - - location_created_location_id: Optional[str] = FieldInfo(alias="LocationCreatedLocationId", default=None) - - location_created_location_name: Optional[str] = FieldInfo(alias="LocationCreatedLocationName", default=None) - - location_created_province_state: Optional[str] = FieldInfo(alias="LocationCreatedProvinceState", default=None) - - location_created_sublocation: Optional[str] = FieldInfo(alias="LocationCreatedSublocation", default=None) - - location_created_world_region: Optional[str] = FieldInfo(alias="LocationCreatedWorldRegion", default=None) - - location_shown_city: Optional[List[str]] = FieldInfo(alias="LocationShownCity", default=None) - - location_shown_country_code: Optional[List[str]] = FieldInfo(alias="LocationShownCountryCode", default=None) - - location_shown_country_name: Optional[List[str]] = FieldInfo(alias="LocationShownCountryName", default=None) - - location_shown_gps_altitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSAltitude", default=None) - - location_shown_gps_latitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSLatitude", default=None) - - location_shown_gps_longitude: Optional[List[str]] = FieldInfo(alias="LocationShownGPSLongitude", default=None) - - location_shown_location_id: Optional[List[str]] = FieldInfo(alias="LocationShownLocationId", default=None) - - location_shown_location_name: Optional[List[str]] = FieldInfo(alias="LocationShownLocationName", default=None) - - location_shown_province_state: Optional[List[str]] = FieldInfo(alias="LocationShownProvinceState", default=None) - - location_shown_sublocation: Optional[List[str]] = FieldInfo(alias="LocationShownSublocation", default=None) - - location_shown_world_region: Optional[List[str]] = FieldInfo(alias="LocationShownWorldRegion", default=None) - - max_avail_height: Optional[float] = FieldInfo(alias="MaxAvailHeight", default=None) - - max_avail_width: Optional[float] = FieldInfo(alias="MaxAvailWidth", default=None) - - api_model_age: Optional[List[float]] = FieldInfo(alias="ModelAge", default=None) - - api_model_release_id: Optional[List[str]] = FieldInfo(alias="ModelReleaseID", default=None) - - object_attribute_reference: Optional[str] = FieldInfo(alias="ObjectAttributeReference", default=None) - - object_name: Optional[str] = FieldInfo(alias="ObjectName", default=None) - - offset_time_original: Optional[str] = FieldInfo(alias="OffsetTimeOriginal", default=None) - - organisation_in_image_code: Optional[List[str]] = FieldInfo(alias="OrganisationInImageCode", default=None) - - organisation_in_image_name: Optional[List[str]] = FieldInfo(alias="OrganisationInImageName", default=None) - - orientation: Optional[str] = FieldInfo(alias="Orientation", default=None) - - original_transmission_reference: Optional[str] = FieldInfo(alias="OriginalTransmissionReference", default=None) - - person_in_image: Optional[List[str]] = FieldInfo(alias="PersonInImage", default=None) - - person_in_image_cv_term_cv_id: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermCvId", default=None) - - person_in_image_cv_term_id: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermId", default=None) - - person_in_image_cv_term_name: Optional[List[str]] = FieldInfo(alias="PersonInImageCvTermName", default=None) - - person_in_image_cv_term_refined_about: Optional[List[str]] = FieldInfo( - alias="PersonInImageCvTermRefinedAbout", default=None - ) - - person_in_image_description: Optional[List[str]] = FieldInfo(alias="PersonInImageDescription", default=None) - - person_in_image_id: Optional[List[str]] = FieldInfo(alias="PersonInImageId", default=None) - - person_in_image_name: Optional[List[str]] = FieldInfo(alias="PersonInImageName", default=None) - - product_in_image_description: Optional[List[str]] = FieldInfo(alias="ProductInImageDescription", default=None) - - product_in_image_gtin: Optional[List[float]] = FieldInfo(alias="ProductInImageGTIN", default=None) - - product_in_image_name: Optional[List[str]] = FieldInfo(alias="ProductInImageName", default=None) - - property_release_id: Optional[List[str]] = FieldInfo(alias="PropertyReleaseID", default=None) - - province_state: Optional[str] = FieldInfo(alias="ProvinceState", default=None) - - rating: Optional[int] = FieldInfo(alias="Rating", default=None) - - registry_entry_role: Optional[List[str]] = FieldInfo(alias="RegistryEntryRole", default=None) - - registry_item_id: Optional[List[str]] = FieldInfo(alias="RegistryItemID", default=None) - - registry_organisation_id: Optional[List[str]] = FieldInfo(alias="RegistryOrganisationID", default=None) - - resolution_unit: Optional[str] = FieldInfo(alias="ResolutionUnit", default=None) - - rights: Optional[str] = FieldInfo(alias="Rights", default=None) - - scene: Optional[List[str]] = FieldInfo(alias="Scene", default=None) - - source: Optional[str] = FieldInfo(alias="Source", default=None) - - special_instructions: Optional[str] = FieldInfo(alias="SpecialInstructions", default=None) - - state: Optional[str] = FieldInfo(alias="State", default=None) - - subject: Optional[List[str]] = FieldInfo(alias="Subject", default=None) - - subject_code: Optional[List[str]] = FieldInfo(alias="SubjectCode", default=None) - - subject_reference: Optional[List[str]] = FieldInfo(alias="SubjectReference", default=None) - - sublocation: Optional[str] = FieldInfo(alias="Sublocation", default=None) - - time_created: Optional[str] = FieldInfo(alias="TimeCreated", default=None) - - title: Optional[str] = FieldInfo(alias="Title", default=None) - - transmission_reference: Optional[str] = FieldInfo(alias="TransmissionReference", default=None) - - usage_terms: Optional[str] = FieldInfo(alias="UsageTerms", default=None) - - web_statement: Optional[str] = FieldInfo(alias="WebStatement", default=None) - - writer: Optional[str] = FieldInfo(alias="Writer", default=None) - - writer_editor: Optional[str] = FieldInfo(alias="WriterEditor", default=None) - - x_resolution: Optional[float] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[float] = FieldInfo(alias="YResolution", default=None) - - -class ExtensionStatus(BaseModel): - aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( - alias="aws-auto-tagging", default=None - ) - - google_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( - alias="google-auto-tagging", default=None - ) - - remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) - - -class MetadataExif(BaseModel): - exif: Optional[ExifDetails] = None - """Object containing Exif details.""" - - gps: Optional[Gps] = None - """Object containing GPS information.""" - - image: Optional[ExifImage] = None - """Object containing EXIF image information.""" - - interoperability: Optional[Interoperability] = None - """JSON object.""" - - makernote: Optional[Dict[str, object]] = None - - thumbnail: Optional[Thumbnail] = None - """Object containing Thumbnail information.""" - - -class Metadata(BaseModel): - audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) - """The audio codec used in the video (only for video).""" - - bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) - """The bit rate of the video in kbps (only for video).""" - - density: Optional[int] = None - """The density of the image in DPI.""" - - duration: Optional[int] = None - """The duration of the video in seconds (only for video).""" - - exif: Optional[MetadataExif] = None - - format: Optional[str] = None - """The format of the file (e.g., 'jpg', 'mp4').""" - - has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) - """Indicates if the image has a color profile.""" - - has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) - """Indicates if the image contains transparent areas.""" - - height: Optional[int] = None - """The height of the image or video in pixels.""" - - p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) - """Perceptual hash of the image.""" - - quality: Optional[int] = None - """The quality indicator of the image.""" - - size: Optional[int] = None - """The file size in bytes.""" - - video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) - """The video codec used in the video (only for video).""" - - width: Optional[int] = None - """The width of the image or video in pixels.""" - - -class VersionInfo(BaseModel): - id: Optional[str] = None - """Unique identifier of the file version.""" - - name: Optional[str] = None - """Name of the file version.""" - - -class FileUploadV2Response(BaseModel): - ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) - """An array of tags assigned to the uploaded file by auto tagging.""" - - audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) - """The audio codec used in the video (only for video).""" - - bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) - """The bit rate of the video in kbps (only for video).""" - - custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) - """ - Value of custom coordinates associated with the image in the format - `x,y,width,height`. If `customCoordinates` are not defined, then it is `null`. - Send `customCoordinates` in `responseFields` in API request to get the value of - this field. - """ - - custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) - """A key-value data associated with the asset. - - Use `responseField` in API request to get `customMetadata` in the upload API - response. Before setting any custom metadata on an asset, you have to create the - field using custom metadata fields API. Send `customMetadata` in - `responseFields` in API request to get the value of this field. - """ - - duration: Optional[int] = None - """The duration of the video in seconds (only for video).""" - - embedded_metadata: Optional[EmbeddedMetadata] = FieldInfo(alias="embeddedMetadata", default=None) - """Consolidated embedded metadata associated with the file. - - It includes exif, iptc, and xmp data. Send `embeddedMetadata` in - `responseFields` in API request to get embeddedMetadata in the upload API - response. - """ - - extension_status: Optional[ExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) - """ - Extension names with their processing status at the time of completion of the - request. It could have one of the following status values: - - `success`: The extension has been successfully applied. `failed`: The extension - has failed and will not be retried. `pending`: The extension will finish - processing in some time. On completion, the final status (success / failed) will - be sent to the `webhookUrl` provided. - - If no extension was requested, then this parameter is not returned. - """ - - file_id: Optional[str] = FieldInfo(alias="fileId", default=None) - """Unique fileId. - - Store this fileld in your database, as this will be used to perform update - action on this file. - """ - - file_path: Optional[str] = FieldInfo(alias="filePath", default=None) - """The relative path of the file in the media library e.g. - - `/marketing-assets/new-banner.jpg`. - """ - - file_type: Optional[str] = FieldInfo(alias="fileType", default=None) - """Type of the uploaded file. Possible values are `image`, `non-image`.""" - - height: Optional[float] = None - """Height of the image in pixels (Only for images)""" - - is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) - """Is the file marked as private. - - It can be either `true` or `false`. Send `isPrivateFile` in `responseFields` in - API request to get the value of this field. - """ - - is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) - """Is the file published or in draft state. - - It can be either `true` or `false`. Send `isPublished` in `responseFields` in - API request to get the value of this field. - """ - - metadata: Optional[Metadata] = None - """Legacy metadata. - - Send `metadata` in `responseFields` in API request to get metadata in the upload - API response. - """ - - name: Optional[str] = None - """Name of the asset.""" - - size: Optional[float] = None - """Size of the image file in Bytes.""" - - tags: Optional[List[str]] = None - """The array of tags associated with the asset. - - If no tags are set, it will be `null`. Send `tags` in `responseFields` in API - request to get the value of this field. - """ - - thumbnail_url: Optional[str] = FieldInfo(alias="thumbnailUrl", default=None) - """In the case of an image, a small thumbnail URL.""" - - url: Optional[str] = None - """A publicly accessible URL of the file.""" - - version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) - """An object containing the file or file version's `id` (versionId) and `name`.""" - - video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) - """The video codec used in the video (only for video).""" - - width: Optional[float] = None - """Width of the image in pixels (Only for Images)""" diff --git a/src/imagekit/types/files/__init__.py b/src/imagekit/types/files/__init__.py index f82cdc3..b828070 100644 --- a/src/imagekit/types/files/__init__.py +++ b/src/imagekit/types/files/__init__.py @@ -2,17 +2,17 @@ from __future__ import annotations -from .batch_delete_params import BatchDeleteParams as BatchDeleteParams -from .detail_update_params import DetailUpdateParams as DetailUpdateParams -from .purge_execute_params import PurgeExecuteParams as PurgeExecuteParams -from .batch_delete_response import BatchDeleteResponse as BatchDeleteResponse -from .purge_status_response import PurgeStatusResponse as PurgeStatusResponse +from .bulk_delete_params import BulkDeleteParams as BulkDeleteParams +from .bulk_add_tags_params import BulkAddTagsParams as BulkAddTagsParams +from .bulk_delete_response import BulkDeleteResponse as BulkDeleteResponse +from .version_get_response import VersionGetResponse as VersionGetResponse +from .metadata_get_response import MetadataGetResponse as MetadataGetResponse from .version_list_response import VersionListResponse as VersionListResponse -from .detail_update_response import DetailUpdateResponse as DetailUpdateResponse -from .purge_execute_response import PurgeExecuteResponse as PurgeExecuteResponse -from .detail_retrieve_response import DetailRetrieveResponse as DetailRetrieveResponse -from .metadata_from_url_params import MetadataFromURLParams as MetadataFromURLParams +from .bulk_add_tags_response import BulkAddTagsResponse as BulkAddTagsResponse +from .bulk_remove_tags_params import BulkRemoveTagsParams as BulkRemoveTagsParams from .version_restore_response import VersionRestoreResponse as VersionRestoreResponse -from .version_retrieve_response import VersionRetrieveResponse as VersionRetrieveResponse -from .metadata_from_url_response import MetadataFromURLResponse as MetadataFromURLResponse -from .metadata_retrieve_response import MetadataRetrieveResponse as MetadataRetrieveResponse +from .bulk_remove_tags_response import BulkRemoveTagsResponse as BulkRemoveTagsResponse +from .bulk_remove_ai_tags_params import BulkRemoveAITagsParams as BulkRemoveAITagsParams +from .bulk_remove_ai_tags_response import BulkRemoveAITagsResponse as BulkRemoveAITagsResponse +from .metadata_get_from_url_params import MetadataGetFromURLParams as MetadataGetFromURLParams +from .metadata_get_from_url_response import MetadataGetFromURLResponse as MetadataGetFromURLResponse diff --git a/src/imagekit/types/file_add_tags_params.py b/src/imagekit/types/files/bulk_add_tags_params.py similarity index 79% rename from src/imagekit/types/file_add_tags_params.py rename to src/imagekit/types/files/bulk_add_tags_params.py index bfedb89..3103a51 100644 --- a/src/imagekit/types/file_add_tags_params.py +++ b/src/imagekit/types/files/bulk_add_tags_params.py @@ -5,12 +5,12 @@ from typing import List from typing_extensions import Required, Annotated, TypedDict -from .._utils import PropertyInfo +from ..._utils import PropertyInfo -__all__ = ["FileAddTagsParams"] +__all__ = ["BulkAddTagsParams"] -class FileAddTagsParams(TypedDict, total=False): +class BulkAddTagsParams(TypedDict, total=False): file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] """An array of fileIds to which you want to add tags.""" diff --git a/src/imagekit/types/file_add_tags_response.py b/src/imagekit/types/files/bulk_add_tags_response.py similarity index 77% rename from src/imagekit/types/file_add_tags_response.py rename to src/imagekit/types/files/bulk_add_tags_response.py index d4ac397..059ae52 100644 --- a/src/imagekit/types/file_add_tags_response.py +++ b/src/imagekit/types/files/bulk_add_tags_response.py @@ -4,11 +4,11 @@ from pydantic import Field as FieldInfo -from .._models import BaseModel +from ..._models import BaseModel -__all__ = ["FileAddTagsResponse"] +__all__ = ["BulkAddTagsResponse"] -class FileAddTagsResponse(BaseModel): +class BulkAddTagsResponse(BaseModel): successfully_updated_file_ids: Optional[List[str]] = FieldInfo(alias="successfullyUpdatedFileIds", default=None) """An array of fileIds that in which tags were successfully added.""" diff --git a/src/imagekit/types/files/batch_delete_params.py b/src/imagekit/types/files/bulk_delete_params.py similarity index 82% rename from src/imagekit/types/files/batch_delete_params.py rename to src/imagekit/types/files/bulk_delete_params.py index ed7a66d..b00f0bf 100644 --- a/src/imagekit/types/files/batch_delete_params.py +++ b/src/imagekit/types/files/bulk_delete_params.py @@ -7,9 +7,9 @@ from ..._utils import PropertyInfo -__all__ = ["BatchDeleteParams"] +__all__ = ["BulkDeleteParams"] -class BatchDeleteParams(TypedDict, total=False): +class BulkDeleteParams(TypedDict, total=False): file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] """An array of fileIds which you want to delete.""" diff --git a/src/imagekit/types/files/batch_delete_response.py b/src/imagekit/types/files/bulk_delete_response.py similarity index 84% rename from src/imagekit/types/files/batch_delete_response.py rename to src/imagekit/types/files/bulk_delete_response.py index 00090fb..af431f3 100644 --- a/src/imagekit/types/files/batch_delete_response.py +++ b/src/imagekit/types/files/bulk_delete_response.py @@ -6,9 +6,9 @@ from ..._models import BaseModel -__all__ = ["BatchDeleteResponse"] +__all__ = ["BulkDeleteResponse"] -class BatchDeleteResponse(BaseModel): +class BulkDeleteResponse(BaseModel): successfully_deleted_file_ids: Optional[List[str]] = FieldInfo(alias="successfullyDeletedFileIds", default=None) """An array of fileIds that were successfully deleted.""" diff --git a/src/imagekit/types/file_remove_ai_tags_params.py b/src/imagekit/types/files/bulk_remove_ai_tags_params.py similarity index 79% rename from src/imagekit/types/file_remove_ai_tags_params.py rename to src/imagekit/types/files/bulk_remove_ai_tags_params.py index b00b379..7164c4f 100644 --- a/src/imagekit/types/file_remove_ai_tags_params.py +++ b/src/imagekit/types/files/bulk_remove_ai_tags_params.py @@ -5,12 +5,12 @@ from typing import List from typing_extensions import Required, Annotated, TypedDict -from .._utils import PropertyInfo +from ..._utils import PropertyInfo -__all__ = ["FileRemoveAITagsParams"] +__all__ = ["BulkRemoveAITagsParams"] -class FileRemoveAITagsParams(TypedDict, total=False): +class BulkRemoveAITagsParams(TypedDict, total=False): ai_tags: Required[Annotated[List[str], PropertyInfo(alias="AITags")]] """An array of AITags that you want to remove from the files.""" diff --git a/src/imagekit/types/file_remove_ai_tags_response.py b/src/imagekit/types/files/bulk_remove_ai_tags_response.py similarity index 75% rename from src/imagekit/types/file_remove_ai_tags_response.py rename to src/imagekit/types/files/bulk_remove_ai_tags_response.py index 3e3a5f2..155d03c 100644 --- a/src/imagekit/types/file_remove_ai_tags_response.py +++ b/src/imagekit/types/files/bulk_remove_ai_tags_response.py @@ -4,11 +4,11 @@ from pydantic import Field as FieldInfo -from .._models import BaseModel +from ..._models import BaseModel -__all__ = ["FileRemoveAITagsResponse"] +__all__ = ["BulkRemoveAITagsResponse"] -class FileRemoveAITagsResponse(BaseModel): +class BulkRemoveAITagsResponse(BaseModel): successfully_updated_file_ids: Optional[List[str]] = FieldInfo(alias="successfullyUpdatedFileIds", default=None) """An array of fileIds that in which AITags were successfully removed.""" diff --git a/src/imagekit/types/file_remove_tags_params.py b/src/imagekit/types/files/bulk_remove_tags_params.py similarity index 78% rename from src/imagekit/types/file_remove_tags_params.py rename to src/imagekit/types/files/bulk_remove_tags_params.py index 33903de..e9f9ffc 100644 --- a/src/imagekit/types/file_remove_tags_params.py +++ b/src/imagekit/types/files/bulk_remove_tags_params.py @@ -5,12 +5,12 @@ from typing import List from typing_extensions import Required, Annotated, TypedDict -from .._utils import PropertyInfo +from ..._utils import PropertyInfo -__all__ = ["FileRemoveTagsParams"] +__all__ = ["BulkRemoveTagsParams"] -class FileRemoveTagsParams(TypedDict, total=False): +class BulkRemoveTagsParams(TypedDict, total=False): file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] """An array of fileIds from which you want to remove tags.""" diff --git a/src/imagekit/types/file_remove_tags_response.py b/src/imagekit/types/files/bulk_remove_tags_response.py similarity index 76% rename from src/imagekit/types/file_remove_tags_response.py rename to src/imagekit/types/files/bulk_remove_tags_response.py index 016caca..37c1c67 100644 --- a/src/imagekit/types/file_remove_tags_response.py +++ b/src/imagekit/types/files/bulk_remove_tags_response.py @@ -4,11 +4,11 @@ from pydantic import Field as FieldInfo -from .._models import BaseModel +from ..._models import BaseModel -__all__ = ["FileRemoveTagsResponse"] +__all__ = ["BulkRemoveTagsResponse"] -class FileRemoveTagsResponse(BaseModel): +class BulkRemoveTagsResponse(BaseModel): successfully_updated_file_ids: Optional[List[str]] = FieldInfo(alias="successfullyUpdatedFileIds", default=None) """An array of fileIds that in which tags were successfully removed.""" diff --git a/src/imagekit/types/files/metadata_from_url_response.py b/src/imagekit/types/files/metadata_from_url_response.py deleted file mode 100644 index 66225ef..0000000 --- a/src/imagekit/types/files/metadata_from_url_response.py +++ /dev/null @@ -1,76 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, Optional - -from pydantic import Field as FieldInfo - -from ..gps import Gps -from ..._models import BaseModel -from ..thumbnail import Thumbnail -from ..exif_image import ExifImage -from ..exif_details import ExifDetails -from ..interoperability import Interoperability - -__all__ = ["MetadataFromURLResponse", "Exif"] - - -class Exif(BaseModel): - exif: Optional[ExifDetails] = None - """Object containing Exif details.""" - - gps: Optional[Gps] = None - """Object containing GPS information.""" - - image: Optional[ExifImage] = None - """Object containing EXIF image information.""" - - interoperability: Optional[Interoperability] = None - """JSON object.""" - - makernote: Optional[Dict[str, object]] = None - - thumbnail: Optional[Thumbnail] = None - """Object containing Thumbnail information.""" - - -class MetadataFromURLResponse(BaseModel): - audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) - """The audio codec used in the video (only for video).""" - - bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) - """The bit rate of the video in kbps (only for video).""" - - density: Optional[int] = None - """The density of the image in DPI.""" - - duration: Optional[int] = None - """The duration of the video in seconds (only for video).""" - - exif: Optional[Exif] = None - - format: Optional[str] = None - """The format of the file (e.g., 'jpg', 'mp4').""" - - has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) - """Indicates if the image has a color profile.""" - - has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) - """Indicates if the image contains transparent areas.""" - - height: Optional[int] = None - """The height of the image or video in pixels.""" - - p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) - """Perceptual hash of the image.""" - - quality: Optional[int] = None - """The quality indicator of the image.""" - - size: Optional[int] = None - """The file size in bytes.""" - - video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) - """The video codec used in the video (only for video).""" - - width: Optional[int] = None - """The width of the image or video in pixels.""" diff --git a/src/imagekit/types/files/metadata_from_url_params.py b/src/imagekit/types/files/metadata_get_from_url_params.py similarity index 76% rename from src/imagekit/types/files/metadata_from_url_params.py rename to src/imagekit/types/files/metadata_get_from_url_params.py index b00e09b..6fdbb63 100644 --- a/src/imagekit/types/files/metadata_from_url_params.py +++ b/src/imagekit/types/files/metadata_get_from_url_params.py @@ -4,10 +4,10 @@ from typing_extensions import Required, TypedDict -__all__ = ["MetadataFromURLParams"] +__all__ = ["MetadataGetFromURLParams"] -class MetadataFromURLParams(TypedDict, total=False): +class MetadataGetFromURLParams(TypedDict, total=False): url: Required[str] """Should be a valid file URL. diff --git a/src/imagekit/types/files/metadata_get_from_url_response.py b/src/imagekit/types/files/metadata_get_from_url_response.py new file mode 100644 index 0000000..47b1bcd --- /dev/null +++ b/src/imagekit/types/files/metadata_get_from_url_response.py @@ -0,0 +1,181 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "MetadataGetFromURLResponse", + "Exif", + "ExifExif", + "ExifGps", + "ExifImage", + "ExifInteroperability", + "ExifThumbnail", +] + + +class ExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class ExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class ExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class ExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class ExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class Exif(BaseModel): + exif: Optional[ExifExif] = None + """Object containing Exif details.""" + + gps: Optional[ExifGps] = None + """Object containing GPS information.""" + + image: Optional[ExifImage] = None + """Object containing EXIF image information.""" + + interoperability: Optional[ExifInteroperability] = None + """JSON object.""" + + makernote: Optional[Dict[str, object]] = None + + thumbnail: Optional[ExifThumbnail] = None + """Object containing Thumbnail information.""" + + +class MetadataGetFromURLResponse(BaseModel): + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + density: Optional[int] = None + """The density of the image in DPI.""" + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + exif: Optional[Exif] = None + + format: Optional[str] = None + """The format of the file (e.g., 'jpg', 'mp4').""" + + has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) + """Indicates if the image has a color profile.""" + + has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) + """Indicates if the image contains transparent areas.""" + + height: Optional[int] = None + """The height of the image or video in pixels.""" + + p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) + """Perceptual hash of the image.""" + + quality: Optional[int] = None + """The quality indicator of the image.""" + + size: Optional[int] = None + """The file size in bytes.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[int] = None + """The width of the image or video in pixels.""" diff --git a/src/imagekit/types/files/metadata_get_response.py b/src/imagekit/types/files/metadata_get_response.py new file mode 100644 index 0000000..d5a3cbf --- /dev/null +++ b/src/imagekit/types/files/metadata_get_response.py @@ -0,0 +1,173 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["MetadataGetResponse", "Exif", "ExifExif", "ExifGps", "ExifImage", "ExifInteroperability", "ExifThumbnail"] + + +class ExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class ExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class ExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class ExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class ExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class Exif(BaseModel): + exif: Optional[ExifExif] = None + """Object containing Exif details.""" + + gps: Optional[ExifGps] = None + """Object containing GPS information.""" + + image: Optional[ExifImage] = None + """Object containing EXIF image information.""" + + interoperability: Optional[ExifInteroperability] = None + """JSON object.""" + + makernote: Optional[Dict[str, object]] = None + + thumbnail: Optional[ExifThumbnail] = None + """Object containing Thumbnail information.""" + + +class MetadataGetResponse(BaseModel): + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + density: Optional[int] = None + """The density of the image in DPI.""" + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + exif: Optional[Exif] = None + + format: Optional[str] = None + """The format of the file (e.g., 'jpg', 'mp4').""" + + has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) + """Indicates if the image has a color profile.""" + + has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) + """Indicates if the image contains transparent areas.""" + + height: Optional[int] = None + """The height of the image or video in pixels.""" + + p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) + """Perceptual hash of the image.""" + + quality: Optional[int] = None + """The quality indicator of the image.""" + + size: Optional[int] = None + """The file size in bytes.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[int] = None + """The width of the image or video in pixels.""" diff --git a/src/imagekit/types/files/metadata_retrieve_response.py b/src/imagekit/types/files/metadata_retrieve_response.py deleted file mode 100644 index 26e96f7..0000000 --- a/src/imagekit/types/files/metadata_retrieve_response.py +++ /dev/null @@ -1,76 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, Optional - -from pydantic import Field as FieldInfo - -from ..gps import Gps -from ..._models import BaseModel -from ..thumbnail import Thumbnail -from ..exif_image import ExifImage -from ..exif_details import ExifDetails -from ..interoperability import Interoperability - -__all__ = ["MetadataRetrieveResponse", "Exif"] - - -class Exif(BaseModel): - exif: Optional[ExifDetails] = None - """Object containing Exif details.""" - - gps: Optional[Gps] = None - """Object containing GPS information.""" - - image: Optional[ExifImage] = None - """Object containing EXIF image information.""" - - interoperability: Optional[Interoperability] = None - """JSON object.""" - - makernote: Optional[Dict[str, object]] = None - - thumbnail: Optional[Thumbnail] = None - """Object containing Thumbnail information.""" - - -class MetadataRetrieveResponse(BaseModel): - audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) - """The audio codec used in the video (only for video).""" - - bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) - """The bit rate of the video in kbps (only for video).""" - - density: Optional[int] = None - """The density of the image in DPI.""" - - duration: Optional[int] = None - """The duration of the video in seconds (only for video).""" - - exif: Optional[Exif] = None - - format: Optional[str] = None - """The format of the file (e.g., 'jpg', 'mp4').""" - - has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) - """Indicates if the image has a color profile.""" - - has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) - """Indicates if the image contains transparent areas.""" - - height: Optional[int] = None - """The height of the image or video in pixels.""" - - p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) - """Perceptual hash of the image.""" - - quality: Optional[int] = None - """The quality indicator of the image.""" - - size: Optional[int] = None - """The file size in bytes.""" - - video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) - """The video codec used in the video (only for video).""" - - width: Optional[int] = None - """The width of the image or video in pixels.""" diff --git a/src/imagekit/types/files/detail_retrieve_response.py b/src/imagekit/types/files/version_get_response.py similarity index 97% rename from src/imagekit/types/files/detail_retrieve_response.py rename to src/imagekit/types/files/version_get_response.py index b5c6331..f195b99 100644 --- a/src/imagekit/types/files/detail_retrieve_response.py +++ b/src/imagekit/types/files/version_get_response.py @@ -6,7 +6,7 @@ from ..._models import BaseModel -__all__ = ["DetailRetrieveResponse", "AITag", "VersionInfo"] +__all__ = ["VersionGetResponse", "AITag", "VersionInfo"] class AITag(BaseModel): @@ -31,7 +31,7 @@ class VersionInfo(BaseModel): """Name of the file version.""" -class DetailRetrieveResponse(BaseModel): +class VersionGetResponse(BaseModel): ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" diff --git a/src/imagekit/types/bulk_job_copy_folder_params.py b/src/imagekit/types/folder_copy_params.py similarity index 90% rename from src/imagekit/types/bulk_job_copy_folder_params.py rename to src/imagekit/types/folder_copy_params.py index b6c36b7..4ccc7fa 100644 --- a/src/imagekit/types/bulk_job_copy_folder_params.py +++ b/src/imagekit/types/folder_copy_params.py @@ -6,10 +6,10 @@ from .._utils import PropertyInfo -__all__ = ["BulkJobCopyFolderParams"] +__all__ = ["FolderCopyParams"] -class BulkJobCopyFolderParams(TypedDict, total=False): +class FolderCopyParams(TypedDict, total=False): destination_path: Required[Annotated[str, PropertyInfo(alias="destinationPath")]] """ Full path to the destination folder where you want to copy the source folder diff --git a/src/imagekit/types/bulk_job_copy_folder_response.py b/src/imagekit/types/folder_copy_response.py similarity index 81% rename from src/imagekit/types/bulk_job_copy_folder_response.py rename to src/imagekit/types/folder_copy_response.py index 088c6c8..4e2f5ab 100644 --- a/src/imagekit/types/bulk_job_copy_folder_response.py +++ b/src/imagekit/types/folder_copy_response.py @@ -6,10 +6,10 @@ from .._models import BaseModel -__all__ = ["BulkJobCopyFolderResponse"] +__all__ = ["FolderCopyResponse"] -class BulkJobCopyFolderResponse(BaseModel): +class FolderCopyResponse(BaseModel): job_id: Optional[str] = FieldInfo(alias="jobId", default=None) """Unique identifier of the bulk job. diff --git a/src/imagekit/types/bulk_job_move_folder_params.py b/src/imagekit/types/folder_move_params.py similarity index 85% rename from src/imagekit/types/bulk_job_move_folder_params.py rename to src/imagekit/types/folder_move_params.py index 3414b45..59f63cd 100644 --- a/src/imagekit/types/bulk_job_move_folder_params.py +++ b/src/imagekit/types/folder_move_params.py @@ -6,10 +6,10 @@ from .._utils import PropertyInfo -__all__ = ["BulkJobMoveFolderParams"] +__all__ = ["FolderMoveParams"] -class BulkJobMoveFolderParams(TypedDict, total=False): +class FolderMoveParams(TypedDict, total=False): destination_path: Required[Annotated[str, PropertyInfo(alias="destinationPath")]] """ Full path to the destination folder where you want to move the source folder diff --git a/src/imagekit/types/bulk_job_move_folder_response.py b/src/imagekit/types/folder_move_response.py similarity index 81% rename from src/imagekit/types/bulk_job_move_folder_response.py rename to src/imagekit/types/folder_move_response.py index d6e72c3..a2d1a6f 100644 --- a/src/imagekit/types/bulk_job_move_folder_response.py +++ b/src/imagekit/types/folder_move_response.py @@ -6,10 +6,10 @@ from .._models import BaseModel -__all__ = ["BulkJobMoveFolderResponse"] +__all__ = ["FolderMoveResponse"] -class BulkJobMoveFolderResponse(BaseModel): +class FolderMoveResponse(BaseModel): job_id: Optional[str] = FieldInfo(alias="jobId", default=None) """Unique identifier of the bulk job. diff --git a/src/imagekit/types/folder_rename_params.py b/src/imagekit/types/folder_rename_params.py new file mode 100644 index 0000000..8c9caba --- /dev/null +++ b/src/imagekit/types/folder_rename_params.py @@ -0,0 +1,40 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["FolderRenameParams"] + + +class FolderRenameParams(TypedDict, total=False): + folder_path: Required[Annotated[str, PropertyInfo(alias="folderPath")]] + """The full path to the folder you want to rename.""" + + new_folder_name: Required[Annotated[str, PropertyInfo(alias="newFolderName")]] + """The new name for the folder. + + All characters except alphabets and numbers (inclusive of unicode letters, + marks, and numerals in other languages) and `-` will be replaced by an + underscore i.e. `_`. + """ + + purge_cache: Annotated[bool, PropertyInfo(alias="purgeCache")] + """Option to purge cache for the old nested files and their versions' URLs. + + When set to true, it will internally issue a purge cache request on CDN to + remove the cached content of the old nested files and their versions. There will + only be one purge request for all the nested files, which will be counted + against your monthly purge quota. + + Note: A purge cache request will be issued against + `https://ik.imagekit.io/old/folder/path*` (with a wildcard at the end). This + will remove all nested files, their versions' URLs, and any transformations made + using query parameters on these files or their versions. However, the cache for + file transformations made using path parameters will persist. You can purge them + using the purge API. For more details, refer to the purge API documentation. + + Default value - `false` + """ diff --git a/src/imagekit/types/folder_rename_response.py b/src/imagekit/types/folder_rename_response.py new file mode 100644 index 0000000..b693ea0 --- /dev/null +++ b/src/imagekit/types/folder_rename_response.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["FolderRenameResponse"] + + +class FolderRenameResponse(BaseModel): + job_id: Optional[str] = FieldInfo(alias="jobId", default=None) + """Unique identifier of the bulk job. + + This can be used to check the status of the bulk job. + """ diff --git a/src/imagekit/types/folders/__init__.py b/src/imagekit/types/folders/__init__.py new file mode 100644 index 0000000..8c60dd2 --- /dev/null +++ b/src/imagekit/types/folders/__init__.py @@ -0,0 +1,5 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .job_get_response import JobGetResponse as JobGetResponse diff --git a/src/imagekit/types/folders/job_get_response.py b/src/imagekit/types/folders/job_get_response.py new file mode 100644 index 0000000..d63f771 --- /dev/null +++ b/src/imagekit/types/folders/job_get_response.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["JobGetResponse"] + + +class JobGetResponse(BaseModel): + job_id: Optional[str] = FieldInfo(alias="jobId", default=None) + """Unique identifier of the bulk job.""" + + purge_request_id: Optional[str] = FieldInfo(alias="purgeRequestId", default=None) + """Unique identifier of the purge request. + + This will be present only if `purgeCache` is set to `true` in the rename folder + API request. + """ + + status: Optional[str] = None + """Status of the bulk job. Possible values - `Pending`, `Completed`.""" + + type: Optional[str] = None + """Type of the bulk job. + + Possible values - `COPY_FOLDER`, `MOVE_FOLDER`, `RENAME_FOLDER`. + """ diff --git a/src/imagekit/types/gps.py b/src/imagekit/types/gps.py deleted file mode 100644 index db7024b..0000000 --- a/src/imagekit/types/gps.py +++ /dev/null @@ -1,13 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["Gps"] - - -class Gps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) diff --git a/src/imagekit/types/interoperability.py b/src/imagekit/types/interoperability.py deleted file mode 100644 index 244734d..0000000 --- a/src/imagekit/types/interoperability.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["Interoperability"] - - -class Interoperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) diff --git a/src/imagekit/types/thumbnail.py b/src/imagekit/types/thumbnail.py deleted file mode 100644 index b5a913a..0000000 --- a/src/imagekit/types/thumbnail.py +++ /dev/null @@ -1,23 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["Thumbnail"] - - -class Thumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) diff --git a/tests/api_resources/accounts/__init__.py b/tests/api_resources/accounts/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/accounts/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/accounts/test_origins.py b/tests/api_resources/accounts/test_origins.py new file mode 100644 index 0000000..ae49f15 --- /dev/null +++ b/tests/api_resources/accounts/test_origins.py @@ -0,0 +1,2437 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types.accounts import ( + OriginGetResponse, + OriginListResponse, + OriginCreateResponse, + OriginUpdateResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestOrigins: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_1(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_1(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_1(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_1(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_2(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_2(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + s3_force_path_style=True, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_2(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_2(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_3(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_3(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_3(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_3(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_4(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_4(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + base_url_for_canonical_header="https://cdn.example.com", + forward_host_header_to_origin=False, + include_canonical_header=False, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_4(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_4(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_5(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + name="US S3 Storage", + type="WEB_PROXY", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_5(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + name="US S3 Storage", + type="WEB_PROXY", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_5(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + name="US S3 Storage", + type="WEB_PROXY", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_5(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + name="US S3 Storage", + type="WEB_PROXY", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_6(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_6(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="products", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_6(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_6(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_7(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_7(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="uploads", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_7(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_7(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_8(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_8(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_8(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_8(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_1(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_1(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_1(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_2(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + s3_force_path_style=True, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_2(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_2(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_3(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_3(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_3(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_3(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_3(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_4(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_4(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + base_url_for_canonical_header="https://cdn.example.com", + forward_host_header_to_origin=False, + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_4(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_4(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_4(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_5(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_5(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_5(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_5(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_5(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + name="US S3 Storage", + type="WEB_PROXY", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_6(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_6(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="products", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_6(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_6(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_6(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_7(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_7(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="uploads", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_7(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_7(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_7(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_8(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_8(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_8(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_8(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_8(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: ImageKit) -> None: + origin = client.accounts.origins.list() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + origin = client.accounts.origins.delete( + "id", + ) + assert origin is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert origin is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert origin is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_get(self, client: ImageKit) -> None: + origin = client.accounts.origins.get( + "id", + ) + assert_matches_type(OriginGetResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.get( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginGetResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.get( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginGetResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_get(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.get( + "", + ) + + +class TestAsyncOrigins: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_1(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_1(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_1(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_2(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + s3_force_path_style=True, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_2(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_2(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_3(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_3(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_3(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_3(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_4(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_4(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + base_url_for_canonical_header="https://cdn.example.com", + forward_host_header_to_origin=False, + include_canonical_header=False, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_4(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_4(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_5(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + name="US S3 Storage", + type="WEB_PROXY", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_5(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + name="US S3 Storage", + type="WEB_PROXY", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_5(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + name="US S3 Storage", + type="WEB_PROXY", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_5(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + name="US S3 Storage", + type="WEB_PROXY", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_6(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_6(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="products", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_6(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_6(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_7(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_7(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="uploads", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_7(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_7(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_8(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_8(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_8(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_8(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + s3_force_path_style=True, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_3(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_3(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_3(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_3(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_3(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_4(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_4(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + base_url_for_canonical_header="https://cdn.example.com", + forward_host_header_to_origin=False, + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_4(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_4(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_4(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_5(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_5(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_5(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_5(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_5(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + name="US S3 Storage", + type="WEB_PROXY", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_6(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_6(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="products", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_6(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_6(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_6(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_7(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_7(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="uploads", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_7(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_7(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_7(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_8(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_8(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_8(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_8(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_8(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.list() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.delete( + "id", + ) + assert origin is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert origin is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert origin is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_get(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.get( + "id", + ) + assert_matches_type(OriginGetResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.get( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginGetResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.get( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginGetResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_get(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.get( + "", + ) diff --git a/tests/api_resources/accounts/test_url_endpoints.py b/tests/api_resources/accounts/test_url_endpoints.py new file mode 100644 index 0000000..b84517e --- /dev/null +++ b/tests/api_resources/accounts/test_url_endpoints.py @@ -0,0 +1,471 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types.accounts import ( + URLEndpointGetResponse, + URLEndpointListResponse, + URLEndpointCreateResponse, + URLEndpointUpdateResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestURLEndpoints: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create(self, client: ImageKit) -> None: + url_endpoint = client.accounts.url_endpoints.create( + description="My custom URL endpoint", + ) + assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: ImageKit) -> None: + url_endpoint = client.accounts.url_endpoints.create( + description="My custom URL endpoint", + origins=["origin-id-1"], + url_prefix="product-images", + url_rewriter={ + "type": "CLOUDINARY", + "preserve_asset_delivery_types": True, + }, + ) + assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create(self, client: ImageKit) -> None: + response = client.accounts.url_endpoints.with_raw_response.create( + description="My custom URL endpoint", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + url_endpoint = response.parse() + assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create(self, client: ImageKit) -> None: + with client.accounts.url_endpoints.with_streaming_response.create( + description="My custom URL endpoint", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + url_endpoint = response.parse() + assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update(self, client: ImageKit) -> None: + url_endpoint = client.accounts.url_endpoints.update( + id="id", + description="My custom URL endpoint", + ) + assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: ImageKit) -> None: + url_endpoint = client.accounts.url_endpoints.update( + id="id", + description="My custom URL endpoint", + origins=["origin-id-1"], + url_prefix="product-images", + url_rewriter={ + "type": "CLOUDINARY", + "preserve_asset_delivery_types": True, + }, + ) + assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update(self, client: ImageKit) -> None: + response = client.accounts.url_endpoints.with_raw_response.update( + id="id", + description="My custom URL endpoint", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + url_endpoint = response.parse() + assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update(self, client: ImageKit) -> None: + with client.accounts.url_endpoints.with_streaming_response.update( + id="id", + description="My custom URL endpoint", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + url_endpoint = response.parse() + assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.url_endpoints.with_raw_response.update( + id="", + description="My custom URL endpoint", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: ImageKit) -> None: + url_endpoint = client.accounts.url_endpoints.list() + assert_matches_type(URLEndpointListResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: ImageKit) -> None: + response = client.accounts.url_endpoints.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + url_endpoint = response.parse() + assert_matches_type(URLEndpointListResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: ImageKit) -> None: + with client.accounts.url_endpoints.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + url_endpoint = response.parse() + assert_matches_type(URLEndpointListResponse, url_endpoint, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + url_endpoint = client.accounts.url_endpoints.delete( + "id", + ) + assert url_endpoint is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.accounts.url_endpoints.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + url_endpoint = response.parse() + assert url_endpoint is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.accounts.url_endpoints.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + url_endpoint = response.parse() + assert url_endpoint is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.url_endpoints.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_get(self, client: ImageKit) -> None: + url_endpoint = client.accounts.url_endpoints.get( + "id", + ) + assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.accounts.url_endpoints.with_raw_response.get( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + url_endpoint = response.parse() + assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.accounts.url_endpoints.with_streaming_response.get( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + url_endpoint = response.parse() + assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_get(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.url_endpoints.with_raw_response.get( + "", + ) + + +class TestAsyncURLEndpoints: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncImageKit) -> None: + url_endpoint = await async_client.accounts.url_endpoints.create( + description="My custom URL endpoint", + ) + assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncImageKit) -> None: + url_endpoint = await async_client.accounts.url_endpoints.create( + description="My custom URL endpoint", + origins=["origin-id-1"], + url_prefix="product-images", + url_rewriter={ + "type": "CLOUDINARY", + "preserve_asset_delivery_types": True, + }, + ) + assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.url_endpoints.with_raw_response.create( + description="My custom URL endpoint", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + url_endpoint = await response.parse() + assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.url_endpoints.with_streaming_response.create( + description="My custom URL endpoint", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + url_endpoint = await response.parse() + assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncImageKit) -> None: + url_endpoint = await async_client.accounts.url_endpoints.update( + id="id", + description="My custom URL endpoint", + ) + assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncImageKit) -> None: + url_endpoint = await async_client.accounts.url_endpoints.update( + id="id", + description="My custom URL endpoint", + origins=["origin-id-1"], + url_prefix="product-images", + url_rewriter={ + "type": "CLOUDINARY", + "preserve_asset_delivery_types": True, + }, + ) + assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.url_endpoints.with_raw_response.update( + id="id", + description="My custom URL endpoint", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + url_endpoint = await response.parse() + assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.url_endpoints.with_streaming_response.update( + id="id", + description="My custom URL endpoint", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + url_endpoint = await response.parse() + assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.url_endpoints.with_raw_response.update( + id="", + description="My custom URL endpoint", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncImageKit) -> None: + url_endpoint = await async_client.accounts.url_endpoints.list() + assert_matches_type(URLEndpointListResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.url_endpoints.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + url_endpoint = await response.parse() + assert_matches_type(URLEndpointListResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.url_endpoints.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + url_endpoint = await response.parse() + assert_matches_type(URLEndpointListResponse, url_endpoint, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncImageKit) -> None: + url_endpoint = await async_client.accounts.url_endpoints.delete( + "id", + ) + assert url_endpoint is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.url_endpoints.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + url_endpoint = await response.parse() + assert url_endpoint is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.url_endpoints.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + url_endpoint = await response.parse() + assert url_endpoint is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.url_endpoints.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_get(self, async_client: AsyncImageKit) -> None: + url_endpoint = await async_client.accounts.url_endpoints.get( + "id", + ) + assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.url_endpoints.with_raw_response.get( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + url_endpoint = await response.parse() + assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.url_endpoints.with_streaming_response.get( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + url_endpoint = await response.parse() + assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_get(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.url_endpoints.with_raw_response.get( + "", + ) diff --git a/tests/api_resources/test_accounts.py b/tests/api_resources/accounts/test_usage.py similarity index 60% rename from tests/api_resources/test_accounts.py rename to tests/api_resources/accounts/test_usage.py index b136b5e..3d65bf9 100644 --- a/tests/api_resources/test_accounts.py +++ b/tests/api_resources/accounts/test_usage.py @@ -9,91 +9,91 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types import AccountGetUsageResponse from imagekit._utils import parse_date +from imagekit.types.accounts import UsageGetResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -class TestAccounts: +class TestUsage: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_get_usage(self, client: ImageKit) -> None: - account = client.accounts.get_usage( + def test_method_get(self, client: ImageKit) -> None: + usage = client.accounts.usage.get( end_date=parse_date("2019-12-27"), start_date=parse_date("2019-12-27"), ) - assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + assert_matches_type(UsageGetResponse, usage, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_get_usage(self, client: ImageKit) -> None: - response = client.accounts.with_raw_response.get_usage( + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.accounts.usage.with_raw_response.get( end_date=parse_date("2019-12-27"), start_date=parse_date("2019-12-27"), ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - account = response.parse() - assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + usage = response.parse() + assert_matches_type(UsageGetResponse, usage, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_get_usage(self, client: ImageKit) -> None: - with client.accounts.with_streaming_response.get_usage( + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.accounts.usage.with_streaming_response.get( end_date=parse_date("2019-12-27"), start_date=parse_date("2019-12-27"), ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - account = response.parse() - assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + usage = response.parse() + assert_matches_type(UsageGetResponse, usage, path=["response"]) assert cast(Any, response.is_closed) is True -class TestAsyncAccounts: +class TestAsyncUsage: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_get_usage(self, async_client: AsyncImageKit) -> None: - account = await async_client.accounts.get_usage( + async def test_method_get(self, async_client: AsyncImageKit) -> None: + usage = await async_client.accounts.usage.get( end_date=parse_date("2019-12-27"), start_date=parse_date("2019-12-27"), ) - assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + assert_matches_type(UsageGetResponse, usage, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_get_usage(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.with_raw_response.get_usage( + async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.usage.with_raw_response.get( end_date=parse_date("2019-12-27"), start_date=parse_date("2019-12-27"), ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - account = await response.parse() - assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + usage = await response.parse() + assert_matches_type(UsageGetResponse, usage, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_get_usage(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.with_streaming_response.get_usage( + async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.usage.with_streaming_response.get( end_date=parse_date("2019-12-27"), start_date=parse_date("2019-12-27"), ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - account = await response.parse() - assert_matches_type(AccountGetUsageResponse, account, path=["response"]) + usage = await response.parse() + assert_matches_type(UsageGetResponse, usage, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/beta/__init__.py b/tests/api_resources/beta/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/beta/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/beta/v2/__init__.py b/tests/api_resources/beta/v2/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/beta/v2/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/beta/v2/test_files.py b/tests/api_resources/beta/v2/test_files.py new file mode 100644 index 0000000..8efb5e8 --- /dev/null +++ b/tests/api_resources/beta/v2/test_files.py @@ -0,0 +1,214 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types.beta.v2 import FileUploadResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFiles: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_upload(self, client: ImageKit) -> None: + file = client.beta.v2.files.upload( + file=b"raw file contents", + file_name="fileName", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_upload_with_all_params(self, client: ImageKit) -> None: + file = client.beta.v2.files.upload( + file=b"raw file contents", + file_name="fileName", + token="token", + checks='"request.folder" : "marketing/"\n', + custom_coordinates="customCoordinates", + custom_metadata={ + "brand": "bar", + "color": "bar", + }, + description="Running shoes", + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + ], + folder="folder", + is_private_file=True, + is_published=True, + overwrite_ai_tags=True, + overwrite_custom_metadata=True, + overwrite_file=True, + overwrite_tags=True, + response_fields=["tags", "customCoordinates", "isPrivateFile"], + tags=["t-shirt", "round-neck", "men"], + transformation={ + "post": [ + { + "type": "thumbnail", + "value": "w-150,h-150", + }, + { + "protocol": "dash", + "type": "abs", + "value": "sr-240_360_480_720_1080", + }, + ], + "pre": "w-300,h-300,q-80", + }, + use_unique_file_name=True, + webhook_url="https://example.com", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_upload(self, client: ImageKit) -> None: + response = client.beta.v2.files.with_raw_response.upload( + file=b"raw file contents", + file_name="fileName", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_upload(self, client: ImageKit) -> None: + with client.beta.v2.files.with_streaming_response.upload( + file=b"raw file contents", + file_name="fileName", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncFiles: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_upload(self, async_client: AsyncImageKit) -> None: + file = await async_client.beta.v2.files.upload( + file=b"raw file contents", + file_name="fileName", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) -> None: + file = await async_client.beta.v2.files.upload( + file=b"raw file contents", + file_name="fileName", + token="token", + checks='"request.folder" : "marketing/"\n', + custom_coordinates="customCoordinates", + custom_metadata={ + "brand": "bar", + "color": "bar", + }, + description="Running shoes", + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + ], + folder="folder", + is_private_file=True, + is_published=True, + overwrite_ai_tags=True, + overwrite_custom_metadata=True, + overwrite_file=True, + overwrite_tags=True, + response_fields=["tags", "customCoordinates", "isPrivateFile"], + tags=["t-shirt", "round-neck", "men"], + transformation={ + "post": [ + { + "type": "thumbnail", + "value": "w-150,h-150", + }, + { + "protocol": "dash", + "type": "abs", + "value": "sr-240_360_480_720_1080", + }, + ], + "pre": "w-300,h-300,q-80", + }, + use_unique_file_name=True, + webhook_url="https://example.com", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: + response = await async_client.beta.v2.files.with_raw_response.upload( + file=b"raw file contents", + file_name="fileName", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> None: + async with async_client.beta.v2.files.with_streaming_response.upload( + file=b"raw file contents", + file_name="fileName", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/cache/__init__.py b/tests/api_resources/cache/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/cache/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/files/test_purge.py b/tests/api_resources/cache/test_invalidation.py similarity index 53% rename from tests/api_resources/files/test_purge.py rename to tests/api_resources/cache/test_invalidation.py index 5bb67f3..4fe9317 100644 --- a/tests/api_resources/files/test_purge.py +++ b/tests/api_resources/cache/test_invalidation.py @@ -9,168 +9,168 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.files import PurgeStatusResponse, PurgeExecuteResponse +from imagekit.types.cache import InvalidationGetResponse, InvalidationCreateResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -class TestPurge: +class TestInvalidation: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_execute(self, client: ImageKit) -> None: - purge = client.files.purge.execute( + def test_method_create(self, client: ImageKit) -> None: + invalidation = client.cache.invalidation.create( url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", ) - assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + assert_matches_type(InvalidationCreateResponse, invalidation, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_execute(self, client: ImageKit) -> None: - response = client.files.purge.with_raw_response.execute( + def test_raw_response_create(self, client: ImageKit) -> None: + response = client.cache.invalidation.with_raw_response.create( url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - purge = response.parse() - assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + invalidation = response.parse() + assert_matches_type(InvalidationCreateResponse, invalidation, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_execute(self, client: ImageKit) -> None: - with client.files.purge.with_streaming_response.execute( + def test_streaming_response_create(self, client: ImageKit) -> None: + with client.cache.invalidation.with_streaming_response.create( url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - purge = response.parse() - assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + invalidation = response.parse() + assert_matches_type(InvalidationCreateResponse, invalidation, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_status(self, client: ImageKit) -> None: - purge = client.files.purge.status( + def test_method_get(self, client: ImageKit) -> None: + invalidation = client.cache.invalidation.get( "requestId", ) - assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + assert_matches_type(InvalidationGetResponse, invalidation, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_status(self, client: ImageKit) -> None: - response = client.files.purge.with_raw_response.status( + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.cache.invalidation.with_raw_response.get( "requestId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - purge = response.parse() - assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + invalidation = response.parse() + assert_matches_type(InvalidationGetResponse, invalidation, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_status(self, client: ImageKit) -> None: - with client.files.purge.with_streaming_response.status( + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.cache.invalidation.with_streaming_response.get( "requestId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - purge = response.parse() - assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + invalidation = response.parse() + assert_matches_type(InvalidationGetResponse, invalidation, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_status(self, client: ImageKit) -> None: + def test_path_params_get(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `request_id` but received ''"): - client.files.purge.with_raw_response.status( + client.cache.invalidation.with_raw_response.get( "", ) -class TestAsyncPurge: +class TestAsyncInvalidation: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_execute(self, async_client: AsyncImageKit) -> None: - purge = await async_client.files.purge.execute( + async def test_method_create(self, async_client: AsyncImageKit) -> None: + invalidation = await async_client.cache.invalidation.create( url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", ) - assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + assert_matches_type(InvalidationCreateResponse, invalidation, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_execute(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.purge.with_raw_response.execute( + async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: + response = await async_client.cache.invalidation.with_raw_response.create( url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - purge = await response.parse() - assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + invalidation = await response.parse() + assert_matches_type(InvalidationCreateResponse, invalidation, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_execute(self, async_client: AsyncImageKit) -> None: - async with async_client.files.purge.with_streaming_response.execute( + async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: + async with async_client.cache.invalidation.with_streaming_response.create( url="https://ik.imagekit.io/your_imagekit_id/default-image.jpg", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - purge = await response.parse() - assert_matches_type(PurgeExecuteResponse, purge, path=["response"]) + invalidation = await response.parse() + assert_matches_type(InvalidationCreateResponse, invalidation, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_status(self, async_client: AsyncImageKit) -> None: - purge = await async_client.files.purge.status( + async def test_method_get(self, async_client: AsyncImageKit) -> None: + invalidation = await async_client.cache.invalidation.get( "requestId", ) - assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + assert_matches_type(InvalidationGetResponse, invalidation, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_status(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.purge.with_raw_response.status( + async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: + response = await async_client.cache.invalidation.with_raw_response.get( "requestId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - purge = await response.parse() - assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + invalidation = await response.parse() + assert_matches_type(InvalidationGetResponse, invalidation, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_status(self, async_client: AsyncImageKit) -> None: - async with async_client.files.purge.with_streaming_response.status( + async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None: + async with async_client.cache.invalidation.with_streaming_response.get( "requestId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - purge = await response.parse() - assert_matches_type(PurgeStatusResponse, purge, path=["response"]) + invalidation = await response.parse() + assert_matches_type(InvalidationGetResponse, invalidation, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_status(self, async_client: AsyncImageKit) -> None: + async def test_path_params_get(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `request_id` but received ''"): - await async_client.files.purge.with_raw_response.status( + await async_client.cache.invalidation.with_raw_response.get( "", ) diff --git a/tests/api_resources/files/test_batch.py b/tests/api_resources/files/test_batch.py deleted file mode 100644 index 08f8ff9..0000000 --- a/tests/api_resources/files/test_batch.py +++ /dev/null @@ -1,92 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from imagekit import ImageKit, AsyncImageKit -from tests.utils import assert_matches_type -from imagekit.types.files import BatchDeleteResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestBatch: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_delete(self, client: ImageKit) -> None: - batch = client.files.batch.delete( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) - assert_matches_type(BatchDeleteResponse, batch, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_delete(self, client: ImageKit) -> None: - response = client.files.batch.with_raw_response.delete( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - batch = response.parse() - assert_matches_type(BatchDeleteResponse, batch, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_delete(self, client: ImageKit) -> None: - with client.files.batch.with_streaming_response.delete( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - batch = response.parse() - assert_matches_type(BatchDeleteResponse, batch, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncBatch: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_delete(self, async_client: AsyncImageKit) -> None: - batch = await async_client.files.batch.delete( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) - assert_matches_type(BatchDeleteResponse, batch, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.batch.with_raw_response.delete( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - batch = await response.parse() - assert_matches_type(BatchDeleteResponse, batch, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: - async with async_client.files.batch.with_streaming_response.delete( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - batch = await response.parse() - assert_matches_type(BatchDeleteResponse, batch, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/files/test_bulk.py b/tests/api_resources/files/test_bulk.py new file mode 100644 index 0000000..3b7c825 --- /dev/null +++ b/tests/api_resources/files/test_bulk.py @@ -0,0 +1,319 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types.files import ( + BulkDeleteResponse, + BulkAddTagsResponse, + BulkRemoveTagsResponse, + BulkRemoveAITagsResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestBulk: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + bulk = client.files.bulk.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + assert_matches_type(BulkDeleteResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.files.bulk.with_raw_response.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk = response.parse() + assert_matches_type(BulkDeleteResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.files.bulk.with_streaming_response.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk = response.parse() + assert_matches_type(BulkDeleteResponse, bulk, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_add_tags(self, client: ImageKit) -> None: + bulk = client.files.bulk.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + assert_matches_type(BulkAddTagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_add_tags(self, client: ImageKit) -> None: + response = client.files.bulk.with_raw_response.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk = response.parse() + assert_matches_type(BulkAddTagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_add_tags(self, client: ImageKit) -> None: + with client.files.bulk.with_streaming_response.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk = response.parse() + assert_matches_type(BulkAddTagsResponse, bulk, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_remove_ai_tags(self, client: ImageKit) -> None: + bulk = client.files.bulk.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + assert_matches_type(BulkRemoveAITagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_remove_ai_tags(self, client: ImageKit) -> None: + response = client.files.bulk.with_raw_response.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk = response.parse() + assert_matches_type(BulkRemoveAITagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_remove_ai_tags(self, client: ImageKit) -> None: + with client.files.bulk.with_streaming_response.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk = response.parse() + assert_matches_type(BulkRemoveAITagsResponse, bulk, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_remove_tags(self, client: ImageKit) -> None: + bulk = client.files.bulk.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + assert_matches_type(BulkRemoveTagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_remove_tags(self, client: ImageKit) -> None: + response = client.files.bulk.with_raw_response.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk = response.parse() + assert_matches_type(BulkRemoveTagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_remove_tags(self, client: ImageKit) -> None: + with client.files.bulk.with_streaming_response.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk = response.parse() + assert_matches_type(BulkRemoveTagsResponse, bulk, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncBulk: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncImageKit) -> None: + bulk = await async_client.files.bulk.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + assert_matches_type(BulkDeleteResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.bulk.with_raw_response.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk = await response.parse() + assert_matches_type(BulkDeleteResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: + async with async_client.files.bulk.with_streaming_response.delete( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk = await response.parse() + assert_matches_type(BulkDeleteResponse, bulk, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_add_tags(self, async_client: AsyncImageKit) -> None: + bulk = await async_client.files.bulk.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + assert_matches_type(BulkAddTagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_add_tags(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.bulk.with_raw_response.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk = await response.parse() + assert_matches_type(BulkAddTagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_add_tags(self, async_client: AsyncImageKit) -> None: + async with async_client.files.bulk.with_streaming_response.add_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk = await response.parse() + assert_matches_type(BulkAddTagsResponse, bulk, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_remove_ai_tags(self, async_client: AsyncImageKit) -> None: + bulk = await async_client.files.bulk.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + assert_matches_type(BulkRemoveAITagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_remove_ai_tags(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.bulk.with_raw_response.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk = await response.parse() + assert_matches_type(BulkRemoveAITagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_remove_ai_tags(self, async_client: AsyncImageKit) -> None: + async with async_client.files.bulk.with_streaming_response.remove_ai_tags( + ai_tags=["t-shirt", "round-neck", "sale2019"], + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk = await response.parse() + assert_matches_type(BulkRemoveAITagsResponse, bulk, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_remove_tags(self, async_client: AsyncImageKit) -> None: + bulk = await async_client.files.bulk.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + assert_matches_type(BulkRemoveTagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_remove_tags(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.bulk.with_raw_response.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk = await response.parse() + assert_matches_type(BulkRemoveTagsResponse, bulk, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_remove_tags(self, async_client: AsyncImageKit) -> None: + async with async_client.files.bulk.with_streaming_response.remove_tags( + file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], + tags=["t-shirt", "round-neck", "sale2019"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk = await response.parse() + assert_matches_type(BulkRemoveTagsResponse, bulk, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/files/test_details.py b/tests/api_resources/files/test_details.py deleted file mode 100644 index 6191ac1..0000000 --- a/tests/api_resources/files/test_details.py +++ /dev/null @@ -1,348 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from imagekit import ImageKit, AsyncImageKit -from tests.utils import assert_matches_type -from imagekit.types.files import DetailUpdateResponse, DetailRetrieveResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestDetails: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_retrieve(self, client: ImageKit) -> None: - detail = client.files.details.retrieve( - "fileId", - ) - assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_retrieve(self, client: ImageKit) -> None: - response = client.files.details.with_raw_response.retrieve( - "fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - detail = response.parse() - assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_retrieve(self, client: ImageKit) -> None: - with client.files.details.with_streaming_response.retrieve( - "fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - detail = response.parse() - assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_retrieve(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.details.with_raw_response.retrieve( - "", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_1(self, client: ImageKit) -> None: - detail = client.files.details.update( - file_id="fileId", - ) - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: - detail = client.files.details.update( - file_id="fileId", - custom_coordinates="customCoordinates", - custom_metadata={}, - extensions=[ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, - }, - } - ], - remove_ai_tags=["string"], - tags=["tag1", "tag2"], - webhook_url="webhookUrl", - ) - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_1(self, client: ImageKit) -> None: - response = client.files.details.with_raw_response.update( - file_id="fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - detail = response.parse() - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: - with client.files.details.with_streaming_response.update( - file_id="fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - detail = response.parse() - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_1(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.details.with_raw_response.update( - file_id="", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_2(self, client: ImageKit) -> None: - detail = client.files.details.update( - file_id="fileId", - ) - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: - detail = client.files.details.update( - file_id="fileId", - publish={ - "is_published": True, - "include_file_versions": True, - }, - ) - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_2(self, client: ImageKit) -> None: - response = client.files.details.with_raw_response.update( - file_id="fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - detail = response.parse() - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: - with client.files.details.with_streaming_response.update( - file_id="fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - detail = response.parse() - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_2(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.details.with_raw_response.update( - file_id="", - ) - - -class TestAsyncDetails: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_retrieve(self, async_client: AsyncImageKit) -> None: - detail = await async_client.files.details.retrieve( - "fileId", - ) - assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.details.with_raw_response.retrieve( - "fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - detail = await response.parse() - assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncImageKit) -> None: - async with async_client.files.details.with_streaming_response.retrieve( - "fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - detail = await response.parse() - assert_matches_type(DetailRetrieveResponse, detail, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_retrieve(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - await async_client.files.details.with_raw_response.retrieve( - "", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: - detail = await async_client.files.details.update( - file_id="fileId", - ) - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: - detail = await async_client.files.details.update( - file_id="fileId", - custom_coordinates="customCoordinates", - custom_metadata={}, - extensions=[ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, - }, - } - ], - remove_ai_tags=["string"], - tags=["tag1", "tag2"], - webhook_url="webhookUrl", - ) - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.details.with_raw_response.update( - file_id="fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - detail = await response.parse() - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: - async with async_client.files.details.with_streaming_response.update( - file_id="fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - detail = await response.parse() - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - await async_client.files.details.with_raw_response.update( - file_id="", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: - detail = await async_client.files.details.update( - file_id="fileId", - ) - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: - detail = await async_client.files.details.update( - file_id="fileId", - publish={ - "is_published": True, - "include_file_versions": True, - }, - ) - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.details.with_raw_response.update( - file_id="fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - detail = await response.parse() - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: - async with async_client.files.details.with_streaming_response.update( - file_id="fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - detail = await response.parse() - assert_matches_type(DetailUpdateResponse, detail, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - await async_client.files.details.with_raw_response.update( - file_id="", - ) diff --git a/tests/api_resources/files/test_metadata.py b/tests/api_resources/files/test_metadata.py index 9689998..76d23e5 100644 --- a/tests/api_resources/files/test_metadata.py +++ b/tests/api_resources/files/test_metadata.py @@ -9,7 +9,7 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.files import MetadataFromURLResponse, MetadataRetrieveResponse +from imagekit.types.files import MetadataGetResponse, MetadataGetFromURLResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -19,77 +19,77 @@ class TestMetadata: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_retrieve(self, client: ImageKit) -> None: - metadata = client.files.metadata.retrieve( + def test_method_get(self, client: ImageKit) -> None: + metadata = client.files.metadata.get( "fileId", ) - assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetResponse, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_retrieve(self, client: ImageKit) -> None: - response = client.files.metadata.with_raw_response.retrieve( + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.files.metadata.with_raw_response.get( "fileId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = response.parse() - assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetResponse, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_retrieve(self, client: ImageKit) -> None: - with client.files.metadata.with_streaming_response.retrieve( + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.files.metadata.with_streaming_response.get( "fileId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = response.parse() - assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetResponse, metadata, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_retrieve(self, client: ImageKit) -> None: + def test_path_params_get(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.metadata.with_raw_response.retrieve( + client.files.metadata.with_raw_response.get( "", ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_from_url(self, client: ImageKit) -> None: - metadata = client.files.metadata.from_url( - url="url", + def test_method_get_from_url(self, client: ImageKit) -> None: + metadata = client.files.metadata.get_from_url( + url="https://example.com", ) - assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_from_url(self, client: ImageKit) -> None: - response = client.files.metadata.with_raw_response.from_url( - url="url", + def test_raw_response_get_from_url(self, client: ImageKit) -> None: + response = client.files.metadata.with_raw_response.get_from_url( + url="https://example.com", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = response.parse() - assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_from_url(self, client: ImageKit) -> None: - with client.files.metadata.with_streaming_response.from_url( - url="url", + def test_streaming_response_get_from_url(self, client: ImageKit) -> None: + with client.files.metadata.with_streaming_response.get_from_url( + url="https://example.com", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = response.parse() - assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) assert cast(Any, response.is_closed) is True @@ -101,76 +101,76 @@ class TestAsyncMetadata: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_retrieve(self, async_client: AsyncImageKit) -> None: - metadata = await async_client.files.metadata.retrieve( + async def test_method_get(self, async_client: AsyncImageKit) -> None: + metadata = await async_client.files.metadata.get( "fileId", ) - assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetResponse, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.metadata.with_raw_response.retrieve( + async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.metadata.with_raw_response.get( "fileId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = await response.parse() - assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetResponse, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncImageKit) -> None: - async with async_client.files.metadata.with_streaming_response.retrieve( + async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None: + async with async_client.files.metadata.with_streaming_response.get( "fileId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = await response.parse() - assert_matches_type(MetadataRetrieveResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetResponse, metadata, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_retrieve(self, async_client: AsyncImageKit) -> None: + async def test_path_params_get(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - await async_client.files.metadata.with_raw_response.retrieve( + await async_client.files.metadata.with_raw_response.get( "", ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_from_url(self, async_client: AsyncImageKit) -> None: - metadata = await async_client.files.metadata.from_url( - url="url", + async def test_method_get_from_url(self, async_client: AsyncImageKit) -> None: + metadata = await async_client.files.metadata.get_from_url( + url="https://example.com", ) - assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_from_url(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.metadata.with_raw_response.from_url( - url="url", + async def test_raw_response_get_from_url(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.metadata.with_raw_response.get_from_url( + url="https://example.com", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = await response.parse() - assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_from_url(self, async_client: AsyncImageKit) -> None: - async with async_client.files.metadata.with_streaming_response.from_url( - url="url", + async def test_streaming_response_get_from_url(self, async_client: AsyncImageKit) -> None: + async with async_client.files.metadata.with_streaming_response.get_from_url( + url="https://example.com", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = await response.parse() - assert_matches_type(MetadataFromURLResponse, metadata, path=["response"]) + assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/files/test_versions.py b/tests/api_resources/files/test_versions.py index f6560ab..937bf54 100644 --- a/tests/api_resources/files/test_versions.py +++ b/tests/api_resources/files/test_versions.py @@ -9,7 +9,7 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.files import VersionListResponse, VersionRestoreResponse, VersionRetrieveResponse +from imagekit.types.files import VersionGetResponse, VersionListResponse, VersionRestoreResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -17,58 +17,6 @@ class TestVersions: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_retrieve(self, client: ImageKit) -> None: - version = client.files.versions.retrieve( - version_id="versionId", - file_id="fileId", - ) - assert_matches_type(VersionRetrieveResponse, version, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_retrieve(self, client: ImageKit) -> None: - response = client.files.versions.with_raw_response.retrieve( - version_id="versionId", - file_id="fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - version = response.parse() - assert_matches_type(VersionRetrieveResponse, version, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_retrieve(self, client: ImageKit) -> None: - with client.files.versions.with_streaming_response.retrieve( - version_id="versionId", - file_id="fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - version = response.parse() - assert_matches_type(VersionRetrieveResponse, version, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_retrieve(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.versions.with_raw_response.retrieve( - version_id="versionId", - file_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): - client.files.versions.with_raw_response.retrieve( - version_id="", - file_id="fileId", - ) - @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_list(self, client: ImageKit) -> None: @@ -165,17 +113,17 @@ def test_path_params_delete(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_restore(self, client: ImageKit) -> None: - version = client.files.versions.restore( + def test_method_get(self, client: ImageKit) -> None: + version = client.files.versions.get( version_id="versionId", file_id="fileId", ) - assert_matches_type(VersionRestoreResponse, version, path=["response"]) + assert_matches_type(VersionGetResponse, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_restore(self, client: ImageKit) -> None: - response = client.files.versions.with_raw_response.restore( + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.files.versions.with_raw_response.get( version_id="versionId", file_id="fileId", ) @@ -183,12 +131,12 @@ def test_raw_response_restore(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() - assert_matches_type(VersionRestoreResponse, version, path=["response"]) + assert_matches_type(VersionGetResponse, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_restore(self, client: ImageKit) -> None: - with client.files.versions.with_streaming_response.restore( + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.files.versions.with_streaming_response.get( version_id="versionId", file_id="fileId", ) as response: @@ -196,83 +144,83 @@ def test_streaming_response_restore(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() - assert_matches_type(VersionRestoreResponse, version, path=["response"]) + assert_matches_type(VersionGetResponse, version, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_restore(self, client: ImageKit) -> None: + def test_path_params_get(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.versions.with_raw_response.restore( + client.files.versions.with_raw_response.get( version_id="versionId", file_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): - client.files.versions.with_raw_response.restore( + client.files.versions.with_raw_response.get( version_id="", file_id="fileId", ) - -class TestAsyncVersions: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_retrieve(self, async_client: AsyncImageKit) -> None: - version = await async_client.files.versions.retrieve( + def test_method_restore(self, client: ImageKit) -> None: + version = client.files.versions.restore( version_id="versionId", file_id="fileId", ) - assert_matches_type(VersionRetrieveResponse, version, path=["response"]) + assert_matches_type(VersionRestoreResponse, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.versions.with_raw_response.retrieve( + def test_raw_response_restore(self, client: ImageKit) -> None: + response = client.files.versions.with_raw_response.restore( version_id="versionId", file_id="fileId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - version = await response.parse() - assert_matches_type(VersionRetrieveResponse, version, path=["response"]) + version = response.parse() + assert_matches_type(VersionRestoreResponse, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncImageKit) -> None: - async with async_client.files.versions.with_streaming_response.retrieve( + def test_streaming_response_restore(self, client: ImageKit) -> None: + with client.files.versions.with_streaming_response.restore( version_id="versionId", file_id="fileId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - version = await response.parse() - assert_matches_type(VersionRetrieveResponse, version, path=["response"]) + version = response.parse() + assert_matches_type(VersionRestoreResponse, version, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_retrieve(self, async_client: AsyncImageKit) -> None: + def test_path_params_restore(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - await async_client.files.versions.with_raw_response.retrieve( + client.files.versions.with_raw_response.restore( version_id="versionId", file_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): - await async_client.files.versions.with_raw_response.retrieve( + client.files.versions.with_raw_response.restore( version_id="", file_id="fileId", ) + +class TestAsyncVersions: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncImageKit) -> None: @@ -367,6 +315,58 @@ async def test_path_params_delete(self, async_client: AsyncImageKit) -> None: file_id="fileId", ) + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_get(self, async_client: AsyncImageKit) -> None: + version = await async_client.files.versions.get( + version_id="versionId", + file_id="fileId", + ) + assert_matches_type(VersionGetResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.versions.with_raw_response.get( + version_id="versionId", + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + version = await response.parse() + assert_matches_type(VersionGetResponse, version, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None: + async with async_client.files.versions.with_streaming_response.get( + version_id="versionId", + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + version = await response.parse() + assert_matches_type(VersionGetResponse, version, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_get(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.versions.with_raw_response.get( + version_id="versionId", + file_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `version_id` but received ''"): + await async_client.files.versions.with_raw_response.get( + version_id="", + file_id="fileId", + ) + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_restore(self, async_client: AsyncImageKit) -> None: diff --git a/tests/api_resources/folders/__init__.py b/tests/api_resources/folders/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/folders/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/folders/test_job.py b/tests/api_resources/folders/test_job.py new file mode 100644 index 0000000..c86539d --- /dev/null +++ b/tests/api_resources/folders/test_job.py @@ -0,0 +1,108 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types.folders import JobGetResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestJob: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_get(self, client: ImageKit) -> None: + job = client.folders.job.get( + "jobId", + ) + assert_matches_type(JobGetResponse, job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.folders.job.with_raw_response.get( + "jobId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + job = response.parse() + assert_matches_type(JobGetResponse, job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.folders.job.with_streaming_response.get( + "jobId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + job = response.parse() + assert_matches_type(JobGetResponse, job, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_get(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"): + client.folders.job.with_raw_response.get( + "", + ) + + +class TestAsyncJob: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_get(self, async_client: AsyncImageKit) -> None: + job = await async_client.folders.job.get( + "jobId", + ) + assert_matches_type(JobGetResponse, job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: + response = await async_client.folders.job.with_raw_response.get( + "jobId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + job = await response.parse() + assert_matches_type(JobGetResponse, job, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None: + async with async_client.folders.job.with_streaming_response.get( + "jobId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + job = await response.parse() + assert_matches_type(JobGetResponse, job, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_get(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"): + await async_client.folders.job.with_raw_response.get( + "", + ) diff --git a/tests/api_resources/test_assets.py b/tests/api_resources/test_assets.py new file mode 100644 index 0000000..d600600 --- /dev/null +++ b/tests/api_resources/test_assets.py @@ -0,0 +1,108 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types import AssetListResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAssets: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: ImageKit) -> None: + asset = client.assets.list() + assert_matches_type(AssetListResponse, asset, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: ImageKit) -> None: + asset = client.assets.list( + file_type="all", + limit=1, + path="path", + search_query="searchQuery", + skip=0, + sort="ASC_NAME", + type="file", + ) + assert_matches_type(AssetListResponse, asset, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: ImageKit) -> None: + response = client.assets.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + asset = response.parse() + assert_matches_type(AssetListResponse, asset, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: ImageKit) -> None: + with client.assets.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + asset = response.parse() + assert_matches_type(AssetListResponse, asset, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncAssets: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncImageKit) -> None: + asset = await async_client.assets.list() + assert_matches_type(AssetListResponse, asset, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncImageKit) -> None: + asset = await async_client.assets.list( + file_type="all", + limit=1, + path="path", + search_query="searchQuery", + skip=0, + sort="ASC_NAME", + type="file", + ) + assert_matches_type(AssetListResponse, asset, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncImageKit) -> None: + response = await async_client.assets.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + asset = await response.parse() + assert_matches_type(AssetListResponse, asset, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncImageKit) -> None: + async with async_client.assets.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + asset = await response.parse() + assert_matches_type(AssetListResponse, asset, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_bulk_jobs.py b/tests/api_resources/test_bulk_jobs.py deleted file mode 100644 index 64d711f..0000000 --- a/tests/api_resources/test_bulk_jobs.py +++ /dev/null @@ -1,280 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from imagekit import ImageKit, AsyncImageKit -from tests.utils import assert_matches_type -from imagekit.types import ( - BulkJobCopyFolderResponse, - BulkJobMoveFolderResponse, - BulkJobRetrieveStatusResponse, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestBulkJobs: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_copy_folder(self, client: ImageKit) -> None: - bulk_job = client.bulk_jobs.copy_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) - assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_copy_folder_with_all_params(self, client: ImageKit) -> None: - bulk_job = client.bulk_jobs.copy_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - include_versions=True, - ) - assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_copy_folder(self, client: ImageKit) -> None: - response = client.bulk_jobs.with_raw_response.copy_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - bulk_job = response.parse() - assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_copy_folder(self, client: ImageKit) -> None: - with client.bulk_jobs.with_streaming_response.copy_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - bulk_job = response.parse() - assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_move_folder(self, client: ImageKit) -> None: - bulk_job = client.bulk_jobs.move_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) - assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_move_folder(self, client: ImageKit) -> None: - response = client.bulk_jobs.with_raw_response.move_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - bulk_job = response.parse() - assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_move_folder(self, client: ImageKit) -> None: - with client.bulk_jobs.with_streaming_response.move_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - bulk_job = response.parse() - assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_retrieve_status(self, client: ImageKit) -> None: - bulk_job = client.bulk_jobs.retrieve_status( - "jobId", - ) - assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_retrieve_status(self, client: ImageKit) -> None: - response = client.bulk_jobs.with_raw_response.retrieve_status( - "jobId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - bulk_job = response.parse() - assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_retrieve_status(self, client: ImageKit) -> None: - with client.bulk_jobs.with_streaming_response.retrieve_status( - "jobId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - bulk_job = response.parse() - assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_retrieve_status(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"): - client.bulk_jobs.with_raw_response.retrieve_status( - "", - ) - - -class TestAsyncBulkJobs: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_copy_folder(self, async_client: AsyncImageKit) -> None: - bulk_job = await async_client.bulk_jobs.copy_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) - assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_copy_folder_with_all_params(self, async_client: AsyncImageKit) -> None: - bulk_job = await async_client.bulk_jobs.copy_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - include_versions=True, - ) - assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_copy_folder(self, async_client: AsyncImageKit) -> None: - response = await async_client.bulk_jobs.with_raw_response.copy_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - bulk_job = await response.parse() - assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_copy_folder(self, async_client: AsyncImageKit) -> None: - async with async_client.bulk_jobs.with_streaming_response.copy_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - bulk_job = await response.parse() - assert_matches_type(BulkJobCopyFolderResponse, bulk_job, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_move_folder(self, async_client: AsyncImageKit) -> None: - bulk_job = await async_client.bulk_jobs.move_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) - assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_move_folder(self, async_client: AsyncImageKit) -> None: - response = await async_client.bulk_jobs.with_raw_response.move_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - bulk_job = await response.parse() - assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_move_folder(self, async_client: AsyncImageKit) -> None: - async with async_client.bulk_jobs.with_streaming_response.move_folder( - destination_path="/path/of/destination/folder", - source_folder_path="/path/of/source/folder", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - bulk_job = await response.parse() - assert_matches_type(BulkJobMoveFolderResponse, bulk_job, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_retrieve_status(self, async_client: AsyncImageKit) -> None: - bulk_job = await async_client.bulk_jobs.retrieve_status( - "jobId", - ) - assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_retrieve_status(self, async_client: AsyncImageKit) -> None: - response = await async_client.bulk_jobs.with_raw_response.retrieve_status( - "jobId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - bulk_job = await response.parse() - assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_retrieve_status(self, async_client: AsyncImageKit) -> None: - async with async_client.bulk_jobs.with_streaming_response.retrieve_status( - "jobId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - bulk_job = await response.parse() - assert_matches_type(BulkJobRetrieveStatusResponse, bulk_job, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_retrieve_status(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"): - await async_client.bulk_jobs.with_raw_response.retrieve_status( - "", - ) diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index ee92064..f56c498 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -10,13 +10,10 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type from imagekit.types import ( - FileListResponse, + FileGetResponse, FileRenameResponse, - FileAddTagsResponse, - FileUploadV1Response, - FileUploadV2Response, - FileRemoveTagsResponse, - FileRemoveAITagsResponse, + FileUpdateResponse, + FileUploadResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -27,125 +24,167 @@ class TestFiles: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_list(self, client: ImageKit) -> None: - file = client.files.list() - assert_matches_type(FileListResponse, file, path=["response"]) + def test_method_update_overload_1(self, client: ImageKit) -> None: + file = client.files.update( + file_id="fileId", + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_list_with_all_params(self, client: ImageKit) -> None: - file = client.files.list( - file_type="fileType", - limit="limit", - path="path", - search_query="searchQuery", - skip="skip", - sort="sort", - type="file", + def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: + file = client.files.update( + file_id="fileId", + custom_coordinates="customCoordinates", + custom_metadata={}, + description="description", + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + } + ], + remove_ai_tags=["string"], + tags=["tag1", "tag2"], + webhook_url="https://example.com", ) - assert_matches_type(FileListResponse, file, path=["response"]) + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_list(self, client: ImageKit) -> None: - response = client.files.with_raw_response.list() + def test_raw_response_update_overload_1(self, client: ImageKit) -> None: + response = client.files.with_raw_response.update( + file_id="fileId", + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(FileListResponse, file, path=["response"]) + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_list(self, client: ImageKit) -> None: - with client.files.with_streaming_response.list() as response: + def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: + with client.files.with_streaming_response.update( + file_id="fileId", + ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(FileListResponse, file, path=["response"]) + assert_matches_type(FileUpdateResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_delete(self, client: ImageKit) -> None: - file = client.files.delete( - "fileId", + def test_path_params_update_overload_1(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.with_raw_response.update( + file_id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_2(self, client: ImageKit) -> None: + file = client.files.update( + file_id="fileId", ) - assert file is None + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_delete(self, client: ImageKit) -> None: - response = client.files.with_raw_response.delete( - "fileId", + def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: + file = client.files.update( + file_id="fileId", + publish={ + "is_published": True, + "include_file_versions": True, + }, + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_2(self, client: ImageKit) -> None: + response = client.files.with_raw_response.update( + file_id="fileId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert file is None + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_delete(self, client: ImageKit) -> None: - with client.files.with_streaming_response.delete( - "fileId", + def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: + with client.files.with_streaming_response.update( + file_id="fileId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert file is None + assert_matches_type(FileUpdateResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_delete(self, client: ImageKit) -> None: + def test_path_params_update_overload_2(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.with_raw_response.delete( - "", + client.files.with_raw_response.update( + file_id="", ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_add_tags(self, client: ImageKit) -> None: - file = client.files.add_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], + def test_method_delete(self, client: ImageKit) -> None: + file = client.files.delete( + "fileId", ) - assert_matches_type(FileAddTagsResponse, file, path=["response"]) + assert file is None @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_add_tags(self, client: ImageKit) -> None: - response = client.files.with_raw_response.add_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.files.with_raw_response.delete( + "fileId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(FileAddTagsResponse, file, path=["response"]) + assert file is None @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_add_tags(self, client: ImageKit) -> None: - with client.files.with_streaming_response.add_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.files.with_streaming_response.delete( + "fileId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(FileAddTagsResponse, file, path=["response"]) + assert file is None assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.with_raw_response.delete( + "", + ) + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_copy(self, client: ImageKit) -> None: @@ -195,112 +234,80 @@ def test_streaming_response_copy(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_move(self, client: ImageKit) -> None: - file = client.files.move( - destination_path="/folder/to/move/into/", - source_file_path="/path/to/file.jpg", + def test_method_get(self, client: ImageKit) -> None: + file = client.files.get( + "fileId", ) - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileGetResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_move(self, client: ImageKit) -> None: - response = client.files.with_raw_response.move( - destination_path="/folder/to/move/into/", - source_file_path="/path/to/file.jpg", + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.files.with_raw_response.get( + "fileId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileGetResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_move(self, client: ImageKit) -> None: - with client.files.with_streaming_response.move( - destination_path="/folder/to/move/into/", - source_file_path="/path/to/file.jpg", + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.files.with_streaming_response.get( + "fileId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileGetResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_remove_ai_tags(self, client: ImageKit) -> None: - file = client.files.remove_ai_tags( - ai_tags=["t-shirt", "round-neck", "sale2019"], - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) - assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_remove_ai_tags(self, client: ImageKit) -> None: - response = client.files.with_raw_response.remove_ai_tags( - ai_tags=["t-shirt", "round-neck", "sale2019"], - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = response.parse() - assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_remove_ai_tags(self, client: ImageKit) -> None: - with client.files.with_streaming_response.remove_ai_tags( - ai_tags=["t-shirt", "round-neck", "sale2019"], - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = response.parse() - assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True + def test_path_params_get(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.with_raw_response.get( + "", + ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_remove_tags(self, client: ImageKit) -> None: - file = client.files.remove_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], + def test_method_move(self, client: ImageKit) -> None: + file = client.files.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", ) - assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + assert_matches_type(object, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_remove_tags(self, client: ImageKit) -> None: - response = client.files.with_raw_response.remove_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], + def test_raw_response_move(self, client: ImageKit) -> None: + response = client.files.with_raw_response.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + assert_matches_type(object, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_remove_tags(self, client: ImageKit) -> None: - with client.files.with_streaming_response.remove_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], + def test_streaming_response_move(self, client: ImageKit) -> None: + with client.files.with_streaming_response.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + assert_matches_type(object, file, path=["response"]) assert cast(Any, response.is_closed) is True @@ -353,181 +360,229 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload_v1(self, client: ImageKit) -> None: - file = client.files.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", + def test_method_upload(self, client: ImageKit) -> None: + file = client.files.upload( + file=b"raw file contents", file_name="fileName", ) - assert_matches_type(FileUploadV1Response, file, path=["response"]) + assert_matches_type(FileUploadResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload_v1_with_all_params(self, client: ImageKit) -> None: - file = client.files.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", + def test_method_upload_with_all_params(self, client: ImageKit) -> None: + file = client.files.upload( + file=b"raw file contents", file_name="fileName", token="token", checks='"request.folder" : "marketing/"\n', custom_coordinates="customCoordinates", - custom_metadata='"\n {\n "brand": "Nike",\n "color":"red"\n }\n"\n', - expire="expire", - extensions='"\n[\n {"name":"remove-bg","options":{"add_shadow":true,"bg_colour":"green"}},\n {"name":"google-auto-tagging","maxTags":5,"minConfidence":95}\n]\n"\n', + custom_metadata={ + "brand": "bar", + "color": "bar", + }, + description="Running shoes", + expire=0, + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + ], folder="folder", - is_private_file="true", - is_published="true", - overwrite_ai_tags="true", - overwrite_custom_metadata="true", - overwrite_file="overwriteFile", - overwrite_tags="true", + is_private_file=True, + is_published=True, + overwrite_ai_tags=True, + overwrite_custom_metadata=True, + overwrite_file=True, + overwrite_tags=True, public_key="publicKey", - response_fields="responseFields", + response_fields=["tags", "customCoordinates", "isPrivateFile"], signature="signature", - tags="t-shirt,round-neck,men", - transformation='\'{"pre":"width:300,height:300,quality:80","post":[{"type":"thumbnail","value":"width:100,height:100"}]}\'\n', - use_unique_file_name="true", - webhook_url="webhookUrl", - ) - assert_matches_type(FileUploadV1Response, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_upload_v1(self, client: ImageKit) -> None: - response = client.files.with_raw_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", + tags=["t-shirt", "round-neck", "men"], + transformation={ + "post": [ + { + "type": "thumbnail", + "value": "w-150,h-150", + }, + { + "protocol": "dash", + "type": "abs", + "value": "sr-240_360_480_720_1080", + }, + ], + "pre": "w-300,h-300,q-80", + }, + use_unique_file_name=True, + webhook_url="https://example.com", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_upload(self, client: ImageKit) -> None: + response = client.files.with_raw_response.upload( + file=b"raw file contents", file_name="fileName", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(FileUploadV1Response, file, path=["response"]) + assert_matches_type(FileUploadResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_upload_v1(self, client: ImageKit) -> None: - with client.files.with_streaming_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", + def test_streaming_response_upload(self, client: ImageKit) -> None: + with client.files.with_streaming_response.upload( + file=b"raw file contents", file_name="fileName", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(FileUploadV1Response, file, path=["response"]) + assert_matches_type(FileUploadResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True + +class TestAsyncFiles: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload_v2(self, client: ImageKit) -> None: - file = client.files.upload_v2( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", + async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.update( + file_id="fileId", ) - assert_matches_type(FileUploadV2Response, file, path=["response"]) + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload_v2_with_all_params(self, client: ImageKit) -> None: - file = client.files.upload_v2( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", - token="token", - checks='"request.folder" : "marketing/"\n', + async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.update( + file_id="fileId", custom_coordinates="customCoordinates", - custom_metadata='"\n {\n "brand": "Nike",\n "color":"red"\n }\n"\n', - extensions='"\n[\n {"name":"remove-bg","options":{"add_shadow":true,"bg_colour":"green"}},\n {"name":"google-auto-tagging","maxTags":5,"minConfidence":95}\n]\n"\n', - folder="folder", - is_private_file="true", - is_published="true", - overwrite_ai_tags="true", - overwrite_custom_metadata="true", - overwrite_file="overwriteFile", - overwrite_tags="true", - response_fields="responseFields", - tags="t-shirt,round-neck,men", - transformation='\'{"pre":"width:300,height:300,quality:80","post":[{"type":"thumbnail","value":"width:100,height:100"}]}\'\n', - use_unique_file_name="true", - webhook_url="webhookUrl", + custom_metadata={}, + description="description", + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + } + ], + remove_ai_tags=["string"], + tags=["tag1", "tag2"], + webhook_url="https://example.com", ) - assert_matches_type(FileUploadV2Response, file, path=["response"]) + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_upload_v2(self, client: ImageKit) -> None: - response = client.files.with_raw_response.upload_v2( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", + async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.update( + file_id="fileId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = response.parse() - assert_matches_type(FileUploadV2Response, file, path=["response"]) + file = await response.parse() + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_upload_v2(self, client: ImageKit) -> None: - with client.files.with_streaming_response.upload_v2( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", + async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.update( + file_id="fileId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = response.parse() - assert_matches_type(FileUploadV2Response, file, path=["response"]) + file = await response.parse() + assert_matches_type(FileUpdateResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True - -class TestAsyncFiles: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.with_raw_response.update( + file_id="", + ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_list(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.list() - assert_matches_type(FileListResponse, file, path=["response"]) + async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.update( + file_id="fileId", + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.list( - file_type="fileType", - limit="limit", - path="path", - search_query="searchQuery", - skip="skip", - sort="sort", - type="file", + async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.update( + file_id="fileId", + publish={ + "is_published": True, + "include_file_versions": True, + }, ) - assert_matches_type(FileListResponse, file, path=["response"]) + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_list(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.list() + async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.update( + file_id="fileId", + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(FileListResponse, file, path=["response"]) + assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_list(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.list() as response: + async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.update( + file_id="fileId", + ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(FileListResponse, file, path=["response"]) + assert_matches_type(FileUpdateResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.with_raw_response.update( + file_id="", + ) + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_delete(self, async_client: AsyncImageKit) -> None: @@ -570,43 +625,6 @@ async def test_path_params_delete(self, async_client: AsyncImageKit) -> None: "", ) - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_add_tags(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.add_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], - ) - assert_matches_type(FileAddTagsResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_add_tags(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.add_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = await response.parse() - assert_matches_type(FileAddTagsResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_add_tags(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.add_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = await response.parse() - assert_matches_type(FileAddTagsResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_copy(self, async_client: AsyncImageKit) -> None: @@ -656,112 +674,80 @@ async def test_streaming_response_copy(self, async_client: AsyncImageKit) -> Non @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_move(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.move( - destination_path="/folder/to/move/into/", - source_file_path="/path/to/file.jpg", + async def test_method_get(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.get( + "fileId", ) - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileGetResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_move(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.move( - destination_path="/folder/to/move/into/", - source_file_path="/path/to/file.jpg", + async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.get( + "fileId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileGetResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_move(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.move( - destination_path="/folder/to/move/into/", - source_file_path="/path/to/file.jpg", + async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.get( + "fileId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileGetResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_remove_ai_tags(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.remove_ai_tags( - ai_tags=["t-shirt", "round-neck", "sale2019"], - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) - assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_remove_ai_tags(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.remove_ai_tags( - ai_tags=["t-shirt", "round-neck", "sale2019"], - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = await response.parse() - assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_remove_ai_tags(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.remove_ai_tags( - ai_tags=["t-shirt", "round-neck", "sale2019"], - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = await response.parse() - assert_matches_type(FileRemoveAITagsResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True + async def test_path_params_get(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.with_raw_response.get( + "", + ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_remove_tags(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.remove_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], + async def test_method_move(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", ) - assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + assert_matches_type(object, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_remove_tags(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.remove_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], + async def test_raw_response_move(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + assert_matches_type(object, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_remove_tags(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.remove_tags( - file_ids=["598821f949c0a938d57563bd", "598821f949c0a938d57563be"], - tags=["t-shirt", "round-neck", "sale2019"], + async def test_streaming_response_move(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.move( + destination_path="/folder/to/move/into/", + source_file_path="/path/to/file.jpg", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(FileRemoveTagsResponse, file, path=["response"]) + assert_matches_type(object, file, path=["response"]) assert cast(Any, response.is_closed) is True @@ -814,129 +800,98 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_upload_v1(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", + async def test_method_upload(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.upload( + file=b"raw file contents", file_name="fileName", ) - assert_matches_type(FileUploadV1Response, file, path=["response"]) + assert_matches_type(FileUploadResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_upload_v1_with_all_params(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", + async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.upload( + file=b"raw file contents", file_name="fileName", token="token", checks='"request.folder" : "marketing/"\n', custom_coordinates="customCoordinates", - custom_metadata='"\n {\n "brand": "Nike",\n "color":"red"\n }\n"\n', - expire="expire", - extensions='"\n[\n {"name":"remove-bg","options":{"add_shadow":true,"bg_colour":"green"}},\n {"name":"google-auto-tagging","maxTags":5,"minConfidence":95}\n]\n"\n', + custom_metadata={ + "brand": "bar", + "color": "bar", + }, + description="Running shoes", + expire=0, + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + ], folder="folder", - is_private_file="true", - is_published="true", - overwrite_ai_tags="true", - overwrite_custom_metadata="true", - overwrite_file="overwriteFile", - overwrite_tags="true", + is_private_file=True, + is_published=True, + overwrite_ai_tags=True, + overwrite_custom_metadata=True, + overwrite_file=True, + overwrite_tags=True, public_key="publicKey", - response_fields="responseFields", + response_fields=["tags", "customCoordinates", "isPrivateFile"], signature="signature", - tags="t-shirt,round-neck,men", - transformation='\'{"pre":"width:300,height:300,quality:80","post":[{"type":"thumbnail","value":"width:100,height:100"}]}\'\n', - use_unique_file_name="true", - webhook_url="webhookUrl", - ) - assert_matches_type(FileUploadV1Response, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_upload_v1(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = await response.parse() - assert_matches_type(FileUploadV1Response, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_upload_v1(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = await response.parse() - assert_matches_type(FileUploadV1Response, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_upload_v2(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.upload_v2( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", - ) - assert_matches_type(FileUploadV2Response, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_upload_v2_with_all_params(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.upload_v2( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", - token="token", - checks='"request.folder" : "marketing/"\n', - custom_coordinates="customCoordinates", - custom_metadata='"\n {\n "brand": "Nike",\n "color":"red"\n }\n"\n', - extensions='"\n[\n {"name":"remove-bg","options":{"add_shadow":true,"bg_colour":"green"}},\n {"name":"google-auto-tagging","maxTags":5,"minConfidence":95}\n]\n"\n', - folder="folder", - is_private_file="true", - is_published="true", - overwrite_ai_tags="true", - overwrite_custom_metadata="true", - overwrite_file="overwriteFile", - overwrite_tags="true", - response_fields="responseFields", - tags="t-shirt,round-neck,men", - transformation='\'{"pre":"width:300,height:300,quality:80","post":[{"type":"thumbnail","value":"width:100,height:100"}]}\'\n', - use_unique_file_name="true", - webhook_url="webhookUrl", - ) - assert_matches_type(FileUploadV2Response, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_upload_v2(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.upload_v2( - file="https://www.example.com/rest-of-the-image-path.jpg", + tags=["t-shirt", "round-neck", "men"], + transformation={ + "post": [ + { + "type": "thumbnail", + "value": "w-150,h-150", + }, + { + "protocol": "dash", + "type": "abs", + "value": "sr-240_360_480_720_1080", + }, + ], + "pre": "w-300,h-300,q-80", + }, + use_unique_file_name=True, + webhook_url="https://example.com", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.upload( + file=b"raw file contents", file_name="fileName", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(FileUploadV2Response, file, path=["response"]) + assert_matches_type(FileUploadResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_upload_v2(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.upload_v2( - file="https://www.example.com/rest-of-the-image-path.jpg", + async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.upload( + file=b"raw file contents", file_name="fileName", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(FileUploadV2Response, file, path=["response"]) + assert_matches_type(FileUploadResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_folder.py b/tests/api_resources/test_folder.py deleted file mode 100644 index 9b87629..0000000 --- a/tests/api_resources/test_folder.py +++ /dev/null @@ -1,165 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from imagekit import ImageKit, AsyncImageKit -from tests.utils import assert_matches_type - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestFolder: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create(self, client: ImageKit) -> None: - folder = client.folder.create( - folder_name="summer", - parent_folder_path="/product/images/", - ) - assert_matches_type(object, folder, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_create(self, client: ImageKit) -> None: - response = client.folder.with_raw_response.create( - folder_name="summer", - parent_folder_path="/product/images/", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - folder = response.parse() - assert_matches_type(object, folder, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_create(self, client: ImageKit) -> None: - with client.folder.with_streaming_response.create( - folder_name="summer", - parent_folder_path="/product/images/", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - folder = response.parse() - assert_matches_type(object, folder, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_delete(self, client: ImageKit) -> None: - folder = client.folder.delete( - folder_path="/folder/to/delete/", - ) - assert_matches_type(object, folder, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_delete(self, client: ImageKit) -> None: - response = client.folder.with_raw_response.delete( - folder_path="/folder/to/delete/", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - folder = response.parse() - assert_matches_type(object, folder, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_delete(self, client: ImageKit) -> None: - with client.folder.with_streaming_response.delete( - folder_path="/folder/to/delete/", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - folder = response.parse() - assert_matches_type(object, folder, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncFolder: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create(self, async_client: AsyncImageKit) -> None: - folder = await async_client.folder.create( - folder_name="summer", - parent_folder_path="/product/images/", - ) - assert_matches_type(object, folder, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: - response = await async_client.folder.with_raw_response.create( - folder_name="summer", - parent_folder_path="/product/images/", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - folder = await response.parse() - assert_matches_type(object, folder, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: - async with async_client.folder.with_streaming_response.create( - folder_name="summer", - parent_folder_path="/product/images/", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - folder = await response.parse() - assert_matches_type(object, folder, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_delete(self, async_client: AsyncImageKit) -> None: - folder = await async_client.folder.delete( - folder_path="/folder/to/delete/", - ) - assert_matches_type(object, folder, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: - response = await async_client.folder.with_raw_response.delete( - folder_path="/folder/to/delete/", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - folder = await response.parse() - assert_matches_type(object, folder, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: - async with async_client.folder.with_streaming_response.delete( - folder_path="/folder/to/delete/", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - folder = await response.parse() - assert_matches_type(object, folder, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_folders.py b/tests/api_resources/test_folders.py new file mode 100644 index 0000000..917f172 --- /dev/null +++ b/tests/api_resources/test_folders.py @@ -0,0 +1,432 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekit import ImageKit, AsyncImageKit +from tests.utils import assert_matches_type +from imagekit.types import ( + FolderCopyResponse, + FolderMoveResponse, + FolderRenameResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFolders: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create(self, client: ImageKit) -> None: + folder = client.folders.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create(self, client: ImageKit) -> None: + response = client.folders.with_raw_response.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = response.parse() + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create(self, client: ImageKit) -> None: + with client.folders.with_streaming_response.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = response.parse() + assert_matches_type(object, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + folder = client.folders.delete( + folder_path="/folder/to/delete/", + ) + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.folders.with_raw_response.delete( + folder_path="/folder/to/delete/", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = response.parse() + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.folders.with_streaming_response.delete( + folder_path="/folder/to/delete/", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = response.parse() + assert_matches_type(object, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_copy(self, client: ImageKit) -> None: + folder = client.folders.copy( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_copy_with_all_params(self, client: ImageKit) -> None: + folder = client.folders.copy( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + include_versions=True, + ) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_copy(self, client: ImageKit) -> None: + response = client.folders.with_raw_response.copy( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = response.parse() + assert_matches_type(FolderCopyResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_copy(self, client: ImageKit) -> None: + with client.folders.with_streaming_response.copy( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = response.parse() + assert_matches_type(FolderCopyResponse, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_move(self, client: ImageKit) -> None: + folder = client.folders.move( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + assert_matches_type(FolderMoveResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_move(self, client: ImageKit) -> None: + response = client.folders.with_raw_response.move( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = response.parse() + assert_matches_type(FolderMoveResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_move(self, client: ImageKit) -> None: + with client.folders.with_streaming_response.move( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = response.parse() + assert_matches_type(FolderMoveResponse, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_rename(self, client: ImageKit) -> None: + folder = client.folders.rename( + folder_path="/path/of/folder", + new_folder_name="new-folder-name", + ) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_rename_with_all_params(self, client: ImageKit) -> None: + folder = client.folders.rename( + folder_path="/path/of/folder", + new_folder_name="new-folder-name", + purge_cache=True, + ) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_rename(self, client: ImageKit) -> None: + response = client.folders.with_raw_response.rename( + folder_path="/path/of/folder", + new_folder_name="new-folder-name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = response.parse() + assert_matches_type(FolderRenameResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_rename(self, client: ImageKit) -> None: + with client.folders.with_streaming_response.rename( + folder_path="/path/of/folder", + new_folder_name="new-folder-name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = response.parse() + assert_matches_type(FolderRenameResponse, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncFolders: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncImageKit) -> None: + folder = await async_client.folders.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: + response = await async_client.folders.with_raw_response.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = await response.parse() + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: + async with async_client.folders.with_streaming_response.create( + folder_name="summer", + parent_folder_path="/product/images/", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = await response.parse() + assert_matches_type(object, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncImageKit) -> None: + folder = await async_client.folders.delete( + folder_path="/folder/to/delete/", + ) + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: + response = await async_client.folders.with_raw_response.delete( + folder_path="/folder/to/delete/", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = await response.parse() + assert_matches_type(object, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> None: + async with async_client.folders.with_streaming_response.delete( + folder_path="/folder/to/delete/", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = await response.parse() + assert_matches_type(object, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_copy(self, async_client: AsyncImageKit) -> None: + folder = await async_client.folders.copy( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_copy_with_all_params(self, async_client: AsyncImageKit) -> None: + folder = await async_client.folders.copy( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + include_versions=True, + ) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_copy(self, async_client: AsyncImageKit) -> None: + response = await async_client.folders.with_raw_response.copy( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = await response.parse() + assert_matches_type(FolderCopyResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_copy(self, async_client: AsyncImageKit) -> None: + async with async_client.folders.with_streaming_response.copy( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = await response.parse() + assert_matches_type(FolderCopyResponse, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_move(self, async_client: AsyncImageKit) -> None: + folder = await async_client.folders.move( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + assert_matches_type(FolderMoveResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_move(self, async_client: AsyncImageKit) -> None: + response = await async_client.folders.with_raw_response.move( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = await response.parse() + assert_matches_type(FolderMoveResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_move(self, async_client: AsyncImageKit) -> None: + async with async_client.folders.with_streaming_response.move( + destination_path="/path/of/destination/folder", + source_folder_path="/path/of/source/folder", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = await response.parse() + assert_matches_type(FolderMoveResponse, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_rename(self, async_client: AsyncImageKit) -> None: + folder = await async_client.folders.rename( + folder_path="/path/of/folder", + new_folder_name="new-folder-name", + ) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_rename_with_all_params(self, async_client: AsyncImageKit) -> None: + folder = await async_client.folders.rename( + folder_path="/path/of/folder", + new_folder_name="new-folder-name", + purge_cache=True, + ) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_rename(self, async_client: AsyncImageKit) -> None: + response = await async_client.folders.with_raw_response.rename( + folder_path="/path/of/folder", + new_folder_name="new-folder-name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + folder = await response.parse() + assert_matches_type(FolderRenameResponse, folder, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> None: + async with async_client.folders.with_streaming_response.rename( + folder_path="/path/of/folder", + new_folder_name="new-folder-name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + folder = await response.parse() + assert_matches_type(FolderRenameResponse, folder, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/test_client.py b/tests/test_client.py index 9681d18..c11dc77 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -806,9 +806,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien respx_mock.post("/api/v1/files/upload").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - client.files.with_streaming_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" - ).__enter__() + client.files.with_streaming_response.upload(file=b"raw file contents", file_name="fileName").__enter__() assert _get_open_connections(self.client) == 0 @@ -818,9 +816,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client respx_mock.post("/api/v1/files/upload").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - client.files.with_streaming_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" - ).__enter__() + client.files.with_streaming_response.upload(file=b"raw file contents", file_name="fileName").__enter__() assert _get_open_connections(self.client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @@ -849,9 +845,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = client.files.with_raw_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" - ) + response = client.files.with_raw_response.upload(file=b"raw file contents", file_name="fileName") assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -875,10 +869,8 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = client.files.with_raw_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", - extra_headers={"x-stainless-retry-count": Omit()}, + response = client.files.with_raw_response.upload( + file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": Omit()} ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -902,10 +894,8 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = client.files.with_raw_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", - extra_headers={"x-stainless-retry-count": "42"}, + response = client.files.with_raw_response.upload( + file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": "42"} ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1715,8 +1705,8 @@ async def test_retrying_timeout_errors_doesnt_leak( respx_mock.post("/api/v1/files/upload").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - await async_client.files.with_streaming_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" + await async_client.files.with_streaming_response.upload( + file=b"raw file contents", file_name="fileName" ).__aenter__() assert _get_open_connections(self.client) == 0 @@ -1729,8 +1719,8 @@ async def test_retrying_status_errors_doesnt_leak( respx_mock.post("/api/v1/files/upload").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - await async_client.files.with_streaming_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" + await async_client.files.with_streaming_response.upload( + file=b"raw file contents", file_name="fileName" ).__aenter__() assert _get_open_connections(self.client) == 0 @@ -1761,9 +1751,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = await client.files.with_raw_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", file_name="fileName" - ) + response = await client.files.with_raw_response.upload(file=b"raw file contents", file_name="fileName") assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1788,10 +1776,8 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = await client.files.with_raw_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", - extra_headers={"x-stainless-retry-count": Omit()}, + response = await client.files.with_raw_response.upload( + file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": Omit()} ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -1816,10 +1802,8 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = await client.files.with_raw_response.upload_v1( - file="https://www.example.com/rest-of-the-image-path.jpg", - file_name="fileName", - extra_headers={"x-stainless-retry-count": "42"}, + response = await client.files.with_raw_response.upload( + file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": "42"} ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" From 866e215a860c99a034e810d0e19407a84c7bfda6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 17 Aug 2025 06:20:07 +0000 Subject: [PATCH 007/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 6 + src/imagekit/types/__init__.py | 7 + .../types/beta/v2/file_upload_response.py | 131 ++---------------- src/imagekit/types/file_upload_response.py | 131 ++---------------- .../files/metadata_get_from_url_response.py | 127 ++--------------- .../types/files/metadata_get_response.py | 119 ++-------------- src/imagekit/types/shared/__init__.py | 7 + src/imagekit/types/shared/exif_details.py | 63 +++++++++ src/imagekit/types/shared/exif_image.py | 33 +++++ src/imagekit/types/shared/gps.py | 13 ++ src/imagekit/types/shared/interoperability.py | 15 ++ src/imagekit/types/shared/thumbnail.py | 23 +++ 13 files changed, 212 insertions(+), 465 deletions(-) create mode 100644 src/imagekit/types/shared/__init__.py create mode 100644 src/imagekit/types/shared/exif_details.py create mode 100644 src/imagekit/types/shared/exif_image.py create mode 100644 src/imagekit/types/shared/gps.py create mode 100644 src/imagekit/types/shared/interoperability.py create mode 100644 src/imagekit/types/shared/thumbnail.py diff --git a/.stats.yml b/.stats.yml index ee7ab85..d25e9ed 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-c01164d5dc8f8c9ab2b7c1a1c793ac522d565f96e569b0e56a4e9353e39bab85.yml openapi_spec_hash: ac7b3a2b968fe86bf7bb81192209123f -config_hash: 8a4138f8d02720b4736ab63effb7fa2d +config_hash: 963efe3c7e328464ca83ae352b29bbb4 diff --git a/api.md b/api.md index 859942b..1a34bef 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,9 @@ +# Shared Types + +```python +from imagekit.types import ExifDetails, ExifImage, Gps, Interoperability, Thumbnail +``` + # CustomMetadataFields Types: diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 2c5b94c..fe292f8 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -2,6 +2,13 @@ from __future__ import annotations +from .shared import ( + Gps as Gps, + ExifImage as ExifImage, + Thumbnail as Thumbnail, + ExifDetails as ExifDetails, + Interoperability as Interoperability, +) from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams from .asset_list_params import AssetListParams as AssetListParams diff --git a/src/imagekit/types/beta/v2/file_upload_response.py b/src/imagekit/types/beta/v2/file_upload_response.py index d719c38..dab6c04 100644 --- a/src/imagekit/types/beta/v2/file_upload_response.py +++ b/src/imagekit/types/beta/v2/file_upload_response.py @@ -6,20 +6,13 @@ from pydantic import Field as FieldInfo from ...._models import BaseModel +from ...shared.gps import Gps +from ...shared.thumbnail import Thumbnail +from ...shared.exif_image import ExifImage +from ...shared.exif_details import ExifDetails +from ...shared.interoperability import Interoperability -__all__ = [ - "FileUploadResponse", - "AITag", - "ExtensionStatus", - "Metadata", - "MetadataExif", - "MetadataExifExif", - "MetadataExifGps", - "MetadataExifImage", - "MetadataExifInteroperability", - "MetadataExifThumbnail", - "VersionInfo", -] +__all__ = ["FileUploadResponse", "AITag", "ExtensionStatus", "Metadata", "MetadataExif", "VersionInfo"] class AITag(BaseModel): @@ -49,124 +42,22 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) -class MetadataExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class MetadataExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class MetadataExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class MetadataExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class MetadataExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - class MetadataExif(BaseModel): - exif: Optional[MetadataExifExif] = None + exif: Optional[ExifDetails] = None """Object containing Exif details.""" - gps: Optional[MetadataExifGps] = None + gps: Optional[Gps] = None """Object containing GPS information.""" - image: Optional[MetadataExifImage] = None + image: Optional[ExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[MetadataExifInteroperability] = None + interoperability: Optional[Interoperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[MetadataExifThumbnail] = None + thumbnail: Optional[Thumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/file_upload_response.py b/src/imagekit/types/file_upload_response.py index deabddd..bb9f812 100644 --- a/src/imagekit/types/file_upload_response.py +++ b/src/imagekit/types/file_upload_response.py @@ -6,20 +6,13 @@ from pydantic import Field as FieldInfo from .._models import BaseModel +from .shared.gps import Gps +from .shared.thumbnail import Thumbnail +from .shared.exif_image import ExifImage +from .shared.exif_details import ExifDetails +from .shared.interoperability import Interoperability -__all__ = [ - "FileUploadResponse", - "AITag", - "ExtensionStatus", - "Metadata", - "MetadataExif", - "MetadataExifExif", - "MetadataExifGps", - "MetadataExifImage", - "MetadataExifInteroperability", - "MetadataExifThumbnail", - "VersionInfo", -] +__all__ = ["FileUploadResponse", "AITag", "ExtensionStatus", "Metadata", "MetadataExif", "VersionInfo"] class AITag(BaseModel): @@ -49,124 +42,22 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) -class MetadataExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class MetadataExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class MetadataExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class MetadataExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class MetadataExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - class MetadataExif(BaseModel): - exif: Optional[MetadataExifExif] = None + exif: Optional[ExifDetails] = None """Object containing Exif details.""" - gps: Optional[MetadataExifGps] = None + gps: Optional[Gps] = None """Object containing GPS information.""" - image: Optional[MetadataExifImage] = None + image: Optional[ExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[MetadataExifInteroperability] = None + interoperability: Optional[Interoperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[MetadataExifThumbnail] = None + thumbnail: Optional[Thumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/files/metadata_get_from_url_response.py b/src/imagekit/types/files/metadata_get_from_url_response.py index 47b1bcd..e5d3309 100644 --- a/src/imagekit/types/files/metadata_get_from_url_response.py +++ b/src/imagekit/types/files/metadata_get_from_url_response.py @@ -1,140 +1,35 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional +from typing import Dict, Optional from pydantic import Field as FieldInfo from ..._models import BaseModel +from ..shared.gps import Gps +from ..shared.thumbnail import Thumbnail +from ..shared.exif_image import ExifImage +from ..shared.exif_details import ExifDetails +from ..shared.interoperability import Interoperability -__all__ = [ - "MetadataGetFromURLResponse", - "Exif", - "ExifExif", - "ExifGps", - "ExifImage", - "ExifInteroperability", - "ExifThumbnail", -] - - -class ExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class ExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class ExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class ExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class ExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) +__all__ = ["MetadataGetFromURLResponse", "Exif"] class Exif(BaseModel): - exif: Optional[ExifExif] = None + exif: Optional[ExifDetails] = None """Object containing Exif details.""" - gps: Optional[ExifGps] = None + gps: Optional[Gps] = None """Object containing GPS information.""" image: Optional[ExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[ExifInteroperability] = None + interoperability: Optional[Interoperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[ExifThumbnail] = None + thumbnail: Optional[Thumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/files/metadata_get_response.py b/src/imagekit/types/files/metadata_get_response.py index d5a3cbf..7736d05 100644 --- a/src/imagekit/types/files/metadata_get_response.py +++ b/src/imagekit/types/files/metadata_get_response.py @@ -1,132 +1,35 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional +from typing import Dict, Optional from pydantic import Field as FieldInfo from ..._models import BaseModel +from ..shared.gps import Gps +from ..shared.thumbnail import Thumbnail +from ..shared.exif_image import ExifImage +from ..shared.exif_details import ExifDetails +from ..shared.interoperability import Interoperability -__all__ = ["MetadataGetResponse", "Exif", "ExifExif", "ExifGps", "ExifImage", "ExifInteroperability", "ExifThumbnail"] - - -class ExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class ExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class ExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class ExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class ExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) +__all__ = ["MetadataGetResponse", "Exif"] class Exif(BaseModel): - exif: Optional[ExifExif] = None + exif: Optional[ExifDetails] = None """Object containing Exif details.""" - gps: Optional[ExifGps] = None + gps: Optional[Gps] = None """Object containing GPS information.""" image: Optional[ExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[ExifInteroperability] = None + interoperability: Optional[Interoperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[ExifThumbnail] = None + thumbnail: Optional[Thumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/shared/__init__.py b/src/imagekit/types/shared/__init__.py new file mode 100644 index 0000000..35d967c --- /dev/null +++ b/src/imagekit/types/shared/__init__.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .gps import Gps as Gps +from .thumbnail import Thumbnail as Thumbnail +from .exif_image import ExifImage as ExifImage +from .exif_details import ExifDetails as ExifDetails +from .interoperability import Interoperability as Interoperability diff --git a/src/imagekit/types/shared/exif_details.py b/src/imagekit/types/shared/exif_details.py new file mode 100644 index 0000000..24820d7 --- /dev/null +++ b/src/imagekit/types/shared/exif_details.py @@ -0,0 +1,63 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["ExifDetails"] + + +class ExifDetails(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) diff --git a/src/imagekit/types/shared/exif_image.py b/src/imagekit/types/shared/exif_image.py new file mode 100644 index 0000000..63eb6e7 --- /dev/null +++ b/src/imagekit/types/shared/exif_image.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["ExifImage"] + + +class ExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) diff --git a/src/imagekit/types/shared/gps.py b/src/imagekit/types/shared/gps.py new file mode 100644 index 0000000..fa8ac0a --- /dev/null +++ b/src/imagekit/types/shared/gps.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["Gps"] + + +class Gps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) diff --git a/src/imagekit/types/shared/interoperability.py b/src/imagekit/types/shared/interoperability.py new file mode 100644 index 0000000..1eda53f --- /dev/null +++ b/src/imagekit/types/shared/interoperability.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["Interoperability"] + + +class Interoperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) diff --git a/src/imagekit/types/shared/thumbnail.py b/src/imagekit/types/shared/thumbnail.py new file mode 100644 index 0000000..03d674c --- /dev/null +++ b/src/imagekit/types/shared/thumbnail.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["Thumbnail"] + + +class Thumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) From d8ef4783233a8bfa651c8cb92dbaeba8465ea46f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 17 Aug 2025 06:54:02 +0000 Subject: [PATCH 008/177] feat(api): manual updates --- .stats.yml | 6 +- api.md | 41 ++++++++--- .../resources/custom_metadata_fields.py | 9 +-- src/imagekit/resources/files/files.py | 26 +++---- src/imagekit/resources/files/versions.py | 9 +-- src/imagekit/resources/folders/folders.py | 18 ++--- src/imagekit/types/__init__.py | 10 +++ src/imagekit/types/asset_list_response.py | 4 +- .../types/beta/v2/file_upload_params.py | 63 ++--------------- .../types/beta/v2/file_upload_response.py | 2 +- .../custom_metadata_field_delete_response.py | 9 +++ src/imagekit/types/file_copy_response.py | 9 +++ src/imagekit/types/file_get_response.py | 4 +- src/imagekit/types/file_move_response.py | 9 +++ src/imagekit/types/file_update_params.py | 69 ++----------------- src/imagekit/types/file_update_response.py | 4 +- src/imagekit/types/file_upload_params.py | 63 ++--------------- src/imagekit/types/file_upload_response.py | 2 +- src/imagekit/types/files/__init__.py | 1 + .../types/files/version_delete_response.py | 9 +++ .../types/files/version_get_response.py | 4 +- .../types/files/version_list_response.py | 4 +- .../types/files/version_restore_response.py | 4 +- src/imagekit/types/folder_create_response.py | 9 +++ src/imagekit/types/folder_delete_response.py | 9 +++ src/imagekit/types/shared/__init__.py | 3 + .../shared/auto_description_extension.py | 12 ++++ .../types/shared/auto_tagging_extension.py | 20 ++++++ .../types/shared/removedot_bg_extension.py | 44 ++++++++++++ src/imagekit/types/shared_params/__init__.py | 5 ++ .../auto_description_extension.py | 12 ++++ .../shared_params/auto_tagging_extension.py | 20 ++++++ .../shared_params/removedot_bg_extension.py | 43 ++++++++++++ tests/api_resources/files/test_versions.py | 14 ++-- .../test_custom_metadata_fields.py | 13 ++-- tests/api_resources/test_files.py | 34 ++++----- tests/api_resources/test_folders.py | 26 +++---- 37 files changed, 367 insertions(+), 276 deletions(-) create mode 100644 src/imagekit/types/custom_metadata_field_delete_response.py create mode 100644 src/imagekit/types/file_copy_response.py create mode 100644 src/imagekit/types/file_move_response.py create mode 100644 src/imagekit/types/files/version_delete_response.py create mode 100644 src/imagekit/types/folder_create_response.py create mode 100644 src/imagekit/types/folder_delete_response.py create mode 100644 src/imagekit/types/shared/auto_description_extension.py create mode 100644 src/imagekit/types/shared/auto_tagging_extension.py create mode 100644 src/imagekit/types/shared/removedot_bg_extension.py create mode 100644 src/imagekit/types/shared_params/__init__.py create mode 100644 src/imagekit/types/shared_params/auto_description_extension.py create mode 100644 src/imagekit/types/shared_params/auto_tagging_extension.py create mode 100644 src/imagekit/types/shared_params/removedot_bg_extension.py diff --git a/.stats.yml b/.stats.yml index d25e9ed..456c477 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-c01164d5dc8f8c9ab2b7c1a1c793ac522d565f96e569b0e56a4e9353e39bab85.yml -openapi_spec_hash: ac7b3a2b968fe86bf7bb81192209123f -config_hash: 963efe3c7e328464ca83ae352b29bbb4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-584c2ccf3fc1a3ff3abf26b8d3dace2398d0f9ed6f20e4c411a13a81febb5e98.yml +openapi_spec_hash: 14d1614ea3903d6b53f26e135c9cae81 +config_hash: 7e5c039f375ccdba7cf3e61492a273f2 diff --git a/api.md b/api.md index 1a34bef..f9a64a2 100644 --- a/api.md +++ b/api.md @@ -1,7 +1,16 @@ # Shared Types ```python -from imagekit.types import ExifDetails, ExifImage, Gps, Interoperability, Thumbnail +from imagekit.types import ( + AutoDescriptionExtension, + AutoTaggingExtension, + ExifDetails, + ExifImage, + Gps, + Interoperability, + RemovedotBgExtension, + Thumbnail, +) ``` # CustomMetadataFields @@ -13,6 +22,7 @@ from imagekit.types import ( CustomMetadataFieldCreateResponse, CustomMetadataFieldUpdateResponse, CustomMetadataFieldListResponse, + CustomMetadataFieldDeleteResponse, ) ``` @@ -21,7 +31,7 @@ Methods: - client.custom_metadata_fields.create(\*\*params) -> CustomMetadataFieldCreateResponse - client.custom_metadata_fields.update(id, \*\*params) -> CustomMetadataFieldUpdateResponse - client.custom_metadata_fields.list(\*\*params) -> CustomMetadataFieldListResponse -- client.custom_metadata_fields.delete(id) -> object +- client.custom_metadata_fields.delete(id) -> CustomMetadataFieldDeleteResponse # Files @@ -30,7 +40,9 @@ Types: ```python from imagekit.types import ( FileUpdateResponse, + FileCopyResponse, FileGetResponse, + FileMoveResponse, FileRenameResponse, FileUploadResponse, ) @@ -40,9 +52,9 @@ Methods: - client.files.update(file_id, \*\*params) -> FileUpdateResponse - client.files.delete(file_id) -> None -- client.files.copy(\*\*params) -> object +- client.files.copy(\*\*params) -> FileCopyResponse - client.files.get(file_id) -> FileGetResponse -- client.files.move(\*\*params) -> object +- client.files.move(\*\*params) -> FileMoveResponse - client.files.rename(\*\*params) -> FileRenameResponse - client.files.upload(\*\*params) -> FileUploadResponse @@ -71,13 +83,18 @@ Methods: Types: ```python -from imagekit.types.files import VersionListResponse, VersionGetResponse, VersionRestoreResponse +from imagekit.types.files import ( + VersionListResponse, + VersionDeleteResponse, + VersionGetResponse, + VersionRestoreResponse, +) ``` Methods: - client.files.versions.list(file_id) -> VersionListResponse -- client.files.versions.delete(version_id, \*, file_id) -> object +- client.files.versions.delete(version_id, \*, file_id) -> VersionDeleteResponse - client.files.versions.get(version_id, \*, file_id) -> VersionGetResponse - client.files.versions.restore(version_id, \*, file_id) -> VersionRestoreResponse @@ -126,13 +143,19 @@ Methods: Types: ```python -from imagekit.types import FolderCopyResponse, FolderMoveResponse, FolderRenameResponse +from imagekit.types import ( + FolderCreateResponse, + FolderDeleteResponse, + FolderCopyResponse, + FolderMoveResponse, + FolderRenameResponse, +) ``` Methods: -- client.folders.create(\*\*params) -> object -- client.folders.delete(\*\*params) -> object +- client.folders.create(\*\*params) -> FolderCreateResponse +- client.folders.delete(\*\*params) -> FolderDeleteResponse - client.folders.copy(\*\*params) -> FolderCopyResponse - client.folders.move(\*\*params) -> FolderMoveResponse - client.folders.rename(\*\*params) -> FolderRenameResponse diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py index ce4e096..5682c04 100644 --- a/src/imagekit/resources/custom_metadata_fields.py +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -22,6 +22,7 @@ from .._base_client import make_request_options from ..types.custom_metadata_field_list_response import CustomMetadataFieldListResponse from ..types.custom_metadata_field_create_response import CustomMetadataFieldCreateResponse +from ..types.custom_metadata_field_delete_response import CustomMetadataFieldDeleteResponse from ..types.custom_metadata_field_update_response import CustomMetadataFieldUpdateResponse __all__ = ["CustomMetadataFieldsResource", "AsyncCustomMetadataFieldsResource"] @@ -205,7 +206,7 @@ def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> CustomMetadataFieldDeleteResponse: """This API deletes a custom metadata field. Even after deleting a custom metadata @@ -227,7 +228,7 @@ def delete( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=CustomMetadataFieldDeleteResponse, ) @@ -409,7 +410,7 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> CustomMetadataFieldDeleteResponse: """This API deletes a custom metadata field. Even after deleting a custom metadata @@ -431,7 +432,7 @@ async def delete( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=CustomMetadataFieldDeleteResponse, ) diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 8e3a2a2..583f3da 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -44,6 +44,8 @@ ) from ..._base_client import make_request_options from ...types.file_get_response import FileGetResponse +from ...types.file_copy_response import FileCopyResponse +from ...types.file_move_response import FileMoveResponse from ...types.file_rename_response import FileRenameResponse from ...types.file_update_response import FileUpdateResponse from ...types.file_upload_response import FileUploadResponse @@ -89,7 +91,7 @@ def update( file_id: str, *, custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: object | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, @@ -183,7 +185,7 @@ def update( file_id: str, *, custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: object | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, @@ -270,7 +272,7 @@ def copy( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> FileCopyResponse: """ This will copy a file from one folder to another. @@ -308,7 +310,7 @@ def copy( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=FileCopyResponse, ) def get( @@ -356,7 +358,7 @@ def move( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> FileMoveResponse: """ This will move a file and all its versions from one folder to another. @@ -388,7 +390,7 @@ def move( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=FileMoveResponse, ) def rename( @@ -760,7 +762,7 @@ async def update( file_id: str, *, custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: object | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, @@ -854,7 +856,7 @@ async def update( file_id: str, *, custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: object | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, @@ -941,7 +943,7 @@ async def copy( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> FileCopyResponse: """ This will copy a file from one folder to another. @@ -979,7 +981,7 @@ async def copy( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=FileCopyResponse, ) async def get( @@ -1027,7 +1029,7 @@ async def move( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> FileMoveResponse: """ This will move a file and all its versions from one folder to another. @@ -1059,7 +1061,7 @@ async def move( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=FileMoveResponse, ) async def rename( diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py index dd50640..32987d9 100644 --- a/src/imagekit/resources/files/versions.py +++ b/src/imagekit/resources/files/versions.py @@ -16,6 +16,7 @@ from ..._base_client import make_request_options from ...types.files.version_get_response import VersionGetResponse from ...types.files.version_list_response import VersionListResponse +from ...types.files.version_delete_response import VersionDeleteResponse from ...types.files.version_restore_response import VersionRestoreResponse __all__ = ["VersionsResource", "AsyncVersionsResource"] @@ -85,7 +86,7 @@ def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> VersionDeleteResponse: """This API deletes a non-current file version permanently. The API returns an @@ -111,7 +112,7 @@ def delete( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=VersionDeleteResponse, ) def get( @@ -251,7 +252,7 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> VersionDeleteResponse: """This API deletes a non-current file version permanently. The API returns an @@ -277,7 +278,7 @@ async def delete( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=VersionDeleteResponse, ) async def get( diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekit/resources/folders/folders.py index 0e193ef..b0e322d 100644 --- a/src/imagekit/resources/folders/folders.py +++ b/src/imagekit/resources/folders/folders.py @@ -32,6 +32,8 @@ from ..._base_client import make_request_options from ...types.folder_copy_response import FolderCopyResponse from ...types.folder_move_response import FolderMoveResponse +from ...types.folder_create_response import FolderCreateResponse +from ...types.folder_delete_response import FolderDeleteResponse from ...types.folder_rename_response import FolderRenameResponse __all__ = ["FoldersResource", "AsyncFoldersResource"] @@ -72,7 +74,7 @@ def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> FolderCreateResponse: """This will create a new folder. You can specify the folder name and location of @@ -113,7 +115,7 @@ def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=FolderCreateResponse, ) def delete( @@ -126,7 +128,7 @@ def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> FolderDeleteResponse: """This will delete a folder and all its contents permanently. The API returns an @@ -149,7 +151,7 @@ def delete( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=FolderDeleteResponse, ) def copy( @@ -359,7 +361,7 @@ async def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> FolderCreateResponse: """This will create a new folder. You can specify the folder name and location of @@ -400,7 +402,7 @@ async def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=FolderCreateResponse, ) async def delete( @@ -413,7 +415,7 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> FolderDeleteResponse: """This will delete a folder and all its contents permanently. The API returns an @@ -436,7 +438,7 @@ async def delete( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=FolderDeleteResponse, ) async def copy( diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index fe292f8..1517fc1 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -8,11 +8,16 @@ Thumbnail as Thumbnail, ExifDetails as ExifDetails, Interoperability as Interoperability, + AutoTaggingExtension as AutoTaggingExtension, + RemovedotBgExtension as RemovedotBgExtension, + AutoDescriptionExtension as AutoDescriptionExtension, ) from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams from .asset_list_params import AssetListParams as AssetListParams from .file_get_response import FileGetResponse as FileGetResponse +from .file_copy_response import FileCopyResponse as FileCopyResponse +from .file_move_response import FileMoveResponse as FileMoveResponse from .file_rename_params import FileRenameParams as FileRenameParams from .file_update_params import FileUpdateParams as FileUpdateParams from .file_upload_params import FileUploadParams as FileUploadParams @@ -27,6 +32,8 @@ from .folder_delete_params import FolderDeleteParams as FolderDeleteParams from .folder_move_response import FolderMoveResponse as FolderMoveResponse from .folder_rename_params import FolderRenameParams as FolderRenameParams +from .folder_create_response import FolderCreateResponse as FolderCreateResponse +from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse from .folder_rename_response import FolderRenameResponse as FolderRenameResponse from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams @@ -35,6 +42,9 @@ from .custom_metadata_field_create_response import ( CustomMetadataFieldCreateResponse as CustomMetadataFieldCreateResponse, ) +from .custom_metadata_field_delete_response import ( + CustomMetadataFieldDeleteResponse as CustomMetadataFieldDeleteResponse, +) from .custom_metadata_field_update_response import ( CustomMetadataFieldUpdateResponse as CustomMetadataFieldUpdateResponse, ) diff --git a/src/imagekit/types/asset_list_response.py b/src/imagekit/types/asset_list_response.py index 7a0fdd1..b0c1e33 100644 --- a/src/imagekit/types/asset_list_response.py +++ b/src/imagekit/types/asset_list_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Union, Optional +from typing import Dict, List, Union, Optional from typing_extensions import Literal, TypeAlias from pydantic import Field as FieldInfo @@ -52,7 +52,7 @@ class AssetListResponseItemFileDetails(BaseModel): custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) """An string with custom coordinates of the file.""" - custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) """An object with custom metadata for the file.""" file_id: Optional[str] = FieldInfo(alias="fileId", default=None) diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekit/types/beta/v2/file_upload_params.py index 82fa22a..fe02965 100644 --- a/src/imagekit/types/beta/v2/file_upload_params.py +++ b/src/imagekit/types/beta/v2/file_upload_params.py @@ -7,14 +7,13 @@ from ...._types import FileTypes from ...._utils import PropertyInfo +from ...shared_params.auto_tagging_extension import AutoTaggingExtension +from ...shared_params.removedot_bg_extension import RemovedotBgExtension +from ...shared_params.auto_description_extension import AutoDescriptionExtension __all__ = [ "FileUploadParams", "Extension", - "ExtensionRemovedotBgExtension", - "ExtensionRemovedotBgExtensionOptions", - "ExtensionAutoTaggingExtension", - "ExtensionAutoDescriptionExtension", "Transformation", "TransformationPost", "TransformationPostSimplePostTransformation", @@ -198,61 +197,7 @@ class FileUploadParams(TypedDict, total=False): """ -class ExtensionRemovedotBgExtensionOptions(TypedDict, total=False): - add_shadow: bool - """Whether to add an artificial shadow to the result. - - Default is false. Note: Adding shadows is currently only supported for car - photos. - """ - - bg_color: str - """ - Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or - color name (e.g., "green"). If this parameter is set, `bg_image_url` must be - empty. - """ - - bg_image_url: str - """Sets a background image from a URL. - - If this parameter is set, `bg_color` must be empty. - """ - - semitransparency: bool - """Allows semi-transparent regions in the result. - - Default is true. Note: Semitransparency is currently only supported for car - windows. - """ - - -class ExtensionRemovedotBgExtension(TypedDict, total=False): - name: Required[Literal["remove-bg"]] - """Specifies the background removal extension.""" - - options: ExtensionRemovedotBgExtensionOptions - - -class ExtensionAutoTaggingExtension(TypedDict, total=False): - max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] - """Maximum number of tags to attach to the asset.""" - - min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] - """Minimum confidence level for tags to be considered valid.""" - - name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] - """Specifies the auto-tagging extension used.""" - - -class ExtensionAutoDescriptionExtension(TypedDict, total=False): - name: Required[Literal["ai-auto-description"]] - """Specifies the auto description extension.""" - - -Extension: TypeAlias = Union[ - ExtensionRemovedotBgExtension, ExtensionAutoTaggingExtension, ExtensionAutoDescriptionExtension -] +Extension: TypeAlias = Union[RemovedotBgExtension, AutoTaggingExtension, AutoDescriptionExtension] class TransformationPostSimplePostTransformation(TypedDict, total=False): diff --git a/src/imagekit/types/beta/v2/file_upload_response.py b/src/imagekit/types/beta/v2/file_upload_response.py index dab6c04..0b4672a 100644 --- a/src/imagekit/types/beta/v2/file_upload_response.py +++ b/src/imagekit/types/beta/v2/file_upload_response.py @@ -130,7 +130,7 @@ class FileUploadResponse(BaseModel): this field. """ - custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) """A key-value data associated with the asset. Use `responseField` in API request to get `customMetadata` in the upload API diff --git a/src/imagekit/types/custom_metadata_field_delete_response.py b/src/imagekit/types/custom_metadata_field_delete_response.py new file mode 100644 index 0000000..247d6a9 --- /dev/null +++ b/src/imagekit/types/custom_metadata_field_delete_response.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel + +__all__ = ["CustomMetadataFieldDeleteResponse"] + + +class CustomMetadataFieldDeleteResponse(BaseModel): + pass diff --git a/src/imagekit/types/file_copy_response.py b/src/imagekit/types/file_copy_response.py new file mode 100644 index 0000000..81267b0 --- /dev/null +++ b/src/imagekit/types/file_copy_response.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel + +__all__ = ["FileCopyResponse"] + + +class FileCopyResponse(BaseModel): + pass diff --git a/src/imagekit/types/file_get_response.py b/src/imagekit/types/file_get_response.py index 8f229ae..ca7e178 100644 --- a/src/imagekit/types/file_get_response.py +++ b/src/imagekit/types/file_get_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from pydantic import Field as FieldInfo @@ -44,7 +44,7 @@ class FileGetResponse(BaseModel): custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) """An string with custom coordinates of the file.""" - custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) """An object with custom metadata for the file.""" file_id: Optional[str] = FieldInfo(alias="fileId", default=None) diff --git a/src/imagekit/types/file_move_response.py b/src/imagekit/types/file_move_response.py new file mode 100644 index 0000000..b92b949 --- /dev/null +++ b/src/imagekit/types/file_move_response.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel + +__all__ = ["FileMoveResponse"] + + +class FileMoveResponse(BaseModel): + pass diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index d47ec07..1810c39 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -2,19 +2,18 @@ from __future__ import annotations -from typing import List, Union, Iterable, Optional +from typing import Dict, List, Union, Iterable, Optional from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict from .._utils import PropertyInfo +from .shared_params.auto_tagging_extension import AutoTaggingExtension +from .shared_params.removedot_bg_extension import RemovedotBgExtension +from .shared_params.auto_description_extension import AutoDescriptionExtension __all__ = [ "FileUpdateParams", "UpdateFileDetails", "UpdateFileDetailsExtension", - "UpdateFileDetailsExtensionRemovedotBgExtension", - "UpdateFileDetailsExtensionRemovedotBgExtensionOptions", - "UpdateFileDetailsExtensionAutoTaggingExtension", - "UpdateFileDetailsExtensionAutoDescriptionExtension", "ChangePublicationStatus", "ChangePublicationStatusPublish", ] @@ -27,7 +26,7 @@ class UpdateFileDetails(TypedDict, total=False): `10,10,100,100`. Send `null` to unset this value. """ - custom_metadata: Annotated[object, PropertyInfo(alias="customMetadata")] + custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] """A key-value data to be associated with the asset. To unset a key, send `null` value for that key. Before setting any custom @@ -72,63 +71,7 @@ class UpdateFileDetails(TypedDict, total=False): """ -class UpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, total=False): - add_shadow: bool - """Whether to add an artificial shadow to the result. - - Default is false. Note: Adding shadows is currently only supported for car - photos. - """ - - bg_color: str - """ - Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or - color name (e.g., "green"). If this parameter is set, `bg_image_url` must be - empty. - """ - - bg_image_url: str - """Sets a background image from a URL. - - If this parameter is set, `bg_color` must be empty. - """ - - semitransparency: bool - """Allows semi-transparent regions in the result. - - Default is true. Note: Semitransparency is currently only supported for car - windows. - """ - - -class UpdateFileDetailsExtensionRemovedotBgExtension(TypedDict, total=False): - name: Required[Literal["remove-bg"]] - """Specifies the background removal extension.""" - - options: UpdateFileDetailsExtensionRemovedotBgExtensionOptions - - -class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): - max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] - """Maximum number of tags to attach to the asset.""" - - min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] - """Minimum confidence level for tags to be considered valid.""" - - name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] - """Specifies the auto-tagging extension used.""" - - -class UpdateFileDetailsExtensionAutoDescriptionExtension(TypedDict, total=False): - name: Required[Literal["ai-auto-description"]] - """Specifies the auto description extension.""" - - -UpdateFileDetailsExtension: TypeAlias = Union[ - UpdateFileDetailsExtensionRemovedotBgExtension, - UpdateFileDetailsExtensionAutoTaggingExtension, - UpdateFileDetailsExtensionAutoDescriptionExtension, -] +UpdateFileDetailsExtension: TypeAlias = Union[RemovedotBgExtension, AutoTaggingExtension, AutoDescriptionExtension] class ChangePublicationStatus(TypedDict, total=False): diff --git a/src/imagekit/types/file_update_response.py b/src/imagekit/types/file_update_response.py index bd9533f..3c6df6d 100644 --- a/src/imagekit/types/file_update_response.py +++ b/src/imagekit/types/file_update_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -61,7 +61,7 @@ class FileUpdateResponse(BaseModel): custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) """An string with custom coordinates of the file.""" - custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) """An object with custom metadata for the file.""" extension_status: Optional[ExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 291fbf4..292224b 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -7,14 +7,13 @@ from .._types import FileTypes from .._utils import PropertyInfo +from .shared_params.auto_tagging_extension import AutoTaggingExtension +from .shared_params.removedot_bg_extension import RemovedotBgExtension +from .shared_params.auto_description_extension import AutoDescriptionExtension __all__ = [ "FileUploadParams", "Extension", - "ExtensionRemovedotBgExtension", - "ExtensionRemovedotBgExtensionOptions", - "ExtensionAutoTaggingExtension", - "ExtensionAutoDescriptionExtension", "Transformation", "TransformationPost", "TransformationPostSimplePostTransformation", @@ -230,61 +229,7 @@ class FileUploadParams(TypedDict, total=False): """ -class ExtensionRemovedotBgExtensionOptions(TypedDict, total=False): - add_shadow: bool - """Whether to add an artificial shadow to the result. - - Default is false. Note: Adding shadows is currently only supported for car - photos. - """ - - bg_color: str - """ - Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or - color name (e.g., "green"). If this parameter is set, `bg_image_url` must be - empty. - """ - - bg_image_url: str - """Sets a background image from a URL. - - If this parameter is set, `bg_color` must be empty. - """ - - semitransparency: bool - """Allows semi-transparent regions in the result. - - Default is true. Note: Semitransparency is currently only supported for car - windows. - """ - - -class ExtensionRemovedotBgExtension(TypedDict, total=False): - name: Required[Literal["remove-bg"]] - """Specifies the background removal extension.""" - - options: ExtensionRemovedotBgExtensionOptions - - -class ExtensionAutoTaggingExtension(TypedDict, total=False): - max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] - """Maximum number of tags to attach to the asset.""" - - min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] - """Minimum confidence level for tags to be considered valid.""" - - name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] - """Specifies the auto-tagging extension used.""" - - -class ExtensionAutoDescriptionExtension(TypedDict, total=False): - name: Required[Literal["ai-auto-description"]] - """Specifies the auto description extension.""" - - -Extension: TypeAlias = Union[ - ExtensionRemovedotBgExtension, ExtensionAutoTaggingExtension, ExtensionAutoDescriptionExtension -] +Extension: TypeAlias = Union[RemovedotBgExtension, AutoTaggingExtension, AutoDescriptionExtension] class TransformationPostSimplePostTransformation(TypedDict, total=False): diff --git a/src/imagekit/types/file_upload_response.py b/src/imagekit/types/file_upload_response.py index bb9f812..a5e0d1b 100644 --- a/src/imagekit/types/file_upload_response.py +++ b/src/imagekit/types/file_upload_response.py @@ -130,7 +130,7 @@ class FileUploadResponse(BaseModel): this field. """ - custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) """A key-value data associated with the asset. Use `responseField` in API request to get `customMetadata` in the upload API diff --git a/src/imagekit/types/files/__init__.py b/src/imagekit/types/files/__init__.py index b828070..ed8f717 100644 --- a/src/imagekit/types/files/__init__.py +++ b/src/imagekit/types/files/__init__.py @@ -10,6 +10,7 @@ from .version_list_response import VersionListResponse as VersionListResponse from .bulk_add_tags_response import BulkAddTagsResponse as BulkAddTagsResponse from .bulk_remove_tags_params import BulkRemoveTagsParams as BulkRemoveTagsParams +from .version_delete_response import VersionDeleteResponse as VersionDeleteResponse from .version_restore_response import VersionRestoreResponse as VersionRestoreResponse from .bulk_remove_tags_response import BulkRemoveTagsResponse as BulkRemoveTagsResponse from .bulk_remove_ai_tags_params import BulkRemoveAITagsParams as BulkRemoveAITagsParams diff --git a/src/imagekit/types/files/version_delete_response.py b/src/imagekit/types/files/version_delete_response.py new file mode 100644 index 0000000..51b121f --- /dev/null +++ b/src/imagekit/types/files/version_delete_response.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["VersionDeleteResponse"] + + +class VersionDeleteResponse(BaseModel): + pass diff --git a/src/imagekit/types/files/version_get_response.py b/src/imagekit/types/files/version_get_response.py index f195b99..b03324c 100644 --- a/src/imagekit/types/files/version_get_response.py +++ b/src/imagekit/types/files/version_get_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from pydantic import Field as FieldInfo @@ -44,7 +44,7 @@ class VersionGetResponse(BaseModel): custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) """An string with custom coordinates of the file.""" - custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) """An object with custom metadata for the file.""" file_id: Optional[str] = FieldInfo(alias="fileId", default=None) diff --git a/src/imagekit/types/files/version_list_response.py b/src/imagekit/types/files/version_list_response.py index bbe701f..0da0fa8 100644 --- a/src/imagekit/types/files/version_list_response.py +++ b/src/imagekit/types/files/version_list_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from typing_extensions import TypeAlias from pydantic import Field as FieldInfo @@ -50,7 +50,7 @@ class VersionListResponseItem(BaseModel): custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) """An string with custom coordinates of the file.""" - custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) """An object with custom metadata for the file.""" file_id: Optional[str] = FieldInfo(alias="fileId", default=None) diff --git a/src/imagekit/types/files/version_restore_response.py b/src/imagekit/types/files/version_restore_response.py index 27bb064..b2976cd 100644 --- a/src/imagekit/types/files/version_restore_response.py +++ b/src/imagekit/types/files/version_restore_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from pydantic import Field as FieldInfo @@ -44,7 +44,7 @@ class VersionRestoreResponse(BaseModel): custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) """An string with custom coordinates of the file.""" - custom_metadata: Optional[object] = FieldInfo(alias="customMetadata", default=None) + custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) """An object with custom metadata for the file.""" file_id: Optional[str] = FieldInfo(alias="fileId", default=None) diff --git a/src/imagekit/types/folder_create_response.py b/src/imagekit/types/folder_create_response.py new file mode 100644 index 0000000..1f10670 --- /dev/null +++ b/src/imagekit/types/folder_create_response.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel + +__all__ = ["FolderCreateResponse"] + + +class FolderCreateResponse(BaseModel): + pass diff --git a/src/imagekit/types/folder_delete_response.py b/src/imagekit/types/folder_delete_response.py new file mode 100644 index 0000000..40686cb --- /dev/null +++ b/src/imagekit/types/folder_delete_response.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel + +__all__ = ["FolderDeleteResponse"] + + +class FolderDeleteResponse(BaseModel): + pass diff --git a/src/imagekit/types/shared/__init__.py b/src/imagekit/types/shared/__init__.py index 35d967c..8da285c 100644 --- a/src/imagekit/types/shared/__init__.py +++ b/src/imagekit/types/shared/__init__.py @@ -5,3 +5,6 @@ from .exif_image import ExifImage as ExifImage from .exif_details import ExifDetails as ExifDetails from .interoperability import Interoperability as Interoperability +from .auto_tagging_extension import AutoTaggingExtension as AutoTaggingExtension +from .removedot_bg_extension import RemovedotBgExtension as RemovedotBgExtension +from .auto_description_extension import AutoDescriptionExtension as AutoDescriptionExtension diff --git a/src/imagekit/types/shared/auto_description_extension.py b/src/imagekit/types/shared/auto_description_extension.py new file mode 100644 index 0000000..b62a57b --- /dev/null +++ b/src/imagekit/types/shared/auto_description_extension.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["AutoDescriptionExtension"] + + +class AutoDescriptionExtension(BaseModel): + name: Literal["ai-auto-description"] + """Specifies the auto description extension.""" diff --git a/src/imagekit/types/shared/auto_tagging_extension.py b/src/imagekit/types/shared/auto_tagging_extension.py new file mode 100644 index 0000000..3ea6063 --- /dev/null +++ b/src/imagekit/types/shared/auto_tagging_extension.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["AutoTaggingExtension"] + + +class AutoTaggingExtension(BaseModel): + max_tags: int = FieldInfo(alias="maxTags") + """Maximum number of tags to attach to the asset.""" + + min_confidence: int = FieldInfo(alias="minConfidence") + """Minimum confidence level for tags to be considered valid.""" + + name: Literal["google-auto-tagging", "aws-auto-tagging"] + """Specifies the auto-tagging extension used.""" diff --git a/src/imagekit/types/shared/removedot_bg_extension.py b/src/imagekit/types/shared/removedot_bg_extension.py new file mode 100644 index 0000000..b238436 --- /dev/null +++ b/src/imagekit/types/shared/removedot_bg_extension.py @@ -0,0 +1,44 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["RemovedotBgExtension", "Options"] + + +class Options(BaseModel): + add_shadow: Optional[bool] = None + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: Optional[str] = None + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: Optional[str] = None + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: Optional[bool] = None + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class RemovedotBgExtension(BaseModel): + name: Literal["remove-bg"] + """Specifies the background removal extension.""" + + options: Optional[Options] = None diff --git a/src/imagekit/types/shared_params/__init__.py b/src/imagekit/types/shared_params/__init__.py new file mode 100644 index 0000000..cffa993 --- /dev/null +++ b/src/imagekit/types/shared_params/__init__.py @@ -0,0 +1,5 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .auto_tagging_extension import AutoTaggingExtension as AutoTaggingExtension +from .removedot_bg_extension import RemovedotBgExtension as RemovedotBgExtension +from .auto_description_extension import AutoDescriptionExtension as AutoDescriptionExtension diff --git a/src/imagekit/types/shared_params/auto_description_extension.py b/src/imagekit/types/shared_params/auto_description_extension.py new file mode 100644 index 0000000..5243b23 --- /dev/null +++ b/src/imagekit/types/shared_params/auto_description_extension.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["AutoDescriptionExtension"] + + +class AutoDescriptionExtension(TypedDict, total=False): + name: Required[Literal["ai-auto-description"]] + """Specifies the auto description extension.""" diff --git a/src/imagekit/types/shared_params/auto_tagging_extension.py b/src/imagekit/types/shared_params/auto_tagging_extension.py new file mode 100644 index 0000000..d2a792b --- /dev/null +++ b/src/imagekit/types/shared_params/auto_tagging_extension.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["AutoTaggingExtension"] + + +class AutoTaggingExtension(TypedDict, total=False): + max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] + """Maximum number of tags to attach to the asset.""" + + min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] + """Minimum confidence level for tags to be considered valid.""" + + name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] + """Specifies the auto-tagging extension used.""" diff --git a/src/imagekit/types/shared_params/removedot_bg_extension.py b/src/imagekit/types/shared_params/removedot_bg_extension.py new file mode 100644 index 0000000..8d29832 --- /dev/null +++ b/src/imagekit/types/shared_params/removedot_bg_extension.py @@ -0,0 +1,43 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["RemovedotBgExtension", "Options"] + + +class Options(TypedDict, total=False): + add_shadow: bool + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: str + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: str + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: bool + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class RemovedotBgExtension(TypedDict, total=False): + name: Required[Literal["remove-bg"]] + """Specifies the background removal extension.""" + + options: Options diff --git a/tests/api_resources/files/test_versions.py b/tests/api_resources/files/test_versions.py index 937bf54..f9df14d 100644 --- a/tests/api_resources/files/test_versions.py +++ b/tests/api_resources/files/test_versions.py @@ -9,7 +9,7 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.files import VersionGetResponse, VersionListResponse, VersionRestoreResponse +from imagekit.types.files import VersionGetResponse, VersionListResponse, VersionDeleteResponse, VersionRestoreResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -66,7 +66,7 @@ def test_method_delete(self, client: ImageKit) -> None: version_id="versionId", file_id="fileId", ) - assert_matches_type(object, version, path=["response"]) + assert_matches_type(VersionDeleteResponse, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -79,7 +79,7 @@ def test_raw_response_delete(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() - assert_matches_type(object, version, path=["response"]) + assert_matches_type(VersionDeleteResponse, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -92,7 +92,7 @@ def test_streaming_response_delete(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() - assert_matches_type(object, version, path=["response"]) + assert_matches_type(VersionDeleteResponse, version, path=["response"]) assert cast(Any, response.is_closed) is True @@ -270,7 +270,7 @@ async def test_method_delete(self, async_client: AsyncImageKit) -> None: version_id="versionId", file_id="fileId", ) - assert_matches_type(object, version, path=["response"]) + assert_matches_type(VersionDeleteResponse, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -283,7 +283,7 @@ async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = await response.parse() - assert_matches_type(object, version, path=["response"]) + assert_matches_type(VersionDeleteResponse, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -296,7 +296,7 @@ async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = await response.parse() - assert_matches_type(object, version, path=["response"]) + assert_matches_type(VersionDeleteResponse, version, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_custom_metadata_fields.py b/tests/api_resources/test_custom_metadata_fields.py index 8f454cf..77adcf5 100644 --- a/tests/api_resources/test_custom_metadata_fields.py +++ b/tests/api_resources/test_custom_metadata_fields.py @@ -12,6 +12,7 @@ from imagekit.types import ( CustomMetadataFieldListResponse, CustomMetadataFieldCreateResponse, + CustomMetadataFieldDeleteResponse, CustomMetadataFieldUpdateResponse, ) @@ -182,7 +183,7 @@ def test_method_delete(self, client: ImageKit) -> None: custom_metadata_field = client.custom_metadata_fields.delete( "id", ) - assert_matches_type(object, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataFieldDeleteResponse, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -194,7 +195,7 @@ def test_raw_response_delete(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = response.parse() - assert_matches_type(object, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataFieldDeleteResponse, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -206,7 +207,7 @@ def test_streaming_response_delete(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = response.parse() - assert_matches_type(object, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataFieldDeleteResponse, custom_metadata_field, path=["response"]) assert cast(Any, response.is_closed) is True @@ -385,7 +386,7 @@ async def test_method_delete(self, async_client: AsyncImageKit) -> None: custom_metadata_field = await async_client.custom_metadata_fields.delete( "id", ) - assert_matches_type(object, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataFieldDeleteResponse, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -397,7 +398,7 @@ async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = await response.parse() - assert_matches_type(object, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataFieldDeleteResponse, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -409,7 +410,7 @@ async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = await response.parse() - assert_matches_type(object, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataFieldDeleteResponse, custom_metadata_field, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index f56c498..a05d6e2 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -11,6 +11,8 @@ from tests.utils import assert_matches_type from imagekit.types import ( FileGetResponse, + FileCopyResponse, + FileMoveResponse, FileRenameResponse, FileUpdateResponse, FileUploadResponse, @@ -36,7 +38,7 @@ def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> Non file = client.files.update( file_id="fileId", custom_coordinates="customCoordinates", - custom_metadata={}, + custom_metadata={"foo": "bar"}, description="description", extensions=[ { @@ -192,7 +194,7 @@ def test_method_copy(self, client: ImageKit) -> None: destination_path="/folder/to/copy/into/", source_file_path="/path/to/file.jpg", ) - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileCopyResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -202,7 +204,7 @@ def test_method_copy_with_all_params(self, client: ImageKit) -> None: source_file_path="/path/to/file.jpg", include_file_versions=False, ) - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileCopyResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -215,7 +217,7 @@ def test_raw_response_copy(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileCopyResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -228,7 +230,7 @@ def test_streaming_response_copy(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileCopyResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @@ -281,7 +283,7 @@ def test_method_move(self, client: ImageKit) -> None: destination_path="/folder/to/move/into/", source_file_path="/path/to/file.jpg", ) - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileMoveResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -294,7 +296,7 @@ def test_raw_response_move(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileMoveResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -307,7 +309,7 @@ def test_streaming_response_move(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileMoveResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @@ -476,7 +478,7 @@ async def test_method_update_with_all_params_overload_1(self, async_client: Asyn file = await async_client.files.update( file_id="fileId", custom_coordinates="customCoordinates", - custom_metadata={}, + custom_metadata={"foo": "bar"}, description="description", extensions=[ { @@ -632,7 +634,7 @@ async def test_method_copy(self, async_client: AsyncImageKit) -> None: destination_path="/folder/to/copy/into/", source_file_path="/path/to/file.jpg", ) - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileCopyResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -642,7 +644,7 @@ async def test_method_copy_with_all_params(self, async_client: AsyncImageKit) -> source_file_path="/path/to/file.jpg", include_file_versions=False, ) - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileCopyResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -655,7 +657,7 @@ async def test_raw_response_copy(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileCopyResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -668,7 +670,7 @@ async def test_streaming_response_copy(self, async_client: AsyncImageKit) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileCopyResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @@ -721,7 +723,7 @@ async def test_method_move(self, async_client: AsyncImageKit) -> None: destination_path="/folder/to/move/into/", source_file_path="/path/to/file.jpg", ) - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileMoveResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -734,7 +736,7 @@ async def test_raw_response_move(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileMoveResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -747,7 +749,7 @@ async def test_streaming_response_move(self, async_client: AsyncImageKit) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(object, file, path=["response"]) + assert_matches_type(FileMoveResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_folders.py b/tests/api_resources/test_folders.py index 917f172..de14df0 100644 --- a/tests/api_resources/test_folders.py +++ b/tests/api_resources/test_folders.py @@ -12,6 +12,8 @@ from imagekit.types import ( FolderCopyResponse, FolderMoveResponse, + FolderCreateResponse, + FolderDeleteResponse, FolderRenameResponse, ) @@ -28,7 +30,7 @@ def test_method_create(self, client: ImageKit) -> None: folder_name="summer", parent_folder_path="/product/images/", ) - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderCreateResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -41,7 +43,7 @@ def test_raw_response_create(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderCreateResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -54,7 +56,7 @@ def test_streaming_response_create(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderCreateResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -64,7 +66,7 @@ def test_method_delete(self, client: ImageKit) -> None: folder = client.folders.delete( folder_path="/folder/to/delete/", ) - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderDeleteResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -76,7 +78,7 @@ def test_raw_response_delete(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderDeleteResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -88,7 +90,7 @@ def test_streaming_response_delete(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderDeleteResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -236,7 +238,7 @@ async def test_method_create(self, async_client: AsyncImageKit) -> None: folder_name="summer", parent_folder_path="/product/images/", ) - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderCreateResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -249,7 +251,7 @@ async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderCreateResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -262,7 +264,7 @@ async def test_streaming_response_create(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderCreateResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -272,7 +274,7 @@ async def test_method_delete(self, async_client: AsyncImageKit) -> None: folder = await async_client.folders.delete( folder_path="/folder/to/delete/", ) - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderDeleteResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -284,7 +286,7 @@ async def test_raw_response_delete(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderDeleteResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -296,7 +298,7 @@ async def test_streaming_response_delete(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(object, folder, path=["response"]) + assert_matches_type(FolderDeleteResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True From 2de3a40b0083c410ac841487b671e5f780e428d9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 03:58:31 +0000 Subject: [PATCH 009/177] chore: update github action --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc0291c..366eea7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: run: ./scripts/lint build: - if: github.repository == 'stainless-sdks/imagekit-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork) + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork timeout-minutes: 10 name: build permissions: @@ -61,12 +61,14 @@ jobs: run: rye build - name: Get GitHub OIDC Token + if: github.repository == 'stainless-sdks/imagekit-python' id: github-oidc uses: actions/github-script@v6 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Upload tarball + if: github.repository == 'stainless-sdks/imagekit-python' env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} From d5fb29cfa52edd5ecbd9d466192fcb9638548522 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 06:53:38 +0000 Subject: [PATCH 010/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 13 +++ pyproject.toml | 1 + requirements-dev.lock | 13 +++ requirements.lock | 16 +++ src/imagekit/__init__.py | 2 + src/imagekit/_client.py | 6 +- src/imagekit/_exceptions.py | 4 + src/imagekit/resources/__init__.py | 3 + src/imagekit/resources/webhooks.py | 69 ++++++++++++ src/imagekit/types/__init__.py | 10 ++ src/imagekit/types/unwrap_webhook_event.py | 14 +++ ...o_transformation_accepted_webhook_event.py | 73 ++++++++++++ ...ideo_transformation_error_webhook_event.py | 80 ++++++++++++++ ...ideo_transformation_ready_webhook_event.py | 104 ++++++++++++++++++ tests/api_resources/test_webhooks.py | 79 +++++++++++++ 16 files changed, 487 insertions(+), 2 deletions(-) create mode 100644 src/imagekit/resources/webhooks.py create mode 100644 src/imagekit/types/unwrap_webhook_event.py create mode 100644 src/imagekit/types/video_transformation_accepted_webhook_event.py create mode 100644 src/imagekit/types/video_transformation_error_webhook_event.py create mode 100644 src/imagekit/types/video_transformation_ready_webhook_event.py create mode 100644 tests/api_resources/test_webhooks.py diff --git a/.stats.yml b/.stats.yml index 456c477..94f1f4d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-584c2ccf3fc1a3ff3abf26b8d3dace2398d0f9ed6f20e4c411a13a81febb5e98.yml openapi_spec_hash: 14d1614ea3903d6b53f26e135c9cae81 -config_hash: 7e5c039f375ccdba7cf3e61492a273f2 +config_hash: 984f0887e4e3ebc749cd79d0512fea75 diff --git a/api.md b/api.md index f9a64a2..0ff7a74 100644 --- a/api.md +++ b/api.md @@ -243,3 +243,16 @@ from imagekit.types.beta.v2 import FileUploadResponse Methods: - client.beta.v2.files.upload(\*\*params) -> FileUploadResponse + +# Webhooks + +Types: + +```python +from imagekit.types import ( + VideoTransformationAcceptedWebhookEvent, + VideoTransformationReadyWebhookEvent, + VideoTransformationErrorWebhookEvent, + UnwrapWebhookEvent, +) +``` diff --git a/pyproject.toml b/pyproject.toml index 68e2646..c3c06b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ Repository = "https://github.com/stainless-sdks/imagekit-python" [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] +webhooks = ["standardwebhooks"] [tool.rye] managed = true diff --git a/requirements-dev.lock b/requirements-dev.lock index 2d04bf1..396ac99 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -28,11 +28,14 @@ async-timeout==5.0.1 # via aiohttp attrs==25.3.0 # via aiohttp + # via standardwebhooks certifi==2023.7.22 # via httpcore # via httpx colorlog==6.7.0 # via nox +deprecated==1.2.18 + # via standardwebhooks dirty-equals==0.6.0 distlib==0.3.7 # via virtualenv @@ -56,6 +59,7 @@ httpx==0.28.1 # via httpx-aiohttp # via imagekit # via respx + # via standardwebhooks httpx-aiohttp==0.1.8 # via imagekit idna==3.4 @@ -102,6 +106,7 @@ pytest==8.3.3 pytest-asyncio==0.24.0 pytest-xdist==3.7.0 python-dateutil==2.8.2 + # via standardwebhooks # via time-machine pytz==2023.3.post1 # via dirty-equals @@ -115,10 +120,16 @@ six==1.16.0 sniffio==1.3.0 # via anyio # via imagekit +standardwebhooks==1.0.0 + # via imagekit time-machine==2.9.0 tomli==2.0.2 # via mypy # via pytest +types-deprecated==1.2.15.20250304 + # via standardwebhooks +types-python-dateutil==2.9.0.20250822 + # via standardwebhooks typing-extensions==4.12.2 # via anyio # via imagekit @@ -129,6 +140,8 @@ typing-extensions==4.12.2 # via pyright virtualenv==20.24.5 # via nox +wrapt==1.17.3 + # via deprecated yarl==1.20.0 # via aiohttp zipp==3.17.0 diff --git a/requirements.lock b/requirements.lock index 85ed03b..a922302 100644 --- a/requirements.lock +++ b/requirements.lock @@ -26,9 +26,12 @@ async-timeout==5.0.1 # via aiohttp attrs==25.3.0 # via aiohttp + # via standardwebhooks certifi==2023.7.22 # via httpcore # via httpx +deprecated==1.2.18 + # via standardwebhooks distro==1.8.0 # via imagekit exceptiongroup==1.2.2 @@ -43,6 +46,7 @@ httpcore==1.0.9 httpx==0.28.1 # via httpx-aiohttp # via imagekit + # via standardwebhooks httpx-aiohttp==0.1.8 # via imagekit idna==3.4 @@ -59,14 +63,26 @@ pydantic==2.10.3 # via imagekit pydantic-core==2.27.1 # via pydantic +python-dateutil==2.9.0.post0 + # via standardwebhooks +six==1.17.0 + # via python-dateutil sniffio==1.3.0 # via anyio # via imagekit +standardwebhooks==1.0.0 + # via imagekit +types-deprecated==1.2.15.20250304 + # via standardwebhooks +types-python-dateutil==2.9.0.20250822 + # via standardwebhooks typing-extensions==4.12.2 # via anyio # via imagekit # via multidict # via pydantic # via pydantic-core +wrapt==1.17.3 + # via deprecated yarl==1.20.0 # via aiohttp diff --git a/src/imagekit/__init__.py b/src/imagekit/__init__.py index 07a48e8..43d69f6 100644 --- a/src/imagekit/__init__.py +++ b/src/imagekit/__init__.py @@ -34,6 +34,7 @@ InternalServerError, PermissionDeniedError, UnprocessableEntityError, + APIWebhookValidationError, APIResponseValidationError, ) from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient @@ -55,6 +56,7 @@ "APITimeoutError", "APIConnectionError", "APIResponseValidationError", + "APIWebhookValidationError", "BadRequestError", "AuthenticationError", "PermissionDeniedError", diff --git a/src/imagekit/_client.py b/src/imagekit/_client.py index e672ca9..4478350 100644 --- a/src/imagekit/_client.py +++ b/src/imagekit/_client.py @@ -23,7 +23,7 @@ ) from ._utils import is_given, get_async_library from ._version import __version__ -from .resources import assets, custom_metadata_fields +from .resources import assets, webhooks, custom_metadata_fields from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import ImageKitError, APIStatusError from ._base_client import ( @@ -57,6 +57,7 @@ class ImageKit(SyncAPIClient): folders: folders.FoldersResource accounts: accounts.AccountsResource beta: beta.BetaResource + webhooks: webhooks.WebhooksResource with_raw_response: ImageKitWithRawResponse with_streaming_response: ImageKitWithStreamedResponse @@ -130,6 +131,7 @@ def __init__( self.folders = folders.FoldersResource(self) self.accounts = accounts.AccountsResource(self) self.beta = beta.BetaResource(self) + self.webhooks = webhooks.WebhooksResource(self) self.with_raw_response = ImageKitWithRawResponse(self) self.with_streaming_response = ImageKitWithStreamedResponse(self) @@ -264,6 +266,7 @@ class AsyncImageKit(AsyncAPIClient): folders: folders.AsyncFoldersResource accounts: accounts.AsyncAccountsResource beta: beta.AsyncBetaResource + webhooks: webhooks.AsyncWebhooksResource with_raw_response: AsyncImageKitWithRawResponse with_streaming_response: AsyncImageKitWithStreamedResponse @@ -337,6 +340,7 @@ def __init__( self.folders = folders.AsyncFoldersResource(self) self.accounts = accounts.AsyncAccountsResource(self) self.beta = beta.AsyncBetaResource(self) + self.webhooks = webhooks.AsyncWebhooksResource(self) self.with_raw_response = AsyncImageKitWithRawResponse(self) self.with_streaming_response = AsyncImageKitWithStreamedResponse(self) diff --git a/src/imagekit/_exceptions.py b/src/imagekit/_exceptions.py index 990ca06..364ab5a 100644 --- a/src/imagekit/_exceptions.py +++ b/src/imagekit/_exceptions.py @@ -54,6 +54,10 @@ def __init__(self, response: httpx.Response, body: object | None, *, message: st self.status_code = response.status_code +class APIWebhookValidationError(APIError): + pass + + class APIStatusError(APIError): """Raised when an API response has a status code of 4xx or 5xx.""" diff --git a/src/imagekit/resources/__init__.py b/src/imagekit/resources/__init__.py index 6c6a8b6..39999ec 100644 --- a/src/imagekit/resources/__init__.py +++ b/src/imagekit/resources/__init__.py @@ -48,6 +48,7 @@ AccountsResourceWithStreamingResponse, AsyncAccountsResourceWithStreamingResponse, ) +from .webhooks import WebhooksResource, AsyncWebhooksResource from .custom_metadata_fields import ( CustomMetadataFieldsResource, AsyncCustomMetadataFieldsResource, @@ -100,4 +101,6 @@ "AsyncBetaResourceWithRawResponse", "BetaResourceWithStreamingResponse", "AsyncBetaResourceWithStreamingResponse", + "WebhooksResource", + "AsyncWebhooksResource", ] diff --git a/src/imagekit/resources/webhooks.py b/src/imagekit/resources/webhooks.py new file mode 100644 index 0000000..eff046c --- /dev/null +++ b/src/imagekit/resources/webhooks.py @@ -0,0 +1,69 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import json +from typing import Mapping, cast + +from .._models import construct_type +from .._resource import SyncAPIResource, AsyncAPIResource +from .._exceptions import ImageKitError +from ..types.unwrap_webhook_event import UnwrapWebhookEvent + +__all__ = ["WebhooksResource", "AsyncWebhooksResource"] + + +class WebhooksResource(SyncAPIResource): + def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | None = None) -> UnwrapWebhookEvent: + try: + from standardwebhooks import Webhook + except ImportError as exc: + raise ImageKitError("You need to install `imagekit[webhooks]` to use this method") from exc + + if key is None: + key = self._client.private_api_key + if key is None: + raise ValueError( + "Cannot verify a webhook without a key on either the client's private_api_key or passed in as an argument" + ) + + if not isinstance(headers, dict): + headers = dict(headers) + + Webhook(key).verify(payload, headers) + + return cast( + UnwrapWebhookEvent, + construct_type( + type_=UnwrapWebhookEvent, + value=json.loads(payload), + ), + ) + + +class AsyncWebhooksResource(AsyncAPIResource): + def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | None = None) -> UnwrapWebhookEvent: + try: + from standardwebhooks import Webhook + except ImportError as exc: + raise ImageKitError("You need to install `imagekit[webhooks]` to use this method") from exc + + if key is None: + key = self._client.private_api_key + if key is None: + raise ValueError( + "Cannot verify a webhook without a key on either the client's private_api_key or passed in as an argument" + ) + + if not isinstance(headers, dict): + headers = dict(headers) + + Webhook(key).verify(payload, headers) + + return cast( + UnwrapWebhookEvent, + construct_type( + type_=UnwrapWebhookEvent, + value=json.loads(payload), + ), + ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 1517fc1..f6fa307 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -32,6 +32,7 @@ from .folder_delete_params import FolderDeleteParams as FolderDeleteParams from .folder_move_response import FolderMoveResponse as FolderMoveResponse from .folder_rename_params import FolderRenameParams as FolderRenameParams +from .unwrap_webhook_event import UnwrapWebhookEvent as UnwrapWebhookEvent from .folder_create_response import FolderCreateResponse as FolderCreateResponse from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse from .folder_rename_response import FolderRenameResponse as FolderRenameResponse @@ -48,3 +49,12 @@ from .custom_metadata_field_update_response import ( CustomMetadataFieldUpdateResponse as CustomMetadataFieldUpdateResponse, ) +from .video_transformation_error_webhook_event import ( + VideoTransformationErrorWebhookEvent as VideoTransformationErrorWebhookEvent, +) +from .video_transformation_ready_webhook_event import ( + VideoTransformationReadyWebhookEvent as VideoTransformationReadyWebhookEvent, +) +from .video_transformation_accepted_webhook_event import ( + VideoTransformationAcceptedWebhookEvent as VideoTransformationAcceptedWebhookEvent, +) diff --git a/src/imagekit/types/unwrap_webhook_event.py b/src/imagekit/types/unwrap_webhook_event.py new file mode 100644 index 0000000..b87f119 --- /dev/null +++ b/src/imagekit/types/unwrap_webhook_event.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union +from typing_extensions import TypeAlias + +from .video_transformation_error_webhook_event import VideoTransformationErrorWebhookEvent +from .video_transformation_ready_webhook_event import VideoTransformationReadyWebhookEvent +from .video_transformation_accepted_webhook_event import VideoTransformationAcceptedWebhookEvent + +__all__ = ["UnwrapWebhookEvent"] + +UnwrapWebhookEvent: TypeAlias = Union[ + VideoTransformationAcceptedWebhookEvent, VideoTransformationReadyWebhookEvent, VideoTransformationErrorWebhookEvent +] diff --git a/src/imagekit/types/video_transformation_accepted_webhook_event.py b/src/imagekit/types/video_transformation_accepted_webhook_event.py new file mode 100644 index 0000000..58dc145 --- /dev/null +++ b/src/imagekit/types/video_transformation_accepted_webhook_event.py @@ -0,0 +1,73 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = [ + "VideoTransformationAcceptedWebhookEvent", + "Data", + "DataAsset", + "DataTransformation", + "DataTransformationOptions", + "Request", +] + + +class DataAsset(BaseModel): + url: str + """Source asset URL.""" + + +class DataTransformationOptions(BaseModel): + audio_codec: Optional[Literal["aac", "opus"]] = None + + auto_rotate: Optional[bool] = None + + format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + + quality: Optional[int] = None + + stream_protocol: Optional[Literal["HLS", "DASH"]] = None + + variants: Optional[List[str]] = None + + video_codec: Optional[Literal["h264", "vp9"]] = None + + +class DataTransformation(BaseModel): + type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + + options: Optional[DataTransformationOptions] = None + + +class Data(BaseModel): + asset: DataAsset + + transformation: DataTransformation + + +class Request(BaseModel): + url: str + """URL of the submitted request.""" + + x_request_id: str + """Unique ID for the originating request.""" + + user_agent: Optional[str] = None + """User-Agent header of the originating request.""" + + +class VideoTransformationAcceptedWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + + data: Data + + request: Request + + type: Literal["video.transformation.accepted"] diff --git a/src/imagekit/types/video_transformation_error_webhook_event.py b/src/imagekit/types/video_transformation_error_webhook_event.py new file mode 100644 index 0000000..ce29cc9 --- /dev/null +++ b/src/imagekit/types/video_transformation_error_webhook_event.py @@ -0,0 +1,80 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = [ + "VideoTransformationErrorWebhookEvent", + "Data", + "DataAsset", + "DataTransformation", + "DataTransformationError", + "DataTransformationOptions", + "Request", +] + + +class DataAsset(BaseModel): + url: str + """Source asset URL.""" + + +class DataTransformationError(BaseModel): + reason: Literal["encoding_failed", "download_failed", "internal_server_error"] + + +class DataTransformationOptions(BaseModel): + audio_codec: Optional[Literal["aac", "opus"]] = None + + auto_rotate: Optional[bool] = None + + format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + + quality: Optional[int] = None + + stream_protocol: Optional[Literal["HLS", "DASH"]] = None + + variants: Optional[List[str]] = None + + video_codec: Optional[Literal["h264", "vp9"]] = None + + +class DataTransformation(BaseModel): + type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + + error: Optional[DataTransformationError] = None + + options: Optional[DataTransformationOptions] = None + + +class Data(BaseModel): + asset: DataAsset + + transformation: DataTransformation + + +class Request(BaseModel): + url: str + """URL of the submitted request.""" + + x_request_id: str + """Unique ID for the originating request.""" + + user_agent: Optional[str] = None + """User-Agent header of the originating request.""" + + +class VideoTransformationErrorWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + + data: Data + + request: Request + + type: Literal["video.transformation.error"] diff --git a/src/imagekit/types/video_transformation_ready_webhook_event.py b/src/imagekit/types/video_transformation_ready_webhook_event.py new file mode 100644 index 0000000..6935733 --- /dev/null +++ b/src/imagekit/types/video_transformation_ready_webhook_event.py @@ -0,0 +1,104 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = [ + "VideoTransformationReadyWebhookEvent", + "Data", + "DataAsset", + "DataTransformation", + "DataTransformationOptions", + "DataTransformationOutput", + "DataTransformationOutputVideoMetadata", + "Request", + "Timings", +] + + +class DataAsset(BaseModel): + url: str + """Source asset URL.""" + + +class DataTransformationOptions(BaseModel): + audio_codec: Optional[Literal["aac", "opus"]] = None + + auto_rotate: Optional[bool] = None + + format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + + quality: Optional[int] = None + + stream_protocol: Optional[Literal["HLS", "DASH"]] = None + + variants: Optional[List[str]] = None + + video_codec: Optional[Literal["h264", "vp9"]] = None + + +class DataTransformationOutputVideoMetadata(BaseModel): + bitrate: int + + duration: float + + height: int + + width: int + + +class DataTransformationOutput(BaseModel): + url: str + + video_metadata: Optional[DataTransformationOutputVideoMetadata] = None + + +class DataTransformation(BaseModel): + type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + + options: Optional[DataTransformationOptions] = None + + output: Optional[DataTransformationOutput] = None + + +class Data(BaseModel): + asset: DataAsset + + transformation: DataTransformation + + +class Request(BaseModel): + url: str + """URL of the submitted request.""" + + x_request_id: str + """Unique ID for the originating request.""" + + user_agent: Optional[str] = None + """User-Agent header of the originating request.""" + + +class Timings(BaseModel): + download_duration: Optional[int] = None + """Milliseconds spent downloading the source.""" + + encoding_duration: Optional[int] = None + """Milliseconds spent encoding.""" + + +class VideoTransformationReadyWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + + data: Data + + request: Request + + type: Literal["video.transformation.ready"] + + timings: Optional[Timings] = None diff --git a/tests/api_resources/test_webhooks.py b/tests/api_resources/test_webhooks.py new file mode 100644 index 0000000..d12bd64 --- /dev/null +++ b/tests/api_resources/test_webhooks.py @@ -0,0 +1,79 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from datetime import datetime, timezone + +import pytest +import standardwebhooks + +from imagekit import ImageKit + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestWebhooks: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + def test_method_unwrap(self, client: ImageKit) -> None: + key = b"secret" + hook = standardwebhooks.Webhook(key) + + data = """{"id":"id","created_at":"2019-12-27T18:11:19.117Z","data":{"asset":{"url":"https://example.com"},"transformation":{"type":"video-transformation","options":{"audio_codec":"aac","auto_rotate":true,"format":"mp4","quality":0,"stream_protocol":"HLS","variants":["string"],"video_codec":"h264"}}},"request":{"url":"https://example.com","x_request_id":"x_request_id","user_agent":"user_agent"},"type":"video.transformation.accepted"}""" + msg_id = "1" + timestamp = datetime.now(tz=timezone.utc) + sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data) + headers = { + "webhook-id": msg_id, + "webhook-timestamp": str(int(timestamp.timestamp())), + "webhook-signature": sig, + } + + try: + _ = client.webhooks.unwrap(data, headers=headers, key=key) + except standardwebhooks.WebhookVerificationError as e: + raise AssertionError("Failed to unwrap valid webhook") from e + + bad_headers = [ + {**headers, "webhook-signature": hook.sign(msg_id=msg_id, timestamp=timestamp, data="xxx")}, + {**headers, "webhook-id": "bad"}, + {**headers, "webhook-timestamp": "0"}, + ] + for bad_header in bad_headers: + with pytest.raises(standardwebhooks.WebhookVerificationError): + _ = client.webhooks.unwrap(data, headers=bad_header, key=key) + + +class TestAsyncWebhooks: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + def test_method_unwrap(self, client: ImageKit) -> None: + key = b"secret" + hook = standardwebhooks.Webhook(key) + + data = """{"id":"id","created_at":"2019-12-27T18:11:19.117Z","data":{"asset":{"url":"https://example.com"},"transformation":{"type":"video-transformation","options":{"audio_codec":"aac","auto_rotate":true,"format":"mp4","quality":0,"stream_protocol":"HLS","variants":["string"],"video_codec":"h264"}}},"request":{"url":"https://example.com","x_request_id":"x_request_id","user_agent":"user_agent"},"type":"video.transformation.accepted"}""" + msg_id = "1" + timestamp = datetime.now(tz=timezone.utc) + sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data) + headers = { + "webhook-id": msg_id, + "webhook-timestamp": str(int(timestamp.timestamp())), + "webhook-signature": sig, + } + + try: + _ = client.webhooks.unwrap(data, headers=headers, key=key) + except standardwebhooks.WebhookVerificationError as e: + raise AssertionError("Failed to unwrap valid webhook") from e + + bad_headers = [ + {**headers, "webhook-signature": hook.sign(msg_id=msg_id, timestamp=timestamp, data="xxx")}, + {**headers, "webhook-id": "bad"}, + {**headers, "webhook-timestamp": "0"}, + ] + for bad_header in bad_headers: + with pytest.raises(standardwebhooks.WebhookVerificationError): + _ = client.webhooks.unwrap(data, headers=bad_header, key=key) From 0b8c3b67feba83eabfaadd89adb698133c03b4fa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 07:46:25 +0000 Subject: [PATCH 011/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 4 + src/imagekit/resources/webhooks.py | 19 ++++ src/imagekit/types/__init__.py | 1 + .../types/unsafe_unwrap_webhook_event.py | 14 +++ ..._transformation_accepted_webhook_event1.py | 73 ++++++++++++ ...deo_transformation_error_webhook_event1.py | 80 ++++++++++++++ ...deo_transformation_ready_webhook_event1.py | 104 ++++++++++++++++++ 8 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 src/imagekit/types/unsafe_unwrap_webhook_event.py create mode 100644 src/imagekit/types/video_transformation_accepted_webhook_event1.py create mode 100644 src/imagekit/types/video_transformation_error_webhook_event1.py create mode 100644 src/imagekit/types/video_transformation_ready_webhook_event1.py diff --git a/.stats.yml b/.stats.yml index 94f1f4d..ede64f5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-584c2ccf3fc1a3ff3abf26b8d3dace2398d0f9ed6f20e4c411a13a81febb5e98.yml openapi_spec_hash: 14d1614ea3903d6b53f26e135c9cae81 -config_hash: 984f0887e4e3ebc749cd79d0512fea75 +config_hash: 9f3c729a01b07940df835ef5ec13119a diff --git a/api.md b/api.md index 0ff7a74..7bd2e9e 100644 --- a/api.md +++ b/api.md @@ -253,6 +253,10 @@ from imagekit.types import ( VideoTransformationAcceptedWebhookEvent, VideoTransformationReadyWebhookEvent, VideoTransformationErrorWebhookEvent, + VideoTransformationAcceptedWebhookEvent, + VideoTransformationReadyWebhookEvent, + VideoTransformationErrorWebhookEvent, + UnsafeUnwrapWebhookEvent, UnwrapWebhookEvent, ) ``` diff --git a/src/imagekit/resources/webhooks.py b/src/imagekit/resources/webhooks.py index eff046c..dce279e 100644 --- a/src/imagekit/resources/webhooks.py +++ b/src/imagekit/resources/webhooks.py @@ -9,11 +9,21 @@ from .._resource import SyncAPIResource, AsyncAPIResource from .._exceptions import ImageKitError from ..types.unwrap_webhook_event import UnwrapWebhookEvent +from ..types.unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent __all__ = ["WebhooksResource", "AsyncWebhooksResource"] class WebhooksResource(SyncAPIResource): + def unsafe_unwrap(self, payload: str) -> UnsafeUnwrapWebhookEvent: + return cast( + UnsafeUnwrapWebhookEvent, + construct_type( + type_=UnsafeUnwrapWebhookEvent, + value=json.loads(payload), + ), + ) + def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | None = None) -> UnwrapWebhookEvent: try: from standardwebhooks import Webhook @@ -42,6 +52,15 @@ def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | class AsyncWebhooksResource(AsyncAPIResource): + def unsafe_unwrap(self, payload: str) -> UnsafeUnwrapWebhookEvent: + return cast( + UnsafeUnwrapWebhookEvent, + construct_type( + type_=UnsafeUnwrapWebhookEvent, + value=json.loads(payload), + ), + ) + def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | None = None) -> UnwrapWebhookEvent: try: from standardwebhooks import Webhook diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index f6fa307..ac7baed 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -36,6 +36,7 @@ from .folder_create_response import FolderCreateResponse as FolderCreateResponse from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse from .folder_rename_response import FolderRenameResponse as FolderRenameResponse +from .unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent as UnsafeUnwrapWebhookEvent from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams from .custom_metadata_field_list_response import CustomMetadataFieldListResponse as CustomMetadataFieldListResponse diff --git a/src/imagekit/types/unsafe_unwrap_webhook_event.py b/src/imagekit/types/unsafe_unwrap_webhook_event.py new file mode 100644 index 0000000..eb7cc05 --- /dev/null +++ b/src/imagekit/types/unsafe_unwrap_webhook_event.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union +from typing_extensions import TypeAlias + +from .video_transformation_error_webhook_event import VideoTransformationErrorWebhookEvent +from .video_transformation_ready_webhook_event import VideoTransformationReadyWebhookEvent +from .video_transformation_accepted_webhook_event import VideoTransformationAcceptedWebhookEvent + +__all__ = ["UnsafeUnwrapWebhookEvent"] + +UnsafeUnwrapWebhookEvent: TypeAlias = Union[ + VideoTransformationAcceptedWebhookEvent, VideoTransformationReadyWebhookEvent, VideoTransformationErrorWebhookEvent +] diff --git a/src/imagekit/types/video_transformation_accepted_webhook_event1.py b/src/imagekit/types/video_transformation_accepted_webhook_event1.py new file mode 100644 index 0000000..58dc145 --- /dev/null +++ b/src/imagekit/types/video_transformation_accepted_webhook_event1.py @@ -0,0 +1,73 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = [ + "VideoTransformationAcceptedWebhookEvent", + "Data", + "DataAsset", + "DataTransformation", + "DataTransformationOptions", + "Request", +] + + +class DataAsset(BaseModel): + url: str + """Source asset URL.""" + + +class DataTransformationOptions(BaseModel): + audio_codec: Optional[Literal["aac", "opus"]] = None + + auto_rotate: Optional[bool] = None + + format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + + quality: Optional[int] = None + + stream_protocol: Optional[Literal["HLS", "DASH"]] = None + + variants: Optional[List[str]] = None + + video_codec: Optional[Literal["h264", "vp9"]] = None + + +class DataTransformation(BaseModel): + type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + + options: Optional[DataTransformationOptions] = None + + +class Data(BaseModel): + asset: DataAsset + + transformation: DataTransformation + + +class Request(BaseModel): + url: str + """URL of the submitted request.""" + + x_request_id: str + """Unique ID for the originating request.""" + + user_agent: Optional[str] = None + """User-Agent header of the originating request.""" + + +class VideoTransformationAcceptedWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + + data: Data + + request: Request + + type: Literal["video.transformation.accepted"] diff --git a/src/imagekit/types/video_transformation_error_webhook_event1.py b/src/imagekit/types/video_transformation_error_webhook_event1.py new file mode 100644 index 0000000..ce29cc9 --- /dev/null +++ b/src/imagekit/types/video_transformation_error_webhook_event1.py @@ -0,0 +1,80 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = [ + "VideoTransformationErrorWebhookEvent", + "Data", + "DataAsset", + "DataTransformation", + "DataTransformationError", + "DataTransformationOptions", + "Request", +] + + +class DataAsset(BaseModel): + url: str + """Source asset URL.""" + + +class DataTransformationError(BaseModel): + reason: Literal["encoding_failed", "download_failed", "internal_server_error"] + + +class DataTransformationOptions(BaseModel): + audio_codec: Optional[Literal["aac", "opus"]] = None + + auto_rotate: Optional[bool] = None + + format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + + quality: Optional[int] = None + + stream_protocol: Optional[Literal["HLS", "DASH"]] = None + + variants: Optional[List[str]] = None + + video_codec: Optional[Literal["h264", "vp9"]] = None + + +class DataTransformation(BaseModel): + type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + + error: Optional[DataTransformationError] = None + + options: Optional[DataTransformationOptions] = None + + +class Data(BaseModel): + asset: DataAsset + + transformation: DataTransformation + + +class Request(BaseModel): + url: str + """URL of the submitted request.""" + + x_request_id: str + """Unique ID for the originating request.""" + + user_agent: Optional[str] = None + """User-Agent header of the originating request.""" + + +class VideoTransformationErrorWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + + data: Data + + request: Request + + type: Literal["video.transformation.error"] diff --git a/src/imagekit/types/video_transformation_ready_webhook_event1.py b/src/imagekit/types/video_transformation_ready_webhook_event1.py new file mode 100644 index 0000000..6935733 --- /dev/null +++ b/src/imagekit/types/video_transformation_ready_webhook_event1.py @@ -0,0 +1,104 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = [ + "VideoTransformationReadyWebhookEvent", + "Data", + "DataAsset", + "DataTransformation", + "DataTransformationOptions", + "DataTransformationOutput", + "DataTransformationOutputVideoMetadata", + "Request", + "Timings", +] + + +class DataAsset(BaseModel): + url: str + """Source asset URL.""" + + +class DataTransformationOptions(BaseModel): + audio_codec: Optional[Literal["aac", "opus"]] = None + + auto_rotate: Optional[bool] = None + + format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + + quality: Optional[int] = None + + stream_protocol: Optional[Literal["HLS", "DASH"]] = None + + variants: Optional[List[str]] = None + + video_codec: Optional[Literal["h264", "vp9"]] = None + + +class DataTransformationOutputVideoMetadata(BaseModel): + bitrate: int + + duration: float + + height: int + + width: int + + +class DataTransformationOutput(BaseModel): + url: str + + video_metadata: Optional[DataTransformationOutputVideoMetadata] = None + + +class DataTransformation(BaseModel): + type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + + options: Optional[DataTransformationOptions] = None + + output: Optional[DataTransformationOutput] = None + + +class Data(BaseModel): + asset: DataAsset + + transformation: DataTransformation + + +class Request(BaseModel): + url: str + """URL of the submitted request.""" + + x_request_id: str + """Unique ID for the originating request.""" + + user_agent: Optional[str] = None + """User-Agent header of the originating request.""" + + +class Timings(BaseModel): + download_duration: Optional[int] = None + """Milliseconds spent downloading the source.""" + + encoding_duration: Optional[int] = None + """Milliseconds spent encoding.""" + + +class VideoTransformationReadyWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + + data: Data + + request: Request + + type: Literal["video.transformation.ready"] + + timings: Optional[Timings] = None From 713a6fb33d279df3e532eb90070002ddd852142d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 07:59:32 +0000 Subject: [PATCH 012/177] feat(api): manual updates --- .stats.yml | 2 +- README.md | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.stats.yml b/.stats.yml index ede64f5..980c906 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-584c2ccf3fc1a3ff3abf26b8d3dace2398d0f9ed6f20e4c411a13a81febb5e98.yml openapi_spec_hash: 14d1614ea3903d6b53f26e135c9cae81 -config_hash: 9f3c729a01b07940df835ef5ec13119a +config_hash: 91beba074bbcedbfda383cf006796fa1 diff --git a/README.md b/README.md index 0f28441..5788927 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,8 @@ client = ImageKit( ) response = client.files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"", + file_name="file-name.jpg", ) print(response.video_codec) ``` @@ -69,8 +69,8 @@ client = AsyncImageKit( async def main() -> None: response = await client.files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"", + file_name="file-name.jpg", ) print(response.video_codec) @@ -106,8 +106,8 @@ async def main() -> None: http_client=DefaultAioHttpClient(), ) as client: response = await client.files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"", + file_name="file-name.jpg", ) print(response.video_codec) @@ -188,8 +188,8 @@ client = ImageKit() try: client.files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"", + file_name="file-name.jpg", ) except imagekit.APIConnectionError as e: print("The server could not be reached") @@ -234,8 +234,8 @@ client = ImageKit( # Or, configure per-request: client.with_options(max_retries=5).files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"", + file_name="file-name.jpg", ) ``` @@ -260,8 +260,8 @@ client = ImageKit( # Override per-request: client.with_options(timeout=5.0).files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"", + file_name="file-name.jpg", ) ``` @@ -304,8 +304,8 @@ from imagekit import ImageKit client = ImageKit() response = client.files.with_raw_response.upload( - file=b"raw file contents", - file_name="fileName", + file=b"", + file_name="file-name.jpg", ) print(response.headers.get('X-My-Header')) @@ -325,8 +325,8 @@ To stream the response body, use `.with_streaming_response` instead, which requi ```python with client.files.with_streaming_response.upload( - file=b"raw file contents", - file_name="fileName", + file=b"", + file_name="file-name.jpg", ) as response: print(response.headers.get("X-My-Header")) From ab59fd9c9396d337e5f12f58d001711db98afd1d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 08:01:50 +0000 Subject: [PATCH 013/177] feat(api): manual updates --- .stats.yml | 2 +- README.md | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.stats.yml b/.stats.yml index 980c906..ede64f5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-584c2ccf3fc1a3ff3abf26b8d3dace2398d0f9ed6f20e4c411a13a81febb5e98.yml openapi_spec_hash: 14d1614ea3903d6b53f26e135c9cae81 -config_hash: 91beba074bbcedbfda383cf006796fa1 +config_hash: 9f3c729a01b07940df835ef5ec13119a diff --git a/README.md b/README.md index 5788927..0f28441 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,8 @@ client = ImageKit( ) response = client.files.upload( - file=b"", - file_name="file-name.jpg", + file=b"raw file contents", + file_name="fileName", ) print(response.video_codec) ``` @@ -69,8 +69,8 @@ client = AsyncImageKit( async def main() -> None: response = await client.files.upload( - file=b"", - file_name="file-name.jpg", + file=b"raw file contents", + file_name="fileName", ) print(response.video_codec) @@ -106,8 +106,8 @@ async def main() -> None: http_client=DefaultAioHttpClient(), ) as client: response = await client.files.upload( - file=b"", - file_name="file-name.jpg", + file=b"raw file contents", + file_name="fileName", ) print(response.video_codec) @@ -188,8 +188,8 @@ client = ImageKit() try: client.files.upload( - file=b"", - file_name="file-name.jpg", + file=b"raw file contents", + file_name="fileName", ) except imagekit.APIConnectionError as e: print("The server could not be reached") @@ -234,8 +234,8 @@ client = ImageKit( # Or, configure per-request: client.with_options(max_retries=5).files.upload( - file=b"", - file_name="file-name.jpg", + file=b"raw file contents", + file_name="fileName", ) ``` @@ -260,8 +260,8 @@ client = ImageKit( # Override per-request: client.with_options(timeout=5.0).files.upload( - file=b"", - file_name="file-name.jpg", + file=b"raw file contents", + file_name="fileName", ) ``` @@ -304,8 +304,8 @@ from imagekit import ImageKit client = ImageKit() response = client.files.with_raw_response.upload( - file=b"", - file_name="file-name.jpg", + file=b"raw file contents", + file_name="fileName", ) print(response.headers.get('X-My-Header')) @@ -325,8 +325,8 @@ To stream the response body, use `.with_streaming_response` instead, which requi ```python with client.files.with_streaming_response.upload( - file=b"", - file_name="file-name.jpg", + file=b"raw file contents", + file_name="fileName", ) as response: print(response.headers.get("X-My-Header")) From f5db9e8b2198618df08f693027b373c3694a7b63 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 08:03:49 +0000 Subject: [PATCH 014/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 15 -- src/imagekit/types/__init__.py | 10 -- .../types/beta/v2/file_upload_params.py | 63 ++++++++- .../types/beta/v2/file_upload_response.py | 131 ++++++++++++++++-- src/imagekit/types/file_update_params.py | 65 ++++++++- src/imagekit/types/file_upload_params.py | 63 ++++++++- src/imagekit/types/file_upload_response.py | 131 ++++++++++++++++-- .../files/metadata_get_from_url_response.py | 127 +++++++++++++++-- .../types/files/metadata_get_response.py | 119 ++++++++++++++-- src/imagekit/types/shared/__init__.py | 10 -- .../shared/auto_description_extension.py | 12 -- .../types/shared/auto_tagging_extension.py | 20 --- src/imagekit/types/shared/exif_details.py | 63 --------- src/imagekit/types/shared/exif_image.py | 33 ----- src/imagekit/types/shared/gps.py | 13 -- src/imagekit/types/shared/interoperability.py | 15 -- .../types/shared/removedot_bg_extension.py | 44 ------ src/imagekit/types/shared/thumbnail.py | 23 --- src/imagekit/types/shared_params/__init__.py | 5 - .../auto_description_extension.py | 12 -- .../shared_params/auto_tagging_extension.py | 20 --- .../shared_params/removedot_bg_extension.py | 43 ------ 23 files changed, 644 insertions(+), 395 deletions(-) delete mode 100644 src/imagekit/types/shared/__init__.py delete mode 100644 src/imagekit/types/shared/auto_description_extension.py delete mode 100644 src/imagekit/types/shared/auto_tagging_extension.py delete mode 100644 src/imagekit/types/shared/exif_details.py delete mode 100644 src/imagekit/types/shared/exif_image.py delete mode 100644 src/imagekit/types/shared/gps.py delete mode 100644 src/imagekit/types/shared/interoperability.py delete mode 100644 src/imagekit/types/shared/removedot_bg_extension.py delete mode 100644 src/imagekit/types/shared/thumbnail.py delete mode 100644 src/imagekit/types/shared_params/__init__.py delete mode 100644 src/imagekit/types/shared_params/auto_description_extension.py delete mode 100644 src/imagekit/types/shared_params/auto_tagging_extension.py delete mode 100644 src/imagekit/types/shared_params/removedot_bg_extension.py diff --git a/.stats.yml b/.stats.yml index ede64f5..254a6c3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-584c2ccf3fc1a3ff3abf26b8d3dace2398d0f9ed6f20e4c411a13a81febb5e98.yml openapi_spec_hash: 14d1614ea3903d6b53f26e135c9cae81 -config_hash: 9f3c729a01b07940df835ef5ec13119a +config_hash: e2f52106d0ea435659ba3ff7074406f5 diff --git a/api.md b/api.md index 7bd2e9e..adf733d 100644 --- a/api.md +++ b/api.md @@ -1,18 +1,3 @@ -# Shared Types - -```python -from imagekit.types import ( - AutoDescriptionExtension, - AutoTaggingExtension, - ExifDetails, - ExifImage, - Gps, - Interoperability, - RemovedotBgExtension, - Thumbnail, -) -``` - # CustomMetadataFields Types: diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index ac7baed..31fb04a 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -2,16 +2,6 @@ from __future__ import annotations -from .shared import ( - Gps as Gps, - ExifImage as ExifImage, - Thumbnail as Thumbnail, - ExifDetails as ExifDetails, - Interoperability as Interoperability, - AutoTaggingExtension as AutoTaggingExtension, - RemovedotBgExtension as RemovedotBgExtension, - AutoDescriptionExtension as AutoDescriptionExtension, -) from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams from .asset_list_params import AssetListParams as AssetListParams diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekit/types/beta/v2/file_upload_params.py index fe02965..82fa22a 100644 --- a/src/imagekit/types/beta/v2/file_upload_params.py +++ b/src/imagekit/types/beta/v2/file_upload_params.py @@ -7,13 +7,14 @@ from ...._types import FileTypes from ...._utils import PropertyInfo -from ...shared_params.auto_tagging_extension import AutoTaggingExtension -from ...shared_params.removedot_bg_extension import RemovedotBgExtension -from ...shared_params.auto_description_extension import AutoDescriptionExtension __all__ = [ "FileUploadParams", "Extension", + "ExtensionRemovedotBgExtension", + "ExtensionRemovedotBgExtensionOptions", + "ExtensionAutoTaggingExtension", + "ExtensionAutoDescriptionExtension", "Transformation", "TransformationPost", "TransformationPostSimplePostTransformation", @@ -197,7 +198,61 @@ class FileUploadParams(TypedDict, total=False): """ -Extension: TypeAlias = Union[RemovedotBgExtension, AutoTaggingExtension, AutoDescriptionExtension] +class ExtensionRemovedotBgExtensionOptions(TypedDict, total=False): + add_shadow: bool + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: str + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: str + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: bool + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class ExtensionRemovedotBgExtension(TypedDict, total=False): + name: Required[Literal["remove-bg"]] + """Specifies the background removal extension.""" + + options: ExtensionRemovedotBgExtensionOptions + + +class ExtensionAutoTaggingExtension(TypedDict, total=False): + max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] + """Maximum number of tags to attach to the asset.""" + + min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] + """Minimum confidence level for tags to be considered valid.""" + + name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] + """Specifies the auto-tagging extension used.""" + + +class ExtensionAutoDescriptionExtension(TypedDict, total=False): + name: Required[Literal["ai-auto-description"]] + """Specifies the auto description extension.""" + + +Extension: TypeAlias = Union[ + ExtensionRemovedotBgExtension, ExtensionAutoTaggingExtension, ExtensionAutoDescriptionExtension +] class TransformationPostSimplePostTransformation(TypedDict, total=False): diff --git a/src/imagekit/types/beta/v2/file_upload_response.py b/src/imagekit/types/beta/v2/file_upload_response.py index 0b4672a..05d1d6e 100644 --- a/src/imagekit/types/beta/v2/file_upload_response.py +++ b/src/imagekit/types/beta/v2/file_upload_response.py @@ -6,13 +6,20 @@ from pydantic import Field as FieldInfo from ...._models import BaseModel -from ...shared.gps import Gps -from ...shared.thumbnail import Thumbnail -from ...shared.exif_image import ExifImage -from ...shared.exif_details import ExifDetails -from ...shared.interoperability import Interoperability -__all__ = ["FileUploadResponse", "AITag", "ExtensionStatus", "Metadata", "MetadataExif", "VersionInfo"] +__all__ = [ + "FileUploadResponse", + "AITag", + "ExtensionStatus", + "Metadata", + "MetadataExif", + "MetadataExifExif", + "MetadataExifGps", + "MetadataExifImage", + "MetadataExifInteroperability", + "MetadataExifThumbnail", + "VersionInfo", +] class AITag(BaseModel): @@ -42,22 +49,124 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) +class MetadataExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class MetadataExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class MetadataExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class MetadataExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class MetadataExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + class MetadataExif(BaseModel): - exif: Optional[ExifDetails] = None + exif: Optional[MetadataExifExif] = None """Object containing Exif details.""" - gps: Optional[Gps] = None + gps: Optional[MetadataExifGps] = None """Object containing GPS information.""" - image: Optional[ExifImage] = None + image: Optional[MetadataExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[Interoperability] = None + interoperability: Optional[MetadataExifInteroperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[Thumbnail] = None + thumbnail: Optional[MetadataExifThumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index 1810c39..0750108 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -6,14 +6,15 @@ from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict from .._utils import PropertyInfo -from .shared_params.auto_tagging_extension import AutoTaggingExtension -from .shared_params.removedot_bg_extension import RemovedotBgExtension -from .shared_params.auto_description_extension import AutoDescriptionExtension __all__ = [ "FileUpdateParams", "UpdateFileDetails", "UpdateFileDetailsExtension", + "UpdateFileDetailsExtensionRemovedotBgExtension", + "UpdateFileDetailsExtensionRemovedotBgExtensionOptions", + "UpdateFileDetailsExtensionAutoTaggingExtension", + "UpdateFileDetailsExtensionAutoDescriptionExtension", "ChangePublicationStatus", "ChangePublicationStatusPublish", ] @@ -71,7 +72,63 @@ class UpdateFileDetails(TypedDict, total=False): """ -UpdateFileDetailsExtension: TypeAlias = Union[RemovedotBgExtension, AutoTaggingExtension, AutoDescriptionExtension] +class UpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, total=False): + add_shadow: bool + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: str + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: str + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: bool + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class UpdateFileDetailsExtensionRemovedotBgExtension(TypedDict, total=False): + name: Required[Literal["remove-bg"]] + """Specifies the background removal extension.""" + + options: UpdateFileDetailsExtensionRemovedotBgExtensionOptions + + +class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): + max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] + """Maximum number of tags to attach to the asset.""" + + min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] + """Minimum confidence level for tags to be considered valid.""" + + name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] + """Specifies the auto-tagging extension used.""" + + +class UpdateFileDetailsExtensionAutoDescriptionExtension(TypedDict, total=False): + name: Required[Literal["ai-auto-description"]] + """Specifies the auto description extension.""" + + +UpdateFileDetailsExtension: TypeAlias = Union[ + UpdateFileDetailsExtensionRemovedotBgExtension, + UpdateFileDetailsExtensionAutoTaggingExtension, + UpdateFileDetailsExtensionAutoDescriptionExtension, +] class ChangePublicationStatus(TypedDict, total=False): diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 292224b..291fbf4 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -7,13 +7,14 @@ from .._types import FileTypes from .._utils import PropertyInfo -from .shared_params.auto_tagging_extension import AutoTaggingExtension -from .shared_params.removedot_bg_extension import RemovedotBgExtension -from .shared_params.auto_description_extension import AutoDescriptionExtension __all__ = [ "FileUploadParams", "Extension", + "ExtensionRemovedotBgExtension", + "ExtensionRemovedotBgExtensionOptions", + "ExtensionAutoTaggingExtension", + "ExtensionAutoDescriptionExtension", "Transformation", "TransformationPost", "TransformationPostSimplePostTransformation", @@ -229,7 +230,61 @@ class FileUploadParams(TypedDict, total=False): """ -Extension: TypeAlias = Union[RemovedotBgExtension, AutoTaggingExtension, AutoDescriptionExtension] +class ExtensionRemovedotBgExtensionOptions(TypedDict, total=False): + add_shadow: bool + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: str + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: str + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: bool + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class ExtensionRemovedotBgExtension(TypedDict, total=False): + name: Required[Literal["remove-bg"]] + """Specifies the background removal extension.""" + + options: ExtensionRemovedotBgExtensionOptions + + +class ExtensionAutoTaggingExtension(TypedDict, total=False): + max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] + """Maximum number of tags to attach to the asset.""" + + min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] + """Minimum confidence level for tags to be considered valid.""" + + name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] + """Specifies the auto-tagging extension used.""" + + +class ExtensionAutoDescriptionExtension(TypedDict, total=False): + name: Required[Literal["ai-auto-description"]] + """Specifies the auto description extension.""" + + +Extension: TypeAlias = Union[ + ExtensionRemovedotBgExtension, ExtensionAutoTaggingExtension, ExtensionAutoDescriptionExtension +] class TransformationPostSimplePostTransformation(TypedDict, total=False): diff --git a/src/imagekit/types/file_upload_response.py b/src/imagekit/types/file_upload_response.py index a5e0d1b..8e0883b 100644 --- a/src/imagekit/types/file_upload_response.py +++ b/src/imagekit/types/file_upload_response.py @@ -6,13 +6,20 @@ from pydantic import Field as FieldInfo from .._models import BaseModel -from .shared.gps import Gps -from .shared.thumbnail import Thumbnail -from .shared.exif_image import ExifImage -from .shared.exif_details import ExifDetails -from .shared.interoperability import Interoperability -__all__ = ["FileUploadResponse", "AITag", "ExtensionStatus", "Metadata", "MetadataExif", "VersionInfo"] +__all__ = [ + "FileUploadResponse", + "AITag", + "ExtensionStatus", + "Metadata", + "MetadataExif", + "MetadataExifExif", + "MetadataExifGps", + "MetadataExifImage", + "MetadataExifInteroperability", + "MetadataExifThumbnail", + "VersionInfo", +] class AITag(BaseModel): @@ -42,22 +49,124 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) +class MetadataExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class MetadataExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class MetadataExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class MetadataExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class MetadataExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + class MetadataExif(BaseModel): - exif: Optional[ExifDetails] = None + exif: Optional[MetadataExifExif] = None """Object containing Exif details.""" - gps: Optional[Gps] = None + gps: Optional[MetadataExifGps] = None """Object containing GPS information.""" - image: Optional[ExifImage] = None + image: Optional[MetadataExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[Interoperability] = None + interoperability: Optional[MetadataExifInteroperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[Thumbnail] = None + thumbnail: Optional[MetadataExifThumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/files/metadata_get_from_url_response.py b/src/imagekit/types/files/metadata_get_from_url_response.py index e5d3309..47b1bcd 100644 --- a/src/imagekit/types/files/metadata_get_from_url_response.py +++ b/src/imagekit/types/files/metadata_get_from_url_response.py @@ -1,35 +1,140 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, Optional +from typing import Dict, List, Optional from pydantic import Field as FieldInfo from ..._models import BaseModel -from ..shared.gps import Gps -from ..shared.thumbnail import Thumbnail -from ..shared.exif_image import ExifImage -from ..shared.exif_details import ExifDetails -from ..shared.interoperability import Interoperability -__all__ = ["MetadataGetFromURLResponse", "Exif"] +__all__ = [ + "MetadataGetFromURLResponse", + "Exif", + "ExifExif", + "ExifGps", + "ExifImage", + "ExifInteroperability", + "ExifThumbnail", +] + + +class ExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class ExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class ExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class ExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class ExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) class Exif(BaseModel): - exif: Optional[ExifDetails] = None + exif: Optional[ExifExif] = None """Object containing Exif details.""" - gps: Optional[Gps] = None + gps: Optional[ExifGps] = None """Object containing GPS information.""" image: Optional[ExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[Interoperability] = None + interoperability: Optional[ExifInteroperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[Thumbnail] = None + thumbnail: Optional[ExifThumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/files/metadata_get_response.py b/src/imagekit/types/files/metadata_get_response.py index 7736d05..d5a3cbf 100644 --- a/src/imagekit/types/files/metadata_get_response.py +++ b/src/imagekit/types/files/metadata_get_response.py @@ -1,35 +1,132 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, Optional +from typing import Dict, List, Optional from pydantic import Field as FieldInfo from ..._models import BaseModel -from ..shared.gps import Gps -from ..shared.thumbnail import Thumbnail -from ..shared.exif_image import ExifImage -from ..shared.exif_details import ExifDetails -from ..shared.interoperability import Interoperability -__all__ = ["MetadataGetResponse", "Exif"] +__all__ = ["MetadataGetResponse", "Exif", "ExifExif", "ExifGps", "ExifImage", "ExifInteroperability", "ExifThumbnail"] + + +class ExifExif(BaseModel): + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) + + color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) + + create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) + + custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) + + date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) + + exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) + + exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) + + exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) + + exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) + + exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) + + exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) + + exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) + + flash: Optional[int] = FieldInfo(alias="Flash", default=None) + + flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) + + f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) + + focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) + + focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) + + focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) + + focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) + + interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) + + iso: Optional[int] = FieldInfo(alias="ISO", default=None) + + metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) + + scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) + + shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) + + sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) + + white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) + + +class ExifGps(BaseModel): + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) + + +class ExifImage(BaseModel): + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) + + gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) + + make: Optional[str] = FieldInfo(alias="Make", default=None) + + model: Optional[str] = FieldInfo(alias="Model", default=None) + + modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) + + orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + software: Optional[str] = FieldInfo(alias="Software", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) + + +class ExifInteroperability(BaseModel): + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) + + interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) + + +class ExifThumbnail(BaseModel): + compression: Optional[int] = FieldInfo(alias="Compression", default=None) + + resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) + + thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) + + thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) + + x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) + + y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) class Exif(BaseModel): - exif: Optional[ExifDetails] = None + exif: Optional[ExifExif] = None """Object containing Exif details.""" - gps: Optional[Gps] = None + gps: Optional[ExifGps] = None """Object containing GPS information.""" image: Optional[ExifImage] = None """Object containing EXIF image information.""" - interoperability: Optional[Interoperability] = None + interoperability: Optional[ExifInteroperability] = None """JSON object.""" makernote: Optional[Dict[str, object]] = None - thumbnail: Optional[Thumbnail] = None + thumbnail: Optional[ExifThumbnail] = None """Object containing Thumbnail information.""" diff --git a/src/imagekit/types/shared/__init__.py b/src/imagekit/types/shared/__init__.py deleted file mode 100644 index 8da285c..0000000 --- a/src/imagekit/types/shared/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .gps import Gps as Gps -from .thumbnail import Thumbnail as Thumbnail -from .exif_image import ExifImage as ExifImage -from .exif_details import ExifDetails as ExifDetails -from .interoperability import Interoperability as Interoperability -from .auto_tagging_extension import AutoTaggingExtension as AutoTaggingExtension -from .removedot_bg_extension import RemovedotBgExtension as RemovedotBgExtension -from .auto_description_extension import AutoDescriptionExtension as AutoDescriptionExtension diff --git a/src/imagekit/types/shared/auto_description_extension.py b/src/imagekit/types/shared/auto_description_extension.py deleted file mode 100644 index b62a57b..0000000 --- a/src/imagekit/types/shared/auto_description_extension.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["AutoDescriptionExtension"] - - -class AutoDescriptionExtension(BaseModel): - name: Literal["ai-auto-description"] - """Specifies the auto description extension.""" diff --git a/src/imagekit/types/shared/auto_tagging_extension.py b/src/imagekit/types/shared/auto_tagging_extension.py deleted file mode 100644 index 3ea6063..0000000 --- a/src/imagekit/types/shared/auto_tagging_extension.py +++ /dev/null @@ -1,20 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["AutoTaggingExtension"] - - -class AutoTaggingExtension(BaseModel): - max_tags: int = FieldInfo(alias="maxTags") - """Maximum number of tags to attach to the asset.""" - - min_confidence: int = FieldInfo(alias="minConfidence") - """Minimum confidence level for tags to be considered valid.""" - - name: Literal["google-auto-tagging", "aws-auto-tagging"] - """Specifies the auto-tagging extension used.""" diff --git a/src/imagekit/types/shared/exif_details.py b/src/imagekit/types/shared/exif_details.py deleted file mode 100644 index 24820d7..0000000 --- a/src/imagekit/types/shared/exif_details.py +++ /dev/null @@ -1,63 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["ExifDetails"] - - -class ExifDetails(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) diff --git a/src/imagekit/types/shared/exif_image.py b/src/imagekit/types/shared/exif_image.py deleted file mode 100644 index 63eb6e7..0000000 --- a/src/imagekit/types/shared/exif_image.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["ExifImage"] - - -class ExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) diff --git a/src/imagekit/types/shared/gps.py b/src/imagekit/types/shared/gps.py deleted file mode 100644 index fa8ac0a..0000000 --- a/src/imagekit/types/shared/gps.py +++ /dev/null @@ -1,13 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["Gps"] - - -class Gps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) diff --git a/src/imagekit/types/shared/interoperability.py b/src/imagekit/types/shared/interoperability.py deleted file mode 100644 index 1eda53f..0000000 --- a/src/imagekit/types/shared/interoperability.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["Interoperability"] - - -class Interoperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) diff --git a/src/imagekit/types/shared/removedot_bg_extension.py b/src/imagekit/types/shared/removedot_bg_extension.py deleted file mode 100644 index b238436..0000000 --- a/src/imagekit/types/shared/removedot_bg_extension.py +++ /dev/null @@ -1,44 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["RemovedotBgExtension", "Options"] - - -class Options(BaseModel): - add_shadow: Optional[bool] = None - """Whether to add an artificial shadow to the result. - - Default is false. Note: Adding shadows is currently only supported for car - photos. - """ - - bg_color: Optional[str] = None - """ - Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or - color name (e.g., "green"). If this parameter is set, `bg_image_url` must be - empty. - """ - - bg_image_url: Optional[str] = None - """Sets a background image from a URL. - - If this parameter is set, `bg_color` must be empty. - """ - - semitransparency: Optional[bool] = None - """Allows semi-transparent regions in the result. - - Default is true. Note: Semitransparency is currently only supported for car - windows. - """ - - -class RemovedotBgExtension(BaseModel): - name: Literal["remove-bg"] - """Specifies the background removal extension.""" - - options: Optional[Options] = None diff --git a/src/imagekit/types/shared/thumbnail.py b/src/imagekit/types/shared/thumbnail.py deleted file mode 100644 index 03d674c..0000000 --- a/src/imagekit/types/shared/thumbnail.py +++ /dev/null @@ -1,23 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["Thumbnail"] - - -class Thumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) diff --git a/src/imagekit/types/shared_params/__init__.py b/src/imagekit/types/shared_params/__init__.py deleted file mode 100644 index cffa993..0000000 --- a/src/imagekit/types/shared_params/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .auto_tagging_extension import AutoTaggingExtension as AutoTaggingExtension -from .removedot_bg_extension import RemovedotBgExtension as RemovedotBgExtension -from .auto_description_extension import AutoDescriptionExtension as AutoDescriptionExtension diff --git a/src/imagekit/types/shared_params/auto_description_extension.py b/src/imagekit/types/shared_params/auto_description_extension.py deleted file mode 100644 index 5243b23..0000000 --- a/src/imagekit/types/shared_params/auto_description_extension.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, TypedDict - -__all__ = ["AutoDescriptionExtension"] - - -class AutoDescriptionExtension(TypedDict, total=False): - name: Required[Literal["ai-auto-description"]] - """Specifies the auto description extension.""" diff --git a/src/imagekit/types/shared_params/auto_tagging_extension.py b/src/imagekit/types/shared_params/auto_tagging_extension.py deleted file mode 100644 index d2a792b..0000000 --- a/src/imagekit/types/shared_params/auto_tagging_extension.py +++ /dev/null @@ -1,20 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, Annotated, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["AutoTaggingExtension"] - - -class AutoTaggingExtension(TypedDict, total=False): - max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] - """Maximum number of tags to attach to the asset.""" - - min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] - """Minimum confidence level for tags to be considered valid.""" - - name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] - """Specifies the auto-tagging extension used.""" diff --git a/src/imagekit/types/shared_params/removedot_bg_extension.py b/src/imagekit/types/shared_params/removedot_bg_extension.py deleted file mode 100644 index 8d29832..0000000 --- a/src/imagekit/types/shared_params/removedot_bg_extension.py +++ /dev/null @@ -1,43 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, TypedDict - -__all__ = ["RemovedotBgExtension", "Options"] - - -class Options(TypedDict, total=False): - add_shadow: bool - """Whether to add an artificial shadow to the result. - - Default is false. Note: Adding shadows is currently only supported for car - photos. - """ - - bg_color: str - """ - Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or - color name (e.g., "green"). If this parameter is set, `bg_image_url` must be - empty. - """ - - bg_image_url: str - """Sets a background image from a URL. - - If this parameter is set, `bg_color` must be empty. - """ - - semitransparency: bool - """Allows semi-transparent regions in the result. - - Default is true. Note: Semitransparency is currently only supported for car - windows. - """ - - -class RemovedotBgExtension(TypedDict, total=False): - name: Required[Literal["remove-bg"]] - """Specifies the background removal extension.""" - - options: Options From cd24047b48d45829a05c5224b81cd04eb9f6f07d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 08:12:52 +0000 Subject: [PATCH 015/177] feat(api): manual updates --- .stats.yml | 6 +++--- .../types/accounts/origin_create_response.py | 14 +++++++------- src/imagekit/types/accounts/origin_get_response.py | 14 +++++++------- .../types/accounts/origin_list_response.py | 14 +++++++------- .../types/accounts/origin_update_response.py | 14 +++++++------- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/.stats.yml b/.stats.yml index 254a6c3..91f8d8c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-584c2ccf3fc1a3ff3abf26b8d3dace2398d0f9ed6f20e4c411a13a81febb5e98.yml -openapi_spec_hash: 14d1614ea3903d6b53f26e135c9cae81 -config_hash: e2f52106d0ea435659ba3ff7074406f5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-a1cf25a2c075ef11eea56c771578a9c36aa5f37677389988c9fb0c776399bc1b.yml +openapi_spec_hash: 8fed9fded4a79267764133be71b296e6 +config_hash: e212bc0b32d2d9fe583f77bccfae0375 diff --git a/src/imagekit/types/accounts/origin_create_response.py b/src/imagekit/types/accounts/origin_create_response.py index f4036d6..72699bc 100644 --- a/src/imagekit/types/accounts/origin_create_response.py +++ b/src/imagekit/types/accounts/origin_create_response.py @@ -36,7 +36,7 @@ class S3(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" type: Literal["S3"] @@ -64,7 +64,7 @@ class S3Compatible(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") @@ -92,7 +92,7 @@ class CloudinaryBackup(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" type: Literal["CLOUDINARY_BACKUP"] @@ -108,7 +108,7 @@ class WebFolder(BaseModel): This is generated by ImageKit when you create a new origin. """ - base_url: object = FieldInfo(alias="baseUrl") + base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") @@ -162,7 +162,7 @@ class GoogleCloudStorageGcs(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str type: Literal["GCS"] @@ -187,7 +187,7 @@ class AzureBlobStorage(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str type: Literal["AZURE_BLOB"] @@ -202,7 +202,7 @@ class AkeneoPim(BaseModel): This is generated by ImageKit when you create a new origin. """ - base_url: object = FieldInfo(alias="baseUrl") + base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") diff --git a/src/imagekit/types/accounts/origin_get_response.py b/src/imagekit/types/accounts/origin_get_response.py index dc7ddca..059365f 100644 --- a/src/imagekit/types/accounts/origin_get_response.py +++ b/src/imagekit/types/accounts/origin_get_response.py @@ -36,7 +36,7 @@ class S3(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" type: Literal["S3"] @@ -64,7 +64,7 @@ class S3Compatible(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") @@ -92,7 +92,7 @@ class CloudinaryBackup(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" type: Literal["CLOUDINARY_BACKUP"] @@ -108,7 +108,7 @@ class WebFolder(BaseModel): This is generated by ImageKit when you create a new origin. """ - base_url: object = FieldInfo(alias="baseUrl") + base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") @@ -162,7 +162,7 @@ class GoogleCloudStorageGcs(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str type: Literal["GCS"] @@ -187,7 +187,7 @@ class AzureBlobStorage(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str type: Literal["AZURE_BLOB"] @@ -202,7 +202,7 @@ class AkeneoPim(BaseModel): This is generated by ImageKit when you create a new origin. """ - base_url: object = FieldInfo(alias="baseUrl") + base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") diff --git a/src/imagekit/types/accounts/origin_list_response.py b/src/imagekit/types/accounts/origin_list_response.py index 1108ff6..235c899 100644 --- a/src/imagekit/types/accounts/origin_list_response.py +++ b/src/imagekit/types/accounts/origin_list_response.py @@ -37,7 +37,7 @@ class OriginListResponseItemS3(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" type: Literal["S3"] @@ -65,7 +65,7 @@ class OriginListResponseItemS3Compatible(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") @@ -93,7 +93,7 @@ class OriginListResponseItemCloudinaryBackup(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" type: Literal["CLOUDINARY_BACKUP"] @@ -109,7 +109,7 @@ class OriginListResponseItemWebFolder(BaseModel): This is generated by ImageKit when you create a new origin. """ - base_url: object = FieldInfo(alias="baseUrl") + base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") @@ -163,7 +163,7 @@ class OriginListResponseItemGoogleCloudStorageGcs(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str type: Literal["GCS"] @@ -188,7 +188,7 @@ class OriginListResponseItemAzureBlobStorage(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str type: Literal["AZURE_BLOB"] @@ -203,7 +203,7 @@ class OriginListResponseItemAkeneoPim(BaseModel): This is generated by ImageKit when you create a new origin. """ - base_url: object = FieldInfo(alias="baseUrl") + base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") diff --git a/src/imagekit/types/accounts/origin_update_response.py b/src/imagekit/types/accounts/origin_update_response.py index a7ec735..1b74313 100644 --- a/src/imagekit/types/accounts/origin_update_response.py +++ b/src/imagekit/types/accounts/origin_update_response.py @@ -36,7 +36,7 @@ class S3(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" type: Literal["S3"] @@ -64,7 +64,7 @@ class S3Compatible(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") @@ -92,7 +92,7 @@ class CloudinaryBackup(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str """Path prefix inside the bucket.""" type: Literal["CLOUDINARY_BACKUP"] @@ -108,7 +108,7 @@ class WebFolder(BaseModel): This is generated by ImageKit when you create a new origin. """ - base_url: object = FieldInfo(alias="baseUrl") + base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") @@ -162,7 +162,7 @@ class GoogleCloudStorageGcs(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str type: Literal["GCS"] @@ -187,7 +187,7 @@ class AzureBlobStorage(BaseModel): name: str """Display name of the origin.""" - prefix: object + prefix: str type: Literal["AZURE_BLOB"] @@ -202,7 +202,7 @@ class AkeneoPim(BaseModel): This is generated by ImageKit when you create a new origin. """ - base_url: object = FieldInfo(alias="baseUrl") + base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") From e532ad5a2ba21a5b645c257d76b1811b7e2245fb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 08:17:07 +0000 Subject: [PATCH 016/177] feat(api): manual updates --- .stats.yml | 2 +- src/imagekit/resources/files/files.py | 212 +--------------------- src/imagekit/types/file_update_params.py | 149 +++++++-------- tests/api_resources/test_files.py | 220 ++++++++--------------- 4 files changed, 156 insertions(+), 427 deletions(-) diff --git a/.stats.yml b/.stats.yml index 91f8d8c..0384e02 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-a1cf25a2c075ef11eea56c771578a9c36aa5f37677389988c9fb0c776399bc1b.yml openapi_spec_hash: 8fed9fded4a79267764133be71b296e6 -config_hash: e212bc0b32d2d9fe583f77bccfae0375 +config_hash: 398ac75e62a73363899d6839f61a5977 diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 583f3da..fd3d1fb 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -2,8 +2,8 @@ from __future__ import annotations -from typing import Dict, List, Union, Mapping, Iterable, Optional, cast -from typing_extensions import Literal, overload +from typing import Dict, List, Mapping, Iterable, cast +from typing_extensions import Literal import httpx @@ -85,76 +85,11 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ return FilesResourceWithStreamingResponse(self) - @overload def update( self, file_id: str, *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUpdateResponse: - """ - This API updates the details or attributes of the current version of the file. - You can update `tags`, `customCoordinates`, `customMetadata`, publication - status, remove existing `AITags` and apply extensions using this API. - - Args: - custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. - `10,10,100,100`. Send `null` to unset this value. - - custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` - value for that key. Before setting any custom metadata on an asset you have to - create the field using custom metadata fields API. - - description: Optional text to describe the contents of the file. - - extensions: Array of extensions to be applied to the asset. Each extension can be configured - with specific parameters based on the extension type. - - remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. - `["car", "vehicle", "motorsports"]`. - - If you want to remove all AITags associated with the file, send a string - - "all". - - Note: The remove operation for `AITags` executes before any of the `extensions` - are processed. - - tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send - `null` to unset all tags associated with the file. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - file_id: str, - *, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + update: file_update_params.Update | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -168,8 +103,6 @@ def update( status, remove existing `AITags` and apply extensions using this API. Args: - publish: Configure the publication status of a file and its versions. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -178,44 +111,11 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - def update( - self, - file_id: str, - *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._patch( f"/v1/files/{file_id}/details", - body=maybe_transform( - { - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "description": description, - "extensions": extensions, - "remove_ai_tags": remove_ai_tags, - "tags": tags, - "webhook_url": webhook_url, - "publish": publish, - }, - file_update_params.FileUpdateParams, - ), + body=maybe_transform(update, file_update_params.FileUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -756,76 +656,11 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ return AsyncFilesResourceWithStreamingResponse(self) - @overload async def update( self, file_id: str, *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUpdateResponse: - """ - This API updates the details or attributes of the current version of the file. - You can update `tags`, `customCoordinates`, `customMetadata`, publication - status, remove existing `AITags` and apply extensions using this API. - - Args: - custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. - `10,10,100,100`. Send `null` to unset this value. - - custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` - value for that key. Before setting any custom metadata on an asset you have to - create the field using custom metadata fields API. - - description: Optional text to describe the contents of the file. - - extensions: Array of extensions to be applied to the asset. Each extension can be configured - with specific parameters based on the extension type. - - remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. - `["car", "vehicle", "motorsports"]`. - - If you want to remove all AITags associated with the file, send a string - - "all". - - Note: The remove operation for `AITags` executes before any of the `extensions` - are processed. - - tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send - `null` to unset all tags associated with the file. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def update( - self, - file_id: str, - *, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + update: file_update_params.Update | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -839,8 +674,6 @@ async def update( status, remove existing `AITags` and apply extensions using this API. Args: - publish: Configure the publication status of a file and its versions. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -849,44 +682,11 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - async def update( - self, - file_id: str, - *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._patch( f"/v1/files/{file_id}/details", - body=await async_maybe_transform( - { - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "description": description, - "extensions": extensions, - "remove_ai_tags": remove_ai_tags, - "tags": tags, - "webhook_url": webhook_url, - "publish": publish, - }, - file_update_params.FileUpdateParams, - ), + body=await async_maybe_transform(update, file_update_params.FileUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index 0750108..49e4fb5 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -9,70 +9,23 @@ __all__ = [ "FileUpdateParams", - "UpdateFileDetails", - "UpdateFileDetailsExtension", - "UpdateFileDetailsExtensionRemovedotBgExtension", - "UpdateFileDetailsExtensionRemovedotBgExtensionOptions", - "UpdateFileDetailsExtensionAutoTaggingExtension", - "UpdateFileDetailsExtensionAutoDescriptionExtension", - "ChangePublicationStatus", - "ChangePublicationStatusPublish", + "Update", + "UpdateUpdateFileDetails", + "UpdateUpdateFileDetailsExtension", + "UpdateUpdateFileDetailsExtensionRemovedotBgExtension", + "UpdateUpdateFileDetailsExtensionRemovedotBgExtensionOptions", + "UpdateUpdateFileDetailsExtensionAutoTaggingExtension", + "UpdateUpdateFileDetailsExtensionAutoDescriptionExtension", + "UpdateChangePublicationStatus", + "UpdateChangePublicationStatusPublish", ] -class UpdateFileDetails(TypedDict, total=False): - custom_coordinates: Annotated[Optional[str], PropertyInfo(alias="customCoordinates")] - """Define an important area in the image in the format `x,y,width,height` e.g. - - `10,10,100,100`. Send `null` to unset this value. - """ - - custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] - """A key-value data to be associated with the asset. - - To unset a key, send `null` value for that key. Before setting any custom - metadata on an asset you have to create the field using custom metadata fields - API. - """ - - description: str - """Optional text to describe the contents of the file.""" - - extensions: Iterable[UpdateFileDetailsExtension] - """Array of extensions to be applied to the asset. - - Each extension can be configured with specific parameters based on the extension - type. - """ - - remove_ai_tags: Annotated[Union[List[str], Literal["all"]], PropertyInfo(alias="removeAITags")] - """An array of AITags associated with the file that you want to remove, e.g. +class FileUpdateParams(TypedDict, total=False): + update: Update - `["car", "vehicle", "motorsports"]`. - - If you want to remove all AITags associated with the file, send a string - - "all". - Note: The remove operation for `AITags` executes before any of the `extensions` - are processed. - """ - - tags: Optional[List[str]] - """An array of tags associated with the file, such as `["tag1", "tag2"]`. - - Send `null` to unset all tags associated with the file. - """ - - webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] - """ - The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - """ - - -class UpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, total=False): +class UpdateUpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, total=False): add_shadow: bool """Whether to add an artificial shadow to the result. @@ -101,14 +54,14 @@ class UpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, total=Fal """ -class UpdateFileDetailsExtensionRemovedotBgExtension(TypedDict, total=False): +class UpdateUpdateFileDetailsExtensionRemovedotBgExtension(TypedDict, total=False): name: Required[Literal["remove-bg"]] """Specifies the background removal extension.""" - options: UpdateFileDetailsExtensionRemovedotBgExtensionOptions + options: UpdateUpdateFileDetailsExtensionRemovedotBgExtensionOptions -class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): +class UpdateUpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] """Maximum number of tags to attach to the asset.""" @@ -119,24 +72,71 @@ class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): """Specifies the auto-tagging extension used.""" -class UpdateFileDetailsExtensionAutoDescriptionExtension(TypedDict, total=False): +class UpdateUpdateFileDetailsExtensionAutoDescriptionExtension(TypedDict, total=False): name: Required[Literal["ai-auto-description"]] """Specifies the auto description extension.""" -UpdateFileDetailsExtension: TypeAlias = Union[ - UpdateFileDetailsExtensionRemovedotBgExtension, - UpdateFileDetailsExtensionAutoTaggingExtension, - UpdateFileDetailsExtensionAutoDescriptionExtension, +UpdateUpdateFileDetailsExtension: TypeAlias = Union[ + UpdateUpdateFileDetailsExtensionRemovedotBgExtension, + UpdateUpdateFileDetailsExtensionAutoTaggingExtension, + UpdateUpdateFileDetailsExtensionAutoDescriptionExtension, ] -class ChangePublicationStatus(TypedDict, total=False): - publish: ChangePublicationStatusPublish - """Configure the publication status of a file and its versions.""" +class UpdateUpdateFileDetails(TypedDict, total=False): + custom_coordinates: Annotated[Optional[str], PropertyInfo(alias="customCoordinates")] + """Define an important area in the image in the format `x,y,width,height` e.g. + + `10,10,100,100`. Send `null` to unset this value. + """ + + custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] + """A key-value data to be associated with the asset. + + To unset a key, send `null` value for that key. Before setting any custom + metadata on an asset you have to create the field using custom metadata fields + API. + """ + + description: str + """Optional text to describe the contents of the file.""" + + extensions: Iterable[UpdateUpdateFileDetailsExtension] + """Array of extensions to be applied to the asset. + + Each extension can be configured with specific parameters based on the extension + type. + """ + + remove_ai_tags: Annotated[Union[List[str], Literal["all"]], PropertyInfo(alias="removeAITags")] + """An array of AITags associated with the file that you want to remove, e.g. + + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + """ + + tags: Optional[List[str]] + """An array of tags associated with the file, such as `["tag1", "tag2"]`. + + Send `null` to unset all tags associated with the file. + """ -class ChangePublicationStatusPublish(TypedDict, total=False): + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ + + +class UpdateChangePublicationStatusPublish(TypedDict, total=False): is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] """Set to `true` to publish the file. Set to `false` to unpublish the file.""" @@ -147,4 +147,9 @@ class ChangePublicationStatusPublish(TypedDict, total=False): """ -FileUpdateParams: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] +class UpdateChangePublicationStatus(TypedDict, total=False): + publish: UpdateChangePublicationStatusPublish + """Configure the publication status of a file and its versions.""" + + +Update: TypeAlias = Union[UpdateUpdateFileDetails, UpdateChangePublicationStatus] diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index a05d6e2..5cd148b 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -26,7 +26,7 @@ class TestFiles: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_overload_1(self, client: ImageKit) -> None: + def test_method_update(self, client: ImageKit) -> None: file = client.files.update( file_id="fileId", ) @@ -34,86 +34,48 @@ def test_method_update_overload_1(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: + def test_method_update_with_all_params(self, client: ImageKit) -> None: file = client.files.update( file_id="fileId", - custom_coordinates="customCoordinates", - custom_metadata={"foo": "bar"}, - description="description", - extensions=[ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, + update={ + "custom_coordinates": "10,10,100,100", + "custom_metadata": { + "brand": "bar", + "color": "bar", + }, + "description": "description", + "extensions": [ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, }, - } - ], - remove_ai_tags=["string"], - tags=["tag1", "tag2"], - webhook_url="https://example.com", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_1(self, client: ImageKit) -> None: - response = client.files.with_raw_response.update( - file_id="fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: - with client.files.with_streaming_response.update( - file_id="fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_1(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.with_raw_response.update( - file_id="", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_2(self, client: ImageKit) -> None: - file = client.files.update( - file_id="fileId", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: - file = client.files.update( - file_id="fileId", - publish={ - "is_published": True, - "include_file_versions": True, + { + "max_tags": 10, + "min_confidence": 80, + "name": "google-auto-tagging", + }, + { + "max_tags": 10, + "min_confidence": 80, + "name": "aws-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + "remove_ai_tags": ["car", "vehicle", "motorsports"], + "tags": ["tag1", "tag2"], + "webhook_url": "https://webhook.site/0d6b6c7a-8e5a-4b3a-8b7c-0d6b6c7a8e5a", }, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update_overload_2(self, client: ImageKit) -> None: + def test_raw_response_update(self, client: ImageKit) -> None: response = client.files.with_raw_response.update( file_id="fileId", ) @@ -125,7 +87,7 @@ def test_raw_response_update_overload_2(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: + def test_streaming_response_update(self, client: ImageKit) -> None: with client.files.with_streaming_response.update( file_id="fileId", ) as response: @@ -139,7 +101,7 @@ def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update_overload_2(self, client: ImageKit) -> None: + def test_path_params_update(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.files.with_raw_response.update( file_id="", @@ -466,7 +428,7 @@ class TestAsyncFiles: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_method_update(self, async_client: AsyncImageKit) -> None: file = await async_client.files.update( file_id="fileId", ) @@ -474,86 +436,48 @@ async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> No @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_method_update_with_all_params(self, async_client: AsyncImageKit) -> None: file = await async_client.files.update( file_id="fileId", - custom_coordinates="customCoordinates", - custom_metadata={"foo": "bar"}, - description="description", - extensions=[ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, + update={ + "custom_coordinates": "10,10,100,100", + "custom_metadata": { + "brand": "bar", + "color": "bar", + }, + "description": "description", + "extensions": [ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, }, - } - ], - remove_ai_tags=["string"], - tags=["tag1", "tag2"], - webhook_url="https://example.com", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.update( - file_id="fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = await response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.update( - file_id="fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = await response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - await async_client.files.with_raw_response.update( - file_id="", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.update( - file_id="fileId", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.update( - file_id="fileId", - publish={ - "is_published": True, - "include_file_versions": True, + { + "max_tags": 10, + "min_confidence": 80, + "name": "google-auto-tagging", + }, + { + "max_tags": 10, + "min_confidence": 80, + "name": "aws-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + "remove_ai_tags": ["car", "vehicle", "motorsports"], + "tags": ["tag1", "tag2"], + "webhook_url": "https://webhook.site/0d6b6c7a-8e5a-4b3a-8b7c-0d6b6c7a8e5a", }, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.update( file_id="fileId", ) @@ -565,7 +489,7 @@ async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + async def test_streaming_response_update(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.update( file_id="fileId", ) as response: @@ -579,7 +503,7 @@ async def test_streaming_response_update_overload_2(self, async_client: AsyncIma @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: + async def test_path_params_update(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.files.with_raw_response.update( file_id="", From 4299c75c1d7888dce5bad8ac77a45a4a0625a5ab Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 08:23:21 +0000 Subject: [PATCH 017/177] feat(api): manual updates --- .stats.yml | 2 +- src/imagekit/resources/files/files.py | 212 +++++++++++++++++++++- src/imagekit/types/file_update_params.py | 149 ++++++++------- tests/api_resources/test_files.py | 220 +++++++++++++++-------- 4 files changed, 427 insertions(+), 156 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0384e02..91f8d8c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-a1cf25a2c075ef11eea56c771578a9c36aa5f37677389988c9fb0c776399bc1b.yml openapi_spec_hash: 8fed9fded4a79267764133be71b296e6 -config_hash: 398ac75e62a73363899d6839f61a5977 +config_hash: e212bc0b32d2d9fe583f77bccfae0375 diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index fd3d1fb..583f3da 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -2,8 +2,8 @@ from __future__ import annotations -from typing import Dict, List, Mapping, Iterable, cast -from typing_extensions import Literal +from typing import Dict, List, Union, Mapping, Iterable, Optional, cast +from typing_extensions import Literal, overload import httpx @@ -85,11 +85,76 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ return FilesResourceWithStreamingResponse(self) + @overload def update( self, file_id: str, *, - update: file_update_params.Update | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUpdateResponse: + """ + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. + + Args: + custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. + `10,10,100,100`. Send `null` to unset this value. + + custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` + value for that key. Before setting any custom metadata on an asset you have to + create the field using custom metadata fields API. + + description: Optional text to describe the contents of the file. + + extensions: Array of extensions to be applied to the asset. Each extension can be configured + with specific parameters based on the extension type. + + remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". + + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + + tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send + `null` to unset all tags associated with the file. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + file_id: str, + *, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -103,6 +168,8 @@ def update( status, remove existing `AITags` and apply extensions using this API. Args: + publish: Configure the publication status of a file and its versions. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -111,11 +178,44 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + def update( + self, + file_id: str, + *, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._patch( f"/v1/files/{file_id}/details", - body=maybe_transform(update, file_update_params.FileUpdateParams), + body=maybe_transform( + { + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "extensions": extensions, + "remove_ai_tags": remove_ai_tags, + "tags": tags, + "webhook_url": webhook_url, + "publish": publish, + }, + file_update_params.FileUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -656,11 +756,76 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ return AsyncFilesResourceWithStreamingResponse(self) + @overload async def update( self, file_id: str, *, - update: file_update_params.Update | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUpdateResponse: + """ + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. + + Args: + custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. + `10,10,100,100`. Send `null` to unset this value. + + custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` + value for that key. Before setting any custom metadata on an asset you have to + create the field using custom metadata fields API. + + description: Optional text to describe the contents of the file. + + extensions: Array of extensions to be applied to the asset. Each extension can be configured + with specific parameters based on the extension type. + + remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". + + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + + tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send + `null` to unset all tags associated with the file. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def update( + self, + file_id: str, + *, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -674,6 +839,8 @@ async def update( status, remove existing `AITags` and apply extensions using this API. Args: + publish: Configure the publication status of a file and its versions. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -682,11 +849,44 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + async def update( + self, + file_id: str, + *, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[List[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._patch( f"/v1/files/{file_id}/details", - body=await async_maybe_transform(update, file_update_params.FileUpdateParams), + body=await async_maybe_transform( + { + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "extensions": extensions, + "remove_ai_tags": remove_ai_tags, + "tags": tags, + "webhook_url": webhook_url, + "publish": publish, + }, + file_update_params.FileUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index 49e4fb5..0750108 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -9,23 +9,70 @@ __all__ = [ "FileUpdateParams", - "Update", - "UpdateUpdateFileDetails", - "UpdateUpdateFileDetailsExtension", - "UpdateUpdateFileDetailsExtensionRemovedotBgExtension", - "UpdateUpdateFileDetailsExtensionRemovedotBgExtensionOptions", - "UpdateUpdateFileDetailsExtensionAutoTaggingExtension", - "UpdateUpdateFileDetailsExtensionAutoDescriptionExtension", - "UpdateChangePublicationStatus", - "UpdateChangePublicationStatusPublish", + "UpdateFileDetails", + "UpdateFileDetailsExtension", + "UpdateFileDetailsExtensionRemovedotBgExtension", + "UpdateFileDetailsExtensionRemovedotBgExtensionOptions", + "UpdateFileDetailsExtensionAutoTaggingExtension", + "UpdateFileDetailsExtensionAutoDescriptionExtension", + "ChangePublicationStatus", + "ChangePublicationStatusPublish", ] -class FileUpdateParams(TypedDict, total=False): - update: Update +class UpdateFileDetails(TypedDict, total=False): + custom_coordinates: Annotated[Optional[str], PropertyInfo(alias="customCoordinates")] + """Define an important area in the image in the format `x,y,width,height` e.g. + + `10,10,100,100`. Send `null` to unset this value. + """ + + custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] + """A key-value data to be associated with the asset. + + To unset a key, send `null` value for that key. Before setting any custom + metadata on an asset you have to create the field using custom metadata fields + API. + """ + + description: str + """Optional text to describe the contents of the file.""" + + extensions: Iterable[UpdateFileDetailsExtension] + """Array of extensions to be applied to the asset. + + Each extension can be configured with specific parameters based on the extension + type. + """ + + remove_ai_tags: Annotated[Union[List[str], Literal["all"]], PropertyInfo(alias="removeAITags")] + """An array of AITags associated with the file that you want to remove, e.g. + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". -class UpdateUpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, total=False): + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + """ + + tags: Optional[List[str]] + """An array of tags associated with the file, such as `["tag1", "tag2"]`. + + Send `null` to unset all tags associated with the file. + """ + + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ + + +class UpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, total=False): add_shadow: bool """Whether to add an artificial shadow to the result. @@ -54,14 +101,14 @@ class UpdateUpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, tot """ -class UpdateUpdateFileDetailsExtensionRemovedotBgExtension(TypedDict, total=False): +class UpdateFileDetailsExtensionRemovedotBgExtension(TypedDict, total=False): name: Required[Literal["remove-bg"]] """Specifies the background removal extension.""" - options: UpdateUpdateFileDetailsExtensionRemovedotBgExtensionOptions + options: UpdateFileDetailsExtensionRemovedotBgExtensionOptions -class UpdateUpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): +class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] """Maximum number of tags to attach to the asset.""" @@ -72,71 +119,24 @@ class UpdateUpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=Fals """Specifies the auto-tagging extension used.""" -class UpdateUpdateFileDetailsExtensionAutoDescriptionExtension(TypedDict, total=False): +class UpdateFileDetailsExtensionAutoDescriptionExtension(TypedDict, total=False): name: Required[Literal["ai-auto-description"]] """Specifies the auto description extension.""" -UpdateUpdateFileDetailsExtension: TypeAlias = Union[ - UpdateUpdateFileDetailsExtensionRemovedotBgExtension, - UpdateUpdateFileDetailsExtensionAutoTaggingExtension, - UpdateUpdateFileDetailsExtensionAutoDescriptionExtension, +UpdateFileDetailsExtension: TypeAlias = Union[ + UpdateFileDetailsExtensionRemovedotBgExtension, + UpdateFileDetailsExtensionAutoTaggingExtension, + UpdateFileDetailsExtensionAutoDescriptionExtension, ] -class UpdateUpdateFileDetails(TypedDict, total=False): - custom_coordinates: Annotated[Optional[str], PropertyInfo(alias="customCoordinates")] - """Define an important area in the image in the format `x,y,width,height` e.g. - - `10,10,100,100`. Send `null` to unset this value. - """ - - custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] - """A key-value data to be associated with the asset. - - To unset a key, send `null` value for that key. Before setting any custom - metadata on an asset you have to create the field using custom metadata fields - API. - """ - - description: str - """Optional text to describe the contents of the file.""" - - extensions: Iterable[UpdateUpdateFileDetailsExtension] - """Array of extensions to be applied to the asset. - - Each extension can be configured with specific parameters based on the extension - type. - """ - - remove_ai_tags: Annotated[Union[List[str], Literal["all"]], PropertyInfo(alias="removeAITags")] - """An array of AITags associated with the file that you want to remove, e.g. - - `["car", "vehicle", "motorsports"]`. - - If you want to remove all AITags associated with the file, send a string - - "all". - - Note: The remove operation for `AITags` executes before any of the `extensions` - are processed. - """ - - tags: Optional[List[str]] - """An array of tags associated with the file, such as `["tag1", "tag2"]`. - - Send `null` to unset all tags associated with the file. - """ - - webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] - """ - The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - """ +class ChangePublicationStatus(TypedDict, total=False): + publish: ChangePublicationStatusPublish + """Configure the publication status of a file and its versions.""" -class UpdateChangePublicationStatusPublish(TypedDict, total=False): +class ChangePublicationStatusPublish(TypedDict, total=False): is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] """Set to `true` to publish the file. Set to `false` to unpublish the file.""" @@ -147,9 +147,4 @@ class UpdateChangePublicationStatusPublish(TypedDict, total=False): """ -class UpdateChangePublicationStatus(TypedDict, total=False): - publish: UpdateChangePublicationStatusPublish - """Configure the publication status of a file and its versions.""" - - -Update: TypeAlias = Union[UpdateUpdateFileDetails, UpdateChangePublicationStatus] +FileUpdateParams: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 5cd148b..a05d6e2 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -26,7 +26,7 @@ class TestFiles: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update(self, client: ImageKit) -> None: + def test_method_update_overload_1(self, client: ImageKit) -> None: file = client.files.update( file_id="fileId", ) @@ -34,48 +34,86 @@ def test_method_update(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_with_all_params(self, client: ImageKit) -> None: + def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: file = client.files.update( file_id="fileId", - update={ - "custom_coordinates": "10,10,100,100", - "custom_metadata": { - "brand": "bar", - "color": "bar", - }, - "description": "description", - "extensions": [ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, - }, - }, - { - "max_tags": 10, - "min_confidence": 80, - "name": "google-auto-tagging", - }, - { - "max_tags": 10, - "min_confidence": 80, - "name": "aws-auto-tagging", + custom_coordinates="customCoordinates", + custom_metadata={"foo": "bar"}, + description="description", + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, }, - {"name": "ai-auto-description"}, - ], - "remove_ai_tags": ["car", "vehicle", "motorsports"], - "tags": ["tag1", "tag2"], - "webhook_url": "https://webhook.site/0d6b6c7a-8e5a-4b3a-8b7c-0d6b6c7a8e5a", + } + ], + remove_ai_tags=["string"], + tags=["tag1", "tag2"], + webhook_url="https://example.com", + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_1(self, client: ImageKit) -> None: + response = client.files.with_raw_response.update( + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: + with client.files.with_streaming_response.update( + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_1(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.with_raw_response.update( + file_id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_2(self, client: ImageKit) -> None: + file = client.files.update( + file_id="fileId", + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: + file = client.files.update( + file_id="fileId", + publish={ + "is_published": True, + "include_file_versions": True, }, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update(self, client: ImageKit) -> None: + def test_raw_response_update_overload_2(self, client: ImageKit) -> None: response = client.files.with_raw_response.update( file_id="fileId", ) @@ -87,7 +125,7 @@ def test_raw_response_update(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update(self, client: ImageKit) -> None: + def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: with client.files.with_streaming_response.update( file_id="fileId", ) as response: @@ -101,7 +139,7 @@ def test_streaming_response_update(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update(self, client: ImageKit) -> None: + def test_path_params_update_overload_2(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.files.with_raw_response.update( file_id="", @@ -428,7 +466,7 @@ class TestAsyncFiles: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update(self, async_client: AsyncImageKit) -> None: + async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: file = await async_client.files.update( file_id="fileId", ) @@ -436,48 +474,86 @@ async def test_method_update(self, async_client: AsyncImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncImageKit) -> None: + async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: file = await async_client.files.update( file_id="fileId", - update={ - "custom_coordinates": "10,10,100,100", - "custom_metadata": { - "brand": "bar", - "color": "bar", - }, - "description": "description", - "extensions": [ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, - }, - }, - { - "max_tags": 10, - "min_confidence": 80, - "name": "google-auto-tagging", - }, - { - "max_tags": 10, - "min_confidence": 80, - "name": "aws-auto-tagging", + custom_coordinates="customCoordinates", + custom_metadata={"foo": "bar"}, + description="description", + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, }, - {"name": "ai-auto-description"}, - ], - "remove_ai_tags": ["car", "vehicle", "motorsports"], - "tags": ["tag1", "tag2"], - "webhook_url": "https://webhook.site/0d6b6c7a-8e5a-4b3a-8b7c-0d6b6c7a8e5a", + } + ], + remove_ai_tags=["string"], + tags=["tag1", "tag2"], + webhook_url="https://example.com", + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.update( + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.update( + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.with_raw_response.update( + file_id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.update( + file_id="fileId", + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.update( + file_id="fileId", + publish={ + "is_published": True, + "include_file_versions": True, }, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: + async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.update( file_id="fileId", ) @@ -489,7 +565,7 @@ async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update(self, async_client: AsyncImageKit) -> None: + async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.update( file_id="fileId", ) as response: @@ -503,7 +579,7 @@ async def test_streaming_response_update(self, async_client: AsyncImageKit) -> N @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update(self, async_client: AsyncImageKit) -> None: + async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.files.with_raw_response.update( file_id="", From e6859bdd948fa5bccd99badf93dfbe304f7441d2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 08:29:39 +0000 Subject: [PATCH 018/177] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 91f8d8c..2b05889 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-a1cf25a2c075ef11eea56c771578a9c36aa5f37677389988c9fb0c776399bc1b.yml -openapi_spec_hash: 8fed9fded4a79267764133be71b296e6 -config_hash: e212bc0b32d2d9fe583f77bccfae0375 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-ba44a73e45777c7f0831ac2026a9b63ae01f681b6acff7c7f80d7294d1f4ee4a.yml +openapi_spec_hash: df7bdce53da43b2ceae08a2a47bd1b52 +config_hash: b75c4e4432c2d0650589863f8336849b From ca8ed07a61b9290476e8743e6714bafe76407da8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 08:33:12 +0000 Subject: [PATCH 019/177] feat(api): manual updates --- .stats.yml | 4 ++-- src/imagekit/types/file_update_params.py | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2b05889..dc77336 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-ba44a73e45777c7f0831ac2026a9b63ae01f681b6acff7c7f80d7294d1f4ee4a.yml -openapi_spec_hash: df7bdce53da43b2ceae08a2a47bd1b52 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-7df229db9f102454c11cef7c98953e5b6463221dd4be66cdb4f4e93f41d447ae.yml +openapi_spec_hash: ecaba4c44e684a0611699e09fca9891b config_hash: b75c4e4432c2d0650589863f8336849b diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index 0750108..e89f4ad 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -11,10 +11,10 @@ "FileUpdateParams", "UpdateFileDetails", "UpdateFileDetailsExtension", - "UpdateFileDetailsExtensionRemovedotBgExtension", - "UpdateFileDetailsExtensionRemovedotBgExtensionOptions", + "UpdateFileDetailsExtensionRemoveBg", + "UpdateFileDetailsExtensionRemoveBgOptions", "UpdateFileDetailsExtensionAutoTaggingExtension", - "UpdateFileDetailsExtensionAutoDescriptionExtension", + "UpdateFileDetailsExtensionAIAutoDescription", "ChangePublicationStatus", "ChangePublicationStatusPublish", ] @@ -72,7 +72,7 @@ class UpdateFileDetails(TypedDict, total=False): """ -class UpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, total=False): +class UpdateFileDetailsExtensionRemoveBgOptions(TypedDict, total=False): add_shadow: bool """Whether to add an artificial shadow to the result. @@ -101,11 +101,11 @@ class UpdateFileDetailsExtensionRemovedotBgExtensionOptions(TypedDict, total=Fal """ -class UpdateFileDetailsExtensionRemovedotBgExtension(TypedDict, total=False): +class UpdateFileDetailsExtensionRemoveBg(TypedDict, total=False): name: Required[Literal["remove-bg"]] """Specifies the background removal extension.""" - options: UpdateFileDetailsExtensionRemovedotBgExtensionOptions + options: UpdateFileDetailsExtensionRemoveBgOptions class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): @@ -119,15 +119,15 @@ class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): """Specifies the auto-tagging extension used.""" -class UpdateFileDetailsExtensionAutoDescriptionExtension(TypedDict, total=False): +class UpdateFileDetailsExtensionAIAutoDescription(TypedDict, total=False): name: Required[Literal["ai-auto-description"]] """Specifies the auto description extension.""" UpdateFileDetailsExtension: TypeAlias = Union[ - UpdateFileDetailsExtensionRemovedotBgExtension, + UpdateFileDetailsExtensionRemoveBg, UpdateFileDetailsExtensionAutoTaggingExtension, - UpdateFileDetailsExtensionAutoDescriptionExtension, + UpdateFileDetailsExtensionAIAutoDescription, ] From 27a4d031b0751f7f78cc4fd65859dc91eee13b53 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 09:57:41 +0000 Subject: [PATCH 020/177] feat(api): manual updates --- .stats.yml | 4 +- .../accounts/url_endpoint_create_params.py | 18 +++------ .../accounts/url_endpoint_update_params.py | 18 +++------ .../types/beta/v2/file_upload_params.py | 39 ++++++++----------- src/imagekit/types/file_upload_params.py | 39 ++++++++----------- 5 files changed, 46 insertions(+), 72 deletions(-) diff --git a/.stats.yml b/.stats.yml index dc77336..9d8aa40 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-7df229db9f102454c11cef7c98953e5b6463221dd4be66cdb4f4e93f41d447ae.yml -openapi_spec_hash: ecaba4c44e684a0611699e09fca9891b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-6c237ebd6f81741286e7cfbaeac1356da3e18c7fe43b74d6c358d62bfb40dbb9.yml +openapi_spec_hash: ad6a65d74e3eb865a5d2915177f92ea7 config_hash: b75c4e4432c2d0650589863f8336849b diff --git a/src/imagekit/types/accounts/url_endpoint_create_params.py b/src/imagekit/types/accounts/url_endpoint_create_params.py index e604253..b3a81f5 100644 --- a/src/imagekit/types/accounts/url_endpoint_create_params.py +++ b/src/imagekit/types/accounts/url_endpoint_create_params.py @@ -7,13 +7,7 @@ from ..._utils import PropertyInfo -__all__ = [ - "URLEndpointCreateParams", - "URLRewriter", - "URLRewriterCloudinaryURLRewriter", - "URLRewriterImgixURLRewriter", - "URLRewriterAkamaiURLRewriter", -] +__all__ = ["URLEndpointCreateParams", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] class URLEndpointCreateParams(TypedDict, total=False): @@ -37,21 +31,19 @@ class URLEndpointCreateParams(TypedDict, total=False): """Configuration for third-party URL rewriting.""" -class URLRewriterCloudinaryURLRewriter(TypedDict, total=False): +class URLRewriterCloudinary(TypedDict, total=False): type: Required[Literal["CLOUDINARY"]] preserve_asset_delivery_types: Annotated[bool, PropertyInfo(alias="preserveAssetDeliveryTypes")] """Whether to preserve `/` in the rewritten URL.""" -class URLRewriterImgixURLRewriter(TypedDict, total=False): +class URLRewriterImgix(TypedDict, total=False): type: Required[Literal["IMGIX"]] -class URLRewriterAkamaiURLRewriter(TypedDict, total=False): +class URLRewriterAkamai(TypedDict, total=False): type: Required[Literal["AKAMAI"]] -URLRewriter: TypeAlias = Union[ - URLRewriterCloudinaryURLRewriter, URLRewriterImgixURLRewriter, URLRewriterAkamaiURLRewriter -] +URLRewriter: TypeAlias = Union[URLRewriterCloudinary, URLRewriterImgix, URLRewriterAkamai] diff --git a/src/imagekit/types/accounts/url_endpoint_update_params.py b/src/imagekit/types/accounts/url_endpoint_update_params.py index d83c39a..16b141a 100644 --- a/src/imagekit/types/accounts/url_endpoint_update_params.py +++ b/src/imagekit/types/accounts/url_endpoint_update_params.py @@ -7,13 +7,7 @@ from ..._utils import PropertyInfo -__all__ = [ - "URLEndpointUpdateParams", - "URLRewriter", - "URLRewriterCloudinaryURLRewriter", - "URLRewriterImgixURLRewriter", - "URLRewriterAkamaiURLRewriter", -] +__all__ = ["URLEndpointUpdateParams", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] class URLEndpointUpdateParams(TypedDict, total=False): @@ -37,21 +31,19 @@ class URLEndpointUpdateParams(TypedDict, total=False): """Configuration for third-party URL rewriting.""" -class URLRewriterCloudinaryURLRewriter(TypedDict, total=False): +class URLRewriterCloudinary(TypedDict, total=False): type: Required[Literal["CLOUDINARY"]] preserve_asset_delivery_types: Annotated[bool, PropertyInfo(alias="preserveAssetDeliveryTypes")] """Whether to preserve `/` in the rewritten URL.""" -class URLRewriterImgixURLRewriter(TypedDict, total=False): +class URLRewriterImgix(TypedDict, total=False): type: Required[Literal["IMGIX"]] -class URLRewriterAkamaiURLRewriter(TypedDict, total=False): +class URLRewriterAkamai(TypedDict, total=False): type: Required[Literal["AKAMAI"]] -URLRewriter: TypeAlias = Union[ - URLRewriterCloudinaryURLRewriter, URLRewriterImgixURLRewriter, URLRewriterAkamaiURLRewriter -] +URLRewriter: TypeAlias = Union[URLRewriterCloudinary, URLRewriterImgix, URLRewriterAkamai] diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekit/types/beta/v2/file_upload_params.py index 82fa22a..4d8470b 100644 --- a/src/imagekit/types/beta/v2/file_upload_params.py +++ b/src/imagekit/types/beta/v2/file_upload_params.py @@ -11,16 +11,16 @@ __all__ = [ "FileUploadParams", "Extension", - "ExtensionRemovedotBgExtension", - "ExtensionRemovedotBgExtensionOptions", + "ExtensionRemoveBg", + "ExtensionRemoveBgOptions", "ExtensionAutoTaggingExtension", - "ExtensionAutoDescriptionExtension", + "ExtensionAIAutoDescription", "Transformation", "TransformationPost", - "TransformationPostSimplePostTransformation", - "TransformationPostConvertGifToVideo", - "TransformationPostGenerateAThumbnail", - "TransformationPostAdaptiveBitrateStreaming", + "TransformationPostTransformation", + "TransformationPostGifToVideo", + "TransformationPostThumbnail", + "TransformationPostAbs", ] @@ -198,7 +198,7 @@ class FileUploadParams(TypedDict, total=False): """ -class ExtensionRemovedotBgExtensionOptions(TypedDict, total=False): +class ExtensionRemoveBgOptions(TypedDict, total=False): add_shadow: bool """Whether to add an artificial shadow to the result. @@ -227,11 +227,11 @@ class ExtensionRemovedotBgExtensionOptions(TypedDict, total=False): """ -class ExtensionRemovedotBgExtension(TypedDict, total=False): +class ExtensionRemoveBg(TypedDict, total=False): name: Required[Literal["remove-bg"]] """Specifies the background removal extension.""" - options: ExtensionRemovedotBgExtensionOptions + options: ExtensionRemoveBgOptions class ExtensionAutoTaggingExtension(TypedDict, total=False): @@ -245,17 +245,15 @@ class ExtensionAutoTaggingExtension(TypedDict, total=False): """Specifies the auto-tagging extension used.""" -class ExtensionAutoDescriptionExtension(TypedDict, total=False): +class ExtensionAIAutoDescription(TypedDict, total=False): name: Required[Literal["ai-auto-description"]] """Specifies the auto description extension.""" -Extension: TypeAlias = Union[ - ExtensionRemovedotBgExtension, ExtensionAutoTaggingExtension, ExtensionAutoDescriptionExtension -] +Extension: TypeAlias = Union[ExtensionRemoveBg, ExtensionAutoTaggingExtension, ExtensionAIAutoDescription] -class TransformationPostSimplePostTransformation(TypedDict, total=False): +class TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" @@ -267,7 +265,7 @@ class TransformationPostSimplePostTransformation(TypedDict, total=False): """ -class TransformationPostConvertGifToVideo(TypedDict, total=False): +class TransformationPostGifToVideo(TypedDict, total=False): type: Required[Literal["gif-to-video"]] """Converts an animated GIF into an MP4.""" @@ -278,7 +276,7 @@ class TransformationPostConvertGifToVideo(TypedDict, total=False): """ -class TransformationPostGenerateAThumbnail(TypedDict, total=False): +class TransformationPostThumbnail(TypedDict, total=False): type: Required[Literal["thumbnail"]] """Generates a thumbnail image.""" @@ -289,7 +287,7 @@ class TransformationPostGenerateAThumbnail(TypedDict, total=False): """ -class TransformationPostAdaptiveBitrateStreaming(TypedDict, total=False): +class TransformationPostAbs(TypedDict, total=False): protocol: Required[Literal["hls", "dash"]] """Streaming protocol to use (`hls` or `dash`).""" @@ -303,10 +301,7 @@ class TransformationPostAdaptiveBitrateStreaming(TypedDict, total=False): TransformationPost: TypeAlias = Union[ - TransformationPostSimplePostTransformation, - TransformationPostConvertGifToVideo, - TransformationPostGenerateAThumbnail, - TransformationPostAdaptiveBitrateStreaming, + TransformationPostTransformation, TransformationPostGifToVideo, TransformationPostThumbnail, TransformationPostAbs ] diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 291fbf4..228e681 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -11,16 +11,16 @@ __all__ = [ "FileUploadParams", "Extension", - "ExtensionRemovedotBgExtension", - "ExtensionRemovedotBgExtensionOptions", + "ExtensionRemoveBg", + "ExtensionRemoveBgOptions", "ExtensionAutoTaggingExtension", - "ExtensionAutoDescriptionExtension", + "ExtensionAIAutoDescription", "Transformation", "TransformationPost", - "TransformationPostSimplePostTransformation", - "TransformationPostConvertGifToVideo", - "TransformationPostGenerateAThumbnail", - "TransformationPostAdaptiveBitrateStreaming", + "TransformationPostTransformation", + "TransformationPostGifToVideo", + "TransformationPostThumbnail", + "TransformationPostAbs", ] @@ -230,7 +230,7 @@ class FileUploadParams(TypedDict, total=False): """ -class ExtensionRemovedotBgExtensionOptions(TypedDict, total=False): +class ExtensionRemoveBgOptions(TypedDict, total=False): add_shadow: bool """Whether to add an artificial shadow to the result. @@ -259,11 +259,11 @@ class ExtensionRemovedotBgExtensionOptions(TypedDict, total=False): """ -class ExtensionRemovedotBgExtension(TypedDict, total=False): +class ExtensionRemoveBg(TypedDict, total=False): name: Required[Literal["remove-bg"]] """Specifies the background removal extension.""" - options: ExtensionRemovedotBgExtensionOptions + options: ExtensionRemoveBgOptions class ExtensionAutoTaggingExtension(TypedDict, total=False): @@ -277,17 +277,15 @@ class ExtensionAutoTaggingExtension(TypedDict, total=False): """Specifies the auto-tagging extension used.""" -class ExtensionAutoDescriptionExtension(TypedDict, total=False): +class ExtensionAIAutoDescription(TypedDict, total=False): name: Required[Literal["ai-auto-description"]] """Specifies the auto description extension.""" -Extension: TypeAlias = Union[ - ExtensionRemovedotBgExtension, ExtensionAutoTaggingExtension, ExtensionAutoDescriptionExtension -] +Extension: TypeAlias = Union[ExtensionRemoveBg, ExtensionAutoTaggingExtension, ExtensionAIAutoDescription] -class TransformationPostSimplePostTransformation(TypedDict, total=False): +class TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" @@ -299,7 +297,7 @@ class TransformationPostSimplePostTransformation(TypedDict, total=False): """ -class TransformationPostConvertGifToVideo(TypedDict, total=False): +class TransformationPostGifToVideo(TypedDict, total=False): type: Required[Literal["gif-to-video"]] """Converts an animated GIF into an MP4.""" @@ -310,7 +308,7 @@ class TransformationPostConvertGifToVideo(TypedDict, total=False): """ -class TransformationPostGenerateAThumbnail(TypedDict, total=False): +class TransformationPostThumbnail(TypedDict, total=False): type: Required[Literal["thumbnail"]] """Generates a thumbnail image.""" @@ -321,7 +319,7 @@ class TransformationPostGenerateAThumbnail(TypedDict, total=False): """ -class TransformationPostAdaptiveBitrateStreaming(TypedDict, total=False): +class TransformationPostAbs(TypedDict, total=False): protocol: Required[Literal["hls", "dash"]] """Streaming protocol to use (`hls` or `dash`).""" @@ -335,10 +333,7 @@ class TransformationPostAdaptiveBitrateStreaming(TypedDict, total=False): TransformationPost: TypeAlias = Union[ - TransformationPostSimplePostTransformation, - TransformationPostConvertGifToVideo, - TransformationPostGenerateAThumbnail, - TransformationPostAdaptiveBitrateStreaming, + TransformationPostTransformation, TransformationPostGifToVideo, TransformationPostThumbnail, TransformationPostAbs ] From df61e22a90735042f83a9b80a0424f4c939be112 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 10:14:55 +0000 Subject: [PATCH 021/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9d8aa40..9c64de6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-6c237ebd6f81741286e7cfbaeac1356da3e18c7fe43b74d6c358d62bfb40dbb9.yml -openapi_spec_hash: ad6a65d74e3eb865a5d2915177f92ea7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-5ed7a3dbaf059adbd91e86cd61520f59c5fdcc8df3f561df9ab07d7afb722f18.yml +openapi_spec_hash: 51d4d2be59d5d3f81a695a9b8786c77e config_hash: b75c4e4432c2d0650589863f8336849b From 23cb25700bae3b22b89c5af8669ba55033cb1053 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 10:21:13 +0000 Subject: [PATCH 022/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9c64de6..fedb1ee 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-5ed7a3dbaf059adbd91e86cd61520f59c5fdcc8df3f561df9ab07d7afb722f18.yml -openapi_spec_hash: 51d4d2be59d5d3f81a695a9b8786c77e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-cb2369e849b98127ee6a2cbd01d928e4546d29c1a0a8e64e9b46f90189c1a992.yml +openapi_spec_hash: f8e732e88daf7c4bfbeb2bd2cdba2cec config_hash: b75c4e4432c2d0650589863f8336849b From f78461fd8a5cd86e1ab0645682c10689bf33e60e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 10:58:42 +0000 Subject: [PATCH 023/177] feat(api): manual updates --- .stats.yml | 2 +- README.md | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.stats.yml b/.stats.yml index fedb1ee..3ae65fa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-cb2369e849b98127ee6a2cbd01d928e4546d29c1a0a8e64e9b46f90189c1a992.yml openapi_spec_hash: f8e732e88daf7c4bfbeb2bd2cdba2cec -config_hash: b75c4e4432c2d0650589863f8336849b +config_hash: c9b1142a72b93ad4d66f0433dca1392e diff --git a/README.md b/README.md index 0f28441..e1be54e 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,8 @@ client = ImageKit( ) response = client.files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"https://www.example.com/public-url.jpg", + file_name="file-name.jpg", ) print(response.video_codec) ``` @@ -69,8 +69,8 @@ client = AsyncImageKit( async def main() -> None: response = await client.files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"https://www.example.com/public-url.jpg", + file_name="file-name.jpg", ) print(response.video_codec) @@ -106,8 +106,8 @@ async def main() -> None: http_client=DefaultAioHttpClient(), ) as client: response = await client.files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"https://www.example.com/public-url.jpg", + file_name="file-name.jpg", ) print(response.video_codec) @@ -188,8 +188,8 @@ client = ImageKit() try: client.files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"https://www.example.com/public-url.jpg", + file_name="file-name.jpg", ) except imagekit.APIConnectionError as e: print("The server could not be reached") @@ -234,8 +234,8 @@ client = ImageKit( # Or, configure per-request: client.with_options(max_retries=5).files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"https://www.example.com/public-url.jpg", + file_name="file-name.jpg", ) ``` @@ -260,8 +260,8 @@ client = ImageKit( # Override per-request: client.with_options(timeout=5.0).files.upload( - file=b"raw file contents", - file_name="fileName", + file=b"https://www.example.com/public-url.jpg", + file_name="file-name.jpg", ) ``` @@ -304,8 +304,8 @@ from imagekit import ImageKit client = ImageKit() response = client.files.with_raw_response.upload( - file=b"raw file contents", - file_name="fileName", + file=b"https://www.example.com/public-url.jpg", + file_name="file-name.jpg", ) print(response.headers.get('X-My-Header')) @@ -325,8 +325,8 @@ To stream the response body, use `.with_streaming_response` instead, which requi ```python with client.files.with_streaming_response.upload( - file=b"raw file contents", - file_name="fileName", + file=b"https://www.example.com/public-url.jpg", + file_name="file-name.jpg", ) as response: print(response.headers.get("X-My-Header")) From 1dc6513b8bf530361bfed8691341762e3cd0db99 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:18:36 +0000 Subject: [PATCH 024/177] feat(api): manual updates --- .stats.yml | 4 ++-- src/imagekit/types/custom_metadata_field_create_params.py | 4 +++- .../types/custom_metadata_field_create_response.py | 2 +- src/imagekit/types/custom_metadata_field_list_response.py | 2 +- src/imagekit/types/custom_metadata_field_update_params.py | 4 +++- .../types/custom_metadata_field_update_response.py | 2 +- tests/api_resources/test_custom_metadata_fields.py | 8 ++++---- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3ae65fa..fe62740 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-cb2369e849b98127ee6a2cbd01d928e4546d29c1a0a8e64e9b46f90189c1a992.yml -openapi_spec_hash: f8e732e88daf7c4bfbeb2bd2cdba2cec +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-cb74df1af0b7cdd4f66573d2d002f003b74702172ddd2c8495c465a7706c4d66.yml +openapi_spec_hash: 9a1fb60cda92b3e693e8c0f0fde0508a config_hash: c9b1142a72b93ad4d66f0433dca1392e diff --git a/src/imagekit/types/custom_metadata_field_create_params.py b/src/imagekit/types/custom_metadata_field_create_params.py index 1d029fd..a0beccf 100644 --- a/src/imagekit/types/custom_metadata_field_create_params.py +++ b/src/imagekit/types/custom_metadata_field_create_params.py @@ -32,7 +32,9 @@ class Schema(TypedDict, total=False): type: Required[Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"]] """Type of the custom metadata field.""" - default_value: Annotated[Union[str, float, bool, List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue")] + default_value: Annotated[ + Union[Union[str, float, bool], List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") + ] """The default value for this custom metadata field. This property is only required if `isValueRequired` property is set to `true`. diff --git a/src/imagekit/types/custom_metadata_field_create_response.py b/src/imagekit/types/custom_metadata_field_create_response.py index dceb4f6..7a410fd 100644 --- a/src/imagekit/types/custom_metadata_field_create_response.py +++ b/src/imagekit/types/custom_metadata_field_create_response.py @@ -14,7 +14,7 @@ class Schema(BaseModel): type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] """Type of the custom metadata field.""" - default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( + default_value: Union[Union[str, float, bool], List[Union[str, float, bool]], None] = FieldInfo( alias="defaultValue", default=None ) """The default value for this custom metadata field. diff --git a/src/imagekit/types/custom_metadata_field_list_response.py b/src/imagekit/types/custom_metadata_field_list_response.py index 03f6c25..288df0b 100644 --- a/src/imagekit/types/custom_metadata_field_list_response.py +++ b/src/imagekit/types/custom_metadata_field_list_response.py @@ -18,7 +18,7 @@ class CustomMetadataFieldListResponseItemSchema(BaseModel): type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] """Type of the custom metadata field.""" - default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( + default_value: Union[Union[str, float, bool], List[Union[str, float, bool]], None] = FieldInfo( alias="defaultValue", default=None ) """The default value for this custom metadata field. diff --git a/src/imagekit/types/custom_metadata_field_update_params.py b/src/imagekit/types/custom_metadata_field_update_params.py index ba751cc..ec68e2a 100644 --- a/src/imagekit/types/custom_metadata_field_update_params.py +++ b/src/imagekit/types/custom_metadata_field_update_params.py @@ -30,7 +30,9 @@ class CustomMetadataFieldUpdateParams(TypedDict, total=False): class Schema(TypedDict, total=False): - default_value: Annotated[Union[str, float, bool, List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue")] + default_value: Annotated[ + Union[Union[str, float, bool], List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") + ] """The default value for this custom metadata field. This property is only required if `isValueRequired` property is set to `true`. diff --git a/src/imagekit/types/custom_metadata_field_update_response.py b/src/imagekit/types/custom_metadata_field_update_response.py index 3789663..869ac16 100644 --- a/src/imagekit/types/custom_metadata_field_update_response.py +++ b/src/imagekit/types/custom_metadata_field_update_response.py @@ -14,7 +14,7 @@ class Schema(BaseModel): type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] """Type of the custom metadata field.""" - default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( + default_value: Union[Union[str, float, bool], List[Union[str, float, bool]], None] = FieldInfo( alias="defaultValue", default=None ) """The default value for this custom metadata field. diff --git a/tests/api_resources/test_custom_metadata_fields.py b/tests/api_resources/test_custom_metadata_fields.py index 77adcf5..f540f73 100644 --- a/tests/api_resources/test_custom_metadata_fields.py +++ b/tests/api_resources/test_custom_metadata_fields.py @@ -40,7 +40,7 @@ def test_method_create_with_all_params(self, client: ImageKit) -> None: name="price", schema={ "type": "Number", - "default_value": "string", + "default_value": "Hello", "is_value_required": True, "max_length": 0, "max_value": 3000, @@ -96,7 +96,7 @@ def test_method_update_with_all_params(self, client: ImageKit) -> None: id="id", label="price", schema={ - "default_value": "string", + "default_value": "Hello", "is_value_required": True, "max_length": 0, "max_value": 3000, @@ -243,7 +243,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncImageKit) name="price", schema={ "type": "Number", - "default_value": "string", + "default_value": "Hello", "is_value_required": True, "max_length": 0, "max_value": 3000, @@ -299,7 +299,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncImageKit) id="id", label="price", schema={ - "default_value": "string", + "default_value": "Hello", "is_value_required": True, "max_length": 0, "max_value": 3000, From 9e5e08d0ff18595e267b382ccde1f1bb12a2e696 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:23:47 +0000 Subject: [PATCH 025/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index fe62740..134be34 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-cb74df1af0b7cdd4f66573d2d002f003b74702172ddd2c8495c465a7706c4d66.yml -openapi_spec_hash: 9a1fb60cda92b3e693e8c0f0fde0508a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-6db4fc859c70677af91f711d10e420694e96273880b0dc7931be2c7cf7a68586.yml +openapi_spec_hash: d4060e780214d95ccd90306aa8f2e28b config_hash: c9b1142a72b93ad4d66f0433dca1392e From cb54bcab99dd0e7f1695759660289aa4bd36af30 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:30:42 +0000 Subject: [PATCH 026/177] feat(api): manual updates --- .stats.yml | 4 ++-- src/imagekit/types/custom_metadata_field_create_params.py | 4 +--- .../types/custom_metadata_field_create_response.py | 2 +- src/imagekit/types/custom_metadata_field_list_response.py | 2 +- src/imagekit/types/custom_metadata_field_update_params.py | 4 +--- .../types/custom_metadata_field_update_response.py | 2 +- tests/api_resources/test_custom_metadata_fields.py | 8 ++++---- 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/.stats.yml b/.stats.yml index 134be34..3ae65fa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-6db4fc859c70677af91f711d10e420694e96273880b0dc7931be2c7cf7a68586.yml -openapi_spec_hash: d4060e780214d95ccd90306aa8f2e28b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-cb2369e849b98127ee6a2cbd01d928e4546d29c1a0a8e64e9b46f90189c1a992.yml +openapi_spec_hash: f8e732e88daf7c4bfbeb2bd2cdba2cec config_hash: c9b1142a72b93ad4d66f0433dca1392e diff --git a/src/imagekit/types/custom_metadata_field_create_params.py b/src/imagekit/types/custom_metadata_field_create_params.py index a0beccf..1d029fd 100644 --- a/src/imagekit/types/custom_metadata_field_create_params.py +++ b/src/imagekit/types/custom_metadata_field_create_params.py @@ -32,9 +32,7 @@ class Schema(TypedDict, total=False): type: Required[Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"]] """Type of the custom metadata field.""" - default_value: Annotated[ - Union[Union[str, float, bool], List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") - ] + default_value: Annotated[Union[str, float, bool, List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue")] """The default value for this custom metadata field. This property is only required if `isValueRequired` property is set to `true`. diff --git a/src/imagekit/types/custom_metadata_field_create_response.py b/src/imagekit/types/custom_metadata_field_create_response.py index 7a410fd..dceb4f6 100644 --- a/src/imagekit/types/custom_metadata_field_create_response.py +++ b/src/imagekit/types/custom_metadata_field_create_response.py @@ -14,7 +14,7 @@ class Schema(BaseModel): type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] """Type of the custom metadata field.""" - default_value: Union[Union[str, float, bool], List[Union[str, float, bool]], None] = FieldInfo( + default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( alias="defaultValue", default=None ) """The default value for this custom metadata field. diff --git a/src/imagekit/types/custom_metadata_field_list_response.py b/src/imagekit/types/custom_metadata_field_list_response.py index 288df0b..03f6c25 100644 --- a/src/imagekit/types/custom_metadata_field_list_response.py +++ b/src/imagekit/types/custom_metadata_field_list_response.py @@ -18,7 +18,7 @@ class CustomMetadataFieldListResponseItemSchema(BaseModel): type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] """Type of the custom metadata field.""" - default_value: Union[Union[str, float, bool], List[Union[str, float, bool]], None] = FieldInfo( + default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( alias="defaultValue", default=None ) """The default value for this custom metadata field. diff --git a/src/imagekit/types/custom_metadata_field_update_params.py b/src/imagekit/types/custom_metadata_field_update_params.py index ec68e2a..ba751cc 100644 --- a/src/imagekit/types/custom_metadata_field_update_params.py +++ b/src/imagekit/types/custom_metadata_field_update_params.py @@ -30,9 +30,7 @@ class CustomMetadataFieldUpdateParams(TypedDict, total=False): class Schema(TypedDict, total=False): - default_value: Annotated[ - Union[Union[str, float, bool], List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") - ] + default_value: Annotated[Union[str, float, bool, List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue")] """The default value for this custom metadata field. This property is only required if `isValueRequired` property is set to `true`. diff --git a/src/imagekit/types/custom_metadata_field_update_response.py b/src/imagekit/types/custom_metadata_field_update_response.py index 869ac16..3789663 100644 --- a/src/imagekit/types/custom_metadata_field_update_response.py +++ b/src/imagekit/types/custom_metadata_field_update_response.py @@ -14,7 +14,7 @@ class Schema(BaseModel): type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] """Type of the custom metadata field.""" - default_value: Union[Union[str, float, bool], List[Union[str, float, bool]], None] = FieldInfo( + default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( alias="defaultValue", default=None ) """The default value for this custom metadata field. diff --git a/tests/api_resources/test_custom_metadata_fields.py b/tests/api_resources/test_custom_metadata_fields.py index f540f73..77adcf5 100644 --- a/tests/api_resources/test_custom_metadata_fields.py +++ b/tests/api_resources/test_custom_metadata_fields.py @@ -40,7 +40,7 @@ def test_method_create_with_all_params(self, client: ImageKit) -> None: name="price", schema={ "type": "Number", - "default_value": "Hello", + "default_value": "string", "is_value_required": True, "max_length": 0, "max_value": 3000, @@ -96,7 +96,7 @@ def test_method_update_with_all_params(self, client: ImageKit) -> None: id="id", label="price", schema={ - "default_value": "Hello", + "default_value": "string", "is_value_required": True, "max_length": 0, "max_value": 3000, @@ -243,7 +243,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncImageKit) name="price", schema={ "type": "Number", - "default_value": "Hello", + "default_value": "string", "is_value_required": True, "max_length": 0, "max_value": 3000, @@ -299,7 +299,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncImageKit) id="id", label="price", schema={ - "default_value": "Hello", + "default_value": "string", "is_value_required": True, "max_length": 0, "max_value": 3000, From bbaf3e8cb88451597f137eaf4799a4ffb7d6956e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:34:30 +0000 Subject: [PATCH 027/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3ae65fa..1bb527b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-cb2369e849b98127ee6a2cbd01d928e4546d29c1a0a8e64e9b46f90189c1a992.yml -openapi_spec_hash: f8e732e88daf7c4bfbeb2bd2cdba2cec +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-7da4f48715dfd85e3bbc25086d62dc4959fb6bd1a9c3fd3933cfe0e80f6ae244.yml +openapi_spec_hash: 260d09fbed77316aae394877e5239398 config_hash: c9b1142a72b93ad4d66f0433dca1392e From 1741c4faa1f08a86fa5c72a7a0f14bc8f6d3cb64 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:37:09 +0000 Subject: [PATCH 028/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1bb527b..825ee65 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-7da4f48715dfd85e3bbc25086d62dc4959fb6bd1a9c3fd3933cfe0e80f6ae244.yml -openapi_spec_hash: 260d09fbed77316aae394877e5239398 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-76afc867b06fdc43b339f2c7d19f25a46481b25e8264ca24ea43daa1ea9234fc.yml +openapi_spec_hash: a1455d2ab02c48a14551362dd8ec2261 config_hash: c9b1142a72b93ad4d66f0433dca1392e From 2223ad44dfc2bde37e74f2579da087ec0952da77 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:46:31 +0000 Subject: [PATCH 029/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 825ee65..aff1f7d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-76afc867b06fdc43b339f2c7d19f25a46481b25e8264ca24ea43daa1ea9234fc.yml -openapi_spec_hash: a1455d2ab02c48a14551362dd8ec2261 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d9f06036e82cb9fcefe298e18ab40671a4454cf02c433e42c7281391543fde39.yml +openapi_spec_hash: bfad95cff6d56f887ac5ecfa1ab2c7dd config_hash: c9b1142a72b93ad4d66f0433dca1392e From 22f7cd2a806119e27542f02bd696e76dff2a00a7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:17:23 +0000 Subject: [PATCH 030/177] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index aff1f7d..5a33818 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d9f06036e82cb9fcefe298e18ab40671a4454cf02c433e42c7281391543fde39.yml -openapi_spec_hash: bfad95cff6d56f887ac5ecfa1ab2c7dd -config_hash: c9b1142a72b93ad4d66f0433dca1392e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-ce1742072cca1d90af9b0be8cc75dac4f2d5b3258041c3cede545e6521f4d72a.yml +openapi_spec_hash: 5e896419003b5ef3728293241e9dd37e +config_hash: ecd4e1fc35135b5e53487ca547e46fd7 From a8ea27ed926b5152f5f1514d123b6e73ef7d5ff7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:18:27 +0000 Subject: [PATCH 031/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5a33818..ba9b6e5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-ce1742072cca1d90af9b0be8cc75dac4f2d5b3258041c3cede545e6521f4d72a.yml -openapi_spec_hash: 5e896419003b5ef3728293241e9dd37e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-a49c22a93734b90653ada66f9b336a7da952642572330f9713282ea6fc06990a.yml +openapi_spec_hash: 7e0a9ea9ef3fad500e045c0c3bc69762 config_hash: ecd4e1fc35135b5e53487ca547e46fd7 From 4bb102724d6868c4e0c9eb8c6ddf8d095df3ba90 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:29:01 +0000 Subject: [PATCH 032/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index ba9b6e5..bdd3cec 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-a49c22a93734b90653ada66f9b336a7da952642572330f9713282ea6fc06990a.yml -openapi_spec_hash: 7e0a9ea9ef3fad500e045c0c3bc69762 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-76afc867b06fdc43b339f2c7d19f25a46481b25e8264ca24ea43daa1ea9234fc.yml +openapi_spec_hash: a1455d2ab02c48a14551362dd8ec2261 config_hash: ecd4e1fc35135b5e53487ca547e46fd7 From 827bf3c9fe0e1c8098c2c5a719059aa0bf732196 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:34:49 +0000 Subject: [PATCH 033/177] feat(api): manual updates --- .stats.yml | 4 +- src/imagekit/resources/accounts/origins.py | 172 +++++++++++------- .../types/accounts/origin_create_params.py | 89 ++++++--- .../types/accounts/origin_update_params.py | 89 ++++++--- 4 files changed, 238 insertions(+), 116 deletions(-) diff --git a/.stats.yml b/.stats.yml index bdd3cec..fbcd50b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-76afc867b06fdc43b339f2c7d19f25a46481b25e8264ca24ea43daa1ea9234fc.yml -openapi_spec_hash: a1455d2ab02c48a14551362dd8ec2261 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-4abcc684cb38a6caeb1d20789c3f42f050aa02a1e11cd15b56a758b269961368.yml +openapi_spec_hash: c197897c7befdd521213bdaabbf8b134 config_hash: ecd4e1fc35135b5e53487ca547e46fd7 diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index 13c8d75..a921258 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -55,7 +55,9 @@ def create( bucket: str, name: str, secret_key: str, - type: Literal["S3"], + type: Literal[ + "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -105,7 +107,9 @@ def create( endpoint: str, name: str, secret_key: str, - type: Literal["S3_COMPATIBLE"], + type: Literal[ + "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -159,7 +163,9 @@ def create( bucket: str, name: str, secret_key: str, - type: Literal["CLOUDINARY_BACKUP"], + type: Literal[ + "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -206,7 +212,9 @@ def create( *, base_url: str, name: str, - type: Literal["WEB_FOLDER"], + type: Literal[ + "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, @@ -248,7 +256,9 @@ def create( self, *, name: str, - type: Literal["WEB_PROXY"], + type: Literal[ + "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -288,7 +298,9 @@ def create( client_email: str, name: str, private_key: str, - type: Literal["GCS"], + type: Literal[ + "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -329,7 +341,9 @@ def create( container: str, name: str, sas_token: str, - type: Literal["AZURE_BLOB"], + type: Literal[ + "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -371,7 +385,9 @@ def create( client_secret: str, name: str, password: str, - type: Literal["AKENEO_PIM"], + type: Literal[ + "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" + ], username: str, base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, @@ -430,14 +446,9 @@ def create( bucket: str | NotGiven = NOT_GIVEN, name: str, secret_key: str | NotGiven = NOT_GIVEN, - type: Literal["S3"] - | Literal["S3_COMPATIBLE"] - | Literal["CLOUDINARY_BACKUP"] - | Literal["WEB_FOLDER"] - | Literal["WEB_PROXY"] - | Literal["GCS"] - | Literal["AZURE_BLOB"] - | Literal["AKENEO_PIM"], + type: Literal[ + "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -509,7 +520,9 @@ def update( bucket: str, name: str, secret_key: str, - type: Literal["S3"], + type: Literal[ + "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -563,7 +576,9 @@ def update( endpoint: str, name: str, secret_key: str, - type: Literal["S3_COMPATIBLE"], + type: Literal[ + "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -621,7 +636,9 @@ def update( bucket: str, name: str, secret_key: str, - type: Literal["CLOUDINARY_BACKUP"], + type: Literal[ + "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -672,7 +689,9 @@ def update( *, base_url: str, name: str, - type: Literal["WEB_FOLDER"], + type: Literal[ + "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, @@ -718,7 +737,9 @@ def update( id: str, *, name: str, - type: Literal["WEB_PROXY"], + type: Literal[ + "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -762,7 +783,9 @@ def update( client_email: str, name: str, private_key: str, - type: Literal["GCS"], + type: Literal[ + "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -807,7 +830,9 @@ def update( container: str, name: str, sas_token: str, - type: Literal["AZURE_BLOB"], + type: Literal[ + "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -853,7 +878,9 @@ def update( client_secret: str, name: str, password: str, - type: Literal["AKENEO_PIM"], + type: Literal[ + "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" + ], username: str, base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, @@ -916,14 +943,9 @@ def update( bucket: str | NotGiven = NOT_GIVEN, name: str, secret_key: str | NotGiven = NOT_GIVEN, - type: Literal["S3"] - | Literal["S3_COMPATIBLE"] - | Literal["CLOUDINARY_BACKUP"] - | Literal["WEB_FOLDER"] - | Literal["WEB_PROXY"] - | Literal["GCS"] - | Literal["AZURE_BLOB"] - | Literal["AKENEO_PIM"], + type: Literal[ + "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1121,7 +1143,9 @@ async def create( bucket: str, name: str, secret_key: str, - type: Literal["S3"], + type: Literal[ + "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1171,7 +1195,9 @@ async def create( endpoint: str, name: str, secret_key: str, - type: Literal["S3_COMPATIBLE"], + type: Literal[ + "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1225,7 +1251,9 @@ async def create( bucket: str, name: str, secret_key: str, - type: Literal["CLOUDINARY_BACKUP"], + type: Literal[ + "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1272,7 +1300,9 @@ async def create( *, base_url: str, name: str, - type: Literal["WEB_FOLDER"], + type: Literal[ + "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, @@ -1314,7 +1344,9 @@ async def create( self, *, name: str, - type: Literal["WEB_PROXY"], + type: Literal[ + "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -1354,7 +1386,9 @@ async def create( client_email: str, name: str, private_key: str, - type: Literal["GCS"], + type: Literal[ + "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1395,7 +1429,9 @@ async def create( container: str, name: str, sas_token: str, - type: Literal["AZURE_BLOB"], + type: Literal[ + "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1437,7 +1473,9 @@ async def create( client_secret: str, name: str, password: str, - type: Literal["AKENEO_PIM"], + type: Literal[ + "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" + ], username: str, base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, @@ -1496,14 +1534,9 @@ async def create( bucket: str | NotGiven = NOT_GIVEN, name: str, secret_key: str | NotGiven = NOT_GIVEN, - type: Literal["S3"] - | Literal["S3_COMPATIBLE"] - | Literal["CLOUDINARY_BACKUP"] - | Literal["WEB_FOLDER"] - | Literal["WEB_PROXY"] - | Literal["GCS"] - | Literal["AZURE_BLOB"] - | Literal["AKENEO_PIM"], + type: Literal[ + "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1575,7 +1608,9 @@ async def update( bucket: str, name: str, secret_key: str, - type: Literal["S3"], + type: Literal[ + "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1629,7 +1664,9 @@ async def update( endpoint: str, name: str, secret_key: str, - type: Literal["S3_COMPATIBLE"], + type: Literal[ + "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1687,7 +1724,9 @@ async def update( bucket: str, name: str, secret_key: str, - type: Literal["CLOUDINARY_BACKUP"], + type: Literal[ + "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1738,7 +1777,9 @@ async def update( *, base_url: str, name: str, - type: Literal["WEB_FOLDER"], + type: Literal[ + "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, @@ -1784,7 +1825,9 @@ async def update( id: str, *, name: str, - type: Literal["WEB_PROXY"], + type: Literal[ + "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -1828,7 +1871,9 @@ async def update( client_email: str, name: str, private_key: str, - type: Literal["GCS"], + type: Literal[ + "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1873,7 +1918,9 @@ async def update( container: str, name: str, sas_token: str, - type: Literal["AZURE_BLOB"], + type: Literal[ + "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, @@ -1919,7 +1966,9 @@ async def update( client_secret: str, name: str, password: str, - type: Literal["AKENEO_PIM"], + type: Literal[ + "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" + ], username: str, base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, @@ -1982,14 +2031,9 @@ async def update( bucket: str | NotGiven = NOT_GIVEN, name: str, secret_key: str | NotGiven = NOT_GIVEN, - type: Literal["S3"] - | Literal["S3_COMPATIBLE"] - | Literal["CLOUDINARY_BACKUP"] - | Literal["WEB_FOLDER"] - | Literal["WEB_PROXY"] - | Literal["GCS"] - | Literal["AZURE_BLOB"] - | Literal["AKENEO_PIM"], + type: Literal[ + "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ], base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, include_canonical_header: bool | NotGiven = NOT_GIVEN, prefix: str | NotGiven = NOT_GIVEN, diff --git a/src/imagekit/types/accounts/origin_create_params.py b/src/imagekit/types/accounts/origin_create_params.py index 7489a1d..e977fba 100644 --- a/src/imagekit/types/accounts/origin_create_params.py +++ b/src/imagekit/types/accounts/origin_create_params.py @@ -9,18 +9,18 @@ __all__ = [ "OriginCreateParams", - "S3", - "S3Compatible", - "CloudinaryBackup", - "WebFolder", - "WebProxy", - "GoogleCloudStorageGcs", - "AzureBlobStorage", - "AkeneoPim", + "S3Origin", + "S3CompatibleOrigin", + "CloudinaryBackupOrigin", + "WebFolderOrigin", + "WebProxyOrigin", + "GcsOrigin", + "AzureBlobOrigin", + "AkeneoPimOrigin", ] -class S3(TypedDict, total=False): +class S3Origin(TypedDict, total=False): access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] """Access key for the bucket.""" @@ -33,7 +33,11 @@ class S3(TypedDict, total=False): secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] """Secret key for the bucket.""" - type: Required[Literal["S3"]] + type: Required[ + Literal[ + "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -45,7 +49,7 @@ class S3(TypedDict, total=False): """Path prefix inside the bucket.""" -class S3Compatible(TypedDict, total=False): +class S3CompatibleOrigin(TypedDict, total=False): access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] """Access key for the bucket.""" @@ -61,7 +65,11 @@ class S3Compatible(TypedDict, total=False): secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] """Secret key for the bucket.""" - type: Required[Literal["S3_COMPATIBLE"]] + type: Required[ + Literal[ + "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -76,7 +84,7 @@ class S3Compatible(TypedDict, total=False): """Use path-style S3 URLs?""" -class CloudinaryBackup(TypedDict, total=False): +class CloudinaryBackupOrigin(TypedDict, total=False): access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] """Access key for the bucket.""" @@ -89,7 +97,11 @@ class CloudinaryBackup(TypedDict, total=False): secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] """Secret key for the bucket.""" - type: Required[Literal["CLOUDINARY_BACKUP"]] + type: Required[ + Literal[ + "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -101,14 +113,18 @@ class CloudinaryBackup(TypedDict, total=False): """Path prefix inside the bucket.""" -class WebFolder(TypedDict, total=False): +class WebFolderOrigin(TypedDict, total=False): base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] """Root URL for the web folder origin.""" name: Required[str] """Display name of the origin.""" - type: Required[Literal["WEB_FOLDER"]] + type: Required[ + Literal[ + "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -120,11 +136,15 @@ class WebFolder(TypedDict, total=False): """Whether to send a Canonical header.""" -class WebProxy(TypedDict, total=False): +class WebProxyOrigin(TypedDict, total=False): name: Required[str] """Display name of the origin.""" - type: Required[Literal["WEB_PROXY"]] + type: Required[ + Literal[ + "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -133,7 +153,7 @@ class WebProxy(TypedDict, total=False): """Whether to send a Canonical header.""" -class GoogleCloudStorageGcs(TypedDict, total=False): +class GcsOrigin(TypedDict, total=False): bucket: Required[str] client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] @@ -143,7 +163,11 @@ class GoogleCloudStorageGcs(TypedDict, total=False): private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] - type: Required[Literal["GCS"]] + type: Required[ + Literal[ + "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -154,7 +178,7 @@ class GoogleCloudStorageGcs(TypedDict, total=False): prefix: str -class AzureBlobStorage(TypedDict, total=False): +class AzureBlobOrigin(TypedDict, total=False): account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] container: Required[str] @@ -164,7 +188,11 @@ class AzureBlobStorage(TypedDict, total=False): sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] - type: Required[Literal["AZURE_BLOB"]] + type: Required[ + Literal[ + "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -175,7 +203,7 @@ class AzureBlobStorage(TypedDict, total=False): prefix: str -class AkeneoPim(TypedDict, total=False): +class AkeneoPimOrigin(TypedDict, total=False): base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] """Akeneo instance base URL.""" @@ -191,7 +219,11 @@ class AkeneoPim(TypedDict, total=False): password: Required[str] """Akeneo API password.""" - type: Required[Literal["AKENEO_PIM"]] + type: Required[ + Literal[ + "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" + ] + ] username: Required[str] """Akeneo API username.""" @@ -204,5 +236,12 @@ class AkeneoPim(TypedDict, total=False): OriginCreateParams: TypeAlias = Union[ - S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim + S3Origin, + S3CompatibleOrigin, + CloudinaryBackupOrigin, + WebFolderOrigin, + WebProxyOrigin, + GcsOrigin, + AzureBlobOrigin, + AkeneoPimOrigin, ] diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekit/types/accounts/origin_update_params.py index a7b39fb..781d46b 100644 --- a/src/imagekit/types/accounts/origin_update_params.py +++ b/src/imagekit/types/accounts/origin_update_params.py @@ -9,18 +9,18 @@ __all__ = [ "OriginUpdateParams", - "S3", - "S3Compatible", - "CloudinaryBackup", - "WebFolder", - "WebProxy", - "GoogleCloudStorageGcs", - "AzureBlobStorage", - "AkeneoPim", + "S3Origin", + "S3CompatibleOrigin", + "CloudinaryBackupOrigin", + "WebFolderOrigin", + "WebProxyOrigin", + "GcsOrigin", + "AzureBlobOrigin", + "AkeneoPimOrigin", ] -class S3(TypedDict, total=False): +class S3Origin(TypedDict, total=False): access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] """Access key for the bucket.""" @@ -33,7 +33,11 @@ class S3(TypedDict, total=False): secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] """Secret key for the bucket.""" - type: Required[Literal["S3"]] + type: Required[ + Literal[ + "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -45,7 +49,7 @@ class S3(TypedDict, total=False): """Path prefix inside the bucket.""" -class S3Compatible(TypedDict, total=False): +class S3CompatibleOrigin(TypedDict, total=False): access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] """Access key for the bucket.""" @@ -61,7 +65,11 @@ class S3Compatible(TypedDict, total=False): secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] """Secret key for the bucket.""" - type: Required[Literal["S3_COMPATIBLE"]] + type: Required[ + Literal[ + "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -76,7 +84,7 @@ class S3Compatible(TypedDict, total=False): """Use path-style S3 URLs?""" -class CloudinaryBackup(TypedDict, total=False): +class CloudinaryBackupOrigin(TypedDict, total=False): access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] """Access key for the bucket.""" @@ -89,7 +97,11 @@ class CloudinaryBackup(TypedDict, total=False): secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] """Secret key for the bucket.""" - type: Required[Literal["CLOUDINARY_BACKUP"]] + type: Required[ + Literal[ + "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -101,14 +113,18 @@ class CloudinaryBackup(TypedDict, total=False): """Path prefix inside the bucket.""" -class WebFolder(TypedDict, total=False): +class WebFolderOrigin(TypedDict, total=False): base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] """Root URL for the web folder origin.""" name: Required[str] """Display name of the origin.""" - type: Required[Literal["WEB_FOLDER"]] + type: Required[ + Literal[ + "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -120,11 +136,15 @@ class WebFolder(TypedDict, total=False): """Whether to send a Canonical header.""" -class WebProxy(TypedDict, total=False): +class WebProxyOrigin(TypedDict, total=False): name: Required[str] """Display name of the origin.""" - type: Required[Literal["WEB_PROXY"]] + type: Required[ + Literal[ + "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -133,7 +153,7 @@ class WebProxy(TypedDict, total=False): """Whether to send a Canonical header.""" -class GoogleCloudStorageGcs(TypedDict, total=False): +class GcsOrigin(TypedDict, total=False): bucket: Required[str] client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] @@ -143,7 +163,11 @@ class GoogleCloudStorageGcs(TypedDict, total=False): private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] - type: Required[Literal["GCS"]] + type: Required[ + Literal[ + "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -154,7 +178,7 @@ class GoogleCloudStorageGcs(TypedDict, total=False): prefix: str -class AzureBlobStorage(TypedDict, total=False): +class AzureBlobOrigin(TypedDict, total=False): account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] container: Required[str] @@ -164,7 +188,11 @@ class AzureBlobStorage(TypedDict, total=False): sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] - type: Required[Literal["AZURE_BLOB"]] + type: Required[ + Literal[ + "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" + ] + ] base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] """URL used in the Canonical header (if enabled).""" @@ -175,7 +203,7 @@ class AzureBlobStorage(TypedDict, total=False): prefix: str -class AkeneoPim(TypedDict, total=False): +class AkeneoPimOrigin(TypedDict, total=False): base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] """Akeneo instance base URL.""" @@ -191,7 +219,11 @@ class AkeneoPim(TypedDict, total=False): password: Required[str] """Akeneo API password.""" - type: Required[Literal["AKENEO_PIM"]] + type: Required[ + Literal[ + "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" + ] + ] username: Required[str] """Akeneo API username.""" @@ -204,5 +236,12 @@ class AkeneoPim(TypedDict, total=False): OriginUpdateParams: TypeAlias = Union[ - S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim + S3Origin, + S3CompatibleOrigin, + CloudinaryBackupOrigin, + WebFolderOrigin, + WebProxyOrigin, + GcsOrigin, + AzureBlobOrigin, + AkeneoPimOrigin, ] From e72ef3a2a95fa9e2bb461e1a192de26b6038ce83 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:43:31 +0000 Subject: [PATCH 034/177] feat(api): manual updates --- .stats.yml | 4 +- src/imagekit/resources/accounts/origins.py | 1945 +------------- .../types/accounts/origin_create_params.py | 244 +- .../types/accounts/origin_update_params.py | 244 +- tests/api_resources/accounts/test_origins.py | 2370 ++--------------- 5 files changed, 362 insertions(+), 4445 deletions(-) diff --git a/.stats.yml b/.stats.yml index fbcd50b..0604c95 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-4abcc684cb38a6caeb1d20789c3f42f050aa02a1e11cd15b56a758b269961368.yml -openapi_spec_hash: c197897c7befdd521213bdaabbf8b134 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3fced4085838ae20641cfa2775c6d36757bbaae28415892b2e9ee438e3b56a85.yml +openapi_spec_hash: 58327d97499fdad00856caa35ca3f16a config_hash: ecd4e1fc35135b5e53487ca547e46fd7 diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index a921258..f4e565d 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -3,12 +3,11 @@ from __future__ import annotations from typing import Any, cast -from typing_extensions import Literal, overload import httpx from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from ..._utils import required_args, maybe_transform, async_maybe_transform +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -47,20 +46,10 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: """ return OriginsResourceWithStreamingResponse(self) - @overload def create( self, *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal[ - "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + body: origin_create_params.Body, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -74,1440 +63,6 @@ def create( Creates a new origin and returns the origin object. Args: - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def create( - self, - *, - access_key: str, - bucket: str, - endpoint: str, - name: str, - secret_key: str, - type: Literal[ - "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - endpoint: Custom S3-compatible endpoint. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - s3_force_path_style: Use path-style S3 URLs? - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def create( - self, - *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal[ - "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def create( - self, - *, - base_url: str, - name: str, - type: Literal[ - "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - base_url: Root URL for the web folder origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - forward_host_header_to_origin: Forward the Host header to origin? - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def create( - self, - *, - name: str, - type: Literal[ - "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def create( - self, - *, - bucket: str, - client_email: str, - name: str, - private_key: str, - type: Literal[ - "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def create( - self, - *, - account_name: str, - container: str, - name: str, - sas_token: str, - type: Literal[ - "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def create( - self, - *, - base_url: str, - client_id: str, - client_secret: str, - name: str, - password: str, - type: Literal[ - "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" - ], - username: str, - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - base_url: Akeneo instance base URL. - - client_id: Akeneo API client ID. - - client_secret: Akeneo API client secret. - - name: Display name of the origin. - - password: Akeneo API password. - - username: Akeneo API username. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @required_args( - ["access_key", "bucket", "name", "secret_key", "type"], - ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], - ["base_url", "name", "type"], - ["name", "type"], - ["bucket", "client_email", "name", "private_key", "type"], - ["account_name", "container", "name", "sas_token", "type"], - ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], - ) - def create( - self, - *, - access_key: str | NotGiven = NOT_GIVEN, - bucket: str | NotGiven = NOT_GIVEN, - name: str, - secret_key: str | NotGiven = NOT_GIVEN, - type: Literal[ - "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - endpoint: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - base_url: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - client_email: str | NotGiven = NOT_GIVEN, - private_key: str | NotGiven = NOT_GIVEN, - account_name: str | NotGiven = NOT_GIVEN, - container: str | NotGiven = NOT_GIVEN, - sas_token: str | NotGiven = NOT_GIVEN, - client_id: str | NotGiven = NOT_GIVEN, - client_secret: str | NotGiven = NOT_GIVEN, - password: str | NotGiven = NOT_GIVEN, - username: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - return cast( - OriginCreateResponse, - self._post( - "/v1/accounts/origins", - body=maybe_transform( - { - "access_key": access_key, - "bucket": bucket, - "name": name, - "secret_key": secret_key, - "type": type, - "base_url_for_canonical_header": base_url_for_canonical_header, - "include_canonical_header": include_canonical_header, - "prefix": prefix, - "endpoint": endpoint, - "s3_force_path_style": s3_force_path_style, - "base_url": base_url, - "forward_host_header_to_origin": forward_host_header_to_origin, - "client_email": client_email, - "private_key": private_key, - "account_name": account_name, - "container": container, - "sas_token": sas_token, - "client_id": client_id, - "client_secret": client_secret, - "password": password, - "username": username, - }, - origin_create_params.OriginCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast( - Any, OriginCreateResponse - ), # Union types cannot be passed in as arguments in the type system - ), - ) - - @overload - def update( - self, - id: str, - *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal[ - "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - access_key: str, - bucket: str, - endpoint: str, - name: str, - secret_key: str, - type: Literal[ - "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - endpoint: Custom S3-compatible endpoint. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - s3_force_path_style: Use path-style S3 URLs? - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal[ - "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - base_url: str, - name: str, - type: Literal[ - "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - base_url: Root URL for the web folder origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - forward_host_header_to_origin: Forward the Host header to origin? - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - name: str, - type: Literal[ - "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - bucket: str, - client_email: str, - name: str, - private_key: str, - type: Literal[ - "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - account_name: str, - container: str, - name: str, - sas_token: str, - type: Literal[ - "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - base_url: str, - client_id: str, - client_secret: str, - name: str, - password: str, - type: Literal[ - "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" - ], - username: str, - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - base_url: Akeneo instance base URL. - - client_id: Akeneo API client ID. - - client_secret: Akeneo API client secret. - - name: Display name of the origin. - - password: Akeneo API password. - - username: Akeneo API username. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @required_args( - ["access_key", "bucket", "name", "secret_key", "type"], - ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], - ["base_url", "name", "type"], - ["name", "type"], - ["bucket", "client_email", "name", "private_key", "type"], - ["account_name", "container", "name", "sas_token", "type"], - ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], - ) - def update( - self, - id: str, - *, - access_key: str | NotGiven = NOT_GIVEN, - bucket: str | NotGiven = NOT_GIVEN, - name: str, - secret_key: str | NotGiven = NOT_GIVEN, - type: Literal[ - "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - endpoint: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - base_url: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - client_email: str | NotGiven = NOT_GIVEN, - private_key: str | NotGiven = NOT_GIVEN, - account_name: str | NotGiven = NOT_GIVEN, - container: str | NotGiven = NOT_GIVEN, - sas_token: str | NotGiven = NOT_GIVEN, - client_id: str | NotGiven = NOT_GIVEN, - client_secret: str | NotGiven = NOT_GIVEN, - password: str | NotGiven = NOT_GIVEN, - username: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return cast( - OriginUpdateResponse, - self._put( - f"/v1/accounts/origins/{id}", - body=maybe_transform( - { - "access_key": access_key, - "bucket": bucket, - "name": name, - "secret_key": secret_key, - "type": type, - "base_url_for_canonical_header": base_url_for_canonical_header, - "include_canonical_header": include_canonical_header, - "prefix": prefix, - "endpoint": endpoint, - "s3_force_path_style": s3_force_path_style, - "base_url": base_url, - "forward_host_header_to_origin": forward_host_header_to_origin, - "client_email": client_email, - "private_key": private_key, - "account_name": account_name, - "container": container, - "sas_token": sas_token, - "client_id": client_id, - "client_secret": client_secret, - "password": password, - "username": username, - }, - origin_update_params.OriginUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast( - Any, OriginUpdateResponse - ), # Union types cannot be passed in as arguments in the type system - ), - ) - - def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginListResponse: - """**Note:** This API is currently in beta. - - - Returns an array of all configured origins for the current account. - """ - return self._get( - "/v1/accounts/origins", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=OriginListResponse, - ) - - def delete( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> None: - """**Note:** This API is currently in beta. - - - Permanently removes the origin identified by `id`. If the origin is in use by - any URL‑endpoints, the API will return an error. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - f"/v1/accounts/origins/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def get( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginGetResponse: - """**Note:** This API is currently in beta. - - - Retrieves the origin identified by `id`. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return cast( - OriginGetResponse, - self._get( - f"/v1/accounts/origins/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast(Any, OriginGetResponse), # Union types cannot be passed in as arguments in the type system - ), - ) - - -class AsyncOriginsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers - """ - return AsyncOriginsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response - """ - return AsyncOriginsResourceWithStreamingResponse(self) - - @overload - async def create( - self, - *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal[ - "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def create( - self, - *, - access_key: str, - bucket: str, - endpoint: str, - name: str, - secret_key: str, - type: Literal[ - "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - endpoint: Custom S3-compatible endpoint. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - s3_force_path_style: Use path-style S3 URLs? - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def create( - self, - *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal[ - "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def create( - self, - *, - base_url: str, - name: str, - type: Literal[ - "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - base_url: Root URL for the web folder origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - forward_host_header_to_origin: Forward the Host header to origin? - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def create( - self, - *, - name: str, - type: Literal[ - "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def create( - self, - *, - bucket: str, - client_email: str, - name: str, - private_key: str, - type: Literal[ - "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def create( - self, - *, - account_name: str, - container: str, - name: str, - sas_token: str, - type: Literal[ - "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def create( - self, - *, - base_url: str, - client_id: str, - client_secret: str, - name: str, - password: str, - type: Literal[ - "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" - ], - username: str, - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: - base_url: Akeneo instance base URL. - - client_id: Akeneo API client ID. - - client_secret: Akeneo API client secret. - - name: Display name of the origin. - - password: Akeneo API password. - - username: Akeneo API username. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1516,80 +71,11 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @required_args( - ["access_key", "bucket", "name", "secret_key", "type"], - ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], - ["base_url", "name", "type"], - ["name", "type"], - ["bucket", "client_email", "name", "private_key", "type"], - ["account_name", "container", "name", "sas_token", "type"], - ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], - ) - async def create( - self, - *, - access_key: str | NotGiven = NOT_GIVEN, - bucket: str | NotGiven = NOT_GIVEN, - name: str, - secret_key: str | NotGiven = NOT_GIVEN, - type: Literal[ - "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - endpoint: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - base_url: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - client_email: str | NotGiven = NOT_GIVEN, - private_key: str | NotGiven = NOT_GIVEN, - account_name: str | NotGiven = NOT_GIVEN, - container: str | NotGiven = NOT_GIVEN, - sas_token: str | NotGiven = NOT_GIVEN, - client_id: str | NotGiven = NOT_GIVEN, - client_secret: str | NotGiven = NOT_GIVEN, - password: str | NotGiven = NOT_GIVEN, - username: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: return cast( OriginCreateResponse, - await self._post( + self._post( "/v1/accounts/origins", - body=await async_maybe_transform( - { - "access_key": access_key, - "bucket": bucket, - "name": name, - "secret_key": secret_key, - "type": type, - "base_url_for_canonical_header": base_url_for_canonical_header, - "include_canonical_header": include_canonical_header, - "prefix": prefix, - "endpoint": endpoint, - "s3_force_path_style": s3_force_path_style, - "base_url": base_url, - "forward_host_header_to_origin": forward_host_header_to_origin, - "client_email": client_email, - "private_key": private_key, - "account_name": account_name, - "container": container, - "sas_token": sas_token, - "client_id": client_id, - "client_secret": client_secret, - "password": password, - "username": username, - }, - origin_create_params.OriginCreateParams, - ), + body=maybe_transform(body, origin_create_params.OriginCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1599,21 +85,11 @@ async def create( ), ) - @overload - async def update( + def update( self, id: str, *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal[ - "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + body: origin_update_params.Body, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1630,20 +106,6 @@ async def update( id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1652,114 +114,66 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginUpdateResponse, + self._put( + f"/v1/accounts/origins/{id}", + body=maybe_transform(body, origin_update_params.OriginUpdateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, OriginUpdateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) - @overload - async def update( + def list( self, - id: str, *, - access_key: str, - bucket: str, - endpoint: str, - name: str, - secret_key: str, - type: Literal[ - "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: + ) -> OriginListResponse: """**Note:** This API is currently in beta. - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - endpoint: Custom S3-compatible endpoint. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - s3_force_path_style: Use path-style S3 URLs? - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + Returns an array of all configured origins for the current account. """ - ... + return self._get( + "/v1/accounts/origins", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=OriginListResponse, + ) - @overload - async def update( + def delete( self, id: str, *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal[ - "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: + ) -> None: """**Note:** This API is currently in beta. - Updates the origin identified by `id` and returns the updated origin object. + Permanently removes the origin identified by `id`. If the origin is in use by + any URL‑endpoints, the API will return an error. Args: id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1768,47 +182,37 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) - @overload - async def update( + def get( self, id: str, *, - base_url: str, - name: str, - type: Literal[ - "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: + ) -> OriginGetResponse: """**Note:** This API is currently in beta. - Updates the origin identified by `id` and returns the updated origin object. + Retrieves the origin identified by `id`. Args: id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - base_url: Root URL for the web folder origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - forward_host_header_to_origin: Forward the Host header to origin? - - include_canonical_header: Whether to send a Canonical header. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1817,135 +221,57 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @overload - async def update( - self, - id: str, - *, - name: str, - type: Literal[ - "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginGetResponse, + self._get( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast(Any, OriginGetResponse), # Union types cannot be passed in as arguments in the type system + ), + ) - extra_body: Add additional JSON properties to the request - timeout: Override the client-level default timeout for this request, in seconds +class AsyncOriginsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: """ - ... - - @overload - async def update( - self, - id: str, - *, - bucket: str, - client_email: str, - name: str, - private_key: str, - type: Literal[ - "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. - extra_query: Add additional query parameters to the request + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncOriginsResourceWithRawResponse(self) - extra_body: Add additional JSON properties to the request + @cached_property + def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. - timeout: Override the client-level default timeout for this request, in seconds + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ - ... + return AsyncOriginsResourceWithStreamingResponse(self) - @overload - async def update( + async def create( self, - id: str, *, - account_name: str, - container: str, - name: str, - sas_token: str, - type: Literal[ - "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + body: origin_create_params.Body, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: + ) -> OriginCreateResponse: """**Note:** This API is currently in beta. - Updates the origin identified by `id` and returns the updated origin object. + Creates a new origin and returns the origin object. Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1954,24 +280,25 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... + return cast( + OriginCreateResponse, + await self._post( + "/v1/accounts/origins", + body=await async_maybe_transform(body, origin_create_params.OriginCreateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, OriginCreateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) - @overload async def update( self, id: str, *, - base_url: str, - client_id: str, - client_secret: str, - name: str, - password: str, - type: Literal[ - "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" - ], - username: str, - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + body: origin_update_params.Body, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1988,22 +315,6 @@ async def update( id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - base_url: Akeneo instance base URL. - - client_id: Akeneo API client ID. - - client_secret: Akeneo API client secret. - - name: Display name of the origin. - - password: Akeneo API password. - - username: Akeneo API username. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -2012,83 +323,13 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @required_args( - ["access_key", "bucket", "name", "secret_key", "type"], - ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], - ["base_url", "name", "type"], - ["name", "type"], - ["bucket", "client_email", "name", "private_key", "type"], - ["account_name", "container", "name", "sas_token", "type"], - ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], - ) - async def update( - self, - id: str, - *, - access_key: str | NotGiven = NOT_GIVEN, - bucket: str | NotGiven = NOT_GIVEN, - name: str, - secret_key: str | NotGiven = NOT_GIVEN, - type: Literal[ - "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - endpoint: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - base_url: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - client_email: str | NotGiven = NOT_GIVEN, - private_key: str | NotGiven = NOT_GIVEN, - account_name: str | NotGiven = NOT_GIVEN, - container: str | NotGiven = NOT_GIVEN, - sas_token: str | NotGiven = NOT_GIVEN, - client_id: str | NotGiven = NOT_GIVEN, - client_secret: str | NotGiven = NOT_GIVEN, - password: str | NotGiven = NOT_GIVEN, - username: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( OriginUpdateResponse, await self._put( f"/v1/accounts/origins/{id}", - body=await async_maybe_transform( - { - "access_key": access_key, - "bucket": bucket, - "name": name, - "secret_key": secret_key, - "type": type, - "base_url_for_canonical_header": base_url_for_canonical_header, - "include_canonical_header": include_canonical_header, - "prefix": prefix, - "endpoint": endpoint, - "s3_force_path_style": s3_force_path_style, - "base_url": base_url, - "forward_host_header_to_origin": forward_host_header_to_origin, - "client_email": client_email, - "private_key": private_key, - "account_name": account_name, - "container": container, - "sas_token": sas_token, - "client_id": client_id, - "client_secret": client_secret, - "password": password, - "username": username, - }, - origin_update_params.OriginUpdateParams, - ), + body=await async_maybe_transform(body, origin_update_params.OriginUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/imagekit/types/accounts/origin_create_params.py b/src/imagekit/types/accounts/origin_create_params.py index e977fba..07126d0 100644 --- a/src/imagekit/types/accounts/origin_create_params.py +++ b/src/imagekit/types/accounts/origin_create_params.py @@ -2,246 +2,14 @@ from __future__ import annotations -from typing import Union -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Required, TypedDict -from ..._utils import PropertyInfo +__all__ = ["OriginCreateParams", "Body"] -__all__ = [ - "OriginCreateParams", - "S3Origin", - "S3CompatibleOrigin", - "CloudinaryBackupOrigin", - "WebFolderOrigin", - "WebProxyOrigin", - "GcsOrigin", - "AzureBlobOrigin", - "AkeneoPimOrigin", -] +class OriginCreateParams(TypedDict, total=False): + body: Required[Body] -class S3Origin(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[ - Literal[ - "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class S3CompatibleOrigin(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - endpoint: Required[str] - """Custom S3-compatible endpoint.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[ - Literal[ - "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] - """Use path-style S3 URLs?""" - - -class CloudinaryBackupOrigin(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[ - Literal[ - "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class WebFolderOrigin(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Root URL for the web folder origin.""" - - name: Required[str] - """Display name of the origin.""" - - type: Required[ - Literal[ - "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] - """Forward the Host header to origin?""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class WebProxyOrigin(TypedDict, total=False): - name: Required[str] - """Display name of the origin.""" - - type: Required[ - Literal[ - "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class GcsOrigin(TypedDict, total=False): - bucket: Required[str] - - client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] - - name: Required[str] - """Display name of the origin.""" - - private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] - - type: Required[ - Literal[ - "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class AzureBlobOrigin(TypedDict, total=False): - account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] - - container: Required[str] - - name: Required[str] - """Display name of the origin.""" - - sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] - - type: Required[ - Literal[ - "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class AkeneoPimOrigin(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Akeneo instance base URL.""" - - client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] - """Akeneo API client ID.""" - - client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] - """Akeneo API client secret.""" - - name: Required[str] - """Display name of the origin.""" - - password: Required[str] - """Akeneo API password.""" - - type: Required[ - Literal[ - "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" - ] - ] - - username: Required[str] - """Akeneo API username.""" - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -OriginCreateParams: TypeAlias = Union[ - S3Origin, - S3CompatibleOrigin, - CloudinaryBackupOrigin, - WebFolderOrigin, - WebProxyOrigin, - GcsOrigin, - AzureBlobOrigin, - AkeneoPimOrigin, -] +class Body(total=False): + pass diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekit/types/accounts/origin_update_params.py index 781d46b..8393247 100644 --- a/src/imagekit/types/accounts/origin_update_params.py +++ b/src/imagekit/types/accounts/origin_update_params.py @@ -2,246 +2,14 @@ from __future__ import annotations -from typing import Union -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Required, TypedDict -from ..._utils import PropertyInfo +__all__ = ["OriginUpdateParams", "Body"] -__all__ = [ - "OriginUpdateParams", - "S3Origin", - "S3CompatibleOrigin", - "CloudinaryBackupOrigin", - "WebFolderOrigin", - "WebProxyOrigin", - "GcsOrigin", - "AzureBlobOrigin", - "AkeneoPimOrigin", -] +class OriginUpdateParams(TypedDict, total=False): + body: Required[Body] -class S3Origin(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[ - Literal[ - "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class S3CompatibleOrigin(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - endpoint: Required[str] - """Custom S3-compatible endpoint.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[ - Literal[ - "S3_COMPATIBLE", "S3", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] - """Use path-style S3 URLs?""" - - -class CloudinaryBackupOrigin(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[ - Literal[ - "CLOUDINARY_BACKUP", "S3", "S3_COMPATIBLE", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class WebFolderOrigin(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Root URL for the web folder origin.""" - - name: Required[str] - """Display name of the origin.""" - - type: Required[ - Literal[ - "WEB_FOLDER", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_PROXY", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] - """Forward the Host header to origin?""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class WebProxyOrigin(TypedDict, total=False): - name: Required[str] - """Display name of the origin.""" - - type: Required[ - Literal[ - "WEB_PROXY", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "GCS", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class GcsOrigin(TypedDict, total=False): - bucket: Required[str] - - client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] - - name: Required[str] - """Display name of the origin.""" - - private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] - - type: Required[ - Literal[ - "GCS", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "AZURE_BLOB", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class AzureBlobOrigin(TypedDict, total=False): - account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] - - container: Required[str] - - name: Required[str] - """Display name of the origin.""" - - sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] - - type: Required[ - Literal[ - "AZURE_BLOB", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AKENEO_PIM" - ] - ] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class AkeneoPimOrigin(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Akeneo instance base URL.""" - - client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] - """Akeneo API client ID.""" - - client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] - """Akeneo API client secret.""" - - name: Required[str] - """Display name of the origin.""" - - password: Required[str] - """Akeneo API password.""" - - type: Required[ - Literal[ - "AKENEO_PIM", "S3", "S3_COMPATIBLE", "CLOUDINARY_BACKUP", "WEB_FOLDER", "WEB_PROXY", "GCS", "AZURE_BLOB" - ] - ] - - username: Required[str] - """Akeneo API username.""" - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -OriginUpdateParams: TypeAlias = Union[ - S3Origin, - S3CompatibleOrigin, - CloudinaryBackupOrigin, - WebFolderOrigin, - WebProxyOrigin, - GcsOrigin, - AzureBlobOrigin, - AkeneoPimOrigin, -] +class Body(total=False): + pass diff --git a/tests/api_resources/accounts/test_origins.py b/tests/api_resources/accounts/test_origins.py index ae49f15..90c2a36 100644 --- a/tests/api_resources/accounts/test_origins.py +++ b/tests/api_resources/accounts/test_origins.py @@ -24,2263 +24,409 @@ class TestOrigins: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_create_overload_1(self, client: ImageKit) -> None: + def test_method_create(self, client: ImageKit) -> None: origin = client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", + body={ + "name": "name", + "type": "S3", + }, ) assert_matches_type(OriginCreateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_create_with_all_params_overload_1(self, client: ImageKit) -> None: + def test_method_create_with_all_params(self, client: ImageKit) -> None: origin = client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_create_overload_1(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_create_overload_1(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_overload_2(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_with_all_params_overload_2(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - s3_force_path_style=True, - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_create_overload_2(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_create_overload_2(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_overload_3(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_with_all_params_overload_3(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_create_overload_3(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_create_overload_3(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_overload_4(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_with_all_params_overload_4(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - base_url_for_canonical_header="https://cdn.example.com", - forward_host_header_to_origin=False, - include_canonical_header=False, - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_create_overload_4(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.create( - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_create_overload_4(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.create( - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_overload_5(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - name="US S3 Storage", - type="WEB_PROXY", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_with_all_params_overload_5(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - name="US S3 Storage", - type="WEB_PROXY", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_create_overload_5(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.create( - name="US S3 Storage", - type="WEB_PROXY", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_create_overload_5(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.create( - name="US S3 Storage", - type="WEB_PROXY", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_overload_6(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_with_all_params_overload_6(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="products", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_create_overload_6(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.create( - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_create_overload_6(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.create( - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_overload_7(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_with_all_params_overload_7(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="uploads", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_create_overload_7(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.create( - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_create_overload_7(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.create( - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_overload_8(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_with_all_params_overload_8(self, client: ImageKit) -> None: - origin = client.accounts.origins.create( - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_create_overload_8(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.create( - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_create_overload_8(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.create( - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_1(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_1(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_1(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_2(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - s3_force_path_style=True, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_2(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_2(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_3(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_3(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_3(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_3(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_3(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_4(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_4(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - base_url_for_canonical_header="https://cdn.example.com", - forward_host_header_to_origin=False, - include_canonical_header=False, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_4(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_4(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_4(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_5(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_5(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_5(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_5(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_5(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - name="US S3 Storage", - type="WEB_PROXY", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_6(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_6(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="products", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_6(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_6(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_6(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_7(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_7(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="uploads", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_7(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_7(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_7(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_8(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_8(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_8(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_8(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_8(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_list(self, client: ImageKit) -> None: - origin = client.accounts.origins.list() - assert_matches_type(OriginListResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_list(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginListResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_list(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginListResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_delete(self, client: ImageKit) -> None: - origin = client.accounts.origins.delete( - "id", - ) - assert origin is None - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_delete(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.delete( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert origin is None - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_delete(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.delete( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert origin is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_delete(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.delete( - "", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_get(self, client: ImageKit) -> None: - origin = client.accounts.origins.get( - "id", - ) - assert_matches_type(OriginGetResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_get(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.get( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginGetResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_get(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.get( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginGetResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_get(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.get( - "", - ) - - -class TestAsyncOrigins: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_overload_1(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create_overload_1(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create_overload_1(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_overload_2(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - s3_force_path_style=True, - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create_overload_2(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create_overload_2(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_overload_3(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_with_all_params_overload_3(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create_overload_3(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create_overload_3(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_overload_4(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_with_all_params_overload_4(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - base_url_for_canonical_header="https://cdn.example.com", - forward_host_header_to_origin=False, - include_canonical_header=False, - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create_overload_4(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create_overload_4(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_overload_5(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - name="US S3 Storage", - type="WEB_PROXY", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_with_all_params_overload_5(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - name="US S3 Storage", - type="WEB_PROXY", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create_overload_5(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( - name="US S3 Storage", - type="WEB_PROXY", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create_overload_5(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - name="US S3 Storage", - type="WEB_PROXY", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_overload_6(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_with_all_params_overload_6(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="products", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create_overload_6(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create_overload_6(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_overload_7(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_with_all_params_overload_7(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="uploads", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create_overload_7(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create_overload_7(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_overload_8(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_with_all_params_overload_8(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create_overload_8(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create_overload_8(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", + body={ + "name": "name", + "type": "S3", + "access_key": "x", + "account_name": "x", + "base_url": "https://example.com", + "base_url_for_canonical_header": "https://example.com", + "bucket": "x", + "client_email": "dev@stainless.com", + "client_id": "x", + "client_secret": "x", + "container": "x", + "endpoint": "https://example.com", + "forward_host_header_to_origin": True, + "include_canonical_header": True, + "password": "x", + "prefix": "prefix", + "private_key": "x", + "s3_force_path_style": True, + "sas_token": "x", + "secret_key": "x", + "username": "x", + }, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + body={ + "name": "name", + "type": "S3", + }, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", + def test_streaming_response_create(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + body={ + "name": "name", + "type": "S3", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + origin = response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( + def test_method_update(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", + body={ + "name": "name", + "type": "S3", + }, ) assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( + def test_method_update_with_all_params(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - s3_force_path_style=True, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( + body={ + "name": "name", + "type": "S3", + "access_key": "x", + "account_name": "x", + "base_url": "https://example.com", + "base_url_for_canonical_header": "https://example.com", + "bucket": "x", + "client_email": "dev@stainless.com", + "client_id": "x", + "client_secret": "x", + "container": "x", + "endpoint": "https://example.com", + "forward_host_header_to_origin": True, + "include_canonical_header": True, + "password": "x", + "prefix": "prefix", + "private_key": "x", + "s3_force_path_style": True, + "sas_token": "x", + "secret_key": "x", + "username": "x", + }, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", + body={ + "name": "name", + "type": "S3", + }, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() + origin = response.parse() assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( + def test_streaming_response_update(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", + body={ + "name": "name", + "type": "S3", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() + origin = response.parse() assert_matches_type(OriginUpdateResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: + def test_path_params_update(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( + client.accounts.origins.with_raw_response.update( id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", + body={ + "name": "name", + "type": "S3", + }, ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_overload_3(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_3(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + def test_method_list(self, client: ImageKit) -> None: + origin = client.accounts.origins.list() + assert_matches_type(OriginListResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_update_overload_3(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) + def test_raw_response_list(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + origin = response.parse() + assert_matches_type(OriginListResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update_overload_3(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) as response: + def test_streaming_response_list(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + origin = response.parse() + assert_matches_type(OriginListResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update_overload_3(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_4(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_4(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - base_url_for_canonical_header="https://cdn.example.com", - forward_host_header_to_origin=False, - include_canonical_header=False, + def test_method_delete(self, client: ImageKit) -> None: + origin = client.accounts.origins.delete( + "id", ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert origin is None @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_update_overload_4(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.delete( + "id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + origin = response.parse() + assert origin is None @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update_overload_4(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.delete( + "id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + origin = response.parse() + assert origin is None assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update_overload_4(self, async_client: AsyncImageKit) -> None: + def test_path_params_delete(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", + client.accounts.origins.with_raw_response.delete( + "", ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_overload_5(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_5(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, + def test_method_get(self, client: ImageKit) -> None: + origin = client.accounts.origins.get( + "id", ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginGetResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_update_overload_5(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.get( + "id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + origin = response.parse() + assert_matches_type(OriginGetResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update_overload_5(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.get( + "id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + origin = response.parse() + assert_matches_type(OriginGetResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update_overload_5(self, async_client: AsyncImageKit) -> None: + def test_path_params_get(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - name="US S3 Storage", - type="WEB_PROXY", + client.accounts.origins.with_raw_response.get( + "", ) - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_6(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_6(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="products", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_6(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_6(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_6(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_7(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) +class TestAsyncOrigins: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_with_all_params_overload_7(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="uploads", + async def test_method_create(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + body={ + "name": "name", + "type": "S3", + }, ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_update_overload_7(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", + async def test_method_create_with_all_params(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + body={ + "name": "name", + "type": "S3", + "access_key": "x", + "account_name": "x", + "base_url": "https://example.com", + "base_url_for_canonical_header": "https://example.com", + "bucket": "x", + "client_email": "dev@stainless.com", + "client_id": "x", + "client_secret": "x", + "container": "x", + "endpoint": "https://example.com", + "forward_host_header_to_origin": True, + "include_canonical_header": True, + "password": "x", + "prefix": "prefix", + "private_key": "x", + "s3_force_path_style": True, + "sas_token": "x", + "secret_key": "x", + "username": "x", + }, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + body={ + "name": "name", + "type": "S3", + }, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update_overload_7(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", + async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + body={ + "name": "name", + "type": "S3", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update_overload_7(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_8(self, async_client: AsyncImageKit) -> None: + async def test_method_update(self, async_client: AsyncImageKit) -> None: origin = await async_client.accounts.origins.update( id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", + body={ + "name": "name", + "type": "S3", + }, ) assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_with_all_params_overload_8(self, async_client: AsyncImageKit) -> None: + async def test_method_update_with_all_params(self, async_client: AsyncImageKit) -> None: origin = await async_client.accounts.origins.update( id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_8(self, async_client: AsyncImageKit) -> None: + body={ + "name": "name", + "type": "S3", + "access_key": "x", + "account_name": "x", + "base_url": "https://example.com", + "base_url_for_canonical_header": "https://example.com", + "bucket": "x", + "client_email": "dev@stainless.com", + "client_id": "x", + "client_secret": "x", + "container": "x", + "endpoint": "https://example.com", + "forward_host_header_to_origin": True, + "include_canonical_header": True, + "password": "x", + "prefix": "prefix", + "private_key": "x", + "s3_force_path_style": True, + "sas_token": "x", + "secret_key": "x", + "username": "x", + }, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: response = await async_client.accounts.origins.with_raw_response.update( id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", + body={ + "name": "name", + "type": "S3", + }, ) assert response.is_closed is True @@ -2290,16 +436,13 @@ async def test_raw_response_update_overload_8(self, async_client: AsyncImageKit) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update_overload_8(self, async_client: AsyncImageKit) -> None: + async def test_streaming_response_update(self, async_client: AsyncImageKit) -> None: async with async_client.accounts.origins.with_streaming_response.update( id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", + body={ + "name": "name", + "type": "S3", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -2311,17 +454,14 @@ async def test_streaming_response_update_overload_8(self, async_client: AsyncIma @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update_overload_8(self, async_client: AsyncImageKit) -> None: + async def test_path_params_update(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): await async_client.accounts.origins.with_raw_response.update( id="", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", + body={ + "name": "name", + "type": "S3", + }, ) @pytest.mark.skip(reason="Prism tests are disabled") From 5dca9d31744c35a6f39639ab8bc617df801575b3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:50:58 +0000 Subject: [PATCH 035/177] feat(api): manual updates --- .stats.yml | 6 +- src/imagekit/resources/accounts/origins.py | 1077 ++++++++++-- .../types/accounts/origin_create_params.py | 216 ++- .../types/accounts/origin_update_params.py | 205 ++- tests/api_resources/accounts/test_origins.py | 1464 ++++++++++++++--- 5 files changed, 2649 insertions(+), 319 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0604c95..4fc82ca 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3fced4085838ae20641cfa2775c6d36757bbaae28415892b2e9ee438e3b56a85.yml -openapi_spec_hash: 58327d97499fdad00856caa35ca3f16a -config_hash: ecd4e1fc35135b5e53487ca547e46fd7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-76afc867b06fdc43b339f2c7d19f25a46481b25e8264ca24ea43daa1ea9234fc.yml +openapi_spec_hash: a1455d2ab02c48a14551362dd8ec2261 +config_hash: 396f0b1c74b8b5bc4dd6b5d87e374d90 diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index f4e565d..9c1fb39 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -3,11 +3,12 @@ from __future__ import annotations from typing import Any, cast +from typing_extensions import Literal, overload import httpx from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from ..._utils import maybe_transform, async_maybe_transform +from ..._utils import required_args, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -49,7 +50,7 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: def create( self, *, - body: origin_create_params.Body, + origin: origin_create_params.Origin, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -63,6 +64,662 @@ def create( Creates a new origin and returns the origin object. Args: + origin: Schema for origin resources. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return cast( + OriginCreateResponse, + self._post( + "/v1/accounts/origins", + body=maybe_transform(origin, origin_create_params.OriginCreateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, OriginCreateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + @overload + def update( + self, + id: str, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["S3"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + access_key: str, + bucket: str, + endpoint: str, + name: str, + secret_key: str, + type: Literal["S3_COMPATIBLE"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + endpoint: Custom S3-compatible endpoint. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + s3_force_path_style: Use path-style S3 URLs? + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["CLOUDINARY_BACKUP"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + base_url: str, + name: str, + type: Literal["WEB_FOLDER"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + base_url: Root URL for the web folder origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + forward_host_header_to_origin: Forward the Host header to origin? + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + name: str, + type: Literal["WEB_PROXY"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + bucket: str, + client_email: str, + name: str, + private_key: str, + type: Literal["GCS"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + account_name: str, + container: str, + name: str, + sas_token: str, + type: Literal["AZURE_BLOB"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + base_url: str, + client_id: str, + client_secret: str, + name: str, + password: str, + type: Literal["AKENEO_PIM"], + username: str, + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + base_url: Akeneo instance base URL. + + client_id: Akeneo API client ID. + + client_secret: Akeneo API client secret. + + name: Display name of the origin. + + password: Akeneo API password. + + username: Akeneo API username. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args( + ["access_key", "bucket", "name", "secret_key", "type"], + ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], + ["base_url", "name", "type"], + ["name", "type"], + ["bucket", "client_email", "name", "private_key", "type"], + ["account_name", "container", "name", "sas_token", "type"], + ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], + ) + def update( + self, + id: str, + *, + access_key: str | NotGiven = NOT_GIVEN, + bucket: str | NotGiven = NOT_GIVEN, + name: str, + secret_key: str | NotGiven = NOT_GIVEN, + type: Literal["S3"] + | Literal["S3_COMPATIBLE"] + | Literal["CLOUDINARY_BACKUP"] + | Literal["WEB_FOLDER"] + | Literal["WEB_PROXY"] + | Literal["GCS"] + | Literal["AZURE_BLOB"] + | Literal["AKENEO_PIM"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + endpoint: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + client_email: str | NotGiven = NOT_GIVEN, + private_key: str | NotGiven = NOT_GIVEN, + account_name: str | NotGiven = NOT_GIVEN, + container: str | NotGiven = NOT_GIVEN, + sas_token: str | NotGiven = NOT_GIVEN, + client_id: str | NotGiven = NOT_GIVEN, + client_secret: str | NotGiven = NOT_GIVEN, + password: str | NotGiven = NOT_GIVEN, + username: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginUpdateResponse, + self._put( + f"/v1/accounts/origins/{id}", + body=maybe_transform( + { + "access_key": access_key, + "bucket": bucket, + "name": name, + "secret_key": secret_key, + "type": type, + "base_url_for_canonical_header": base_url_for_canonical_header, + "include_canonical_header": include_canonical_header, + "prefix": prefix, + "endpoint": endpoint, + "s3_force_path_style": s3_force_path_style, + "base_url": base_url, + "forward_host_header_to_origin": forward_host_header_to_origin, + "client_email": client_email, + "private_key": private_key, + "account_name": account_name, + "container": container, + "sas_token": sas_token, + "client_id": client_id, + "client_secret": client_secret, + "password": password, + "username": username, + }, + origin_update_params.OriginUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, OriginUpdateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginListResponse: + """**Note:** This API is currently in beta. + + + Returns an array of all configured origins for the current account. + """ + return self._get( + "/v1/accounts/origins", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=OriginListResponse, + ) + + def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """**Note:** This API is currently in beta. + + + Permanently removes the origin identified by `id`. If the origin is in use by + any URL‑endpoints, the API will return an error. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def get( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginGetResponse: + """**Note:** This API is currently in beta. + + + Retrieves the origin identified by `id`. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginGetResponse, + self._get( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast(Any, OriginGetResponse), # Union types cannot be passed in as arguments in the type system + ), + ) + + +class AsyncOriginsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncOriginsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncOriginsResourceWithStreamingResponse(self) + + async def create( + self, + *, + origin: origin_create_params.Origin, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginCreateResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + origin: Schema for origin resources. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -73,9 +730,9 @@ def create( """ return cast( OriginCreateResponse, - self._post( + await self._post( "/v1/accounts/origins", - body=maybe_transform(body, origin_create_params.OriginCreateParams), + body=await async_maybe_transform(origin, origin_create_params.OriginCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -85,11 +742,19 @@ def create( ), ) - def update( + @overload + async def update( self, id: str, *, - body: origin_update_params.Body, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["S3"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -106,6 +771,20 @@ def update( id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -114,66 +793,110 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return cast( - OriginUpdateResponse, - self._put( - f"/v1/accounts/origins/{id}", - body=maybe_transform(body, origin_update_params.OriginUpdateParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast( - Any, OriginUpdateResponse - ), # Union types cannot be passed in as arguments in the type system - ), - ) + ... - def list( + @overload + async def update( self, + id: str, *, + access_key: str, + bucket: str, + endpoint: str, + name: str, + secret_key: str, + type: Literal["S3_COMPATIBLE"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginListResponse: + ) -> OriginUpdateResponse: """**Note:** This API is currently in beta. - Returns an array of all configured origins for the current account. + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + endpoint: Custom S3-compatible endpoint. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + s3_force_path_style: Use path-style S3 URLs? + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds """ - return self._get( - "/v1/accounts/origins", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=OriginListResponse, - ) + ... - def delete( + @overload + async def update( self, id: str, *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["CLOUDINARY_BACKUP"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> None: + ) -> OriginUpdateResponse: """**Note:** This API is currently in beta. - Permanently removes the origin identified by `id`. If the origin is in use by - any URL‑endpoints, the API will return an error. + Updates the origin identified by `id` and returns the updated origin object. Args: id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -182,37 +905,45 @@ def delete( timeout: Override the client-level default timeout for this request, in seconds """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - f"/v1/accounts/origins/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) + ... - def get( + @overload + async def update( self, id: str, *, + base_url: str, + name: str, + type: Literal["WEB_FOLDER"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginGetResponse: + ) -> OriginUpdateResponse: """**Note:** This API is currently in beta. - Retrieves the origin identified by `id`. + Updates the origin identified by `id` and returns the updated origin object. Args: id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. + base_url: Root URL for the web folder origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + forward_host_header_to_origin: Forward the Host header to origin? + + include_canonical_header: Whether to send a Canonical header. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -221,57 +952,129 @@ def get( timeout: Override the client-level default timeout for this request, in seconds """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return cast( - OriginGetResponse, - self._get( - f"/v1/accounts/origins/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast(Any, OriginGetResponse), # Union types cannot be passed in as arguments in the type system - ), - ) + ... + @overload + async def update( + self, + id: str, + *, + name: str, + type: Literal["WEB_PROXY"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. -class AsyncOriginsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers - """ - return AsyncOriginsResourceWithRawResponse(self) + Updates the origin identified by `id` and returns the updated origin object. - @cached_property - def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. + ... - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + @overload + async def update( + self, + id: str, + *, + bucket: str, + client_email: str, + name: str, + private_key: str, + type: Literal["GCS"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds """ - return AsyncOriginsResourceWithStreamingResponse(self) + ... - async def create( + @overload + async def update( self, + id: str, *, - body: origin_create_params.Body, + account_name: str, + container: str, + name: str, + sas_token: str, + type: Literal["AZURE_BLOB"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: + ) -> OriginUpdateResponse: """**Note:** This API is currently in beta. - Creates a new origin and returns the origin object. + Updates the origin identified by `id` and returns the updated origin object. Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -280,25 +1083,22 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ - return cast( - OriginCreateResponse, - await self._post( - "/v1/accounts/origins", - body=await async_maybe_transform(body, origin_create_params.OriginCreateParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast( - Any, OriginCreateResponse - ), # Union types cannot be passed in as arguments in the type system - ), - ) + ... + @overload async def update( self, id: str, *, - body: origin_update_params.Body, + base_url: str, + client_id: str, + client_secret: str, + name: str, + password: str, + type: Literal["AKENEO_PIM"], + username: str, + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -315,6 +1115,22 @@ async def update( id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. + base_url: Akeneo instance base URL. + + client_id: Akeneo API client ID. + + client_secret: Akeneo API client secret. + + name: Display name of the origin. + + password: Akeneo API password. + + username: Akeneo API username. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -323,13 +1139,88 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @required_args( + ["access_key", "bucket", "name", "secret_key", "type"], + ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], + ["base_url", "name", "type"], + ["name", "type"], + ["bucket", "client_email", "name", "private_key", "type"], + ["account_name", "container", "name", "sas_token", "type"], + ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], + ) + async def update( + self, + id: str, + *, + access_key: str | NotGiven = NOT_GIVEN, + bucket: str | NotGiven = NOT_GIVEN, + name: str, + secret_key: str | NotGiven = NOT_GIVEN, + type: Literal["S3"] + | Literal["S3_COMPATIBLE"] + | Literal["CLOUDINARY_BACKUP"] + | Literal["WEB_FOLDER"] + | Literal["WEB_PROXY"] + | Literal["GCS"] + | Literal["AZURE_BLOB"] + | Literal["AKENEO_PIM"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + endpoint: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + client_email: str | NotGiven = NOT_GIVEN, + private_key: str | NotGiven = NOT_GIVEN, + account_name: str | NotGiven = NOT_GIVEN, + container: str | NotGiven = NOT_GIVEN, + sas_token: str | NotGiven = NOT_GIVEN, + client_id: str | NotGiven = NOT_GIVEN, + client_secret: str | NotGiven = NOT_GIVEN, + password: str | NotGiven = NOT_GIVEN, + username: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginUpdateResponse: if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( OriginUpdateResponse, await self._put( f"/v1/accounts/origins/{id}", - body=await async_maybe_transform(body, origin_update_params.OriginUpdateParams), + body=await async_maybe_transform( + { + "access_key": access_key, + "bucket": bucket, + "name": name, + "secret_key": secret_key, + "type": type, + "base_url_for_canonical_header": base_url_for_canonical_header, + "include_canonical_header": include_canonical_header, + "prefix": prefix, + "endpoint": endpoint, + "s3_force_path_style": s3_force_path_style, + "base_url": base_url, + "forward_host_header_to_origin": forward_host_header_to_origin, + "client_email": client_email, + "private_key": private_key, + "account_name": account_name, + "container": container, + "sas_token": sas_token, + "client_id": client_id, + "client_secret": client_secret, + "password": password, + "username": username, + }, + origin_update_params.OriginUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/imagekit/types/accounts/origin_create_params.py b/src/imagekit/types/accounts/origin_create_params.py index 07126d0..9982645 100644 --- a/src/imagekit/types/accounts/origin_create_params.py +++ b/src/imagekit/types/accounts/origin_create_params.py @@ -2,14 +2,220 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing import Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -__all__ = ["OriginCreateParams", "Body"] +from ..._utils import PropertyInfo + +__all__ = [ + "OriginCreateParams", + "Origin", + "OriginS3", + "OriginS3Compatible", + "OriginCloudinaryBackup", + "OriginWebFolder", + "OriginWebProxy", + "OriginGoogleCloudStorageGcs", + "OriginAzureBlobStorage", + "OriginAkeneoPim", +] class OriginCreateParams(TypedDict, total=False): - body: Required[Body] + origin: Required[Origin] + """Schema for origin resources.""" + + +class OriginS3(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class OriginS3Compatible(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + endpoint: Required[str] + """Custom S3-compatible endpoint.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3_COMPATIBLE"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] + """Use path-style S3 URLs?""" + + +class OriginCloudinaryBackup(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["CLOUDINARY_BACKUP"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class OriginWebFolder(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Root URL for the web folder origin.""" + + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_FOLDER"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] + """Forward the Host header to origin?""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class OriginWebProxy(TypedDict, total=False): + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_PROXY"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class OriginGoogleCloudStorageGcs(TypedDict, total=False): + bucket: Required[str] + + client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] + + name: Required[str] + """Display name of the origin.""" + + private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] + + type: Required[Literal["GCS"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class OriginAzureBlobStorage(TypedDict, total=False): + account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] + + container: Required[str] + + name: Required[str] + """Display name of the origin.""" + + sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] + + type: Required[Literal["AZURE_BLOB"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class OriginAkeneoPim(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Akeneo instance base URL.""" + + client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] + """Akeneo API client ID.""" + + client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] + """Akeneo API client secret.""" + + name: Required[str] + """Display name of the origin.""" + + password: Required[str] + """Akeneo API password.""" + + type: Required[Literal["AKENEO_PIM"]] + + username: Required[str] + """Akeneo API username.""" + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" -class Body(total=False): - pass +Origin: TypeAlias = Union[ + OriginS3, + OriginS3Compatible, + OriginCloudinaryBackup, + OriginWebFolder, + OriginWebProxy, + OriginGoogleCloudStorageGcs, + OriginAzureBlobStorage, + OriginAkeneoPim, +] diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekit/types/accounts/origin_update_params.py index 8393247..a7b39fb 100644 --- a/src/imagekit/types/accounts/origin_update_params.py +++ b/src/imagekit/types/accounts/origin_update_params.py @@ -2,14 +2,207 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing import Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -__all__ = ["OriginUpdateParams", "Body"] +from ..._utils import PropertyInfo +__all__ = [ + "OriginUpdateParams", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "GoogleCloudStorageGcs", + "AzureBlobStorage", + "AkeneoPim", +] -class OriginUpdateParams(TypedDict, total=False): - body: Required[Body] +class S3(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" -class Body(total=False): - pass + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class S3Compatible(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + endpoint: Required[str] + """Custom S3-compatible endpoint.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3_COMPATIBLE"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] + """Use path-style S3 URLs?""" + + +class CloudinaryBackup(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["CLOUDINARY_BACKUP"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class WebFolder(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Root URL for the web folder origin.""" + + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_FOLDER"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] + """Forward the Host header to origin?""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class WebProxy(TypedDict, total=False): + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_PROXY"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class GoogleCloudStorageGcs(TypedDict, total=False): + bucket: Required[str] + + client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] + + name: Required[str] + """Display name of the origin.""" + + private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] + + type: Required[Literal["GCS"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AzureBlobStorage(TypedDict, total=False): + account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] + + container: Required[str] + + name: Required[str] + """Display name of the origin.""" + + sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] + + type: Required[Literal["AZURE_BLOB"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AkeneoPim(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Akeneo instance base URL.""" + + client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] + """Akeneo API client ID.""" + + client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] + """Akeneo API client secret.""" + + name: Required[str] + """Display name of the origin.""" + + password: Required[str] + """Akeneo API password.""" + + type: Required[Literal["AKENEO_PIM"]] + + username: Required[str] + """Akeneo API username.""" + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +OriginUpdateParams: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +] diff --git a/tests/api_resources/accounts/test_origins.py b/tests/api_resources/accounts/test_origins.py index 90c2a36..6573ec8 100644 --- a/tests/api_resources/accounts/test_origins.py +++ b/tests/api_resources/accounts/test_origins.py @@ -26,8 +26,11 @@ class TestOrigins: @parametrize def test_method_create(self, client: ImageKit) -> None: origin = client.accounts.origins.create( - body={ - "name": "name", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", "type": "S3", }, ) @@ -37,28 +40,15 @@ def test_method_create(self, client: ImageKit) -> None: @parametrize def test_method_create_with_all_params(self, client: ImageKit) -> None: origin = client.accounts.origins.create( - body={ - "name": "name", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", "type": "S3", - "access_key": "x", - "account_name": "x", - "base_url": "https://example.com", - "base_url_for_canonical_header": "https://example.com", - "bucket": "x", - "client_email": "dev@stainless.com", - "client_id": "x", - "client_secret": "x", - "container": "x", - "endpoint": "https://example.com", - "forward_host_header_to_origin": True, - "include_canonical_header": True, - "password": "x", - "prefix": "prefix", - "private_key": "x", - "s3_force_path_style": True, - "sas_token": "x", - "secret_key": "x", - "username": "x", + "base_url_for_canonical_header": "https://cdn.example.com", + "include_canonical_header": False, + "prefix": "images", }, ) assert_matches_type(OriginCreateResponse, origin, path=["response"]) @@ -67,8 +57,11 @@ def test_method_create_with_all_params(self, client: ImageKit) -> None: @parametrize def test_raw_response_create(self, client: ImageKit) -> None: response = client.accounts.origins.with_raw_response.create( - body={ - "name": "name", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", "type": "S3", }, ) @@ -82,8 +75,11 @@ def test_raw_response_create(self, client: ImageKit) -> None: @parametrize def test_streaming_response_create(self, client: ImageKit) -> None: with client.accounts.origins.with_streaming_response.create( - body={ - "name": "name", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", "type": "S3", }, ) as response: @@ -97,56 +93,43 @@ def test_streaming_response_create(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update(self, client: ImageKit) -> None: + def test_method_update_overload_1(self, client: ImageKit) -> None: origin = client.accounts.origins.update( id="id", - body={ - "name": "name", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_with_all_params(self, client: ImageKit) -> None: + def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: origin = client.accounts.origins.update( id="id", - body={ - "name": "name", - "type": "S3", - "access_key": "x", - "account_name": "x", - "base_url": "https://example.com", - "base_url_for_canonical_header": "https://example.com", - "bucket": "x", - "client_email": "dev@stainless.com", - "client_id": "x", - "client_secret": "x", - "container": "x", - "endpoint": "https://example.com", - "forward_host_header_to_origin": True, - "include_canonical_header": True, - "password": "x", - "prefix": "prefix", - "private_key": "x", - "s3_force_path_style": True, - "sas_token": "x", - "secret_key": "x", - "username": "x", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", ) assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update(self, client: ImageKit) -> None: + def test_raw_response_update_overload_1(self, client: ImageKit) -> None: response = client.accounts.origins.with_raw_response.update( id="id", - body={ - "name": "name", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) assert response.is_closed is True @@ -156,13 +139,14 @@ def test_raw_response_update(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update(self, client: ImageKit) -> None: + def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: with client.accounts.origins.with_streaming_response.update( id="id", - body={ - "name": "name", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -174,275 +158,1328 @@ def test_streaming_response_update(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update(self, client: ImageKit) -> None: + def test_path_params_update_overload_1(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): client.accounts.origins.with_raw_response.update( id="", - body={ - "name": "name", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_list(self, client: ImageKit) -> None: - origin = client.accounts.origins.list() - assert_matches_type(OriginListResponse, origin, path=["response"]) + def test_method_update_overload_2(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_list(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.list() + def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + s3_force_path_style=True, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_2(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginListResponse, origin, path=["response"]) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_list(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.list() as response: + def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginListResponse, origin, path=["response"]) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_delete(self, client: ImageKit) -> None: - origin = client.accounts.origins.delete( - "id", + def test_path_params_update_overload_2(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_3(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", ) - assert origin is None + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_delete(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.delete( - "id", + def test_method_update_with_all_params_overload_3(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_3(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert origin is None + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_delete(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.delete( - "id", + def test_streaming_response_update_overload_3(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert origin is None + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_delete(self, client: ImageKit) -> None: + def test_path_params_update_overload_3(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.delete( - "", + client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_get(self, client: ImageKit) -> None: - origin = client.accounts.origins.get( - "id", + def test_method_update_overload_4(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", ) - assert_matches_type(OriginGetResponse, origin, path=["response"]) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_get(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.get( - "id", + def test_method_update_with_all_params_overload_4(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + base_url_for_canonical_header="https://cdn.example.com", + forward_host_header_to_origin=False, + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_4(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginGetResponse, origin, path=["response"]) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_get(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.get( - "id", + def test_streaming_response_update_overload_4(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginGetResponse, origin, path=["response"]) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_get(self, client: ImageKit) -> None: + def test_path_params_update_overload_4(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.get( - "", + client.accounts.origins.with_raw_response.update( + id="", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", ) + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_5(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) -class TestAsyncOrigins: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_5(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_create(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - body={ - "name": "name", - "type": "S3", - }, + def test_raw_response_update_overload_5(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - body={ - "name": "name", - "type": "S3", - "access_key": "x", - "account_name": "x", - "base_url": "https://example.com", - "base_url_for_canonical_header": "https://example.com", - "bucket": "x", - "client_email": "dev@stainless.com", - "client_id": "x", - "client_secret": "x", - "container": "x", - "endpoint": "https://example.com", - "forward_host_header_to_origin": True, - "include_canonical_header": True, - "password": "x", - "prefix": "prefix", - "private_key": "x", - "s3_force_path_style": True, - "sas_token": "x", - "secret_key": "x", - "username": "x", - }, + def test_streaming_response_update_overload_5(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_5(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + name="US S3 Storage", + type="WEB_PROXY", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_6(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( - body={ - "name": "name", - "type": "S3", - }, + def test_method_update_with_all_params_overload_6(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="products", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_6(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - body={ - "name": "name", - "type": "S3", - }, + def test_streaming_response_update_overload_6(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( + def test_path_params_update_overload_6(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_7(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( id="id", - body={ - "name": "name", - "type": "S3", - }, + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", ) assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( + def test_method_update_with_all_params_overload_7(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( id="id", - body={ - "name": "name", - "type": "S3", - "access_key": "x", - "account_name": "x", - "base_url": "https://example.com", - "base_url_for_canonical_header": "https://example.com", - "bucket": "x", - "client_email": "dev@stainless.com", - "client_id": "x", - "client_secret": "x", - "container": "x", - "endpoint": "https://example.com", - "forward_host_header_to_origin": True, - "include_canonical_header": True, - "password": "x", - "prefix": "prefix", - "private_key": "x", - "s3_force_path_style": True, - "sas_token": "x", - "secret_key": "x", - "username": "x", - }, + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="uploads", ) assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( + def test_raw_response_update_overload_7(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( id="id", - body={ - "name": "name", - "type": "S3", - }, + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() + origin = response.parse() assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( + def test_streaming_response_update_overload_7(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( id="id", - body={ - "name": "name", - "type": "S3", - }, + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_7(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_8(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_8(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_8(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_8(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_8(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: ImageKit) -> None: + origin = client.accounts.origins.list() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + origin = client.accounts.origins.delete( + "id", + ) + assert origin is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert origin is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert origin is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_get(self, client: ImageKit) -> None: + origin = client.accounts.origins.get( + "id", + ) + assert_matches_type(OriginGetResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.get( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginGetResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.get( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginGetResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_get(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.get( + "", + ) + + +class TestAsyncOrigins: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + "base_url_for_canonical_header": "https://cdn.example.com", + "include_canonical_header": False, + "prefix": "images", + }, + ) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + s3_force_path_style=True, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_3(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_3(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_3(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_3(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_3(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_4(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_4(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + base_url_for_canonical_header="https://cdn.example.com", + forward_host_header_to_origin=False, + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_4(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_4(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_4(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_5(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_5(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_5(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_5(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_5(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + name="US S3 Storage", + type="WEB_PROXY", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_6(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_6(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="products", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_6(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_6(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_6(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_7(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_7(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="uploads", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_7(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_7(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_7(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_8(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_8(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_8(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_8(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -454,14 +1491,17 @@ async def test_streaming_response_update(self, async_client: AsyncImageKit) -> N @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update(self, async_client: AsyncImageKit) -> None: + async def test_path_params_update_overload_8(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): await async_client.accounts.origins.with_raw_response.update( id="", - body={ - "name": "name", - "type": "S3", - }, + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", ) @pytest.mark.skip(reason="Prism tests are disabled") From 10e24af3b0d2d7112878c6ab375c09a525d8e859 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:04:35 +0000 Subject: [PATCH 036/177] feat(api): manual updates --- .stats.yml | 2 +- src/imagekit/resources/accounts/origins.py | 1047 +----------- src/imagekit/resources/files/files.py | 212 +-- .../types/accounts/origin_update_params.py | 49 +- src/imagekit/types/file_update_params.py | 149 +- tests/api_resources/accounts/test_origins.py | 1398 ++--------------- tests/api_resources/test_files.py | 220 +-- 7 files changed, 443 insertions(+), 2634 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4fc82ca..4f127f1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-76afc867b06fdc43b339f2c7d19f25a46481b25e8264ca24ea43daa1ea9234fc.yml openapi_spec_hash: a1455d2ab02c48a14551362dd8ec2261 -config_hash: 396f0b1c74b8b5bc4dd6b5d87e374d90 +config_hash: c434cea5e670c34d574784866661bebd diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index 9c1fb39..da1e08e 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -3,12 +3,11 @@ from __future__ import annotations from typing import Any, cast -from typing_extensions import Literal, overload import httpx from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from ..._utils import required_args, maybe_transform, async_maybe_transform +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -88,19 +87,11 @@ def create( ), ) - @overload def update( self, id: str, *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal["S3"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + origin: origin_update_params.Origin, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -117,607 +108,6 @@ def update( id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - access_key: str, - bucket: str, - endpoint: str, - name: str, - secret_key: str, - type: Literal["S3_COMPATIBLE"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - endpoint: Custom S3-compatible endpoint. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - s3_force_path_style: Use path-style S3 URLs? - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal["CLOUDINARY_BACKUP"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - base_url: str, - name: str, - type: Literal["WEB_FOLDER"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - base_url: Root URL for the web folder origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - forward_host_header_to_origin: Forward the Host header to origin? - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - name: str, - type: Literal["WEB_PROXY"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - bucket: str, - client_email: str, - name: str, - private_key: str, - type: Literal["GCS"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - account_name: str, - container: str, - name: str, - sas_token: str, - type: Literal["AZURE_BLOB"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - id: str, - *, - base_url: str, - client_id: str, - client_secret: str, - name: str, - password: str, - type: Literal["AKENEO_PIM"], - username: str, - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - base_url: Akeneo instance base URL. - - client_id: Akeneo API client ID. - - client_secret: Akeneo API client secret. - - name: Display name of the origin. - - password: Akeneo API password. - - username: Akeneo API username. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @required_args( - ["access_key", "bucket", "name", "secret_key", "type"], - ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], - ["base_url", "name", "type"], - ["name", "type"], - ["bucket", "client_email", "name", "private_key", "type"], - ["account_name", "container", "name", "sas_token", "type"], - ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], - ) - def update( - self, - id: str, - *, - access_key: str | NotGiven = NOT_GIVEN, - bucket: str | NotGiven = NOT_GIVEN, - name: str, - secret_key: str | NotGiven = NOT_GIVEN, - type: Literal["S3"] - | Literal["S3_COMPATIBLE"] - | Literal["CLOUDINARY_BACKUP"] - | Literal["WEB_FOLDER"] - | Literal["WEB_PROXY"] - | Literal["GCS"] - | Literal["AZURE_BLOB"] - | Literal["AKENEO_PIM"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - endpoint: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - base_url: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - client_email: str | NotGiven = NOT_GIVEN, - private_key: str | NotGiven = NOT_GIVEN, - account_name: str | NotGiven = NOT_GIVEN, - container: str | NotGiven = NOT_GIVEN, - sas_token: str | NotGiven = NOT_GIVEN, - client_id: str | NotGiven = NOT_GIVEN, - client_secret: str | NotGiven = NOT_GIVEN, - password: str | NotGiven = NOT_GIVEN, - username: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return cast( - OriginUpdateResponse, - self._put( - f"/v1/accounts/origins/{id}", - body=maybe_transform( - { - "access_key": access_key, - "bucket": bucket, - "name": name, - "secret_key": secret_key, - "type": type, - "base_url_for_canonical_header": base_url_for_canonical_header, - "include_canonical_header": include_canonical_header, - "prefix": prefix, - "endpoint": endpoint, - "s3_force_path_style": s3_force_path_style, - "base_url": base_url, - "forward_host_header_to_origin": forward_host_header_to_origin, - "client_email": client_email, - "private_key": private_key, - "account_name": account_name, - "container": container, - "sas_token": sas_token, - "client_id": client_id, - "client_secret": client_secret, - "password": password, - "username": username, - }, - origin_update_params.OriginUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast( - Any, OriginUpdateResponse - ), # Union types cannot be passed in as arguments in the type system - ), - ) - - def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginListResponse: - """**Note:** This API is currently in beta. - - - Returns an array of all configured origins for the current account. - """ - return self._get( - "/v1/accounts/origins", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=OriginListResponse, - ) - - def delete( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> None: - """**Note:** This API is currently in beta. - - - Permanently removes the origin identified by `id`. If the origin is in use by - any URL‑endpoints, the API will return an error. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - f"/v1/accounts/origins/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def get( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginGetResponse: - """**Note:** This API is currently in beta. - - - Retrieves the origin identified by `id`. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return cast( - OriginGetResponse, - self._get( - f"/v1/accounts/origins/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast(Any, OriginGetResponse), # Union types cannot be passed in as arguments in the type system - ), - ) - - -class AsyncOriginsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers - """ - return AsyncOriginsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response - """ - return AsyncOriginsResourceWithStreamingResponse(self) - - async def create( - self, - *, - origin: origin_create_params.Origin, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: - """**Note:** This API is currently in beta. - - - Creates a new origin and returns the origin object. - - Args: origin: Schema for origin resources. extra_headers: Send extra headers @@ -728,122 +118,66 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - OriginCreateResponse, - await self._post( - "/v1/accounts/origins", - body=await async_maybe_transform(origin, origin_create_params.OriginCreateParams), + OriginUpdateResponse, + self._put( + f"/v1/accounts/origins/{id}", + body=maybe_transform(origin, origin_update_params.OriginUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=cast( - Any, OriginCreateResponse + Any, OriginUpdateResponse ), # Union types cannot be passed in as arguments in the type system ), ) - @overload - async def update( + def list( self, - id: str, *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal["S3"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: + ) -> OriginListResponse: """**Note:** This API is currently in beta. - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + Returns an array of all configured origins for the current account. """ - ... + return self._get( + "/v1/accounts/origins", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=OriginListResponse, + ) - @overload - async def update( + def delete( self, id: str, *, - access_key: str, - bucket: str, - endpoint: str, - name: str, - secret_key: str, - type: Literal["S3_COMPATIBLE"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: + ) -> None: """**Note:** This API is currently in beta. - Updates the origin identified by `id` and returns the updated origin object. + Permanently removes the origin identified by `id`. If the origin is in use by + any URL‑endpoints, the API will return an error. Args: id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - endpoint: Custom S3-compatible endpoint. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - - s3_force_path_style: Use path-style S3 URLs? - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -852,51 +186,37 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) - @overload - async def update( + def get( self, id: str, *, - access_key: str, - bucket: str, - name: str, - secret_key: str, - type: Literal["CLOUDINARY_BACKUP"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: + ) -> OriginGetResponse: """**Note:** This API is currently in beta. - Updates the origin identified by `id` and returns the updated origin object. + Retrieves the origin identified by `id`. Args: id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - access_key: Access key for the bucket. - - bucket: S3 bucket name. - - name: Display name of the origin. - - secret_key: Secret key for the bucket. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - prefix: Path prefix inside the bucket. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -905,175 +225,58 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @overload - async def update( - self, - id: str, - *, - base_url: str, - name: str, - type: Literal["WEB_FOLDER"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - base_url: Root URL for the web folder origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - forward_host_header_to_origin: Forward the Host header to origin? - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginGetResponse, + self._get( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast(Any, OriginGetResponse), # Union types cannot be passed in as arguments in the type system + ), + ) - extra_body: Add additional JSON properties to the request - timeout: Override the client-level default timeout for this request, in seconds +class AsyncOriginsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: """ - ... - - @overload - async def update( - self, - id: str, - *, - name: str, - type: Literal["WEB_PROXY"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. - timeout: Override the client-level default timeout for this request, in seconds + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ - ... - - @overload - async def update( - self, - id: str, - *, - bucket: str, - client_email: str, - name: str, - private_key: str, - type: Literal["GCS"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: - """**Note:** This API is currently in beta. - - - Updates the origin identified by `id` and returns the updated origin object. - - Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request + return AsyncOriginsResourceWithRawResponse(self) - extra_body: Add additional JSON properties to the request + @cached_property + def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. - timeout: Override the client-level default timeout for this request, in seconds + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ - ... + return AsyncOriginsResourceWithStreamingResponse(self) - @overload - async def update( + async def create( self, - id: str, *, - account_name: str, - container: str, - name: str, - sas_token: str, - type: Literal["AZURE_BLOB"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + origin: origin_create_params.Origin, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: + ) -> OriginCreateResponse: """**Note:** This API is currently in beta. - Updates the origin identified by `id` and returns the updated origin object. + Creates a new origin and returns the origin object. Args: - id: Unique identifier for the origin. This is generated by ImageKit when you create - a new origin. - - name: Display name of the origin. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. + origin: Schema for origin resources. extra_headers: Send extra headers @@ -1083,22 +286,25 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... + return cast( + OriginCreateResponse, + await self._post( + "/v1/accounts/origins", + body=await async_maybe_transform(origin, origin_create_params.OriginCreateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, OriginCreateResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) - @overload async def update( self, id: str, *, - base_url: str, - client_id: str, - client_secret: str, - name: str, - password: str, - type: Literal["AKENEO_PIM"], - username: str, - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + origin: origin_update_params.Origin, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1115,21 +321,7 @@ async def update( id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - base_url: Akeneo instance base URL. - - client_id: Akeneo API client ID. - - client_secret: Akeneo API client secret. - - name: Display name of the origin. - - password: Akeneo API password. - - username: Akeneo API username. - - base_url_for_canonical_header: URL used in the Canonical header (if enabled). - - include_canonical_header: Whether to send a Canonical header. + origin: Schema for origin resources. extra_headers: Send extra headers @@ -1139,88 +331,13 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @required_args( - ["access_key", "bucket", "name", "secret_key", "type"], - ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], - ["base_url", "name", "type"], - ["name", "type"], - ["bucket", "client_email", "name", "private_key", "type"], - ["account_name", "container", "name", "sas_token", "type"], - ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], - ) - async def update( - self, - id: str, - *, - access_key: str | NotGiven = NOT_GIVEN, - bucket: str | NotGiven = NOT_GIVEN, - name: str, - secret_key: str | NotGiven = NOT_GIVEN, - type: Literal["S3"] - | Literal["S3_COMPATIBLE"] - | Literal["CLOUDINARY_BACKUP"] - | Literal["WEB_FOLDER"] - | Literal["WEB_PROXY"] - | Literal["GCS"] - | Literal["AZURE_BLOB"] - | Literal["AKENEO_PIM"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - endpoint: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - base_url: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - client_email: str | NotGiven = NOT_GIVEN, - private_key: str | NotGiven = NOT_GIVEN, - account_name: str | NotGiven = NOT_GIVEN, - container: str | NotGiven = NOT_GIVEN, - sas_token: str | NotGiven = NOT_GIVEN, - client_id: str | NotGiven = NOT_GIVEN, - client_secret: str | NotGiven = NOT_GIVEN, - password: str | NotGiven = NOT_GIVEN, - username: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( OriginUpdateResponse, await self._put( f"/v1/accounts/origins/{id}", - body=await async_maybe_transform( - { - "access_key": access_key, - "bucket": bucket, - "name": name, - "secret_key": secret_key, - "type": type, - "base_url_for_canonical_header": base_url_for_canonical_header, - "include_canonical_header": include_canonical_header, - "prefix": prefix, - "endpoint": endpoint, - "s3_force_path_style": s3_force_path_style, - "base_url": base_url, - "forward_host_header_to_origin": forward_host_header_to_origin, - "client_email": client_email, - "private_key": private_key, - "account_name": account_name, - "container": container, - "sas_token": sas_token, - "client_id": client_id, - "client_secret": client_secret, - "password": password, - "username": username, - }, - origin_update_params.OriginUpdateParams, - ), + body=await async_maybe_transform(origin, origin_update_params.OriginUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 583f3da..fd3d1fb 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -2,8 +2,8 @@ from __future__ import annotations -from typing import Dict, List, Union, Mapping, Iterable, Optional, cast -from typing_extensions import Literal, overload +from typing import Dict, List, Mapping, Iterable, cast +from typing_extensions import Literal import httpx @@ -85,76 +85,11 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ return FilesResourceWithStreamingResponse(self) - @overload def update( self, file_id: str, *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUpdateResponse: - """ - This API updates the details or attributes of the current version of the file. - You can update `tags`, `customCoordinates`, `customMetadata`, publication - status, remove existing `AITags` and apply extensions using this API. - - Args: - custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. - `10,10,100,100`. Send `null` to unset this value. - - custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` - value for that key. Before setting any custom metadata on an asset you have to - create the field using custom metadata fields API. - - description: Optional text to describe the contents of the file. - - extensions: Array of extensions to be applied to the asset. Each extension can be configured - with specific parameters based on the extension type. - - remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. - `["car", "vehicle", "motorsports"]`. - - If you want to remove all AITags associated with the file, send a string - - "all". - - Note: The remove operation for `AITags` executes before any of the `extensions` - are processed. - - tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send - `null` to unset all tags associated with the file. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def update( - self, - file_id: str, - *, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + update: file_update_params.Update | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -168,8 +103,6 @@ def update( status, remove existing `AITags` and apply extensions using this API. Args: - publish: Configure the publication status of a file and its versions. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -178,44 +111,11 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - def update( - self, - file_id: str, - *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._patch( f"/v1/files/{file_id}/details", - body=maybe_transform( - { - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "description": description, - "extensions": extensions, - "remove_ai_tags": remove_ai_tags, - "tags": tags, - "webhook_url": webhook_url, - "publish": publish, - }, - file_update_params.FileUpdateParams, - ), + body=maybe_transform(update, file_update_params.FileUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -756,76 +656,11 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ return AsyncFilesResourceWithStreamingResponse(self) - @overload async def update( self, file_id: str, *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUpdateResponse: - """ - This API updates the details or attributes of the current version of the file. - You can update `tags`, `customCoordinates`, `customMetadata`, publication - status, remove existing `AITags` and apply extensions using this API. - - Args: - custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. - `10,10,100,100`. Send `null` to unset this value. - - custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` - value for that key. Before setting any custom metadata on an asset you have to - create the field using custom metadata fields API. - - description: Optional text to describe the contents of the file. - - extensions: Array of extensions to be applied to the asset. Each extension can be configured - with specific parameters based on the extension type. - - remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. - `["car", "vehicle", "motorsports"]`. - - If you want to remove all AITags associated with the file, send a string - - "all". - - Note: The remove operation for `AITags` executes before any of the `extensions` - are processed. - - tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send - `null` to unset all tags associated with the file. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def update( - self, - file_id: str, - *, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + update: file_update_params.Update | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -839,8 +674,6 @@ async def update( status, remove existing `AITags` and apply extensions using this API. Args: - publish: Configure the publication status of a file and its versions. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -849,44 +682,11 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - async def update( - self, - file_id: str, - *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Iterable[file_update_params.UpdateFileDetailsExtension] | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[List[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[List[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._patch( f"/v1/files/{file_id}/details", - body=await async_maybe_transform( - { - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "description": description, - "extensions": extensions, - "remove_ai_tags": remove_ai_tags, - "tags": tags, - "webhook_url": webhook_url, - "publish": publish, - }, - file_update_params.FileUpdateParams, - ), + body=await async_maybe_transform(update, file_update_params.FileUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekit/types/accounts/origin_update_params.py index a7b39fb..978a83d 100644 --- a/src/imagekit/types/accounts/origin_update_params.py +++ b/src/imagekit/types/accounts/origin_update_params.py @@ -9,18 +9,24 @@ __all__ = [ "OriginUpdateParams", - "S3", - "S3Compatible", - "CloudinaryBackup", - "WebFolder", - "WebProxy", - "GoogleCloudStorageGcs", - "AzureBlobStorage", - "AkeneoPim", + "Origin", + "OriginS3", + "OriginS3Compatible", + "OriginCloudinaryBackup", + "OriginWebFolder", + "OriginWebProxy", + "OriginGoogleCloudStorageGcs", + "OriginAzureBlobStorage", + "OriginAkeneoPim", ] -class S3(TypedDict, total=False): +class OriginUpdateParams(TypedDict, total=False): + origin: Required[Origin] + """Schema for origin resources.""" + + +class OriginS3(TypedDict, total=False): access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] """Access key for the bucket.""" @@ -45,7 +51,7 @@ class S3(TypedDict, total=False): """Path prefix inside the bucket.""" -class S3Compatible(TypedDict, total=False): +class OriginS3Compatible(TypedDict, total=False): access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] """Access key for the bucket.""" @@ -76,7 +82,7 @@ class S3Compatible(TypedDict, total=False): """Use path-style S3 URLs?""" -class CloudinaryBackup(TypedDict, total=False): +class OriginCloudinaryBackup(TypedDict, total=False): access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] """Access key for the bucket.""" @@ -101,7 +107,7 @@ class CloudinaryBackup(TypedDict, total=False): """Path prefix inside the bucket.""" -class WebFolder(TypedDict, total=False): +class OriginWebFolder(TypedDict, total=False): base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] """Root URL for the web folder origin.""" @@ -120,7 +126,7 @@ class WebFolder(TypedDict, total=False): """Whether to send a Canonical header.""" -class WebProxy(TypedDict, total=False): +class OriginWebProxy(TypedDict, total=False): name: Required[str] """Display name of the origin.""" @@ -133,7 +139,7 @@ class WebProxy(TypedDict, total=False): """Whether to send a Canonical header.""" -class GoogleCloudStorageGcs(TypedDict, total=False): +class OriginGoogleCloudStorageGcs(TypedDict, total=False): bucket: Required[str] client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] @@ -154,7 +160,7 @@ class GoogleCloudStorageGcs(TypedDict, total=False): prefix: str -class AzureBlobStorage(TypedDict, total=False): +class OriginAzureBlobStorage(TypedDict, total=False): account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] container: Required[str] @@ -175,7 +181,7 @@ class AzureBlobStorage(TypedDict, total=False): prefix: str -class AkeneoPim(TypedDict, total=False): +class OriginAkeneoPim(TypedDict, total=False): base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] """Akeneo instance base URL.""" @@ -203,6 +209,13 @@ class AkeneoPim(TypedDict, total=False): """Whether to send a Canonical header.""" -OriginUpdateParams: TypeAlias = Union[ - S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +Origin: TypeAlias = Union[ + OriginS3, + OriginS3Compatible, + OriginCloudinaryBackup, + OriginWebFolder, + OriginWebProxy, + OriginGoogleCloudStorageGcs, + OriginAzureBlobStorage, + OriginAkeneoPim, ] diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index e89f4ad..ea6a9cb 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -9,70 +9,23 @@ __all__ = [ "FileUpdateParams", - "UpdateFileDetails", - "UpdateFileDetailsExtension", - "UpdateFileDetailsExtensionRemoveBg", - "UpdateFileDetailsExtensionRemoveBgOptions", - "UpdateFileDetailsExtensionAutoTaggingExtension", - "UpdateFileDetailsExtensionAIAutoDescription", - "ChangePublicationStatus", - "ChangePublicationStatusPublish", + "Update", + "UpdateUpdateFileDetails", + "UpdateUpdateFileDetailsExtension", + "UpdateUpdateFileDetailsExtensionRemoveBg", + "UpdateUpdateFileDetailsExtensionRemoveBgOptions", + "UpdateUpdateFileDetailsExtensionAutoTaggingExtension", + "UpdateUpdateFileDetailsExtensionAIAutoDescription", + "UpdateChangePublicationStatus", + "UpdateChangePublicationStatusPublish", ] -class UpdateFileDetails(TypedDict, total=False): - custom_coordinates: Annotated[Optional[str], PropertyInfo(alias="customCoordinates")] - """Define an important area in the image in the format `x,y,width,height` e.g. - - `10,10,100,100`. Send `null` to unset this value. - """ - - custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] - """A key-value data to be associated with the asset. - - To unset a key, send `null` value for that key. Before setting any custom - metadata on an asset you have to create the field using custom metadata fields - API. - """ - - description: str - """Optional text to describe the contents of the file.""" - - extensions: Iterable[UpdateFileDetailsExtension] - """Array of extensions to be applied to the asset. - - Each extension can be configured with specific parameters based on the extension - type. - """ - - remove_ai_tags: Annotated[Union[List[str], Literal["all"]], PropertyInfo(alias="removeAITags")] - """An array of AITags associated with the file that you want to remove, e.g. +class FileUpdateParams(TypedDict, total=False): + update: Update - `["car", "vehicle", "motorsports"]`. - - If you want to remove all AITags associated with the file, send a string - - "all". - Note: The remove operation for `AITags` executes before any of the `extensions` - are processed. - """ - - tags: Optional[List[str]] - """An array of tags associated with the file, such as `["tag1", "tag2"]`. - - Send `null` to unset all tags associated with the file. - """ - - webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] - """ - The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - """ - - -class UpdateFileDetailsExtensionRemoveBgOptions(TypedDict, total=False): +class UpdateUpdateFileDetailsExtensionRemoveBgOptions(TypedDict, total=False): add_shadow: bool """Whether to add an artificial shadow to the result. @@ -101,14 +54,14 @@ class UpdateFileDetailsExtensionRemoveBgOptions(TypedDict, total=False): """ -class UpdateFileDetailsExtensionRemoveBg(TypedDict, total=False): +class UpdateUpdateFileDetailsExtensionRemoveBg(TypedDict, total=False): name: Required[Literal["remove-bg"]] """Specifies the background removal extension.""" - options: UpdateFileDetailsExtensionRemoveBgOptions + options: UpdateUpdateFileDetailsExtensionRemoveBgOptions -class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): +class UpdateUpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] """Maximum number of tags to attach to the asset.""" @@ -119,24 +72,71 @@ class UpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): """Specifies the auto-tagging extension used.""" -class UpdateFileDetailsExtensionAIAutoDescription(TypedDict, total=False): +class UpdateUpdateFileDetailsExtensionAIAutoDescription(TypedDict, total=False): name: Required[Literal["ai-auto-description"]] """Specifies the auto description extension.""" -UpdateFileDetailsExtension: TypeAlias = Union[ - UpdateFileDetailsExtensionRemoveBg, - UpdateFileDetailsExtensionAutoTaggingExtension, - UpdateFileDetailsExtensionAIAutoDescription, +UpdateUpdateFileDetailsExtension: TypeAlias = Union[ + UpdateUpdateFileDetailsExtensionRemoveBg, + UpdateUpdateFileDetailsExtensionAutoTaggingExtension, + UpdateUpdateFileDetailsExtensionAIAutoDescription, ] -class ChangePublicationStatus(TypedDict, total=False): - publish: ChangePublicationStatusPublish - """Configure the publication status of a file and its versions.""" +class UpdateUpdateFileDetails(TypedDict, total=False): + custom_coordinates: Annotated[Optional[str], PropertyInfo(alias="customCoordinates")] + """Define an important area in the image in the format `x,y,width,height` e.g. + + `10,10,100,100`. Send `null` to unset this value. + """ + + custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] + """A key-value data to be associated with the asset. + + To unset a key, send `null` value for that key. Before setting any custom + metadata on an asset you have to create the field using custom metadata fields + API. + """ + + description: str + """Optional text to describe the contents of the file.""" + + extensions: Iterable[UpdateUpdateFileDetailsExtension] + """Array of extensions to be applied to the asset. + + Each extension can be configured with specific parameters based on the extension + type. + """ + + remove_ai_tags: Annotated[Union[List[str], Literal["all"]], PropertyInfo(alias="removeAITags")] + """An array of AITags associated with the file that you want to remove, e.g. + + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + """ + + tags: Optional[List[str]] + """An array of tags associated with the file, such as `["tag1", "tag2"]`. + + Send `null` to unset all tags associated with the file. + """ -class ChangePublicationStatusPublish(TypedDict, total=False): + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ + + +class UpdateChangePublicationStatusPublish(TypedDict, total=False): is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] """Set to `true` to publish the file. Set to `false` to unpublish the file.""" @@ -147,4 +147,9 @@ class ChangePublicationStatusPublish(TypedDict, total=False): """ -FileUpdateParams: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] +class UpdateChangePublicationStatus(TypedDict, total=False): + publish: UpdateChangePublicationStatusPublish + """Configure the publication status of a file and its versions.""" + + +Update: TypeAlias = Union[UpdateUpdateFileDetails, UpdateChangePublicationStatus] diff --git a/tests/api_resources/accounts/test_origins.py b/tests/api_resources/accounts/test_origins.py index 6573ec8..171e5e2 100644 --- a/tests/api_resources/accounts/test_origins.py +++ b/tests/api_resources/accounts/test_origins.py @@ -93,43 +93,49 @@ def test_streaming_response_create(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_overload_1(self, client: ImageKit) -> None: + def test_method_update(self, client: ImageKit) -> None: origin = client.accounts.origins.update( id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, ) assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: + def test_method_update_with_all_params(self, client: ImageKit) -> None: origin = client.accounts.origins.update( id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + "base_url_for_canonical_header": "https://cdn.example.com", + "include_canonical_header": False, + "prefix": "images", + }, ) assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update_overload_1(self, client: ImageKit) -> None: + def test_raw_response_update(self, client: ImageKit) -> None: response = client.accounts.origins.with_raw_response.update( id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, ) assert response.is_closed is True @@ -139,14 +145,16 @@ def test_raw_response_update_overload_1(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: + def test_streaming_response_update(self, client: ImageKit) -> None: with client.accounts.origins.with_streaming_response.update( id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -158,705 +166,263 @@ def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update_overload_1(self, client: ImageKit) -> None: + def test_path_params_update(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): client.accounts.origins.with_raw_response.update( id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_overload_2(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - s3_force_path_style=True, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + def test_method_list(self, client: ImageKit) -> None: + origin = client.accounts.origins.list() + assert_matches_type(OriginListResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update_overload_2(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) + def test_raw_response_list(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginListResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) as response: + def test_streaming_response_list(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginListResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update_overload_2(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_3(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_3(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", + def test_method_delete(self, client: ImageKit) -> None: + origin = client.accounts.origins.delete( + "id", ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert origin is None @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update_overload_3(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.delete( + "id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert origin is None @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update_overload_3(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.delete( + "id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert origin is None assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update_overload_3(self, client: ImageKit) -> None: + def test_path_params_delete(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", + client.accounts.origins.with_raw_response.delete( + "", ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_overload_4(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_4(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - base_url_for_canonical_header="https://cdn.example.com", - forward_host_header_to_origin=False, - include_canonical_header=False, + def test_method_get(self, client: ImageKit) -> None: + origin = client.accounts.origins.get( + "id", ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginGetResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update_overload_4(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.get( + "id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginGetResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update_overload_4(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.get( + "id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginGetResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update_overload_4(self, client: ImageKit) -> None: + def test_path_params_get(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", + client.accounts.origins.with_raw_response.get( + "", ) + +class TestAsyncOrigins: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_overload_5(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", + async def test_method_create(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_with_all_params_overload_5(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, + async def test_method_create_with_all_params(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + "base_url_for_canonical_header": "https://cdn.example.com", + "include_canonical_header": False, + "prefix": "images", + }, ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginCreateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update_overload_5(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", + async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update_overload_5(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", + async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + origin = await response.parse() + assert_matches_type(OriginCreateResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update_overload_5(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - name="US S3 Storage", - type="WEB_PROXY", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_6(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( + async def test_method_update(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, ) assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_with_all_params_overload_6(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( + async def test_method_update_with_all_params(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="products", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + "base_url_for_canonical_header": "https://cdn.example.com", + "include_canonical_header": False, + "prefix": "images", + }, ) assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update_overload_6(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( + async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() + origin = await response.parse() assert_matches_type(OriginUpdateResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update_overload_6(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( + async def test_streaming_response_update(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_6(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_7(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_7(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="uploads", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_7(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_7(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_7(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_8(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_8(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_8(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_8(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_8(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( - id="", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_list(self, client: ImageKit) -> None: - origin = client.accounts.origins.list() - assert_matches_type(OriginListResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_list(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginListResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_list(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginListResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_delete(self, client: ImageKit) -> None: - origin = client.accounts.origins.delete( - "id", - ) - assert origin is None - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_delete(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.delete( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert origin is None - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_delete(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.delete( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert origin is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_delete(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.delete( - "", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_get(self, client: ImageKit) -> None: - origin = client.accounts.origins.get( - "id", - ) - assert_matches_type(OriginGetResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_get(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.get( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginGetResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_get(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.get( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = response.parse() - assert_matches_type(OriginGetResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_get(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.get( - "", - ) - - -class TestAsyncOrigins: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - "base_url_for_canonical_header": "https://cdn.example.com", - "include_canonical_header": False, - "prefix": "images", - }, - ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( origin={ "access_key": "AKIATEST123", "bucket": "test-bucket", @@ -864,622 +430,6 @@ async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: "secret_key": "secrettest123", "type": "S3", }, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - s3_force_path_style=True, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - endpoint="https://s3.eu-central-1.wasabisys.com", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="S3_COMPATIBLE", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_3(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_3(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="raw-assets", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_3(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_3(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_3(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - access_key="AKIAIOSFODNN7EXAMPLE", - bucket="product-images", - name="US S3 Storage", - secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - type="CLOUDINARY_BACKUP", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_4(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_4(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - base_url_for_canonical_header="https://cdn.example.com", - forward_host_header_to_origin=False, - include_canonical_header=False, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_4(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_4(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_4(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - base_url="https://images.example.com/assets", - name="US S3 Storage", - type="WEB_FOLDER", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_5(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_5(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_5(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_5(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - name="US S3 Storage", - type="WEB_PROXY", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_5(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - name="US S3 Storage", - type="WEB_PROXY", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_6(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_6(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="products", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_6(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_6(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_6(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - bucket="gcs-media", - client_email="service-account@project.iam.gserviceaccount.com", - name="US S3 Storage", - private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", - type="GCS", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_7(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_7(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - prefix="uploads", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_7(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_7(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_7(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.accounts.origins.with_raw_response.update( - id="", - account_name="account123", - container="images", - name="US S3 Storage", - sas_token="?sv=2023-01-03&sr=c&sig=abc123", - type="AZURE_BLOB", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_8(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_8(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - base_url_for_canonical_header="https://cdn.example.com", - include_canonical_header=False, - ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_8(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_8(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.update( - id="id", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1491,17 +441,17 @@ async def test_streaming_response_update_overload_8(self, async_client: AsyncIma @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update_overload_8(self, async_client: AsyncImageKit) -> None: + async def test_path_params_update(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): await async_client.accounts.origins.with_raw_response.update( id="", - base_url="https://akeneo.company.com", - client_id="akeneo-client-id", - client_secret="akeneo-client-secret", - name="US S3 Storage", - password="strongpassword123", - type="AKENEO_PIM", - username="integration-user", + origin={ + "access_key": "AKIATEST123", + "bucket": "test-bucket", + "name": "My S3 Origin", + "secret_key": "secrettest123", + "type": "S3", + }, ) @pytest.mark.skip(reason="Prism tests are disabled") diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index a05d6e2..5cd148b 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -26,7 +26,7 @@ class TestFiles: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_overload_1(self, client: ImageKit) -> None: + def test_method_update(self, client: ImageKit) -> None: file = client.files.update( file_id="fileId", ) @@ -34,86 +34,48 @@ def test_method_update_overload_1(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: + def test_method_update_with_all_params(self, client: ImageKit) -> None: file = client.files.update( file_id="fileId", - custom_coordinates="customCoordinates", - custom_metadata={"foo": "bar"}, - description="description", - extensions=[ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, + update={ + "custom_coordinates": "10,10,100,100", + "custom_metadata": { + "brand": "bar", + "color": "bar", + }, + "description": "description", + "extensions": [ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, }, - } - ], - remove_ai_tags=["string"], - tags=["tag1", "tag2"], - webhook_url="https://example.com", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_update_overload_1(self, client: ImageKit) -> None: - response = client.files.with_raw_response.update( - file_id="fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: - with client.files.with_streaming_response.update( - file_id="fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_path_params_update_overload_1(self, client: ImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.with_raw_response.update( - file_id="", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_overload_2(self, client: ImageKit) -> None: - file = client.files.update( - file_id="fileId", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: - file = client.files.update( - file_id="fileId", - publish={ - "is_published": True, - "include_file_versions": True, + { + "max_tags": 10, + "min_confidence": 80, + "name": "google-auto-tagging", + }, + { + "max_tags": 10, + "min_confidence": 80, + "name": "aws-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + "remove_ai_tags": ["car", "vehicle", "motorsports"], + "tags": ["tag1", "tag2"], + "webhook_url": "https://webhook.site/0d6b6c7a-8e5a-4b3a-8b7c-0d6b6c7a8e5a", }, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update_overload_2(self, client: ImageKit) -> None: + def test_raw_response_update(self, client: ImageKit) -> None: response = client.files.with_raw_response.update( file_id="fileId", ) @@ -125,7 +87,7 @@ def test_raw_response_update_overload_2(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: + def test_streaming_response_update(self, client: ImageKit) -> None: with client.files.with_streaming_response.update( file_id="fileId", ) as response: @@ -139,7 +101,7 @@ def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update_overload_2(self, client: ImageKit) -> None: + def test_path_params_update(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.files.with_raw_response.update( file_id="", @@ -466,7 +428,7 @@ class TestAsyncFiles: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_method_update(self, async_client: AsyncImageKit) -> None: file = await async_client.files.update( file_id="fileId", ) @@ -474,86 +436,48 @@ async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> No @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_method_update_with_all_params(self, async_client: AsyncImageKit) -> None: file = await async_client.files.update( file_id="fileId", - custom_coordinates="customCoordinates", - custom_metadata={"foo": "bar"}, - description="description", - extensions=[ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, + update={ + "custom_coordinates": "10,10,100,100", + "custom_metadata": { + "brand": "bar", + "color": "bar", + }, + "description": "description", + "extensions": [ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, }, - } - ], - remove_ai_tags=["string"], - tags=["tag1", "tag2"], - webhook_url="https://example.com", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.update( - file_id="fileId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = await response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.update( - file_id="fileId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = await response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - await async_client.files.with_raw_response.update( - file_id="", - ) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.update( - file_id="fileId", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.update( - file_id="fileId", - publish={ - "is_published": True, - "include_file_versions": True, + { + "max_tags": 10, + "min_confidence": 80, + "name": "google-auto-tagging", + }, + { + "max_tags": 10, + "min_confidence": 80, + "name": "aws-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + "remove_ai_tags": ["car", "vehicle", "motorsports"], + "tags": ["tag1", "tag2"], + "webhook_url": "https://webhook.site/0d6b6c7a-8e5a-4b3a-8b7c-0d6b6c7a8e5a", }, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.update( file_id="fileId", ) @@ -565,7 +489,7 @@ async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + async def test_streaming_response_update(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.update( file_id="fileId", ) as response: @@ -579,7 +503,7 @@ async def test_streaming_response_update_overload_2(self, async_client: AsyncIma @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: + async def test_path_params_update(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.files.with_raw_response.update( file_id="", From 8fa502d73f39b4c175fae5dc95634d5031524e8d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:08:58 +0000 Subject: [PATCH 037/177] feat(api): manual updates --- .stats.yml | 4 +-- .../types/accounts/origin_create_params.py | 12 +++---- .../types/accounts/origin_create_response.py | 16 ++++++---- .../types/accounts/origin_get_response.py | 16 ++++++---- .../types/accounts/origin_list_response.py | 32 +++++++++++-------- .../types/accounts/origin_update_params.py | 12 +++---- .../types/accounts/origin_update_response.py | 16 ++++++---- .../accounts/url_endpoint_create_response.py | 21 +++++------- .../accounts/url_endpoint_get_response.py | 21 +++++------- .../accounts/url_endpoint_list_response.py | 26 ++++++++------- .../accounts/url_endpoint_update_response.py | 21 +++++------- 11 files changed, 98 insertions(+), 99 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4f127f1..61a9411 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-76afc867b06fdc43b339f2c7d19f25a46481b25e8264ca24ea43daa1ea9234fc.yml -openapi_spec_hash: a1455d2ab02c48a14551362dd8ec2261 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-4bc3e70493ee36b6dd29a92334f55232a5429d1bf03139d1f072f854c3ba5a6e.yml +openapi_spec_hash: 9b8384f2a421b73c3f03d1ca84c26113 config_hash: c434cea5e670c34d574784866661bebd diff --git a/src/imagekit/types/accounts/origin_create_params.py b/src/imagekit/types/accounts/origin_create_params.py index 9982645..86c3e38 100644 --- a/src/imagekit/types/accounts/origin_create_params.py +++ b/src/imagekit/types/accounts/origin_create_params.py @@ -15,8 +15,8 @@ "OriginCloudinaryBackup", "OriginWebFolder", "OriginWebProxy", - "OriginGoogleCloudStorageGcs", - "OriginAzureBlobStorage", + "OriginGcs", + "OriginAzureBlob", "OriginAkeneoPim", ] @@ -139,7 +139,7 @@ class OriginWebProxy(TypedDict, total=False): """Whether to send a Canonical header.""" -class OriginGoogleCloudStorageGcs(TypedDict, total=False): +class OriginGcs(TypedDict, total=False): bucket: Required[str] client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] @@ -160,7 +160,7 @@ class OriginGoogleCloudStorageGcs(TypedDict, total=False): prefix: str -class OriginAzureBlobStorage(TypedDict, total=False): +class OriginAzureBlob(TypedDict, total=False): account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] container: Required[str] @@ -215,7 +215,7 @@ class OriginAkeneoPim(TypedDict, total=False): OriginCloudinaryBackup, OriginWebFolder, OriginWebProxy, - OriginGoogleCloudStorageGcs, - OriginAzureBlobStorage, + OriginGcs, + OriginAzureBlob, OriginAkeneoPim, ] diff --git a/src/imagekit/types/accounts/origin_create_response.py b/src/imagekit/types/accounts/origin_create_response.py index 72699bc..faaa8fd 100644 --- a/src/imagekit/types/accounts/origin_create_response.py +++ b/src/imagekit/types/accounts/origin_create_response.py @@ -1,10 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -14,8 +15,8 @@ "CloudinaryBackup", "WebFolder", "WebProxy", - "GoogleCloudStorageGcs", - "AzureBlobStorage", + "Gcs", + "AzureBlob", "AkeneoPim", ] @@ -145,7 +146,7 @@ class WebProxy(BaseModel): """URL used in the Canonical header (if enabled).""" -class GoogleCloudStorageGcs(BaseModel): +class Gcs(BaseModel): id: str """Unique identifier for the origin. @@ -170,7 +171,7 @@ class GoogleCloudStorageGcs(BaseModel): """URL used in the Canonical header (if enabled).""" -class AzureBlobStorage(BaseModel): +class AzureBlob(BaseModel): id: str """Unique identifier for the origin. @@ -217,6 +218,7 @@ class AkeneoPim(BaseModel): """URL used in the Canonical header (if enabled).""" -OriginCreateResponse: TypeAlias = Union[ - S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +OriginCreateResponse: TypeAlias = Annotated[ + Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], + PropertyInfo(discriminator="type"), ] diff --git a/src/imagekit/types/accounts/origin_get_response.py b/src/imagekit/types/accounts/origin_get_response.py index 059365f..1c1c0a5 100644 --- a/src/imagekit/types/accounts/origin_get_response.py +++ b/src/imagekit/types/accounts/origin_get_response.py @@ -1,10 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -14,8 +15,8 @@ "CloudinaryBackup", "WebFolder", "WebProxy", - "GoogleCloudStorageGcs", - "AzureBlobStorage", + "Gcs", + "AzureBlob", "AkeneoPim", ] @@ -145,7 +146,7 @@ class WebProxy(BaseModel): """URL used in the Canonical header (if enabled).""" -class GoogleCloudStorageGcs(BaseModel): +class Gcs(BaseModel): id: str """Unique identifier for the origin. @@ -170,7 +171,7 @@ class GoogleCloudStorageGcs(BaseModel): """URL used in the Canonical header (if enabled).""" -class AzureBlobStorage(BaseModel): +class AzureBlob(BaseModel): id: str """Unique identifier for the origin. @@ -217,6 +218,7 @@ class AkeneoPim(BaseModel): """URL used in the Canonical header (if enabled).""" -OriginGetResponse: TypeAlias = Union[ - S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +OriginGetResponse: TypeAlias = Annotated[ + Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], + PropertyInfo(discriminator="type"), ] diff --git a/src/imagekit/types/accounts/origin_list_response.py b/src/imagekit/types/accounts/origin_list_response.py index 235c899..8640a6f 100644 --- a/src/imagekit/types/accounts/origin_list_response.py +++ b/src/imagekit/types/accounts/origin_list_response.py @@ -1,10 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -15,8 +16,8 @@ "OriginListResponseItemCloudinaryBackup", "OriginListResponseItemWebFolder", "OriginListResponseItemWebProxy", - "OriginListResponseItemGoogleCloudStorageGcs", - "OriginListResponseItemAzureBlobStorage", + "OriginListResponseItemGcs", + "OriginListResponseItemAzureBlob", "OriginListResponseItemAkeneoPim", ] @@ -146,7 +147,7 @@ class OriginListResponseItemWebProxy(BaseModel): """URL used in the Canonical header (if enabled).""" -class OriginListResponseItemGoogleCloudStorageGcs(BaseModel): +class OriginListResponseItemGcs(BaseModel): id: str """Unique identifier for the origin. @@ -171,7 +172,7 @@ class OriginListResponseItemGoogleCloudStorageGcs(BaseModel): """URL used in the Canonical header (if enabled).""" -class OriginListResponseItemAzureBlobStorage(BaseModel): +class OriginListResponseItemAzureBlob(BaseModel): id: str """Unique identifier for the origin. @@ -218,15 +219,18 @@ class OriginListResponseItemAkeneoPim(BaseModel): """URL used in the Canonical header (if enabled).""" -OriginListResponseItem: TypeAlias = Union[ - OriginListResponseItemS3, - OriginListResponseItemS3Compatible, - OriginListResponseItemCloudinaryBackup, - OriginListResponseItemWebFolder, - OriginListResponseItemWebProxy, - OriginListResponseItemGoogleCloudStorageGcs, - OriginListResponseItemAzureBlobStorage, - OriginListResponseItemAkeneoPim, +OriginListResponseItem: TypeAlias = Annotated[ + Union[ + OriginListResponseItemS3, + OriginListResponseItemS3Compatible, + OriginListResponseItemCloudinaryBackup, + OriginListResponseItemWebFolder, + OriginListResponseItemWebProxy, + OriginListResponseItemGcs, + OriginListResponseItemAzureBlob, + OriginListResponseItemAkeneoPim, + ], + PropertyInfo(discriminator="type"), ] OriginListResponse: TypeAlias = List[OriginListResponseItem] diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekit/types/accounts/origin_update_params.py index 978a83d..36a6425 100644 --- a/src/imagekit/types/accounts/origin_update_params.py +++ b/src/imagekit/types/accounts/origin_update_params.py @@ -15,8 +15,8 @@ "OriginCloudinaryBackup", "OriginWebFolder", "OriginWebProxy", - "OriginGoogleCloudStorageGcs", - "OriginAzureBlobStorage", + "OriginGcs", + "OriginAzureBlob", "OriginAkeneoPim", ] @@ -139,7 +139,7 @@ class OriginWebProxy(TypedDict, total=False): """Whether to send a Canonical header.""" -class OriginGoogleCloudStorageGcs(TypedDict, total=False): +class OriginGcs(TypedDict, total=False): bucket: Required[str] client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] @@ -160,7 +160,7 @@ class OriginGoogleCloudStorageGcs(TypedDict, total=False): prefix: str -class OriginAzureBlobStorage(TypedDict, total=False): +class OriginAzureBlob(TypedDict, total=False): account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] container: Required[str] @@ -215,7 +215,7 @@ class OriginAkeneoPim(TypedDict, total=False): OriginCloudinaryBackup, OriginWebFolder, OriginWebProxy, - OriginGoogleCloudStorageGcs, - OriginAzureBlobStorage, + OriginGcs, + OriginAzureBlob, OriginAkeneoPim, ] diff --git a/src/imagekit/types/accounts/origin_update_response.py b/src/imagekit/types/accounts/origin_update_response.py index 1b74313..7799b94 100644 --- a/src/imagekit/types/accounts/origin_update_response.py +++ b/src/imagekit/types/accounts/origin_update_response.py @@ -1,10 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -14,8 +15,8 @@ "CloudinaryBackup", "WebFolder", "WebProxy", - "GoogleCloudStorageGcs", - "AzureBlobStorage", + "Gcs", + "AzureBlob", "AkeneoPim", ] @@ -145,7 +146,7 @@ class WebProxy(BaseModel): """URL used in the Canonical header (if enabled).""" -class GoogleCloudStorageGcs(BaseModel): +class Gcs(BaseModel): id: str """Unique identifier for the origin. @@ -170,7 +171,7 @@ class GoogleCloudStorageGcs(BaseModel): """URL used in the Canonical header (if enabled).""" -class AzureBlobStorage(BaseModel): +class AzureBlob(BaseModel): id: str """Unique identifier for the origin. @@ -217,6 +218,7 @@ class AkeneoPim(BaseModel): """URL used in the Canonical header (if enabled).""" -OriginUpdateResponse: TypeAlias = Union[ - S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +OriginUpdateResponse: TypeAlias = Annotated[ + Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], + PropertyInfo(discriminator="type"), ] diff --git a/src/imagekit/types/accounts/url_endpoint_create_response.py b/src/imagekit/types/accounts/url_endpoint_create_response.py index e2ddecf..f8ef98f 100644 --- a/src/imagekit/types/accounts/url_endpoint_create_response.py +++ b/src/imagekit/types/accounts/url_endpoint_create_response.py @@ -1,38 +1,33 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel -__all__ = [ - "URLEndpointCreateResponse", - "URLRewriter", - "URLRewriterCloudinaryURLRewriter", - "URLRewriterImgixURLRewriter", - "URLRewriterAkamaiURLRewriter", -] +__all__ = ["URLEndpointCreateResponse", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] -class URLRewriterCloudinaryURLRewriter(BaseModel): +class URLRewriterCloudinary(BaseModel): preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") """Whether to preserve `/` in the rewritten URL.""" type: Literal["CLOUDINARY"] -class URLRewriterImgixURLRewriter(BaseModel): +class URLRewriterImgix(BaseModel): type: Literal["IMGIX"] -class URLRewriterAkamaiURLRewriter(BaseModel): +class URLRewriterAkamai(BaseModel): type: Literal["AKAMAI"] -URLRewriter: TypeAlias = Union[ - URLRewriterCloudinaryURLRewriter, URLRewriterImgixURLRewriter, URLRewriterAkamaiURLRewriter +URLRewriter: TypeAlias = Annotated[ + Union[URLRewriterCloudinary, URLRewriterImgix, URLRewriterAkamai], PropertyInfo(discriminator="type") ] diff --git a/src/imagekit/types/accounts/url_endpoint_get_response.py b/src/imagekit/types/accounts/url_endpoint_get_response.py index ce5b14b..85c1c27 100644 --- a/src/imagekit/types/accounts/url_endpoint_get_response.py +++ b/src/imagekit/types/accounts/url_endpoint_get_response.py @@ -1,38 +1,33 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel -__all__ = [ - "URLEndpointGetResponse", - "URLRewriter", - "URLRewriterCloudinaryURLRewriter", - "URLRewriterImgixURLRewriter", - "URLRewriterAkamaiURLRewriter", -] +__all__ = ["URLEndpointGetResponse", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] -class URLRewriterCloudinaryURLRewriter(BaseModel): +class URLRewriterCloudinary(BaseModel): preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") """Whether to preserve `/` in the rewritten URL.""" type: Literal["CLOUDINARY"] -class URLRewriterImgixURLRewriter(BaseModel): +class URLRewriterImgix(BaseModel): type: Literal["IMGIX"] -class URLRewriterAkamaiURLRewriter(BaseModel): +class URLRewriterAkamai(BaseModel): type: Literal["AKAMAI"] -URLRewriter: TypeAlias = Union[ - URLRewriterCloudinaryURLRewriter, URLRewriterImgixURLRewriter, URLRewriterAkamaiURLRewriter +URLRewriter: TypeAlias = Annotated[ + Union[URLRewriterCloudinary, URLRewriterImgix, URLRewriterAkamai], PropertyInfo(discriminator="type") ] diff --git a/src/imagekit/types/accounts/url_endpoint_list_response.py b/src/imagekit/types/accounts/url_endpoint_list_response.py index 2ab3bfd..addbb17 100644 --- a/src/imagekit/types/accounts/url_endpoint_list_response.py +++ b/src/imagekit/types/accounts/url_endpoint_list_response.py @@ -1,41 +1,45 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ "URLEndpointListResponse", "URLEndpointListResponseItem", "URLEndpointListResponseItemURLRewriter", - "URLEndpointListResponseItemURLRewriterCloudinaryURLRewriter", - "URLEndpointListResponseItemURLRewriterImgixURLRewriter", - "URLEndpointListResponseItemURLRewriterAkamaiURLRewriter", + "URLEndpointListResponseItemURLRewriterCloudinary", + "URLEndpointListResponseItemURLRewriterImgix", + "URLEndpointListResponseItemURLRewriterAkamai", ] -class URLEndpointListResponseItemURLRewriterCloudinaryURLRewriter(BaseModel): +class URLEndpointListResponseItemURLRewriterCloudinary(BaseModel): preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") """Whether to preserve `/` in the rewritten URL.""" type: Literal["CLOUDINARY"] -class URLEndpointListResponseItemURLRewriterImgixURLRewriter(BaseModel): +class URLEndpointListResponseItemURLRewriterImgix(BaseModel): type: Literal["IMGIX"] -class URLEndpointListResponseItemURLRewriterAkamaiURLRewriter(BaseModel): +class URLEndpointListResponseItemURLRewriterAkamai(BaseModel): type: Literal["AKAMAI"] -URLEndpointListResponseItemURLRewriter: TypeAlias = Union[ - URLEndpointListResponseItemURLRewriterCloudinaryURLRewriter, - URLEndpointListResponseItemURLRewriterImgixURLRewriter, - URLEndpointListResponseItemURLRewriterAkamaiURLRewriter, +URLEndpointListResponseItemURLRewriter: TypeAlias = Annotated[ + Union[ + URLEndpointListResponseItemURLRewriterCloudinary, + URLEndpointListResponseItemURLRewriterImgix, + URLEndpointListResponseItemURLRewriterAkamai, + ], + PropertyInfo(discriminator="type"), ] diff --git a/src/imagekit/types/accounts/url_endpoint_update_response.py b/src/imagekit/types/accounts/url_endpoint_update_response.py index 1486105..99e9bbb 100644 --- a/src/imagekit/types/accounts/url_endpoint_update_response.py +++ b/src/imagekit/types/accounts/url_endpoint_update_response.py @@ -1,38 +1,33 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel -__all__ = [ - "URLEndpointUpdateResponse", - "URLRewriter", - "URLRewriterCloudinaryURLRewriter", - "URLRewriterImgixURLRewriter", - "URLRewriterAkamaiURLRewriter", -] +__all__ = ["URLEndpointUpdateResponse", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] -class URLRewriterCloudinaryURLRewriter(BaseModel): +class URLRewriterCloudinary(BaseModel): preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") """Whether to preserve `/` in the rewritten URL.""" type: Literal["CLOUDINARY"] -class URLRewriterImgixURLRewriter(BaseModel): +class URLRewriterImgix(BaseModel): type: Literal["IMGIX"] -class URLRewriterAkamaiURLRewriter(BaseModel): +class URLRewriterAkamai(BaseModel): type: Literal["AKAMAI"] -URLRewriter: TypeAlias = Union[ - URLRewriterCloudinaryURLRewriter, URLRewriterImgixURLRewriter, URLRewriterAkamaiURLRewriter +URLRewriter: TypeAlias = Annotated[ + Union[URLRewriterCloudinary, URLRewriterImgix, URLRewriterAkamai], PropertyInfo(discriminator="type") ] From 2347662f38a82fbe64ff52f8de772f73927ebd2c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:34:52 +0000 Subject: [PATCH 038/177] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 61a9411..878cd0f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-4bc3e70493ee36b6dd29a92334f55232a5429d1bf03139d1f072f854c3ba5a6e.yml -openapi_spec_hash: 9b8384f2a421b73c3f03d1ca84c26113 -config_hash: c434cea5e670c34d574784866661bebd +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-5e37410c61128e976acdb1c3a0df26552e969187d32f4af52555eeb9685d6bc2.yml +openapi_spec_hash: b3d4d81f84221c6bc87065590a907004 +config_hash: 040d180c4960ee032ba08946d86c8764 From f5ce7f7986fbc35c4a031aa4b564b8fc9214772e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:37:09 +0000 Subject: [PATCH 039/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 878cd0f..27d4d89 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-5e37410c61128e976acdb1c3a0df26552e969187d32f4af52555eeb9685d6bc2.yml -openapi_spec_hash: b3d4d81f84221c6bc87065590a907004 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-4bc3e70493ee36b6dd29a92334f55232a5429d1bf03139d1f072f854c3ba5a6e.yml +openapi_spec_hash: 9b8384f2a421b73c3f03d1ca84c26113 config_hash: 040d180c4960ee032ba08946d86c8764 From 901f5d4005b859e555491e8b207fbf5940525eb2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 03:01:41 +0000 Subject: [PATCH 040/177] feat(api): manual updates --- .stats.yml | 4 ++-- src/imagekit/types/asset_list_response.py | 11 ++++++----- src/imagekit/types/file_get_response.py | 8 +++++--- src/imagekit/types/file_update_response.py | 7 ++++--- src/imagekit/types/files/version_get_response.py | 8 +++++--- src/imagekit/types/files/version_list_response.py | 9 +++++---- src/imagekit/types/files/version_restore_response.py | 8 +++++--- 7 files changed, 32 insertions(+), 23 deletions(-) diff --git a/.stats.yml b/.stats.yml index 27d4d89..9ac0471 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-4bc3e70493ee36b6dd29a92334f55232a5429d1bf03139d1f072f854c3ba5a6e.yml -openapi_spec_hash: 9b8384f2a421b73c3f03d1ca84c26113 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-967cd0e731df83a642ded194cacae3628050f679c600b1efd4e66cf269973531.yml +openapi_spec_hash: 98642308bee81ac776b7b1843089b888 config_hash: 040d180c4960ee032ba08946d86c8764 diff --git a/src/imagekit/types/asset_list_response.py b/src/imagekit/types/asset_list_response.py index b0c1e33..a84b162 100644 --- a/src/imagekit/types/asset_list_response.py +++ b/src/imagekit/types/asset_list_response.py @@ -1,6 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Union, Optional +from datetime import datetime from typing_extensions import Literal, TypeAlias from pydantic import Field as FieldInfo @@ -43,7 +44,7 @@ class AssetListResponseItemFileDetails(BaseModel): ai_tags: Optional[List[AssetListResponseItemFileDetailsAITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" - created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) """Date and time when the file was uploaded. The date and time is in ISO8601 format. @@ -102,10 +103,10 @@ class AssetListResponseItemFileDetails(BaseModel): This URL is used to access the thumbnail image of the file in the media library. """ - type: Optional[str] = None + type: Optional[Literal["file", "file-version"]] = None """Type of the asset.""" - updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) """Date and time when the file was last updated. The date and time is in ISO8601 format. @@ -122,7 +123,7 @@ class AssetListResponseItemFileDetails(BaseModel): class AssetListResponseItemFolderDetails(BaseModel): - created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) """Date and time when the folder was created. The date and time is in ISO8601 format. @@ -145,7 +146,7 @@ class AssetListResponseItemFolderDetails(BaseModel): type: Optional[Literal["folder"]] = None """Type of the asset.""" - updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) """Date and time when the folder was last updated. The date and time is in ISO8601 format. diff --git a/src/imagekit/types/file_get_response.py b/src/imagekit/types/file_get_response.py index ca7e178..90dd4cd 100644 --- a/src/imagekit/types/file_get_response.py +++ b/src/imagekit/types/file_get_response.py @@ -1,6 +1,8 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -35,7 +37,7 @@ class FileGetResponse(BaseModel): ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" - created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) """Date and time when the file was uploaded. The date and time is in ISO8601 format. @@ -94,10 +96,10 @@ class FileGetResponse(BaseModel): This URL is used to access the thumbnail image of the file in the media library. """ - type: Optional[str] = None + type: Optional[Literal["file", "file-version"]] = None """Type of the asset.""" - updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) """Date and time when the file was last updated. The date and time is in ISO8601 format. diff --git a/src/imagekit/types/file_update_response.py b/src/imagekit/types/file_update_response.py index 3c6df6d..5bec99c 100644 --- a/src/imagekit/types/file_update_response.py +++ b/src/imagekit/types/file_update_response.py @@ -1,6 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Optional +from datetime import datetime from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -52,7 +53,7 @@ class FileUpdateResponse(BaseModel): ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" - created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) """Date and time when the file was uploaded. The date and time is in ISO8601 format. @@ -113,10 +114,10 @@ class FileUpdateResponse(BaseModel): This URL is used to access the thumbnail image of the file in the media library. """ - type: Optional[str] = None + type: Optional[Literal["file", "file-version"]] = None """Type of the asset.""" - updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) """Date and time when the file was last updated. The date and time is in ISO8601 format. diff --git a/src/imagekit/types/files/version_get_response.py b/src/imagekit/types/files/version_get_response.py index b03324c..5e607a5 100644 --- a/src/imagekit/types/files/version_get_response.py +++ b/src/imagekit/types/files/version_get_response.py @@ -1,6 +1,8 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -35,7 +37,7 @@ class VersionGetResponse(BaseModel): ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" - created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) """Date and time when the file was uploaded. The date and time is in ISO8601 format. @@ -94,10 +96,10 @@ class VersionGetResponse(BaseModel): This URL is used to access the thumbnail image of the file in the media library. """ - type: Optional[str] = None + type: Optional[Literal["file", "file-version"]] = None """Type of the asset.""" - updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) """Date and time when the file was last updated. The date and time is in ISO8601 format. diff --git a/src/imagekit/types/files/version_list_response.py b/src/imagekit/types/files/version_list_response.py index 0da0fa8..8e42a01 100644 --- a/src/imagekit/types/files/version_list_response.py +++ b/src/imagekit/types/files/version_list_response.py @@ -1,7 +1,8 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Optional -from typing_extensions import TypeAlias +from datetime import datetime +from typing_extensions import Literal, TypeAlias from pydantic import Field as FieldInfo @@ -41,7 +42,7 @@ class VersionListResponseItem(BaseModel): ai_tags: Optional[List[VersionListResponseItemAITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" - created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) """Date and time when the file was uploaded. The date and time is in ISO8601 format. @@ -100,10 +101,10 @@ class VersionListResponseItem(BaseModel): This URL is used to access the thumbnail image of the file in the media library. """ - type: Optional[str] = None + type: Optional[Literal["file", "file-version"]] = None """Type of the asset.""" - updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) """Date and time when the file was last updated. The date and time is in ISO8601 format. diff --git a/src/imagekit/types/files/version_restore_response.py b/src/imagekit/types/files/version_restore_response.py index b2976cd..a4503e8 100644 --- a/src/imagekit/types/files/version_restore_response.py +++ b/src/imagekit/types/files/version_restore_response.py @@ -1,6 +1,8 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -35,7 +37,7 @@ class VersionRestoreResponse(BaseModel): ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" - created_at: Optional[str] = FieldInfo(alias="createdAt", default=None) + created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) """Date and time when the file was uploaded. The date and time is in ISO8601 format. @@ -94,10 +96,10 @@ class VersionRestoreResponse(BaseModel): This URL is used to access the thumbnail image of the file in the media library. """ - type: Optional[str] = None + type: Optional[Literal["file", "file-version"]] = None """Type of the asset.""" - updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None) + updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) """Date and time when the file was last updated. The date and time is in ISO8601 format. From ab8c3fdbc430ec4665b8380098aa235918d5aed2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 03:14:44 +0000 Subject: [PATCH 041/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 7 +- .../resources/custom_metadata_fields.py | 19 +++-- src/imagekit/types/__init__.py | 7 +- ...e_response.py => custom_metadata_field.py} | 4 +- .../custom_metadata_field_list_response.py | 80 ++----------------- .../custom_metadata_field_update_response.py | 73 ----------------- .../test_custom_metadata_fields.py | 35 ++++---- 8 files changed, 38 insertions(+), 189 deletions(-) rename src/imagekit/types/{custom_metadata_field_create_response.py => custom_metadata_field.py} (95%) delete mode 100644 src/imagekit/types/custom_metadata_field_update_response.py diff --git a/.stats.yml b/.stats.yml index 9ac0471..ec9a755 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-967cd0e731df83a642ded194cacae3628050f679c600b1efd4e66cf269973531.yml openapi_spec_hash: 98642308bee81ac776b7b1843089b888 -config_hash: 040d180c4960ee032ba08946d86c8764 +config_hash: 733231d3642f7945a9459fbc90ddfb8e diff --git a/api.md b/api.md index adf733d..e9b03cb 100644 --- a/api.md +++ b/api.md @@ -4,8 +4,7 @@ Types: ```python from imagekit.types import ( - CustomMetadataFieldCreateResponse, - CustomMetadataFieldUpdateResponse, + CustomMetadataField, CustomMetadataFieldListResponse, CustomMetadataFieldDeleteResponse, ) @@ -13,8 +12,8 @@ from imagekit.types import ( Methods: -- client.custom_metadata_fields.create(\*\*params) -> CustomMetadataFieldCreateResponse -- client.custom_metadata_fields.update(id, \*\*params) -> CustomMetadataFieldUpdateResponse +- client.custom_metadata_fields.create(\*\*params) -> CustomMetadataField +- client.custom_metadata_fields.update(id, \*\*params) -> CustomMetadataField - client.custom_metadata_fields.list(\*\*params) -> CustomMetadataFieldListResponse - client.custom_metadata_fields.delete(id) -> CustomMetadataFieldDeleteResponse diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py index 5682c04..5c745ea 100644 --- a/src/imagekit/resources/custom_metadata_fields.py +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -20,10 +20,9 @@ async_to_streamed_response_wrapper, ) from .._base_client import make_request_options +from ..types.custom_metadata_field import CustomMetadataField from ..types.custom_metadata_field_list_response import CustomMetadataFieldListResponse -from ..types.custom_metadata_field_create_response import CustomMetadataFieldCreateResponse from ..types.custom_metadata_field_delete_response import CustomMetadataFieldDeleteResponse -from ..types.custom_metadata_field_update_response import CustomMetadataFieldUpdateResponse __all__ = ["CustomMetadataFieldsResource", "AsyncCustomMetadataFieldsResource"] @@ -60,7 +59,7 @@ def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> CustomMetadataFieldCreateResponse: + ) -> CustomMetadataField: """This API creates a new custom metadata field. Once a custom metadata field is @@ -98,7 +97,7 @@ def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=CustomMetadataFieldCreateResponse, + cast_to=CustomMetadataField, ) def update( @@ -113,7 +112,7 @@ def update( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> CustomMetadataFieldUpdateResponse: + ) -> CustomMetadataField: """ This API updates the label or schema of an existing custom metadata field. @@ -150,7 +149,7 @@ def update( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=CustomMetadataFieldUpdateResponse, + cast_to=CustomMetadataField, ) def list( @@ -264,7 +263,7 @@ async def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> CustomMetadataFieldCreateResponse: + ) -> CustomMetadataField: """This API creates a new custom metadata field. Once a custom metadata field is @@ -302,7 +301,7 @@ async def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=CustomMetadataFieldCreateResponse, + cast_to=CustomMetadataField, ) async def update( @@ -317,7 +316,7 @@ async def update( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> CustomMetadataFieldUpdateResponse: + ) -> CustomMetadataField: """ This API updates the label or schema of an existing custom metadata field. @@ -354,7 +353,7 @@ async def update( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=CustomMetadataFieldUpdateResponse, + cast_to=CustomMetadataField, ) async def list( diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 31fb04a..85a1210 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -23,6 +23,7 @@ from .folder_move_response import FolderMoveResponse as FolderMoveResponse from .folder_rename_params import FolderRenameParams as FolderRenameParams from .unwrap_webhook_event import UnwrapWebhookEvent as UnwrapWebhookEvent +from .custom_metadata_field import CustomMetadataField as CustomMetadataField from .folder_create_response import FolderCreateResponse as FolderCreateResponse from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse from .folder_rename_response import FolderRenameResponse as FolderRenameResponse @@ -31,15 +32,9 @@ from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams from .custom_metadata_field_list_response import CustomMetadataFieldListResponse as CustomMetadataFieldListResponse from .custom_metadata_field_update_params import CustomMetadataFieldUpdateParams as CustomMetadataFieldUpdateParams -from .custom_metadata_field_create_response import ( - CustomMetadataFieldCreateResponse as CustomMetadataFieldCreateResponse, -) from .custom_metadata_field_delete_response import ( CustomMetadataFieldDeleteResponse as CustomMetadataFieldDeleteResponse, ) -from .custom_metadata_field_update_response import ( - CustomMetadataFieldUpdateResponse as CustomMetadataFieldUpdateResponse, -) from .video_transformation_error_webhook_event import ( VideoTransformationErrorWebhookEvent as VideoTransformationErrorWebhookEvent, ) diff --git a/src/imagekit/types/custom_metadata_field_create_response.py b/src/imagekit/types/custom_metadata_field.py similarity index 95% rename from src/imagekit/types/custom_metadata_field_create_response.py rename to src/imagekit/types/custom_metadata_field.py index dceb4f6..4c425f7 100644 --- a/src/imagekit/types/custom_metadata_field_create_response.py +++ b/src/imagekit/types/custom_metadata_field.py @@ -7,7 +7,7 @@ from .._models import BaseModel -__all__ = ["CustomMetadataFieldCreateResponse", "Schema"] +__all__ = ["CustomMetadataField", "Schema"] class Schema(BaseModel): @@ -51,7 +51,7 @@ class Schema(BaseModel): """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" -class CustomMetadataFieldCreateResponse(BaseModel): +class CustomMetadataField(BaseModel): id: str """Unique identifier for the custom metadata field. Use this to update the field.""" diff --git a/src/imagekit/types/custom_metadata_field_list_response.py b/src/imagekit/types/custom_metadata_field_list_response.py index 03f6c25..f392874 100644 --- a/src/imagekit/types/custom_metadata_field_list_response.py +++ b/src/imagekit/types/custom_metadata_field_list_response.py @@ -1,80 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing import List +from typing_extensions import TypeAlias -from pydantic import Field as FieldInfo +from .custom_metadata_field import CustomMetadataField -from .._models import BaseModel +__all__ = ["CustomMetadataFieldListResponse"] -__all__ = [ - "CustomMetadataFieldListResponse", - "CustomMetadataFieldListResponseItem", - "CustomMetadataFieldListResponseItemSchema", -] - - -class CustomMetadataFieldListResponseItemSchema(BaseModel): - type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] - """Type of the custom metadata field.""" - - default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( - alias="defaultValue", default=None - ) - """The default value for this custom metadata field. - - Date type of default value depends on the field type. - """ - - is_value_required: Optional[bool] = FieldInfo(alias="isValueRequired", default=None) - """Specifies if the this custom metadata field is required or not.""" - - max_length: Optional[float] = FieldInfo(alias="maxLength", default=None) - """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" - - max_value: Union[str, float, None] = FieldInfo(alias="maxValue", default=None) - """Maximum value of the field. - - Only set if field type is `Date` or `Number`. For `Date` type field, the value - will be in ISO8601 string format. For `Number` type field, it will be a numeric - value. - """ - - min_length: Optional[float] = FieldInfo(alias="minLength", default=None) - """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" - - min_value: Union[str, float, None] = FieldInfo(alias="minValue", default=None) - """Minimum value of the field. - - Only set if field type is `Date` or `Number`. For `Date` type field, the value - will be in ISO8601 string format. For `Number` type field, it will be a numeric - value. - """ - - select_options: Optional[List[Union[str, float, bool]]] = FieldInfo(alias="selectOptions", default=None) - """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" - - -class CustomMetadataFieldListResponseItem(BaseModel): - id: str - """Unique identifier for the custom metadata field. Use this to update the field.""" - - label: str - """Human readable name of the custom metadata field. - - This name is displayed as form field label to the users while setting field - value on the asset in the media library UI. - """ - - name: str - """API name of the custom metadata field. - - This becomes the key while setting `customMetadata` (key-value object) for an - asset using upload or update API. - """ - - schema_: CustomMetadataFieldListResponseItemSchema = FieldInfo(alias="schema") - """An object that describes the rules for the custom metadata field value.""" - - -CustomMetadataFieldListResponse: TypeAlias = List[CustomMetadataFieldListResponseItem] +CustomMetadataFieldListResponse: TypeAlias = List[CustomMetadataField] diff --git a/src/imagekit/types/custom_metadata_field_update_response.py b/src/imagekit/types/custom_metadata_field_update_response.py deleted file mode 100644 index 3789663..0000000 --- a/src/imagekit/types/custom_metadata_field_update_response.py +++ /dev/null @@ -1,73 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Union, Optional -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["CustomMetadataFieldUpdateResponse", "Schema"] - - -class Schema(BaseModel): - type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] - """Type of the custom metadata field.""" - - default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( - alias="defaultValue", default=None - ) - """The default value for this custom metadata field. - - Date type of default value depends on the field type. - """ - - is_value_required: Optional[bool] = FieldInfo(alias="isValueRequired", default=None) - """Specifies if the this custom metadata field is required or not.""" - - max_length: Optional[float] = FieldInfo(alias="maxLength", default=None) - """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" - - max_value: Union[str, float, None] = FieldInfo(alias="maxValue", default=None) - """Maximum value of the field. - - Only set if field type is `Date` or `Number`. For `Date` type field, the value - will be in ISO8601 string format. For `Number` type field, it will be a numeric - value. - """ - - min_length: Optional[float] = FieldInfo(alias="minLength", default=None) - """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" - - min_value: Union[str, float, None] = FieldInfo(alias="minValue", default=None) - """Minimum value of the field. - - Only set if field type is `Date` or `Number`. For `Date` type field, the value - will be in ISO8601 string format. For `Number` type field, it will be a numeric - value. - """ - - select_options: Optional[List[Union[str, float, bool]]] = FieldInfo(alias="selectOptions", default=None) - """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" - - -class CustomMetadataFieldUpdateResponse(BaseModel): - id: str - """Unique identifier for the custom metadata field. Use this to update the field.""" - - label: str - """Human readable name of the custom metadata field. - - This name is displayed as form field label to the users while setting field - value on the asset in the media library UI. - """ - - name: str - """API name of the custom metadata field. - - This becomes the key while setting `customMetadata` (key-value object) for an - asset using upload or update API. - """ - - schema_: Schema = FieldInfo(alias="schema") - """An object that describes the rules for the custom metadata field value.""" diff --git a/tests/api_resources/test_custom_metadata_fields.py b/tests/api_resources/test_custom_metadata_fields.py index 77adcf5..a2e3318 100644 --- a/tests/api_resources/test_custom_metadata_fields.py +++ b/tests/api_resources/test_custom_metadata_fields.py @@ -10,10 +10,9 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type from imagekit.types import ( + CustomMetadataField, CustomMetadataFieldListResponse, - CustomMetadataFieldCreateResponse, CustomMetadataFieldDeleteResponse, - CustomMetadataFieldUpdateResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -30,7 +29,7 @@ def test_method_create(self, client: ImageKit) -> None: name="price", schema={"type": "Number"}, ) - assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -49,7 +48,7 @@ def test_method_create_with_all_params(self, client: ImageKit) -> None: "select_options": ["small", "medium", "large", 30, 40, True], }, ) - assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -63,7 +62,7 @@ def test_raw_response_create(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = response.parse() - assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -77,7 +76,7 @@ def test_streaming_response_create(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = response.parse() - assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) assert cast(Any, response.is_closed) is True @@ -87,7 +86,7 @@ def test_method_update(self, client: ImageKit) -> None: custom_metadata_field = client.custom_metadata_fields.update( id="id", ) - assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -105,7 +104,7 @@ def test_method_update_with_all_params(self, client: ImageKit) -> None: "select_options": ["small", "medium", "large", 30, 40, True], }, ) - assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -117,7 +116,7 @@ def test_raw_response_update(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = response.parse() - assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -129,7 +128,7 @@ def test_streaming_response_update(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = response.parse() - assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) assert cast(Any, response.is_closed) is True @@ -233,7 +232,7 @@ async def test_method_create(self, async_client: AsyncImageKit) -> None: name="price", schema={"type": "Number"}, ) - assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -252,7 +251,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncImageKit) "select_options": ["small", "medium", "large", 30, 40, True], }, ) - assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -266,7 +265,7 @@ async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = await response.parse() - assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -280,7 +279,7 @@ async def test_streaming_response_create(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = await response.parse() - assert_matches_type(CustomMetadataFieldCreateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) assert cast(Any, response.is_closed) is True @@ -290,7 +289,7 @@ async def test_method_update(self, async_client: AsyncImageKit) -> None: custom_metadata_field = await async_client.custom_metadata_fields.update( id="id", ) - assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -308,7 +307,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncImageKit) "select_options": ["small", "medium", "large", 30, 40, True], }, ) - assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -320,7 +319,7 @@ async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = await response.parse() - assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -332,7 +331,7 @@ async def test_streaming_response_update(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" custom_metadata_field = await response.parse() - assert_matches_type(CustomMetadataFieldUpdateResponse, custom_metadata_field, path=["response"]) + assert_matches_type(CustomMetadataField, custom_metadata_field, path=["response"]) assert cast(Any, response.is_closed) is True From 35a42fb320f76094a379274b79cc1d0fafb67614 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 03:19:16 +0000 Subject: [PATCH 042/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 16 +- src/imagekit/resources/files/files.py | 10 +- src/imagekit/resources/files/versions.py | 19 +-- src/imagekit/types/__init__.py | 3 +- src/imagekit/types/asset_list_response.py | 157 +----------------- .../types/{file_get_response.py => file.py} | 4 +- src/imagekit/types/file_update_response.py | 114 +------------ src/imagekit/types/files/__init__.py | 2 - .../types/files/version_get_response.py | 115 ------------- .../types/files/version_list_response.py | 123 +------------- .../types/files/version_restore_response.py | 115 ------------- src/imagekit/types/folder.py | 42 +++++ tests/api_resources/files/test_versions.py | 27 +-- tests/api_resources/test_files.py | 14 +- 15 files changed, 105 insertions(+), 658 deletions(-) rename src/imagekit/types/{file_get_response.py => file.py} (97%) delete mode 100644 src/imagekit/types/files/version_get_response.py delete mode 100644 src/imagekit/types/files/version_restore_response.py create mode 100644 src/imagekit/types/folder.py diff --git a/.stats.yml b/.stats.yml index ec9a755..0fe111b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-967cd0e731df83a642ded194cacae3628050f679c600b1efd4e66cf269973531.yml openapi_spec_hash: 98642308bee81ac776b7b1843089b888 -config_hash: 733231d3642f7945a9459fbc90ddfb8e +config_hash: 91cbeb97fdb75393dffd187ec25a4080 diff --git a/api.md b/api.md index e9b03cb..09a66af 100644 --- a/api.md +++ b/api.md @@ -23,9 +23,10 @@ Types: ```python from imagekit.types import ( + File, + Folder, FileUpdateResponse, FileCopyResponse, - FileGetResponse, FileMoveResponse, FileRenameResponse, FileUploadResponse, @@ -37,7 +38,7 @@ Methods: - client.files.update(file_id, \*\*params) -> FileUpdateResponse - client.files.delete(file_id) -> None - client.files.copy(\*\*params) -> FileCopyResponse -- client.files.get(file_id) -> FileGetResponse +- client.files.get(file_id) -> File - client.files.move(\*\*params) -> FileMoveResponse - client.files.rename(\*\*params) -> FileRenameResponse - client.files.upload(\*\*params) -> FileUploadResponse @@ -67,20 +68,15 @@ Methods: Types: ```python -from imagekit.types.files import ( - VersionListResponse, - VersionDeleteResponse, - VersionGetResponse, - VersionRestoreResponse, -) +from imagekit.types.files import VersionListResponse, VersionDeleteResponse ``` Methods: - client.files.versions.list(file_id) -> VersionListResponse - client.files.versions.delete(version_id, \*, file_id) -> VersionDeleteResponse -- client.files.versions.get(version_id, \*, file_id) -> VersionGetResponse -- client.files.versions.restore(version_id, \*, file_id) -> VersionRestoreResponse +- client.files.versions.get(version_id, \*, file_id) -> File +- client.files.versions.restore(version_id, \*, file_id) -> File ## Metadata diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index fd3d1fb..58b4d98 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -42,8 +42,8 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) +from ...types.file import File from ..._base_client import make_request_options -from ...types.file_get_response import FileGetResponse from ...types.file_copy_response import FileCopyResponse from ...types.file_move_response import FileMoveResponse from ...types.file_rename_response import FileRenameResponse @@ -223,7 +223,7 @@ def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileGetResponse: + ) -> File: """ This API returns an object with details or attributes about the current version of the file. @@ -244,7 +244,7 @@ def get( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FileGetResponse, + cast_to=File, ) def move( @@ -794,7 +794,7 @@ async def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileGetResponse: + ) -> File: """ This API returns an object with details or attributes about the current version of the file. @@ -815,7 +815,7 @@ async def get( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FileGetResponse, + cast_to=File, ) async def move( diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py index 32987d9..09b473e 100644 --- a/src/imagekit/resources/files/versions.py +++ b/src/imagekit/resources/files/versions.py @@ -13,11 +13,10 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) +from ...types.file import File from ..._base_client import make_request_options -from ...types.files.version_get_response import VersionGetResponse from ...types.files.version_list_response import VersionListResponse from ...types.files.version_delete_response import VersionDeleteResponse -from ...types.files.version_restore_response import VersionRestoreResponse __all__ = ["VersionsResource", "AsyncVersionsResource"] @@ -126,7 +125,7 @@ def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> VersionGetResponse: + ) -> File: """ This API returns an object with details or attributes of a file version. @@ -148,7 +147,7 @@ def get( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=VersionGetResponse, + cast_to=File, ) def restore( @@ -162,7 +161,7 @@ def restore( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> VersionRestoreResponse: + ) -> File: """ This API restores a file version as the current file version. @@ -184,7 +183,7 @@ def restore( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=VersionRestoreResponse, + cast_to=File, ) @@ -292,7 +291,7 @@ async def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> VersionGetResponse: + ) -> File: """ This API returns an object with details or attributes of a file version. @@ -314,7 +313,7 @@ async def get( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=VersionGetResponse, + cast_to=File, ) async def restore( @@ -328,7 +327,7 @@ async def restore( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> VersionRestoreResponse: + ) -> File: """ This API restores a file version as the current file version. @@ -350,7 +349,7 @@ async def restore( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=VersionRestoreResponse, + cast_to=File, ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 85a1210..5c759c7 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -2,10 +2,11 @@ from __future__ import annotations +from .file import File as File +from .folder import Folder as Folder from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams from .asset_list_params import AssetListParams as AssetListParams -from .file_get_response import FileGetResponse as FileGetResponse from .file_copy_response import FileCopyResponse as FileCopyResponse from .file_move_response import FileMoveResponse as FileMoveResponse from .file_rename_params import FileRenameParams as FileRenameParams diff --git a/src/imagekit/types/asset_list_response.py b/src/imagekit/types/asset_list_response.py index a84b162..00596e2 100644 --- a/src/imagekit/types/asset_list_response.py +++ b/src/imagekit/types/asset_list_response.py @@ -1,158 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Union, Optional -from datetime import datetime -from typing_extensions import Literal, TypeAlias +from typing import List, Union +from typing_extensions import TypeAlias -from pydantic import Field as FieldInfo +from .file import File +from .folder import Folder -from .._models import BaseModel +__all__ = ["AssetListResponse", "AssetListResponseItem"] -__all__ = [ - "AssetListResponse", - "AssetListResponseItem", - "AssetListResponseItemFileDetails", - "AssetListResponseItemFileDetailsAITag", - "AssetListResponseItemFileDetailsVersionInfo", - "AssetListResponseItemFolderDetails", -] - - -class AssetListResponseItemFileDetailsAITag(BaseModel): - confidence: Optional[float] = None - """Confidence score of the tag.""" - - name: Optional[str] = None - """Name of the tag.""" - - source: Optional[str] = None - """Source of the tag. - - Possible values are `google-auto-tagging` and `aws-auto-tagging`. - """ - - -class AssetListResponseItemFileDetailsVersionInfo(BaseModel): - id: Optional[str] = None - """Unique identifier of the file version.""" - - name: Optional[str] = None - """Name of the file version.""" - - -class AssetListResponseItemFileDetails(BaseModel): - ai_tags: Optional[List[AssetListResponseItemFileDetailsAITag]] = FieldInfo(alias="AITags", default=None) - """An array of tags assigned to the file by auto tagging.""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Date and time when the file was uploaded. - - The date and time is in ISO8601 format. - """ - - custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) - """An string with custom coordinates of the file.""" - - custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) - """An object with custom metadata for the file.""" - - file_id: Optional[str] = FieldInfo(alias="fileId", default=None) - """Unique identifier of the asset.""" - - file_path: Optional[str] = FieldInfo(alias="filePath", default=None) - """Path of the file. - - This is the path you would use in the URL to access the file. For example, if - the file is at the root of the media library, the path will be `/file.jpg`. If - the file is inside a folder named `images`, the path will be `/images/file.jpg`. - """ - - file_type: Optional[str] = FieldInfo(alias="fileType", default=None) - """Type of the file. Possible values are `image`, `non-image`.""" - - has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) - """Specifies if the image has an alpha channel.""" - - height: Optional[float] = None - """Height of the file.""" - - is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) - """Specifies if the file is private or not.""" - - is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) - """Specifies if the file is published or not.""" - - mime: Optional[str] = None - """MIME type of the file.""" - - name: Optional[str] = None - """Name of the asset.""" - - size: Optional[float] = None - """Size of the file in bytes.""" - - tags: Optional[List[str]] = None - """An array of tags assigned to the file. - - Tags are used to search files in the media library. - """ - - thumbnail: Optional[str] = None - """URL of the thumbnail image. - - This URL is used to access the thumbnail image of the file in the media library. - """ - - type: Optional[Literal["file", "file-version"]] = None - """Type of the asset.""" - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - """Date and time when the file was last updated. - - The date and time is in ISO8601 format. - """ - - url: Optional[str] = None - """URL of the file.""" - - version_info: Optional[AssetListResponseItemFileDetailsVersionInfo] = FieldInfo(alias="versionInfo", default=None) - """An object with details of the file version.""" - - width: Optional[float] = None - """Width of the file.""" - - -class AssetListResponseItemFolderDetails(BaseModel): - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Date and time when the folder was created. - - The date and time is in ISO8601 format. - """ - - folder_id: Optional[str] = FieldInfo(alias="folderId", default=None) - """Unique identifier of the asset.""" - - folder_path: Optional[str] = FieldInfo(alias="folderPath", default=None) - """Path of the folder. - - This is the path you would use in the URL to access the folder. For example, if - the folder is at the root of the media library, the path will be /folder. If the - folder is inside another folder named images, the path will be /images/folder. - """ - - name: Optional[str] = None - """Name of the asset.""" - - type: Optional[Literal["folder"]] = None - """Type of the asset.""" - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - """Date and time when the folder was last updated. - - The date and time is in ISO8601 format. - """ - - -AssetListResponseItem: TypeAlias = Union[AssetListResponseItemFileDetails, AssetListResponseItemFolderDetails] +AssetListResponseItem: TypeAlias = Union[File, Folder] AssetListResponse: TypeAlias = List[AssetListResponseItem] diff --git a/src/imagekit/types/file_get_response.py b/src/imagekit/types/file.py similarity index 97% rename from src/imagekit/types/file_get_response.py rename to src/imagekit/types/file.py index 90dd4cd..b674d06 100644 --- a/src/imagekit/types/file_get_response.py +++ b/src/imagekit/types/file.py @@ -8,7 +8,7 @@ from .._models import BaseModel -__all__ = ["FileGetResponse", "AITag", "VersionInfo"] +__all__ = ["File", "AITag", "VersionInfo"] class AITag(BaseModel): @@ -33,7 +33,7 @@ class VersionInfo(BaseModel): """Name of the file version.""" -class FileGetResponse(BaseModel): +class File(BaseModel): ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" diff --git a/src/imagekit/types/file_update_response.py b/src/imagekit/types/file_update_response.py index 5bec99c..34b9731 100644 --- a/src/imagekit/types/file_update_response.py +++ b/src/imagekit/types/file_update_response.py @@ -1,31 +1,17 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional -from datetime import datetime +from typing import Optional from typing_extensions import Literal from pydantic import Field as FieldInfo +from .file import File from .._models import BaseModel -__all__ = ["FileUpdateResponse", "AITag", "ExtensionStatus", "VersionInfo"] +__all__ = ["FileUpdateResponse", "FileUpdateResponseExtensionStatus"] -class AITag(BaseModel): - confidence: Optional[float] = None - """Confidence score of the tag.""" - - name: Optional[str] = None - """Name of the tag.""" - - source: Optional[str] = None - """Source of the tag. - - Possible values are `google-auto-tagging` and `aws-auto-tagging`. - """ - - -class ExtensionStatus(BaseModel): +class FileUpdateResponseExtensionStatus(BaseModel): ai_auto_description: Optional[Literal["success", "pending", "failed"]] = FieldInfo( alias="ai-auto-description", default=None ) @@ -41,93 +27,5 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) -class VersionInfo(BaseModel): - id: Optional[str] = None - """Unique identifier of the file version.""" - - name: Optional[str] = None - """Name of the file version.""" - - -class FileUpdateResponse(BaseModel): - ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) - """An array of tags assigned to the file by auto tagging.""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Date and time when the file was uploaded. - - The date and time is in ISO8601 format. - """ - - custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) - """An string with custom coordinates of the file.""" - - custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) - """An object with custom metadata for the file.""" - - extension_status: Optional[ExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) - - file_id: Optional[str] = FieldInfo(alias="fileId", default=None) - """Unique identifier of the asset.""" - - file_path: Optional[str] = FieldInfo(alias="filePath", default=None) - """Path of the file. - - This is the path you would use in the URL to access the file. For example, if - the file is at the root of the media library, the path will be `/file.jpg`. If - the file is inside a folder named `images`, the path will be `/images/file.jpg`. - """ - - file_type: Optional[str] = FieldInfo(alias="fileType", default=None) - """Type of the file. Possible values are `image`, `non-image`.""" - - has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) - """Specifies if the image has an alpha channel.""" - - height: Optional[float] = None - """Height of the file.""" - - is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) - """Specifies if the file is private or not.""" - - is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) - """Specifies if the file is published or not.""" - - mime: Optional[str] = None - """MIME type of the file.""" - - name: Optional[str] = None - """Name of the asset.""" - - size: Optional[float] = None - """Size of the file in bytes.""" - - tags: Optional[List[str]] = None - """An array of tags assigned to the file. - - Tags are used to search files in the media library. - """ - - thumbnail: Optional[str] = None - """URL of the thumbnail image. - - This URL is used to access the thumbnail image of the file in the media library. - """ - - type: Optional[Literal["file", "file-version"]] = None - """Type of the asset.""" - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - """Date and time when the file was last updated. - - The date and time is in ISO8601 format. - """ - - url: Optional[str] = None - """URL of the file.""" - - version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) - """An object with details of the file version.""" - - width: Optional[float] = None - """Width of the file.""" +class FileUpdateResponse(File): + extension_status: Optional[FileUpdateResponseExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) diff --git a/src/imagekit/types/files/__init__.py b/src/imagekit/types/files/__init__.py index ed8f717..b6dd7da 100644 --- a/src/imagekit/types/files/__init__.py +++ b/src/imagekit/types/files/__init__.py @@ -5,13 +5,11 @@ from .bulk_delete_params import BulkDeleteParams as BulkDeleteParams from .bulk_add_tags_params import BulkAddTagsParams as BulkAddTagsParams from .bulk_delete_response import BulkDeleteResponse as BulkDeleteResponse -from .version_get_response import VersionGetResponse as VersionGetResponse from .metadata_get_response import MetadataGetResponse as MetadataGetResponse from .version_list_response import VersionListResponse as VersionListResponse from .bulk_add_tags_response import BulkAddTagsResponse as BulkAddTagsResponse from .bulk_remove_tags_params import BulkRemoveTagsParams as BulkRemoveTagsParams from .version_delete_response import VersionDeleteResponse as VersionDeleteResponse -from .version_restore_response import VersionRestoreResponse as VersionRestoreResponse from .bulk_remove_tags_response import BulkRemoveTagsResponse as BulkRemoveTagsResponse from .bulk_remove_ai_tags_params import BulkRemoveAITagsParams as BulkRemoveAITagsParams from .bulk_remove_ai_tags_response import BulkRemoveAITagsResponse as BulkRemoveAITagsResponse diff --git a/src/imagekit/types/files/version_get_response.py b/src/imagekit/types/files/version_get_response.py deleted file mode 100644 index 5e607a5..0000000 --- a/src/imagekit/types/files/version_get_response.py +++ /dev/null @@ -1,115 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["VersionGetResponse", "AITag", "VersionInfo"] - - -class AITag(BaseModel): - confidence: Optional[float] = None - """Confidence score of the tag.""" - - name: Optional[str] = None - """Name of the tag.""" - - source: Optional[str] = None - """Source of the tag. - - Possible values are `google-auto-tagging` and `aws-auto-tagging`. - """ - - -class VersionInfo(BaseModel): - id: Optional[str] = None - """Unique identifier of the file version.""" - - name: Optional[str] = None - """Name of the file version.""" - - -class VersionGetResponse(BaseModel): - ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) - """An array of tags assigned to the file by auto tagging.""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Date and time when the file was uploaded. - - The date and time is in ISO8601 format. - """ - - custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) - """An string with custom coordinates of the file.""" - - custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) - """An object with custom metadata for the file.""" - - file_id: Optional[str] = FieldInfo(alias="fileId", default=None) - """Unique identifier of the asset.""" - - file_path: Optional[str] = FieldInfo(alias="filePath", default=None) - """Path of the file. - - This is the path you would use in the URL to access the file. For example, if - the file is at the root of the media library, the path will be `/file.jpg`. If - the file is inside a folder named `images`, the path will be `/images/file.jpg`. - """ - - file_type: Optional[str] = FieldInfo(alias="fileType", default=None) - """Type of the file. Possible values are `image`, `non-image`.""" - - has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) - """Specifies if the image has an alpha channel.""" - - height: Optional[float] = None - """Height of the file.""" - - is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) - """Specifies if the file is private or not.""" - - is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) - """Specifies if the file is published or not.""" - - mime: Optional[str] = None - """MIME type of the file.""" - - name: Optional[str] = None - """Name of the asset.""" - - size: Optional[float] = None - """Size of the file in bytes.""" - - tags: Optional[List[str]] = None - """An array of tags assigned to the file. - - Tags are used to search files in the media library. - """ - - thumbnail: Optional[str] = None - """URL of the thumbnail image. - - This URL is used to access the thumbnail image of the file in the media library. - """ - - type: Optional[Literal["file", "file-version"]] = None - """Type of the asset.""" - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - """Date and time when the file was last updated. - - The date and time is in ISO8601 format. - """ - - url: Optional[str] = None - """URL of the file.""" - - version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) - """An object with details of the file version.""" - - width: Optional[float] = None - """Width of the file.""" diff --git a/src/imagekit/types/files/version_list_response.py b/src/imagekit/types/files/version_list_response.py index 8e42a01..6d0c3f0 100644 --- a/src/imagekit/types/files/version_list_response.py +++ b/src/imagekit/types/files/version_list_response.py @@ -1,123 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional -from datetime import datetime -from typing_extensions import Literal, TypeAlias +from typing import List +from typing_extensions import TypeAlias -from pydantic import Field as FieldInfo +from ..file import File -from ..._models import BaseModel +__all__ = ["VersionListResponse"] -__all__ = [ - "VersionListResponse", - "VersionListResponseItem", - "VersionListResponseItemAITag", - "VersionListResponseItemVersionInfo", -] - - -class VersionListResponseItemAITag(BaseModel): - confidence: Optional[float] = None - """Confidence score of the tag.""" - - name: Optional[str] = None - """Name of the tag.""" - - source: Optional[str] = None - """Source of the tag. - - Possible values are `google-auto-tagging` and `aws-auto-tagging`. - """ - - -class VersionListResponseItemVersionInfo(BaseModel): - id: Optional[str] = None - """Unique identifier of the file version.""" - - name: Optional[str] = None - """Name of the file version.""" - - -class VersionListResponseItem(BaseModel): - ai_tags: Optional[List[VersionListResponseItemAITag]] = FieldInfo(alias="AITags", default=None) - """An array of tags assigned to the file by auto tagging.""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Date and time when the file was uploaded. - - The date and time is in ISO8601 format. - """ - - custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) - """An string with custom coordinates of the file.""" - - custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) - """An object with custom metadata for the file.""" - - file_id: Optional[str] = FieldInfo(alias="fileId", default=None) - """Unique identifier of the asset.""" - - file_path: Optional[str] = FieldInfo(alias="filePath", default=None) - """Path of the file. - - This is the path you would use in the URL to access the file. For example, if - the file is at the root of the media library, the path will be `/file.jpg`. If - the file is inside a folder named `images`, the path will be `/images/file.jpg`. - """ - - file_type: Optional[str] = FieldInfo(alias="fileType", default=None) - """Type of the file. Possible values are `image`, `non-image`.""" - - has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) - """Specifies if the image has an alpha channel.""" - - height: Optional[float] = None - """Height of the file.""" - - is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) - """Specifies if the file is private or not.""" - - is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) - """Specifies if the file is published or not.""" - - mime: Optional[str] = None - """MIME type of the file.""" - - name: Optional[str] = None - """Name of the asset.""" - - size: Optional[float] = None - """Size of the file in bytes.""" - - tags: Optional[List[str]] = None - """An array of tags assigned to the file. - - Tags are used to search files in the media library. - """ - - thumbnail: Optional[str] = None - """URL of the thumbnail image. - - This URL is used to access the thumbnail image of the file in the media library. - """ - - type: Optional[Literal["file", "file-version"]] = None - """Type of the asset.""" - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - """Date and time when the file was last updated. - - The date and time is in ISO8601 format. - """ - - url: Optional[str] = None - """URL of the file.""" - - version_info: Optional[VersionListResponseItemVersionInfo] = FieldInfo(alias="versionInfo", default=None) - """An object with details of the file version.""" - - width: Optional[float] = None - """Width of the file.""" - - -VersionListResponse: TypeAlias = List[VersionListResponseItem] +VersionListResponse: TypeAlias = List[File] diff --git a/src/imagekit/types/files/version_restore_response.py b/src/imagekit/types/files/version_restore_response.py deleted file mode 100644 index a4503e8..0000000 --- a/src/imagekit/types/files/version_restore_response.py +++ /dev/null @@ -1,115 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["VersionRestoreResponse", "AITag", "VersionInfo"] - - -class AITag(BaseModel): - confidence: Optional[float] = None - """Confidence score of the tag.""" - - name: Optional[str] = None - """Name of the tag.""" - - source: Optional[str] = None - """Source of the tag. - - Possible values are `google-auto-tagging` and `aws-auto-tagging`. - """ - - -class VersionInfo(BaseModel): - id: Optional[str] = None - """Unique identifier of the file version.""" - - name: Optional[str] = None - """Name of the file version.""" - - -class VersionRestoreResponse(BaseModel): - ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) - """An array of tags assigned to the file by auto tagging.""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Date and time when the file was uploaded. - - The date and time is in ISO8601 format. - """ - - custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) - """An string with custom coordinates of the file.""" - - custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) - """An object with custom metadata for the file.""" - - file_id: Optional[str] = FieldInfo(alias="fileId", default=None) - """Unique identifier of the asset.""" - - file_path: Optional[str] = FieldInfo(alias="filePath", default=None) - """Path of the file. - - This is the path you would use in the URL to access the file. For example, if - the file is at the root of the media library, the path will be `/file.jpg`. If - the file is inside a folder named `images`, the path will be `/images/file.jpg`. - """ - - file_type: Optional[str] = FieldInfo(alias="fileType", default=None) - """Type of the file. Possible values are `image`, `non-image`.""" - - has_alpha: Optional[bool] = FieldInfo(alias="hasAlpha", default=None) - """Specifies if the image has an alpha channel.""" - - height: Optional[float] = None - """Height of the file.""" - - is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) - """Specifies if the file is private or not.""" - - is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) - """Specifies if the file is published or not.""" - - mime: Optional[str] = None - """MIME type of the file.""" - - name: Optional[str] = None - """Name of the asset.""" - - size: Optional[float] = None - """Size of the file in bytes.""" - - tags: Optional[List[str]] = None - """An array of tags assigned to the file. - - Tags are used to search files in the media library. - """ - - thumbnail: Optional[str] = None - """URL of the thumbnail image. - - This URL is used to access the thumbnail image of the file in the media library. - """ - - type: Optional[Literal["file", "file-version"]] = None - """Type of the asset.""" - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - """Date and time when the file was last updated. - - The date and time is in ISO8601 format. - """ - - url: Optional[str] = None - """URL of the file.""" - - version_info: Optional[VersionInfo] = FieldInfo(alias="versionInfo", default=None) - """An object with details of the file version.""" - - width: Optional[float] = None - """Width of the file.""" diff --git a/src/imagekit/types/folder.py b/src/imagekit/types/folder.py new file mode 100644 index 0000000..17b7287 --- /dev/null +++ b/src/imagekit/types/folder.py @@ -0,0 +1,42 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["Folder"] + + +class Folder(BaseModel): + created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) + """Date and time when the folder was created. + + The date and time is in ISO8601 format. + """ + + folder_id: Optional[str] = FieldInfo(alias="folderId", default=None) + """Unique identifier of the asset.""" + + folder_path: Optional[str] = FieldInfo(alias="folderPath", default=None) + """Path of the folder. + + This is the path you would use in the URL to access the folder. For example, if + the folder is at the root of the media library, the path will be /folder. If the + folder is inside another folder named images, the path will be /images/folder. + """ + + name: Optional[str] = None + """Name of the asset.""" + + type: Optional[Literal["folder"]] = None + """Type of the asset.""" + + updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) + """Date and time when the folder was last updated. + + The date and time is in ISO8601 format. + """ diff --git a/tests/api_resources/files/test_versions.py b/tests/api_resources/files/test_versions.py index f9df14d..1d0121d 100644 --- a/tests/api_resources/files/test_versions.py +++ b/tests/api_resources/files/test_versions.py @@ -9,7 +9,8 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.files import VersionGetResponse, VersionListResponse, VersionDeleteResponse, VersionRestoreResponse +from imagekit.types import File +from imagekit.types.files import VersionListResponse, VersionDeleteResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -118,7 +119,7 @@ def test_method_get(self, client: ImageKit) -> None: version_id="versionId", file_id="fileId", ) - assert_matches_type(VersionGetResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -131,7 +132,7 @@ def test_raw_response_get(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() - assert_matches_type(VersionGetResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -144,7 +145,7 @@ def test_streaming_response_get(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() - assert_matches_type(VersionGetResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) assert cast(Any, response.is_closed) is True @@ -170,7 +171,7 @@ def test_method_restore(self, client: ImageKit) -> None: version_id="versionId", file_id="fileId", ) - assert_matches_type(VersionRestoreResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -183,7 +184,7 @@ def test_raw_response_restore(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() - assert_matches_type(VersionRestoreResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -196,7 +197,7 @@ def test_streaming_response_restore(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = response.parse() - assert_matches_type(VersionRestoreResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) assert cast(Any, response.is_closed) is True @@ -322,7 +323,7 @@ async def test_method_get(self, async_client: AsyncImageKit) -> None: version_id="versionId", file_id="fileId", ) - assert_matches_type(VersionGetResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -335,7 +336,7 @@ async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = await response.parse() - assert_matches_type(VersionGetResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -348,7 +349,7 @@ async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = await response.parse() - assert_matches_type(VersionGetResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) assert cast(Any, response.is_closed) is True @@ -374,7 +375,7 @@ async def test_method_restore(self, async_client: AsyncImageKit) -> None: version_id="versionId", file_id="fileId", ) - assert_matches_type(VersionRestoreResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -387,7 +388,7 @@ async def test_raw_response_restore(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = await response.parse() - assert_matches_type(VersionRestoreResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -400,7 +401,7 @@ async def test_streaming_response_restore(self, async_client: AsyncImageKit) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" version = await response.parse() - assert_matches_type(VersionRestoreResponse, version, path=["response"]) + assert_matches_type(File, version, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 5cd148b..94de220 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -10,7 +10,7 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type from imagekit.types import ( - FileGetResponse, + File, FileCopyResponse, FileMoveResponse, FileRenameResponse, @@ -202,7 +202,7 @@ def test_method_get(self, client: ImageKit) -> None: file = client.files.get( "fileId", ) - assert_matches_type(FileGetResponse, file, path=["response"]) + assert_matches_type(File, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -214,7 +214,7 @@ def test_raw_response_get(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(FileGetResponse, file, path=["response"]) + assert_matches_type(File, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -226,7 +226,7 @@ def test_streaming_response_get(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(FileGetResponse, file, path=["response"]) + assert_matches_type(File, file, path=["response"]) assert cast(Any, response.is_closed) is True @@ -604,7 +604,7 @@ async def test_method_get(self, async_client: AsyncImageKit) -> None: file = await async_client.files.get( "fileId", ) - assert_matches_type(FileGetResponse, file, path=["response"]) + assert_matches_type(File, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -616,7 +616,7 @@ async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(FileGetResponse, file, path=["response"]) + assert_matches_type(File, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -628,7 +628,7 @@ async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(FileGetResponse, file, path=["response"]) + assert_matches_type(File, file, path=["response"]) assert cast(Any, response.is_closed) is True From 626430c6754d3f6afa0380006502ca9e0b78f71b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 03:21:04 +0000 Subject: [PATCH 043/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0fe111b..cf2fe47 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-967cd0e731df83a642ded194cacae3628050f679c600b1efd4e66cf269973531.yml openapi_spec_hash: 98642308bee81ac776b7b1843089b888 -config_hash: 91cbeb97fdb75393dffd187ec25a4080 +config_hash: 734b211088fdf0d30e3d6c8788ac83bc diff --git a/api.md b/api.md index 09a66af..713a5a7 100644 --- a/api.md +++ b/api.md @@ -96,7 +96,7 @@ Methods: Types: ```python -from imagekit.types import AssetListResponse +from imagekit.types import File, Folder, AssetListResponse ``` Methods: From 1074a7964cac3493fd6247ab126569b47070db7a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 03:21:32 +0000 Subject: [PATCH 044/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index cf2fe47..0fe111b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-967cd0e731df83a642ded194cacae3628050f679c600b1efd4e66cf269973531.yml openapi_spec_hash: 98642308bee81ac776b7b1843089b888 -config_hash: 734b211088fdf0d30e3d6c8788ac83bc +config_hash: 91cbeb97fdb75393dffd187ec25a4080 diff --git a/api.md b/api.md index 713a5a7..09a66af 100644 --- a/api.md +++ b/api.md @@ -96,7 +96,7 @@ Methods: Types: ```python -from imagekit.types import File, Folder, AssetListResponse +from imagekit.types import AssetListResponse ``` Methods: From f8e268e8f9dba268d63358a5b40f448ad2a04ea0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 03:28:17 +0000 Subject: [PATCH 045/177] feat(api): manual updates --- .stats.yml | 6 +- api.md | 1 + src/imagekit/resources/accounts/origins.py | 9 +- src/imagekit/types/accounts/__init__.py | 1 + .../types/accounts/origin_create_params.py | 215 +----------------- .../types/accounts/origin_create_response.py | 170 +++++++------- .../types/accounts/origin_get_response.py | 170 +++++++------- .../types/accounts/origin_list_response.py | 186 ++++++++------- src/imagekit/types/accounts/origin_param.py | 206 +++++++++++++++++ .../types/accounts/origin_update_params.py | 215 +----------------- .../types/accounts/origin_update_response.py | 170 +++++++------- 11 files changed, 571 insertions(+), 778 deletions(-) create mode 100644 src/imagekit/types/accounts/origin_param.py diff --git a/.stats.yml b/.stats.yml index 0fe111b..53bd25d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-967cd0e731df83a642ded194cacae3628050f679c600b1efd4e66cf269973531.yml -openapi_spec_hash: 98642308bee81ac776b7b1843089b888 -config_hash: 91cbeb97fdb75393dffd187ec25a4080 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d65a790786704dc315c1fded8ee24d61a55d96054fbbf1e6da429ec96b3e0c88.yml +openapi_spec_hash: 0fa9ee90455e183ec3b5d4e36f1351a9 +config_hash: 89ffae9ef2878c981a64f42cadb85186 diff --git a/api.md b/api.md index 09a66af..459876b 100644 --- a/api.md +++ b/api.md @@ -172,6 +172,7 @@ Types: ```python from imagekit.types.accounts import ( + Origin, OriginCreateResponse, OriginUpdateResponse, OriginListResponse, diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index da1e08e..7b525d3 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -18,6 +18,7 @@ ) from ..._base_client import make_request_options from ...types.accounts import origin_create_params, origin_update_params +from ...types.accounts.origin_param import OriginParam from ...types.accounts.origin_get_response import OriginGetResponse from ...types.accounts.origin_list_response import OriginListResponse from ...types.accounts.origin_create_response import OriginCreateResponse @@ -49,7 +50,7 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: def create( self, *, - origin: origin_create_params.Origin, + origin: OriginParam, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -91,7 +92,7 @@ def update( self, id: str, *, - origin: origin_update_params.Origin, + origin: OriginParam, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -262,7 +263,7 @@ def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: async def create( self, *, - origin: origin_create_params.Origin, + origin: OriginParam, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -304,7 +305,7 @@ async def update( self, id: str, *, - origin: origin_update_params.Origin, + origin: OriginParam, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, diff --git a/src/imagekit/types/accounts/__init__.py b/src/imagekit/types/accounts/__init__.py index cc6d81c..a6cb719 100644 --- a/src/imagekit/types/accounts/__init__.py +++ b/src/imagekit/types/accounts/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +from .origin_param import OriginParam as OriginParam from .usage_get_params import UsageGetParams as UsageGetParams from .usage_get_response import UsageGetResponse as UsageGetResponse from .origin_get_response import OriginGetResponse as OriginGetResponse diff --git a/src/imagekit/types/accounts/origin_create_params.py b/src/imagekit/types/accounts/origin_create_params.py index 86c3e38..babc28f 100644 --- a/src/imagekit/types/accounts/origin_create_params.py +++ b/src/imagekit/types/accounts/origin_create_params.py @@ -2,220 +2,13 @@ from __future__ import annotations -from typing import Union -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Required, TypedDict -from ..._utils import PropertyInfo +from .origin_param import OriginParam -__all__ = [ - "OriginCreateParams", - "Origin", - "OriginS3", - "OriginS3Compatible", - "OriginCloudinaryBackup", - "OriginWebFolder", - "OriginWebProxy", - "OriginGcs", - "OriginAzureBlob", - "OriginAkeneoPim", -] +__all__ = ["OriginCreateParams"] class OriginCreateParams(TypedDict, total=False): - origin: Required[Origin] + origin: Required[OriginParam] """Schema for origin resources.""" - - -class OriginS3(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["S3"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class OriginS3Compatible(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - endpoint: Required[str] - """Custom S3-compatible endpoint.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["S3_COMPATIBLE"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] - """Use path-style S3 URLs?""" - - -class OriginCloudinaryBackup(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["CLOUDINARY_BACKUP"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class OriginWebFolder(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Root URL for the web folder origin.""" - - name: Required[str] - """Display name of the origin.""" - - type: Required[Literal["WEB_FOLDER"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] - """Forward the Host header to origin?""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class OriginWebProxy(TypedDict, total=False): - name: Required[str] - """Display name of the origin.""" - - type: Required[Literal["WEB_PROXY"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class OriginGcs(TypedDict, total=False): - bucket: Required[str] - - client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] - - name: Required[str] - """Display name of the origin.""" - - private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] - - type: Required[Literal["GCS"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class OriginAzureBlob(TypedDict, total=False): - account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] - - container: Required[str] - - name: Required[str] - """Display name of the origin.""" - - sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] - - type: Required[Literal["AZURE_BLOB"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class OriginAkeneoPim(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Akeneo instance base URL.""" - - client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] - """Akeneo API client ID.""" - - client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] - """Akeneo API client secret.""" - - name: Required[str] - """Display name of the origin.""" - - password: Required[str] - """Akeneo API password.""" - - type: Required[Literal["AKENEO_PIM"]] - - username: Required[str] - """Akeneo API username.""" - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -Origin: TypeAlias = Union[ - OriginS3, - OriginS3Compatible, - OriginCloudinaryBackup, - OriginWebFolder, - OriginWebProxy, - OriginGcs, - OriginAzureBlob, - OriginAkeneoPim, -] diff --git a/src/imagekit/types/accounts/origin_create_response.py b/src/imagekit/types/accounts/origin_create_response.py index faaa8fd..f335ba7 100644 --- a/src/imagekit/types/accounts/origin_create_response.py +++ b/src/imagekit/types/accounts/origin_create_response.py @@ -1,11 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias +from typing_extensions import Literal, TypeAlias from pydantic import Field as FieldInfo -from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -15,43 +14,42 @@ "CloudinaryBackup", "WebFolder", "WebProxy", - "Gcs", - "AzureBlob", + "GoogleCloudStorageGcs", + "AzureBlobStorage", "AkeneoPim", ] class S3(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["S3"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class S3Compatible(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ + +class S3Compatible(BaseModel): + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" @@ -59,166 +57,168 @@ class S3Compatible(BaseModel): endpoint: str """Custom S3-compatible endpoint.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") - """Use path-style S3 URLs?""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["S3_COMPATIBLE"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" + + prefix: Optional[str] = None + """Path prefix inside the bucket.""" + + s3_force_path_style: Optional[bool] = FieldInfo(alias="s3ForcePathStyle", default=None) + """Use path-style S3 URLs?""" -class CloudinaryBackup(BaseModel): - id: str - """Unique identifier for the origin. - This is generated by ImageKit when you create a new origin. - """ +class CloudinaryBackup(BaseModel): + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["CLOUDINARY_BACKUP"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class WebFolder(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ +class WebFolder(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" - forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") - """Forward the Host header to origin?""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" type: Literal["WEB_FOLDER"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + forward_host_header_to_origin: Optional[bool] = FieldInfo(alias="forwardHostHeaderToOrigin", default=None) + """Forward the Host header to origin?""" -class WebProxy(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) """Whether to send a Canonical header.""" + +class WebProxy(BaseModel): name: str """Display name of the origin.""" type: Literal["WEB_PROXY"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class Gcs(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ +class GoogleCloudStorageGcs(BaseModel): bucket: str client_email: str = FieldInfo(alias="clientEmail") - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str + private_key: str = FieldInfo(alias="privateKey") type: Literal["GCS"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class AzureBlob(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None - This is generated by ImageKit when you create a new origin. - """ +class AzureBlobStorage(BaseModel): account_name: str = FieldInfo(alias="accountName") container: str - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str + sas_token: str = FieldInfo(alias="sasToken") type: Literal["AZURE_BLOB"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class AkeneoPim(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None - This is generated by ImageKit when you create a new origin. - """ +class AkeneoPim(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" + client_id: str = FieldInfo(alias="clientId") + """Akeneo API client ID.""" + + client_secret: str = FieldInfo(alias="clientSecret") + """Akeneo API client secret.""" name: str """Display name of the origin.""" + password: str + """Akeneo API password.""" + type: Literal["AKENEO_PIM"] + username: str + """Akeneo API username.""" + + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" + -OriginCreateResponse: TypeAlias = Annotated[ - Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], - PropertyInfo(discriminator="type"), +OriginCreateResponse: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim ] diff --git a/src/imagekit/types/accounts/origin_get_response.py b/src/imagekit/types/accounts/origin_get_response.py index 1c1c0a5..56dcc96 100644 --- a/src/imagekit/types/accounts/origin_get_response.py +++ b/src/imagekit/types/accounts/origin_get_response.py @@ -1,11 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias +from typing_extensions import Literal, TypeAlias from pydantic import Field as FieldInfo -from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -15,43 +14,42 @@ "CloudinaryBackup", "WebFolder", "WebProxy", - "Gcs", - "AzureBlob", + "GoogleCloudStorageGcs", + "AzureBlobStorage", "AkeneoPim", ] class S3(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["S3"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class S3Compatible(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ + +class S3Compatible(BaseModel): + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" @@ -59,166 +57,168 @@ class S3Compatible(BaseModel): endpoint: str """Custom S3-compatible endpoint.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") - """Use path-style S3 URLs?""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["S3_COMPATIBLE"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" + + prefix: Optional[str] = None + """Path prefix inside the bucket.""" + + s3_force_path_style: Optional[bool] = FieldInfo(alias="s3ForcePathStyle", default=None) + """Use path-style S3 URLs?""" -class CloudinaryBackup(BaseModel): - id: str - """Unique identifier for the origin. - This is generated by ImageKit when you create a new origin. - """ +class CloudinaryBackup(BaseModel): + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["CLOUDINARY_BACKUP"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class WebFolder(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ +class WebFolder(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" - forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") - """Forward the Host header to origin?""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" type: Literal["WEB_FOLDER"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + forward_host_header_to_origin: Optional[bool] = FieldInfo(alias="forwardHostHeaderToOrigin", default=None) + """Forward the Host header to origin?""" -class WebProxy(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) """Whether to send a Canonical header.""" + +class WebProxy(BaseModel): name: str """Display name of the origin.""" type: Literal["WEB_PROXY"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class Gcs(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ +class GoogleCloudStorageGcs(BaseModel): bucket: str client_email: str = FieldInfo(alias="clientEmail") - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str + private_key: str = FieldInfo(alias="privateKey") type: Literal["GCS"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class AzureBlob(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None - This is generated by ImageKit when you create a new origin. - """ +class AzureBlobStorage(BaseModel): account_name: str = FieldInfo(alias="accountName") container: str - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str + sas_token: str = FieldInfo(alias="sasToken") type: Literal["AZURE_BLOB"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class AkeneoPim(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None - This is generated by ImageKit when you create a new origin. - """ +class AkeneoPim(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" + client_id: str = FieldInfo(alias="clientId") + """Akeneo API client ID.""" + + client_secret: str = FieldInfo(alias="clientSecret") + """Akeneo API client secret.""" name: str """Display name of the origin.""" + password: str + """Akeneo API password.""" + type: Literal["AKENEO_PIM"] + username: str + """Akeneo API username.""" + + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" + -OriginGetResponse: TypeAlias = Annotated[ - Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], - PropertyInfo(discriminator="type"), +OriginGetResponse: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim ] diff --git a/src/imagekit/types/accounts/origin_list_response.py b/src/imagekit/types/accounts/origin_list_response.py index 8640a6f..407f440 100644 --- a/src/imagekit/types/accounts/origin_list_response.py +++ b/src/imagekit/types/accounts/origin_list_response.py @@ -1,11 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias +from typing_extensions import Literal, TypeAlias from pydantic import Field as FieldInfo -from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -16,43 +15,42 @@ "OriginListResponseItemCloudinaryBackup", "OriginListResponseItemWebFolder", "OriginListResponseItemWebProxy", - "OriginListResponseItemGcs", - "OriginListResponseItemAzureBlob", + "OriginListResponseItemGoogleCloudStorageGcs", + "OriginListResponseItemAzureBlobStorage", "OriginListResponseItemAkeneoPim", ] class OriginListResponseItemS3(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["S3"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class OriginListResponseItemS3Compatible(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ + +class OriginListResponseItemS3Compatible(BaseModel): + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" @@ -60,177 +58,177 @@ class OriginListResponseItemS3Compatible(BaseModel): endpoint: str """Custom S3-compatible endpoint.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") - """Use path-style S3 URLs?""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["S3_COMPATIBLE"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" + + prefix: Optional[str] = None + """Path prefix inside the bucket.""" + + s3_force_path_style: Optional[bool] = FieldInfo(alias="s3ForcePathStyle", default=None) + """Use path-style S3 URLs?""" -class OriginListResponseItemCloudinaryBackup(BaseModel): - id: str - """Unique identifier for the origin. - This is generated by ImageKit when you create a new origin. - """ +class OriginListResponseItemCloudinaryBackup(BaseModel): + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["CLOUDINARY_BACKUP"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class OriginListResponseItemWebFolder(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ +class OriginListResponseItemWebFolder(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" - forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") - """Forward the Host header to origin?""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" type: Literal["WEB_FOLDER"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + forward_host_header_to_origin: Optional[bool] = FieldInfo(alias="forwardHostHeaderToOrigin", default=None) + """Forward the Host header to origin?""" -class OriginListResponseItemWebProxy(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) """Whether to send a Canonical header.""" + +class OriginListResponseItemWebProxy(BaseModel): name: str """Display name of the origin.""" type: Literal["WEB_PROXY"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class OriginListResponseItemGcs(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ +class OriginListResponseItemGoogleCloudStorageGcs(BaseModel): bucket: str client_email: str = FieldInfo(alias="clientEmail") - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str + private_key: str = FieldInfo(alias="privateKey") type: Literal["GCS"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class OriginListResponseItemAzureBlob(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None - This is generated by ImageKit when you create a new origin. - """ +class OriginListResponseItemAzureBlobStorage(BaseModel): account_name: str = FieldInfo(alias="accountName") container: str - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str + sas_token: str = FieldInfo(alias="sasToken") type: Literal["AZURE_BLOB"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class OriginListResponseItemAkeneoPim(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None - This is generated by ImageKit when you create a new origin. - """ +class OriginListResponseItemAkeneoPim(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" + client_id: str = FieldInfo(alias="clientId") + """Akeneo API client ID.""" + + client_secret: str = FieldInfo(alias="clientSecret") + """Akeneo API client secret.""" name: str """Display name of the origin.""" + password: str + """Akeneo API password.""" + type: Literal["AKENEO_PIM"] + username: str + """Akeneo API username.""" + + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" + -OriginListResponseItem: TypeAlias = Annotated[ - Union[ - OriginListResponseItemS3, - OriginListResponseItemS3Compatible, - OriginListResponseItemCloudinaryBackup, - OriginListResponseItemWebFolder, - OriginListResponseItemWebProxy, - OriginListResponseItemGcs, - OriginListResponseItemAzureBlob, - OriginListResponseItemAkeneoPim, - ], - PropertyInfo(discriminator="type"), +OriginListResponseItem: TypeAlias = Union[ + OriginListResponseItemS3, + OriginListResponseItemS3Compatible, + OriginListResponseItemCloudinaryBackup, + OriginListResponseItemWebFolder, + OriginListResponseItemWebProxy, + OriginListResponseItemGoogleCloudStorageGcs, + OriginListResponseItemAzureBlobStorage, + OriginListResponseItemAkeneoPim, ] OriginListResponse: TypeAlias = List[OriginListResponseItem] diff --git a/src/imagekit/types/accounts/origin_param.py b/src/imagekit/types/accounts/origin_param.py new file mode 100644 index 0000000..df3e7ea --- /dev/null +++ b/src/imagekit/types/accounts/origin_param.py @@ -0,0 +1,206 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from ..._utils import PropertyInfo + +__all__ = [ + "OriginParam", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "Gcs", + "AzureBlob", + "AkeneoPim", +] + + +class S3(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class S3Compatible(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + endpoint: Required[str] + """Custom S3-compatible endpoint.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3_COMPATIBLE"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] + """Use path-style S3 URLs?""" + + +class CloudinaryBackup(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["CLOUDINARY_BACKUP"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class WebFolder(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Root URL for the web folder origin.""" + + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_FOLDER"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] + """Forward the Host header to origin?""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class WebProxy(TypedDict, total=False): + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_PROXY"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class Gcs(TypedDict, total=False): + bucket: Required[str] + + client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] + + name: Required[str] + """Display name of the origin.""" + + private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] + + type: Required[Literal["GCS"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AzureBlob(TypedDict, total=False): + account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] + + container: Required[str] + + name: Required[str] + """Display name of the origin.""" + + sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] + + type: Required[Literal["AZURE_BLOB"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AkeneoPim(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Akeneo instance base URL.""" + + client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] + """Akeneo API client ID.""" + + client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] + """Akeneo API client secret.""" + + name: Required[str] + """Display name of the origin.""" + + password: Required[str] + """Akeneo API password.""" + + type: Required[Literal["AKENEO_PIM"]] + + username: Required[str] + """Akeneo API username.""" + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +OriginParam: TypeAlias = Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim] diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekit/types/accounts/origin_update_params.py index 36a6425..984cdfe 100644 --- a/src/imagekit/types/accounts/origin_update_params.py +++ b/src/imagekit/types/accounts/origin_update_params.py @@ -2,220 +2,13 @@ from __future__ import annotations -from typing import Union -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Required, TypedDict -from ..._utils import PropertyInfo +from .origin_param import OriginParam -__all__ = [ - "OriginUpdateParams", - "Origin", - "OriginS3", - "OriginS3Compatible", - "OriginCloudinaryBackup", - "OriginWebFolder", - "OriginWebProxy", - "OriginGcs", - "OriginAzureBlob", - "OriginAkeneoPim", -] +__all__ = ["OriginUpdateParams"] class OriginUpdateParams(TypedDict, total=False): - origin: Required[Origin] + origin: Required[OriginParam] """Schema for origin resources.""" - - -class OriginS3(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["S3"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class OriginS3Compatible(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - endpoint: Required[str] - """Custom S3-compatible endpoint.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["S3_COMPATIBLE"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] - """Use path-style S3 URLs?""" - - -class OriginCloudinaryBackup(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["CLOUDINARY_BACKUP"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class OriginWebFolder(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Root URL for the web folder origin.""" - - name: Required[str] - """Display name of the origin.""" - - type: Required[Literal["WEB_FOLDER"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] - """Forward the Host header to origin?""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class OriginWebProxy(TypedDict, total=False): - name: Required[str] - """Display name of the origin.""" - - type: Required[Literal["WEB_PROXY"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class OriginGcs(TypedDict, total=False): - bucket: Required[str] - - client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] - - name: Required[str] - """Display name of the origin.""" - - private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] - - type: Required[Literal["GCS"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class OriginAzureBlob(TypedDict, total=False): - account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] - - container: Required[str] - - name: Required[str] - """Display name of the origin.""" - - sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] - - type: Required[Literal["AZURE_BLOB"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class OriginAkeneoPim(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Akeneo instance base URL.""" - - client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] - """Akeneo API client ID.""" - - client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] - """Akeneo API client secret.""" - - name: Required[str] - """Display name of the origin.""" - - password: Required[str] - """Akeneo API password.""" - - type: Required[Literal["AKENEO_PIM"]] - - username: Required[str] - """Akeneo API username.""" - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -Origin: TypeAlias = Union[ - OriginS3, - OriginS3Compatible, - OriginCloudinaryBackup, - OriginWebFolder, - OriginWebProxy, - OriginGcs, - OriginAzureBlob, - OriginAkeneoPim, -] diff --git a/src/imagekit/types/accounts/origin_update_response.py b/src/imagekit/types/accounts/origin_update_response.py index 7799b94..8791dc2 100644 --- a/src/imagekit/types/accounts/origin_update_response.py +++ b/src/imagekit/types/accounts/origin_update_response.py @@ -1,11 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias +from typing_extensions import Literal, TypeAlias from pydantic import Field as FieldInfo -from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -15,43 +14,42 @@ "CloudinaryBackup", "WebFolder", "WebProxy", - "Gcs", - "AzureBlob", + "GoogleCloudStorageGcs", + "AzureBlobStorage", "AkeneoPim", ] class S3(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["S3"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class S3Compatible(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ + +class S3Compatible(BaseModel): + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" @@ -59,166 +57,168 @@ class S3Compatible(BaseModel): endpoint: str """Custom S3-compatible endpoint.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") - """Use path-style S3 URLs?""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["S3_COMPATIBLE"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" + + prefix: Optional[str] = None + """Path prefix inside the bucket.""" + + s3_force_path_style: Optional[bool] = FieldInfo(alias="s3ForcePathStyle", default=None) + """Use path-style S3 URLs?""" -class CloudinaryBackup(BaseModel): - id: str - """Unique identifier for the origin. - This is generated by ImageKit when you create a new origin. - """ +class CloudinaryBackup(BaseModel): + access_key: str = FieldInfo(alias="accessKey") + """Access key for the bucket.""" bucket: str """S3 bucket name.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" + secret_key: str = FieldInfo(alias="secretKey") + """Secret key for the bucket.""" type: Literal["CLOUDINARY_BACKUP"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class WebFolder(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ +class WebFolder(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" - forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") - """Forward the Host header to origin?""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" type: Literal["WEB_FOLDER"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + forward_host_header_to_origin: Optional[bool] = FieldInfo(alias="forwardHostHeaderToOrigin", default=None) + """Forward the Host header to origin?""" -class WebProxy(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) """Whether to send a Canonical header.""" + +class WebProxy(BaseModel): name: str """Display name of the origin.""" type: Literal["WEB_PROXY"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class Gcs(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ +class GoogleCloudStorageGcs(BaseModel): bucket: str client_email: str = FieldInfo(alias="clientEmail") - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str + private_key: str = FieldInfo(alias="privateKey") type: Literal["GCS"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class AzureBlob(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None - This is generated by ImageKit when you create a new origin. - """ +class AzureBlobStorage(BaseModel): account_name: str = FieldInfo(alias="accountName") container: str - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str + sas_token: str = FieldInfo(alias="sasToken") type: Literal["AZURE_BLOB"] + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class AkeneoPim(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None - This is generated by ImageKit when you create a new origin. - """ +class AkeneoPim(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" + client_id: str = FieldInfo(alias="clientId") + """Akeneo API client ID.""" + + client_secret: str = FieldInfo(alias="clientSecret") + """Akeneo API client secret.""" name: str """Display name of the origin.""" + password: str + """Akeneo API password.""" + type: Literal["AKENEO_PIM"] + username: str + """Akeneo API username.""" + + id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" + -OriginUpdateResponse: TypeAlias = Annotated[ - Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], - PropertyInfo(discriminator="type"), +OriginUpdateResponse: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim ] From 0eb2f3fc5e72f359793784fdf3a02d9a8235c0d5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 03:30:42 +0000 Subject: [PATCH 046/177] feat(api): manual updates --- .stats.yml | 6 +- .../types/accounts/origin_create_response.py | 170 ++++++++-------- .../types/accounts/origin_get_response.py | 170 ++++++++-------- .../types/accounts/origin_list_response.py | 186 +++++++++--------- .../types/accounts/origin_update_response.py | 170 ++++++++-------- 5 files changed, 352 insertions(+), 350 deletions(-) diff --git a/.stats.yml b/.stats.yml index 53bd25d..5afb8fd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d65a790786704dc315c1fded8ee24d61a55d96054fbbf1e6da429ec96b3e0c88.yml -openapi_spec_hash: 0fa9ee90455e183ec3b5d4e36f1351a9 -config_hash: 89ffae9ef2878c981a64f42cadb85186 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-967cd0e731df83a642ded194cacae3628050f679c600b1efd4e66cf269973531.yml +openapi_spec_hash: 98642308bee81ac776b7b1843089b888 +config_hash: ddd6954a6e35eb1a97e5d0cda8209e62 diff --git a/src/imagekit/types/accounts/origin_create_response.py b/src/imagekit/types/accounts/origin_create_response.py index f335ba7..faaa8fd 100644 --- a/src/imagekit/types/accounts/origin_create_response.py +++ b/src/imagekit/types/accounts/origin_create_response.py @@ -1,10 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -14,42 +15,43 @@ "CloudinaryBackup", "WebFolder", "WebProxy", - "GoogleCloudStorageGcs", - "AzureBlobStorage", + "Gcs", + "AzureBlob", "AkeneoPim", ] class S3(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" type: Literal["S3"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - - prefix: Optional[str] = None - """Path prefix inside the bucket.""" - class S3Compatible(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" @@ -57,168 +59,166 @@ class S3Compatible(BaseModel): endpoint: str """Custom S3-compatible endpoint.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" - type: Literal["S3_COMPATIBLE"] + s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") + """Use path-style S3 URLs?""" - id: Optional[str] = None + type: Literal["S3_COMPATIBLE"] base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - - prefix: Optional[str] = None - """Path prefix inside the bucket.""" - - s3_force_path_style: Optional[bool] = FieldInfo(alias="s3ForcePathStyle", default=None) - """Use path-style S3 URLs?""" - class CloudinaryBackup(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" type: Literal["CLOUDINARY_BACKUP"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None - """Path prefix inside the bucket.""" +class WebFolder(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class WebFolder(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" + forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") + """Forward the Host header to origin?""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" type: Literal["WEB_FOLDER"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - forward_host_header_to_origin: Optional[bool] = FieldInfo(alias="forwardHostHeaderToOrigin", default=None) - """Forward the Host header to origin?""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" +class WebProxy(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" -class WebProxy(BaseModel): name: str """Display name of the origin.""" type: Literal["WEB_PROXY"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" +class Gcs(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ -class GoogleCloudStorageGcs(BaseModel): bucket: str client_email: str = FieldInfo(alias="clientEmail") + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - private_key: str = FieldInfo(alias="privateKey") + prefix: str type: Literal["GCS"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None +class AzureBlob(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class AzureBlobStorage(BaseModel): account_name: str = FieldInfo(alias="accountName") container: str + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - sas_token: str = FieldInfo(alias="sasToken") + prefix: str type: Literal["AZURE_BLOB"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None +class AkeneoPim(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class AkeneoPim(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" - client_id: str = FieldInfo(alias="clientId") - """Akeneo API client ID.""" - - client_secret: str = FieldInfo(alias="clientSecret") - """Akeneo API client secret.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" name: str """Display name of the origin.""" - password: str - """Akeneo API password.""" - type: Literal["AKENEO_PIM"] - username: str - """Akeneo API username.""" - - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - -OriginCreateResponse: TypeAlias = Union[ - S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +OriginCreateResponse: TypeAlias = Annotated[ + Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], + PropertyInfo(discriminator="type"), ] diff --git a/src/imagekit/types/accounts/origin_get_response.py b/src/imagekit/types/accounts/origin_get_response.py index 56dcc96..1c1c0a5 100644 --- a/src/imagekit/types/accounts/origin_get_response.py +++ b/src/imagekit/types/accounts/origin_get_response.py @@ -1,10 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -14,42 +15,43 @@ "CloudinaryBackup", "WebFolder", "WebProxy", - "GoogleCloudStorageGcs", - "AzureBlobStorage", + "Gcs", + "AzureBlob", "AkeneoPim", ] class S3(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" type: Literal["S3"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - - prefix: Optional[str] = None - """Path prefix inside the bucket.""" - class S3Compatible(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" @@ -57,168 +59,166 @@ class S3Compatible(BaseModel): endpoint: str """Custom S3-compatible endpoint.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" - type: Literal["S3_COMPATIBLE"] + s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") + """Use path-style S3 URLs?""" - id: Optional[str] = None + type: Literal["S3_COMPATIBLE"] base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - - prefix: Optional[str] = None - """Path prefix inside the bucket.""" - - s3_force_path_style: Optional[bool] = FieldInfo(alias="s3ForcePathStyle", default=None) - """Use path-style S3 URLs?""" - class CloudinaryBackup(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" type: Literal["CLOUDINARY_BACKUP"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None - """Path prefix inside the bucket.""" +class WebFolder(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class WebFolder(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" + forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") + """Forward the Host header to origin?""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" type: Literal["WEB_FOLDER"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - forward_host_header_to_origin: Optional[bool] = FieldInfo(alias="forwardHostHeaderToOrigin", default=None) - """Forward the Host header to origin?""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" +class WebProxy(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" -class WebProxy(BaseModel): name: str """Display name of the origin.""" type: Literal["WEB_PROXY"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" +class Gcs(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ -class GoogleCloudStorageGcs(BaseModel): bucket: str client_email: str = FieldInfo(alias="clientEmail") + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - private_key: str = FieldInfo(alias="privateKey") + prefix: str type: Literal["GCS"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None +class AzureBlob(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class AzureBlobStorage(BaseModel): account_name: str = FieldInfo(alias="accountName") container: str + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - sas_token: str = FieldInfo(alias="sasToken") + prefix: str type: Literal["AZURE_BLOB"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None +class AkeneoPim(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class AkeneoPim(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" - client_id: str = FieldInfo(alias="clientId") - """Akeneo API client ID.""" - - client_secret: str = FieldInfo(alias="clientSecret") - """Akeneo API client secret.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" name: str """Display name of the origin.""" - password: str - """Akeneo API password.""" - type: Literal["AKENEO_PIM"] - username: str - """Akeneo API username.""" - - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - -OriginGetResponse: TypeAlias = Union[ - S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +OriginGetResponse: TypeAlias = Annotated[ + Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], + PropertyInfo(discriminator="type"), ] diff --git a/src/imagekit/types/accounts/origin_list_response.py b/src/imagekit/types/accounts/origin_list_response.py index 407f440..8640a6f 100644 --- a/src/imagekit/types/accounts/origin_list_response.py +++ b/src/imagekit/types/accounts/origin_list_response.py @@ -1,10 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -15,42 +16,43 @@ "OriginListResponseItemCloudinaryBackup", "OriginListResponseItemWebFolder", "OriginListResponseItemWebProxy", - "OriginListResponseItemGoogleCloudStorageGcs", - "OriginListResponseItemAzureBlobStorage", + "OriginListResponseItemGcs", + "OriginListResponseItemAzureBlob", "OriginListResponseItemAkeneoPim", ] class OriginListResponseItemS3(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" type: Literal["S3"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - - prefix: Optional[str] = None - """Path prefix inside the bucket.""" - class OriginListResponseItemS3Compatible(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" @@ -58,177 +60,177 @@ class OriginListResponseItemS3Compatible(BaseModel): endpoint: str """Custom S3-compatible endpoint.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" - type: Literal["S3_COMPATIBLE"] + s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") + """Use path-style S3 URLs?""" - id: Optional[str] = None + type: Literal["S3_COMPATIBLE"] base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - - prefix: Optional[str] = None - """Path prefix inside the bucket.""" - - s3_force_path_style: Optional[bool] = FieldInfo(alias="s3ForcePathStyle", default=None) - """Use path-style S3 URLs?""" - class OriginListResponseItemCloudinaryBackup(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" type: Literal["CLOUDINARY_BACKUP"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None - """Path prefix inside the bucket.""" +class OriginListResponseItemWebFolder(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class OriginListResponseItemWebFolder(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" + forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") + """Forward the Host header to origin?""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" type: Literal["WEB_FOLDER"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - forward_host_header_to_origin: Optional[bool] = FieldInfo(alias="forwardHostHeaderToOrigin", default=None) - """Forward the Host header to origin?""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" +class OriginListResponseItemWebProxy(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" -class OriginListResponseItemWebProxy(BaseModel): name: str """Display name of the origin.""" type: Literal["WEB_PROXY"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" +class OriginListResponseItemGcs(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ -class OriginListResponseItemGoogleCloudStorageGcs(BaseModel): bucket: str client_email: str = FieldInfo(alias="clientEmail") + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - private_key: str = FieldInfo(alias="privateKey") + prefix: str type: Literal["GCS"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None +class OriginListResponseItemAzureBlob(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class OriginListResponseItemAzureBlobStorage(BaseModel): account_name: str = FieldInfo(alias="accountName") container: str + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - sas_token: str = FieldInfo(alias="sasToken") + prefix: str type: Literal["AZURE_BLOB"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None +class OriginListResponseItemAkeneoPim(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class OriginListResponseItemAkeneoPim(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" - client_id: str = FieldInfo(alias="clientId") - """Akeneo API client ID.""" - - client_secret: str = FieldInfo(alias="clientSecret") - """Akeneo API client secret.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" name: str """Display name of the origin.""" - password: str - """Akeneo API password.""" - type: Literal["AKENEO_PIM"] - username: str - """Akeneo API username.""" - - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - -OriginListResponseItem: TypeAlias = Union[ - OriginListResponseItemS3, - OriginListResponseItemS3Compatible, - OriginListResponseItemCloudinaryBackup, - OriginListResponseItemWebFolder, - OriginListResponseItemWebProxy, - OriginListResponseItemGoogleCloudStorageGcs, - OriginListResponseItemAzureBlobStorage, - OriginListResponseItemAkeneoPim, +OriginListResponseItem: TypeAlias = Annotated[ + Union[ + OriginListResponseItemS3, + OriginListResponseItemS3Compatible, + OriginListResponseItemCloudinaryBackup, + OriginListResponseItemWebFolder, + OriginListResponseItemWebProxy, + OriginListResponseItemGcs, + OriginListResponseItemAzureBlob, + OriginListResponseItemAkeneoPim, + ], + PropertyInfo(discriminator="type"), ] OriginListResponse: TypeAlias = List[OriginListResponseItem] diff --git a/src/imagekit/types/accounts/origin_update_response.py b/src/imagekit/types/accounts/origin_update_response.py index 8791dc2..7799b94 100644 --- a/src/imagekit/types/accounts/origin_update_response.py +++ b/src/imagekit/types/accounts/origin_update_response.py @@ -1,10 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union, Optional -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, Annotated, TypeAlias from pydantic import Field as FieldInfo +from ..._utils import PropertyInfo from ..._models import BaseModel __all__ = [ @@ -14,42 +15,43 @@ "CloudinaryBackup", "WebFolder", "WebProxy", - "GoogleCloudStorageGcs", - "AzureBlobStorage", + "Gcs", + "AzureBlob", "AkeneoPim", ] class S3(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" type: Literal["S3"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - - prefix: Optional[str] = None - """Path prefix inside the bucket.""" - class S3Compatible(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" @@ -57,168 +59,166 @@ class S3Compatible(BaseModel): endpoint: str """Custom S3-compatible endpoint.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" - type: Literal["S3_COMPATIBLE"] + s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") + """Use path-style S3 URLs?""" - id: Optional[str] = None + type: Literal["S3_COMPATIBLE"] base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - - prefix: Optional[str] = None - """Path prefix inside the bucket.""" - - s3_force_path_style: Optional[bool] = FieldInfo(alias="s3ForcePathStyle", default=None) - """Use path-style S3 URLs?""" - class CloudinaryBackup(BaseModel): - access_key: str = FieldInfo(alias="accessKey") - """Access key for the bucket.""" + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ bucket: str """S3 bucket name.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - secret_key: str = FieldInfo(alias="secretKey") - """Secret key for the bucket.""" + prefix: str + """Path prefix inside the bucket.""" type: Literal["CLOUDINARY_BACKUP"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None - """Path prefix inside the bucket.""" +class WebFolder(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class WebFolder(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" + forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") + """Forward the Host header to origin?""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" type: Literal["WEB_FOLDER"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - forward_host_header_to_origin: Optional[bool] = FieldInfo(alias="forwardHostHeaderToOrigin", default=None) - """Forward the Host header to origin?""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" +class WebProxy(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" -class WebProxy(BaseModel): name: str """Display name of the origin.""" type: Literal["WEB_PROXY"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" +class Gcs(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ -class GoogleCloudStorageGcs(BaseModel): bucket: str client_email: str = FieldInfo(alias="clientEmail") + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - private_key: str = FieldInfo(alias="privateKey") + prefix: str type: Literal["GCS"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None +class AzureBlob(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class AzureBlobStorage(BaseModel): account_name: str = FieldInfo(alias="accountName") container: str + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - sas_token: str = FieldInfo(alias="sasToken") + prefix: str type: Literal["AZURE_BLOB"] - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None +class AkeneoPim(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class AkeneoPim(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" - client_id: str = FieldInfo(alias="clientId") - """Akeneo API client ID.""" - - client_secret: str = FieldInfo(alias="clientSecret") - """Akeneo API client secret.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" name: str """Display name of the origin.""" - password: str - """Akeneo API password.""" - type: Literal["AKENEO_PIM"] - username: str - """Akeneo API username.""" - - id: Optional[str] = None - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - -OriginUpdateResponse: TypeAlias = Union[ - S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +OriginUpdateResponse: TypeAlias = Annotated[ + Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], + PropertyInfo(discriminator="type"), ] From 3d255c5eccfd2f3475ebe9fe1609d2d67f3fc7c0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 05:49:17 +0000 Subject: [PATCH 047/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 5afb8fd..49325e6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-967cd0e731df83a642ded194cacae3628050f679c600b1efd4e66cf269973531.yml openapi_spec_hash: 98642308bee81ac776b7b1843089b888 -config_hash: ddd6954a6e35eb1a97e5d0cda8209e62 +config_hash: 49e367d7f33aeaf63ed738c1c0392d0a diff --git a/api.md b/api.md index 459876b..1b52779 100644 --- a/api.md +++ b/api.md @@ -194,6 +194,7 @@ Types: ```python from imagekit.types.accounts import ( + URLEndpoint, URLEndpointCreateResponse, URLEndpointUpdateResponse, URLEndpointListResponse, From 0b36efaf992df573827b8a41dbe065333c144b64 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 05:55:53 +0000 Subject: [PATCH 048/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 49325e6..6690c82 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-967cd0e731df83a642ded194cacae3628050f679c600b1efd4e66cf269973531.yml -openapi_spec_hash: 98642308bee81ac776b7b1843089b888 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-67e78a2f87dab7c661093c82f338197540584fa3d9a38773d1fdd435d788282f.yml +openapi_spec_hash: 28ec969480eb18203d798e0435e76df3 config_hash: 49e367d7f33aeaf63ed738c1c0392d0a From cb1fbb680395718928be8ca8accf3e19281569bb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 05:56:42 +0000 Subject: [PATCH 049/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 14 +- src/imagekit/resources/accounts/origins.py | 48 ++-- src/imagekit/types/accounts/__init__.py | 4 +- .../types/accounts/origin_create_response.py | 224 ----------------- .../types/accounts/origin_list_response.py | 236 +----------------- ...gin_get_response.py => origin_response.py} | 4 +- .../types/accounts/origin_update_response.py | 224 ----------------- tests/api_resources/accounts/test_origins.py | 48 ++-- 9 files changed, 55 insertions(+), 749 deletions(-) delete mode 100644 src/imagekit/types/accounts/origin_create_response.py rename src/imagekit/types/accounts/{origin_get_response.py => origin_response.py} (98%) delete mode 100644 src/imagekit/types/accounts/origin_update_response.py diff --git a/.stats.yml b/.stats.yml index 6690c82..2159267 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-67e78a2f87dab7c661093c82f338197540584fa3d9a38773d1fdd435d788282f.yml openapi_spec_hash: 28ec969480eb18203d798e0435e76df3 -config_hash: 49e367d7f33aeaf63ed738c1c0392d0a +config_hash: 167d38f07a70976231dcdfa53ffa234c diff --git a/api.md b/api.md index 1b52779..fc45825 100644 --- a/api.md +++ b/api.md @@ -171,22 +171,16 @@ Methods: Types: ```python -from imagekit.types.accounts import ( - Origin, - OriginCreateResponse, - OriginUpdateResponse, - OriginListResponse, - OriginGetResponse, -) +from imagekit.types.accounts import Origin, OriginResponse, OriginListResponse ``` Methods: -- client.accounts.origins.create(\*\*params) -> OriginCreateResponse -- client.accounts.origins.update(id, \*\*params) -> OriginUpdateResponse +- client.accounts.origins.create(\*\*params) -> OriginResponse +- client.accounts.origins.update(id, \*\*params) -> OriginResponse - client.accounts.origins.list() -> OriginListResponse - client.accounts.origins.delete(id) -> None -- client.accounts.origins.get(id) -> OriginGetResponse +- client.accounts.origins.get(id) -> OriginResponse ## URLEndpoints diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index 7b525d3..b789dfb 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -19,10 +19,8 @@ from ..._base_client import make_request_options from ...types.accounts import origin_create_params, origin_update_params from ...types.accounts.origin_param import OriginParam -from ...types.accounts.origin_get_response import OriginGetResponse +from ...types.accounts.origin_response import OriginResponse from ...types.accounts.origin_list_response import OriginListResponse -from ...types.accounts.origin_create_response import OriginCreateResponse -from ...types.accounts.origin_update_response import OriginUpdateResponse __all__ = ["OriginsResource", "AsyncOriginsResource"] @@ -57,7 +55,7 @@ def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: + ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -75,16 +73,14 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ return cast( - OriginCreateResponse, + OriginResponse, self._post( "/v1/accounts/origins", body=maybe_transform(origin, origin_create_params.OriginCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast( - Any, OriginCreateResponse - ), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) @@ -99,7 +95,7 @@ def update( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: + ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -122,16 +118,14 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - OriginUpdateResponse, + OriginResponse, self._put( f"/v1/accounts/origins/{id}", body=maybe_transform(origin, origin_update_params.OriginUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast( - Any, OriginUpdateResponse - ), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) @@ -208,7 +202,7 @@ def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginGetResponse: + ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -229,13 +223,13 @@ def get( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - OriginGetResponse, + OriginResponse, self._get( f"/v1/accounts/origins/{id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, OriginGetResponse), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) @@ -270,7 +264,7 @@ async def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginCreateResponse: + ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -288,16 +282,14 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ return cast( - OriginCreateResponse, + OriginResponse, await self._post( "/v1/accounts/origins", body=await async_maybe_transform(origin, origin_create_params.OriginCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast( - Any, OriginCreateResponse - ), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) @@ -312,7 +304,7 @@ async def update( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginUpdateResponse: + ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -335,16 +327,14 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - OriginUpdateResponse, + OriginResponse, await self._put( f"/v1/accounts/origins/{id}", body=await async_maybe_transform(origin, origin_update_params.OriginUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast( - Any, OriginUpdateResponse - ), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) @@ -421,7 +411,7 @@ async def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginGetResponse: + ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -442,13 +432,13 @@ async def get( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - OriginGetResponse, + OriginResponse, await self._get( f"/v1/accounts/origins/{id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, OriginGetResponse), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) diff --git a/src/imagekit/types/accounts/__init__.py b/src/imagekit/types/accounts/__init__.py index a6cb719..1fd88cd 100644 --- a/src/imagekit/types/accounts/__init__.py +++ b/src/imagekit/types/accounts/__init__.py @@ -3,14 +3,12 @@ from __future__ import annotations from .origin_param import OriginParam as OriginParam +from .origin_response import OriginResponse as OriginResponse from .usage_get_params import UsageGetParams as UsageGetParams from .usage_get_response import UsageGetResponse as UsageGetResponse -from .origin_get_response import OriginGetResponse as OriginGetResponse from .origin_create_params import OriginCreateParams as OriginCreateParams from .origin_list_response import OriginListResponse as OriginListResponse from .origin_update_params import OriginUpdateParams as OriginUpdateParams -from .origin_create_response import OriginCreateResponse as OriginCreateResponse -from .origin_update_response import OriginUpdateResponse as OriginUpdateResponse from .url_endpoint_get_response import URLEndpointGetResponse as URLEndpointGetResponse from .url_endpoint_create_params import URLEndpointCreateParams as URLEndpointCreateParams from .url_endpoint_list_response import URLEndpointListResponse as URLEndpointListResponse diff --git a/src/imagekit/types/accounts/origin_create_response.py b/src/imagekit/types/accounts/origin_create_response.py deleted file mode 100644 index faaa8fd..0000000 --- a/src/imagekit/types/accounts/origin_create_response.py +++ /dev/null @@ -1,224 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias - -from pydantic import Field as FieldInfo - -from ..._utils import PropertyInfo -from ..._models import BaseModel - -__all__ = [ - "OriginCreateResponse", - "S3", - "S3Compatible", - "CloudinaryBackup", - "WebFolder", - "WebProxy", - "Gcs", - "AzureBlob", - "AkeneoPim", -] - - -class S3(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - """S3 bucket name.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - """Path prefix inside the bucket.""" - - type: Literal["S3"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class S3Compatible(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - """S3 bucket name.""" - - endpoint: str - """Custom S3-compatible endpoint.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") - """Use path-style S3 URLs?""" - - type: Literal["S3_COMPATIBLE"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class CloudinaryBackup(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - """S3 bucket name.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - """Path prefix inside the bucket.""" - - type: Literal["CLOUDINARY_BACKUP"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class WebFolder(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - base_url: str = FieldInfo(alias="baseUrl") - """Root URL for the web folder origin.""" - - forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") - """Forward the Host header to origin?""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - type: Literal["WEB_FOLDER"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class WebProxy(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - type: Literal["WEB_PROXY"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class Gcs(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - - client_email: str = FieldInfo(alias="clientEmail") - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - - type: Literal["GCS"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class AzureBlob(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - account_name: str = FieldInfo(alias="accountName") - - container: str - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - - type: Literal["AZURE_BLOB"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class AkeneoPim(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - base_url: str = FieldInfo(alias="baseUrl") - """Akeneo instance base URL.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - type: Literal["AKENEO_PIM"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -OriginCreateResponse: TypeAlias = Annotated[ - Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], - PropertyInfo(discriminator="type"), -] diff --git a/src/imagekit/types/accounts/origin_list_response.py b/src/imagekit/types/accounts/origin_list_response.py index 8640a6f..b0e0931 100644 --- a/src/imagekit/types/accounts/origin_list_response.py +++ b/src/imagekit/types/accounts/origin_list_response.py @@ -1,236 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias +from typing import List +from typing_extensions import TypeAlias -from pydantic import Field as FieldInfo +from .origin_response import OriginResponse -from ..._utils import PropertyInfo -from ..._models import BaseModel +__all__ = ["OriginListResponse"] -__all__ = [ - "OriginListResponse", - "OriginListResponseItem", - "OriginListResponseItemS3", - "OriginListResponseItemS3Compatible", - "OriginListResponseItemCloudinaryBackup", - "OriginListResponseItemWebFolder", - "OriginListResponseItemWebProxy", - "OriginListResponseItemGcs", - "OriginListResponseItemAzureBlob", - "OriginListResponseItemAkeneoPim", -] - - -class OriginListResponseItemS3(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - """S3 bucket name.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - """Path prefix inside the bucket.""" - - type: Literal["S3"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class OriginListResponseItemS3Compatible(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - """S3 bucket name.""" - - endpoint: str - """Custom S3-compatible endpoint.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") - """Use path-style S3 URLs?""" - - type: Literal["S3_COMPATIBLE"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class OriginListResponseItemCloudinaryBackup(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - """S3 bucket name.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - """Path prefix inside the bucket.""" - - type: Literal["CLOUDINARY_BACKUP"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class OriginListResponseItemWebFolder(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - base_url: str = FieldInfo(alias="baseUrl") - """Root URL for the web folder origin.""" - - forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") - """Forward the Host header to origin?""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - type: Literal["WEB_FOLDER"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class OriginListResponseItemWebProxy(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - type: Literal["WEB_PROXY"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class OriginListResponseItemGcs(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - - client_email: str = FieldInfo(alias="clientEmail") - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - - type: Literal["GCS"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class OriginListResponseItemAzureBlob(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - account_name: str = FieldInfo(alias="accountName") - - container: str - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - - type: Literal["AZURE_BLOB"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class OriginListResponseItemAkeneoPim(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - base_url: str = FieldInfo(alias="baseUrl") - """Akeneo instance base URL.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - type: Literal["AKENEO_PIM"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -OriginListResponseItem: TypeAlias = Annotated[ - Union[ - OriginListResponseItemS3, - OriginListResponseItemS3Compatible, - OriginListResponseItemCloudinaryBackup, - OriginListResponseItemWebFolder, - OriginListResponseItemWebProxy, - OriginListResponseItemGcs, - OriginListResponseItemAzureBlob, - OriginListResponseItemAkeneoPim, - ], - PropertyInfo(discriminator="type"), -] - -OriginListResponse: TypeAlias = List[OriginListResponseItem] +OriginListResponse: TypeAlias = List[OriginResponse] diff --git a/src/imagekit/types/accounts/origin_get_response.py b/src/imagekit/types/accounts/origin_response.py similarity index 98% rename from src/imagekit/types/accounts/origin_get_response.py rename to src/imagekit/types/accounts/origin_response.py index 1c1c0a5..d437447 100644 --- a/src/imagekit/types/accounts/origin_get_response.py +++ b/src/imagekit/types/accounts/origin_response.py @@ -9,7 +9,7 @@ from ..._models import BaseModel __all__ = [ - "OriginGetResponse", + "OriginResponse", "S3", "S3Compatible", "CloudinaryBackup", @@ -218,7 +218,7 @@ class AkeneoPim(BaseModel): """URL used in the Canonical header (if enabled).""" -OriginGetResponse: TypeAlias = Annotated[ +OriginResponse: TypeAlias = Annotated[ Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], PropertyInfo(discriminator="type"), ] diff --git a/src/imagekit/types/accounts/origin_update_response.py b/src/imagekit/types/accounts/origin_update_response.py deleted file mode 100644 index 7799b94..0000000 --- a/src/imagekit/types/accounts/origin_update_response.py +++ /dev/null @@ -1,224 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias - -from pydantic import Field as FieldInfo - -from ..._utils import PropertyInfo -from ..._models import BaseModel - -__all__ = [ - "OriginUpdateResponse", - "S3", - "S3Compatible", - "CloudinaryBackup", - "WebFolder", - "WebProxy", - "Gcs", - "AzureBlob", - "AkeneoPim", -] - - -class S3(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - """S3 bucket name.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - """Path prefix inside the bucket.""" - - type: Literal["S3"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class S3Compatible(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - """S3 bucket name.""" - - endpoint: str - """Custom S3-compatible endpoint.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") - """Use path-style S3 URLs?""" - - type: Literal["S3_COMPATIBLE"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class CloudinaryBackup(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - """S3 bucket name.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - """Path prefix inside the bucket.""" - - type: Literal["CLOUDINARY_BACKUP"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class WebFolder(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - base_url: str = FieldInfo(alias="baseUrl") - """Root URL for the web folder origin.""" - - forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") - """Forward the Host header to origin?""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - type: Literal["WEB_FOLDER"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class WebProxy(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - type: Literal["WEB_PROXY"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class Gcs(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - bucket: str - - client_email: str = FieldInfo(alias="clientEmail") - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - - type: Literal["GCS"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class AzureBlob(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - account_name: str = FieldInfo(alias="accountName") - - container: str - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - prefix: str - - type: Literal["AZURE_BLOB"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class AkeneoPim(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - - base_url: str = FieldInfo(alias="baseUrl") - """Akeneo instance base URL.""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - - name: str - """Display name of the origin.""" - - type: Literal["AKENEO_PIM"] - - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -OriginUpdateResponse: TypeAlias = Annotated[ - Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], - PropertyInfo(discriminator="type"), -] diff --git a/tests/api_resources/accounts/test_origins.py b/tests/api_resources/accounts/test_origins.py index 171e5e2..ba060f6 100644 --- a/tests/api_resources/accounts/test_origins.py +++ b/tests/api_resources/accounts/test_origins.py @@ -10,10 +10,8 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type from imagekit.types.accounts import ( - OriginGetResponse, + OriginResponse, OriginListResponse, - OriginCreateResponse, - OriginUpdateResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -34,7 +32,7 @@ def test_method_create(self, client: ImageKit) -> None: "type": "S3", }, ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -51,7 +49,7 @@ def test_method_create_with_all_params(self, client: ImageKit) -> None: "prefix": "images", }, ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -69,7 +67,7 @@ def test_raw_response_create(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -87,7 +85,7 @@ def test_streaming_response_create(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -104,7 +102,7 @@ def test_method_update(self, client: ImageKit) -> None: "type": "S3", }, ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -122,7 +120,7 @@ def test_method_update_with_all_params(self, client: ImageKit) -> None: "prefix": "images", }, ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -141,7 +139,7 @@ def test_raw_response_update(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -160,7 +158,7 @@ def test_streaming_response_update(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -255,7 +253,7 @@ def test_method_get(self, client: ImageKit) -> None: origin = client.accounts.origins.get( "id", ) - assert_matches_type(OriginGetResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -267,7 +265,7 @@ def test_raw_response_get(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginGetResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -279,7 +277,7 @@ def test_streaming_response_get(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginGetResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -309,7 +307,7 @@ async def test_method_create(self, async_client: AsyncImageKit) -> None: "type": "S3", }, ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -326,7 +324,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncImageKit) "prefix": "images", }, ) - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -344,7 +342,7 @@ async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -362,7 +360,7 @@ async def test_streaming_response_create(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginCreateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -379,7 +377,7 @@ async def test_method_update(self, async_client: AsyncImageKit) -> None: "type": "S3", }, ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -397,7 +395,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncImageKit) "prefix": "images", }, ) - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -416,7 +414,7 @@ async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -435,7 +433,7 @@ async def test_streaming_response_update(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginUpdateResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -530,7 +528,7 @@ async def test_method_get(self, async_client: AsyncImageKit) -> None: origin = await async_client.accounts.origins.get( "id", ) - assert_matches_type(OriginGetResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -542,7 +540,7 @@ async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginGetResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -554,7 +552,7 @@ async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginGetResponse, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True From 2f954eb7a688ccbeef7db913314b5d24b285c1d4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 06:07:50 +0000 Subject: [PATCH 050/177] feat(api): manual updates --- .stats.yml | 6 +- api.md | 8 +- src/imagekit/resources/accounts/origins.py | 40 ++-- src/imagekit/types/accounts/__init__.py | 2 +- .../{origin_response.py => origin.py} | 180 +++++++++--------- .../types/accounts/origin_list_response.py | 4 +- tests/api_resources/accounts/test_origins.py | 49 +++-- 7 files changed, 138 insertions(+), 151 deletions(-) rename src/imagekit/types/accounts/{origin_response.py => origin.py} (74%) diff --git a/.stats.yml b/.stats.yml index 2159267..6ac1eba 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-67e78a2f87dab7c661093c82f338197540584fa3d9a38773d1fdd435d788282f.yml -openapi_spec_hash: 28ec969480eb18203d798e0435e76df3 -config_hash: 167d38f07a70976231dcdfa53ffa234c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-554f897c7f0061bb1fe51cd82f5f05e66050db5e868524c374dac827bd7b8c3d.yml +openapi_spec_hash: 95b7298e7f3977ea6c98d9557d2c8d27 +config_hash: 49e367d7f33aeaf63ed738c1c0392d0a diff --git a/api.md b/api.md index fc45825..e50b8f5 100644 --- a/api.md +++ b/api.md @@ -171,16 +171,16 @@ Methods: Types: ```python -from imagekit.types.accounts import Origin, OriginResponse, OriginListResponse +from imagekit.types.accounts import Origin, OriginListResponse ``` Methods: -- client.accounts.origins.create(\*\*params) -> OriginResponse -- client.accounts.origins.update(id, \*\*params) -> OriginResponse +- client.accounts.origins.create(\*\*params) -> Origin +- client.accounts.origins.update(id, \*\*params) -> Origin - client.accounts.origins.list() -> OriginListResponse - client.accounts.origins.delete(id) -> None -- client.accounts.origins.get(id) -> OriginResponse +- client.accounts.origins.get(id) -> Origin ## URLEndpoints diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index b789dfb..aa3f7c6 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -17,9 +17,9 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options -from ...types.accounts import origin_create_params, origin_update_params +from ...types.accounts import Origin, origin_create_params, origin_update_params +from ...types.accounts.origin import Origin from ...types.accounts.origin_param import OriginParam -from ...types.accounts.origin_response import OriginResponse from ...types.accounts.origin_list_response import OriginListResponse __all__ = ["OriginsResource", "AsyncOriginsResource"] @@ -55,7 +55,7 @@ def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginResponse: + ) -> Origin: """**Note:** This API is currently in beta. @@ -73,14 +73,14 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ return cast( - OriginResponse, + Origin, self._post( "/v1/accounts/origins", body=maybe_transform(origin, origin_create_params.OriginCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system ), ) @@ -95,7 +95,7 @@ def update( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginResponse: + ) -> Origin: """**Note:** This API is currently in beta. @@ -118,14 +118,14 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - OriginResponse, + Origin, self._put( f"/v1/accounts/origins/{id}", body=maybe_transform(origin, origin_update_params.OriginUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system ), ) @@ -202,7 +202,7 @@ def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginResponse: + ) -> Origin: """**Note:** This API is currently in beta. @@ -223,13 +223,13 @@ def get( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - OriginResponse, + Origin, self._get( f"/v1/accounts/origins/{id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system ), ) @@ -264,7 +264,7 @@ async def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginResponse: + ) -> Origin: """**Note:** This API is currently in beta. @@ -282,14 +282,14 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ return cast( - OriginResponse, + Origin, await self._post( "/v1/accounts/origins", body=await async_maybe_transform(origin, origin_create_params.OriginCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system ), ) @@ -304,7 +304,7 @@ async def update( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginResponse: + ) -> Origin: """**Note:** This API is currently in beta. @@ -327,14 +327,14 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - OriginResponse, + Origin, await self._put( f"/v1/accounts/origins/{id}", body=await async_maybe_transform(origin, origin_update_params.OriginUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system ), ) @@ -411,7 +411,7 @@ async def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginResponse: + ) -> Origin: """**Note:** This API is currently in beta. @@ -432,13 +432,13 @@ async def get( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - OriginResponse, + Origin, await self._get( f"/v1/accounts/origins/{id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system ), ) diff --git a/src/imagekit/types/accounts/__init__.py b/src/imagekit/types/accounts/__init__.py index 1fd88cd..e7b1f9f 100644 --- a/src/imagekit/types/accounts/__init__.py +++ b/src/imagekit/types/accounts/__init__.py @@ -2,8 +2,8 @@ from __future__ import annotations +from .origin import Origin as Origin from .origin_param import OriginParam as OriginParam -from .origin_response import OriginResponse as OriginResponse from .usage_get_params import UsageGetParams as UsageGetParams from .usage_get_response import UsageGetResponse as UsageGetResponse from .origin_create_params import OriginCreateParams as OriginCreateParams diff --git a/src/imagekit/types/accounts/origin_response.py b/src/imagekit/types/accounts/origin.py similarity index 74% rename from src/imagekit/types/accounts/origin_response.py rename to src/imagekit/types/accounts/origin.py index d437447..d896c78 100644 --- a/src/imagekit/types/accounts/origin_response.py +++ b/src/imagekit/types/accounts/origin.py @@ -8,217 +8,207 @@ from ..._utils import PropertyInfo from ..._models import BaseModel -__all__ = [ - "OriginResponse", - "S3", - "S3Compatible", - "CloudinaryBackup", - "WebFolder", - "WebProxy", - "Gcs", - "AzureBlob", - "AkeneoPim", -] +__all__ = ["Origin", "S3", "S3Compatible", "CloudinaryBackup", "WebFolder", "WebProxy", "Gcs", "AzureBlob", "AkeneoPim"] class S3(BaseModel): - id: str - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - bucket: str """S3 bucket name.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" - type: Literal["S3"] + id: Optional[str] = None + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class S3Compatible(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ +class S3Compatible(BaseModel): bucket: str """S3 bucket name.""" endpoint: str """Custom S3-compatible endpoint.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" + type: Literal["S3_COMPATIBLE"] - s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") - """Use path-style S3 URLs?""" + id: Optional[str] = None + """Unique identifier for the origin. - type: Literal["S3_COMPATIBLE"] + This is generated by ImageKit when you create a new origin. + """ base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class CloudinaryBackup(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" + + s3_force_path_style: Optional[bool] = FieldInfo(alias="s3ForcePathStyle", default=None) + """Use path-style S3 URLs?""" - This is generated by ImageKit when you create a new origin. - """ +class CloudinaryBackup(BaseModel): bucket: str """S3 bucket name.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - """Path prefix inside the bucket.""" - type: Literal["CLOUDINARY_BACKUP"] + id: Optional[str] = None + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class WebFolder(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ +class WebFolder(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" - forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") - """Forward the Host header to origin?""" - - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" type: Literal["WEB_FOLDER"] - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class WebProxy(BaseModel): - id: str + id: Optional[str] = None """Unique identifier for the origin. This is generated by ImageKit when you create a new origin. """ - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Optional[bool] = FieldInfo(alias="forwardHostHeaderToOrigin", default=None) + """Forward the Host header to origin?""" + + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) """Whether to send a Canonical header.""" + +class WebProxy(BaseModel): name: str """Display name of the origin.""" type: Literal["WEB_PROXY"] - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - -class Gcs(BaseModel): - id: str + id: Optional[str] = None """Unique identifier for the origin. This is generated by ImageKit when you create a new origin. """ + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" + + +class Gcs(BaseModel): bucket: str client_email: str = FieldInfo(alias="clientEmail") - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - type: Literal["GCS"] + id: Optional[str] = None + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class AzureBlob(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None - This is generated by ImageKit when you create a new origin. - """ +class AzureBlob(BaseModel): account_name: str = FieldInfo(alias="accountName") container: str - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" - prefix: str - type: Literal["AZURE_BLOB"] + id: Optional[str] = None + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" -class AkeneoPim(BaseModel): - id: str - """Unique identifier for the origin. + prefix: Optional[str] = None - This is generated by ImageKit when you create a new origin. - """ +class AkeneoPim(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" - include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") - """Whether to send a Canonical header.""" - name: str """Display name of the origin.""" type: Literal["AKENEO_PIM"] + id: Optional[str] = None + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" + include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + """Whether to send a Canonical header.""" + -OriginResponse: TypeAlias = Annotated[ +Origin: TypeAlias = Annotated[ Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], PropertyInfo(discriminator="type"), ] diff --git a/src/imagekit/types/accounts/origin_list_response.py b/src/imagekit/types/accounts/origin_list_response.py index b0e0931..e9c0331 100644 --- a/src/imagekit/types/accounts/origin_list_response.py +++ b/src/imagekit/types/accounts/origin_list_response.py @@ -3,8 +3,8 @@ from typing import List from typing_extensions import TypeAlias -from .origin_response import OriginResponse +from .origin import Origin __all__ = ["OriginListResponse"] -OriginListResponse: TypeAlias = List[OriginResponse] +OriginListResponse: TypeAlias = List[Origin] diff --git a/tests/api_resources/accounts/test_origins.py b/tests/api_resources/accounts/test_origins.py index ba060f6..ce2ccfe 100644 --- a/tests/api_resources/accounts/test_origins.py +++ b/tests/api_resources/accounts/test_origins.py @@ -9,10 +9,7 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.accounts import ( - OriginResponse, - OriginListResponse, -) +from imagekit.types.accounts import Origin, OriginListResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -32,7 +29,7 @@ def test_method_create(self, client: ImageKit) -> None: "type": "S3", }, ) - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -49,7 +46,7 @@ def test_method_create_with_all_params(self, client: ImageKit) -> None: "prefix": "images", }, ) - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -67,7 +64,7 @@ def test_raw_response_create(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -85,7 +82,7 @@ def test_streaming_response_create(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -102,7 +99,7 @@ def test_method_update(self, client: ImageKit) -> None: "type": "S3", }, ) - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -120,7 +117,7 @@ def test_method_update_with_all_params(self, client: ImageKit) -> None: "prefix": "images", }, ) - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -139,7 +136,7 @@ def test_raw_response_update(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -158,7 +155,7 @@ def test_streaming_response_update(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -253,7 +250,7 @@ def test_method_get(self, client: ImageKit) -> None: origin = client.accounts.origins.get( "id", ) - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -265,7 +262,7 @@ def test_raw_response_get(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -277,7 +274,7 @@ def test_streaming_response_get(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -307,7 +304,7 @@ async def test_method_create(self, async_client: AsyncImageKit) -> None: "type": "S3", }, ) - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -324,7 +321,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncImageKit) "prefix": "images", }, ) - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -342,7 +339,7 @@ async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -360,7 +357,7 @@ async def test_streaming_response_create(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -377,7 +374,7 @@ async def test_method_update(self, async_client: AsyncImageKit) -> None: "type": "S3", }, ) - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -395,7 +392,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncImageKit) "prefix": "images", }, ) - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -414,7 +411,7 @@ async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -433,7 +430,7 @@ async def test_streaming_response_update(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -528,7 +525,7 @@ async def test_method_get(self, async_client: AsyncImageKit) -> None: origin = await async_client.accounts.origins.get( "id", ) - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -540,7 +537,7 @@ async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -552,7 +549,7 @@ async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(OriginResponse, origin, path=["response"]) + assert_matches_type(Origin, origin, path=["response"]) assert cast(Any, response.is_closed) is True From e6255f0f4d383b50042c9a0376985e12ce39eda6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 06:11:46 +0000 Subject: [PATCH 051/177] feat(api): manual updates --- .stats.yml | 6 +- api.md | 8 +- src/imagekit/resources/accounts/origins.py | 57 +++-- src/imagekit/types/accounts/__init__.py | 3 +- .../types/accounts/origin_create_params.py | 217 +++++++++++++++++- .../types/accounts/origin_list_response.py | 4 +- src/imagekit/types/accounts/origin_param.py | 206 ----------------- .../{origin.py => origin_response.py} | 180 ++++++++------- .../types/accounts/origin_update_params.py | 217 +++++++++++++++++- tests/api_resources/accounts/test_origins.py | 46 ++-- 10 files changed, 580 insertions(+), 364 deletions(-) delete mode 100644 src/imagekit/types/accounts/origin_param.py rename src/imagekit/types/accounts/{origin.py => origin_response.py} (74%) diff --git a/.stats.yml b/.stats.yml index 6ac1eba..8a42af3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-554f897c7f0061bb1fe51cd82f5f05e66050db5e868524c374dac827bd7b8c3d.yml -openapi_spec_hash: 95b7298e7f3977ea6c98d9557d2c8d27 -config_hash: 49e367d7f33aeaf63ed738c1c0392d0a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-fa82106bb6313906d2eaac167e0ca5f60f12a166c743c00a18c22be0e455c1b6.yml +openapi_spec_hash: 8ff6fc6886e8d7a9eee6d45d51e9673c +config_hash: 76b94bb341141f0e9b14cdbb1203b0fa diff --git a/api.md b/api.md index e50b8f5..9e93045 100644 --- a/api.md +++ b/api.md @@ -171,16 +171,16 @@ Methods: Types: ```python -from imagekit.types.accounts import Origin, OriginListResponse +from imagekit.types.accounts import OriginResponse, OriginListResponse ``` Methods: -- client.accounts.origins.create(\*\*params) -> Origin -- client.accounts.origins.update(id, \*\*params) -> Origin +- client.accounts.origins.create(\*\*params) -> OriginResponse +- client.accounts.origins.update(id, \*\*params) -> OriginResponse - client.accounts.origins.list() -> OriginListResponse - client.accounts.origins.delete(id) -> None -- client.accounts.origins.get(id) -> Origin +- client.accounts.origins.get(id) -> OriginResponse ## URLEndpoints diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index aa3f7c6..2a78aab 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -17,9 +17,8 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options -from ...types.accounts import Origin, origin_create_params, origin_update_params -from ...types.accounts.origin import Origin -from ...types.accounts.origin_param import OriginParam +from ...types.accounts import origin_create_params, origin_update_params +from ...types.accounts.origin_response import OriginResponse from ...types.accounts.origin_list_response import OriginListResponse __all__ = ["OriginsResource", "AsyncOriginsResource"] @@ -48,21 +47,21 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: def create( self, *, - origin: OriginParam, + origin: origin_create_params.Origin, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Origin: + ) -> OriginResponse: """**Note:** This API is currently in beta. Creates a new origin and returns the origin object. Args: - origin: Schema for origin resources. + origin: Schema for origin request resources. extra_headers: Send extra headers @@ -73,14 +72,14 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ return cast( - Origin, + OriginResponse, self._post( "/v1/accounts/origins", body=maybe_transform(origin, origin_create_params.OriginCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) @@ -88,14 +87,14 @@ def update( self, id: str, *, - origin: OriginParam, + origin: origin_update_params.Origin, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Origin: + ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -105,7 +104,7 @@ def update( id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - origin: Schema for origin resources. + origin: Schema for origin request resources. extra_headers: Send extra headers @@ -118,14 +117,14 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - Origin, + OriginResponse, self._put( f"/v1/accounts/origins/{id}", body=maybe_transform(origin, origin_update_params.OriginUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) @@ -202,7 +201,7 @@ def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Origin: + ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -223,13 +222,13 @@ def get( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - Origin, + OriginResponse, self._get( f"/v1/accounts/origins/{id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) @@ -257,21 +256,21 @@ def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: async def create( self, *, - origin: OriginParam, + origin: origin_create_params.Origin, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Origin: + ) -> OriginResponse: """**Note:** This API is currently in beta. Creates a new origin and returns the origin object. Args: - origin: Schema for origin resources. + origin: Schema for origin request resources. extra_headers: Send extra headers @@ -282,14 +281,14 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ return cast( - Origin, + OriginResponse, await self._post( "/v1/accounts/origins", body=await async_maybe_transform(origin, origin_create_params.OriginCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) @@ -297,14 +296,14 @@ async def update( self, id: str, *, - origin: OriginParam, + origin: origin_update_params.Origin, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Origin: + ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -314,7 +313,7 @@ async def update( id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - origin: Schema for origin resources. + origin: Schema for origin request resources. extra_headers: Send extra headers @@ -327,14 +326,14 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - Origin, + OriginResponse, await self._put( f"/v1/accounts/origins/{id}", body=await async_maybe_transform(origin, origin_update_params.OriginUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) @@ -411,7 +410,7 @@ async def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Origin: + ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -432,13 +431,13 @@ async def get( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( - Origin, + OriginResponse, await self._get( f"/v1/accounts/origins/{id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=cast(Any, Origin), # Union types cannot be passed in as arguments in the type system + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system ), ) diff --git a/src/imagekit/types/accounts/__init__.py b/src/imagekit/types/accounts/__init__.py index e7b1f9f..b20d482 100644 --- a/src/imagekit/types/accounts/__init__.py +++ b/src/imagekit/types/accounts/__init__.py @@ -2,8 +2,7 @@ from __future__ import annotations -from .origin import Origin as Origin -from .origin_param import OriginParam as OriginParam +from .origin_response import OriginResponse as OriginResponse from .usage_get_params import UsageGetParams as UsageGetParams from .usage_get_response import UsageGetResponse as UsageGetResponse from .origin_create_params import OriginCreateParams as OriginCreateParams diff --git a/src/imagekit/types/accounts/origin_create_params.py b/src/imagekit/types/accounts/origin_create_params.py index babc28f..8299cd9 100644 --- a/src/imagekit/types/accounts/origin_create_params.py +++ b/src/imagekit/types/accounts/origin_create_params.py @@ -2,13 +2,220 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing import Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from .origin_param import OriginParam +from ..._utils import PropertyInfo -__all__ = ["OriginCreateParams"] +__all__ = [ + "OriginCreateParams", + "Origin", + "OriginS3", + "OriginS3Compatible", + "OriginCloudinaryBackup", + "OriginWebFolder", + "OriginWebProxy", + "OriginGcs", + "OriginAzureBlob", + "OriginAkeneoPim", +] class OriginCreateParams(TypedDict, total=False): - origin: Required[OriginParam] - """Schema for origin resources.""" + origin: Required[Origin] + """Schema for origin request resources.""" + + +class OriginS3(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class OriginS3Compatible(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + endpoint: Required[str] + """Custom S3-compatible endpoint.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3_COMPATIBLE"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] + """Use path-style S3 URLs?""" + + +class OriginCloudinaryBackup(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["CLOUDINARY_BACKUP"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class OriginWebFolder(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Root URL for the web folder origin.""" + + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_FOLDER"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] + """Forward the Host header to origin?""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class OriginWebProxy(TypedDict, total=False): + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_PROXY"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class OriginGcs(TypedDict, total=False): + bucket: Required[str] + + client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] + + name: Required[str] + """Display name of the origin.""" + + private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] + + type: Required[Literal["GCS"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class OriginAzureBlob(TypedDict, total=False): + account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] + + container: Required[str] + + name: Required[str] + """Display name of the origin.""" + + sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] + + type: Required[Literal["AZURE_BLOB"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class OriginAkeneoPim(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Akeneo instance base URL.""" + + client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] + """Akeneo API client ID.""" + + client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] + """Akeneo API client secret.""" + + name: Required[str] + """Display name of the origin.""" + + password: Required[str] + """Akeneo API password.""" + + type: Required[Literal["AKENEO_PIM"]] + + username: Required[str] + """Akeneo API username.""" + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +Origin: TypeAlias = Union[ + OriginS3, + OriginS3Compatible, + OriginCloudinaryBackup, + OriginWebFolder, + OriginWebProxy, + OriginGcs, + OriginAzureBlob, + OriginAkeneoPim, +] diff --git a/src/imagekit/types/accounts/origin_list_response.py b/src/imagekit/types/accounts/origin_list_response.py index e9c0331..b0e0931 100644 --- a/src/imagekit/types/accounts/origin_list_response.py +++ b/src/imagekit/types/accounts/origin_list_response.py @@ -3,8 +3,8 @@ from typing import List from typing_extensions import TypeAlias -from .origin import Origin +from .origin_response import OriginResponse __all__ = ["OriginListResponse"] -OriginListResponse: TypeAlias = List[Origin] +OriginListResponse: TypeAlias = List[OriginResponse] diff --git a/src/imagekit/types/accounts/origin_param.py b/src/imagekit/types/accounts/origin_param.py deleted file mode 100644 index df3e7ea..0000000 --- a/src/imagekit/types/accounts/origin_param.py +++ /dev/null @@ -1,206 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Union -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict - -from ..._utils import PropertyInfo - -__all__ = [ - "OriginParam", - "S3", - "S3Compatible", - "CloudinaryBackup", - "WebFolder", - "WebProxy", - "Gcs", - "AzureBlob", - "AkeneoPim", -] - - -class S3(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["S3"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class S3Compatible(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - endpoint: Required[str] - """Custom S3-compatible endpoint.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["S3_COMPATIBLE"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] - """Use path-style S3 URLs?""" - - -class CloudinaryBackup(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["CLOUDINARY_BACKUP"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class WebFolder(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Root URL for the web folder origin.""" - - name: Required[str] - """Display name of the origin.""" - - type: Required[Literal["WEB_FOLDER"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] - """Forward the Host header to origin?""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class WebProxy(TypedDict, total=False): - name: Required[str] - """Display name of the origin.""" - - type: Required[Literal["WEB_PROXY"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class Gcs(TypedDict, total=False): - bucket: Required[str] - - client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] - - name: Required[str] - """Display name of the origin.""" - - private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] - - type: Required[Literal["GCS"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class AzureBlob(TypedDict, total=False): - account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] - - container: Required[str] - - name: Required[str] - """Display name of the origin.""" - - sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] - - type: Required[Literal["AZURE_BLOB"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class AkeneoPim(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Akeneo instance base URL.""" - - client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] - """Akeneo API client ID.""" - - client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] - """Akeneo API client secret.""" - - name: Required[str] - """Display name of the origin.""" - - password: Required[str] - """Akeneo API password.""" - - type: Required[Literal["AKENEO_PIM"]] - - username: Required[str] - """Akeneo API username.""" - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -OriginParam: TypeAlias = Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim] diff --git a/src/imagekit/types/accounts/origin.py b/src/imagekit/types/accounts/origin_response.py similarity index 74% rename from src/imagekit/types/accounts/origin.py rename to src/imagekit/types/accounts/origin_response.py index d896c78..d437447 100644 --- a/src/imagekit/types/accounts/origin.py +++ b/src/imagekit/types/accounts/origin_response.py @@ -8,207 +8,217 @@ from ..._utils import PropertyInfo from ..._models import BaseModel -__all__ = ["Origin", "S3", "S3Compatible", "CloudinaryBackup", "WebFolder", "WebProxy", "Gcs", "AzureBlob", "AkeneoPim"] +__all__ = [ + "OriginResponse", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "Gcs", + "AzureBlob", + "AkeneoPim", +] class S3(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + bucket: str """S3 bucket name.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - type: Literal["S3"] - - id: Optional[str] = None - """Unique identifier for the origin. + prefix: str + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ + type: Literal["S3"] base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None - """Path prefix inside the bucket.""" +class S3Compatible(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class S3Compatible(BaseModel): bucket: str """S3 bucket name.""" endpoint: str """Custom S3-compatible endpoint.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - type: Literal["S3_COMPATIBLE"] + prefix: str + """Path prefix inside the bucket.""" - id: Optional[str] = None - """Unique identifier for the origin. + s3_force_path_style: bool = FieldInfo(alias="s3ForcePathStyle") + """Use path-style S3 URLs?""" - This is generated by ImageKit when you create a new origin. - """ + type: Literal["S3_COMPATIBLE"] base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - - prefix: Optional[str] = None - """Path prefix inside the bucket.""" - s3_force_path_style: Optional[bool] = FieldInfo(alias="s3ForcePathStyle", default=None) - """Use path-style S3 URLs?""" +class CloudinaryBackup(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class CloudinaryBackup(BaseModel): bucket: str """S3 bucket name.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - type: Literal["CLOUDINARY_BACKUP"] - - id: Optional[str] = None - """Unique identifier for the origin. + prefix: str + """Path prefix inside the bucket.""" - This is generated by ImageKit when you create a new origin. - """ + type: Literal["CLOUDINARY_BACKUP"] base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None - """Path prefix inside the bucket.""" +class WebFolder(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class WebFolder(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Root URL for the web folder origin.""" + forward_host_header_to_origin: bool = FieldInfo(alias="forwardHostHeaderToOrigin") + """Forward the Host header to origin?""" + + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" type: Literal["WEB_FOLDER"] - id: Optional[str] = None + base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) + """URL used in the Canonical header (if enabled).""" + + +class WebProxy(BaseModel): + id: str """Unique identifier for the origin. This is generated by ImageKit when you create a new origin. """ - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) - """URL used in the Canonical header (if enabled).""" - - forward_host_header_to_origin: Optional[bool] = FieldInfo(alias="forwardHostHeaderToOrigin", default=None) - """Forward the Host header to origin?""" - - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") """Whether to send a Canonical header.""" - -class WebProxy(BaseModel): name: str """Display name of the origin.""" type: Literal["WEB_PROXY"] - id: Optional[str] = None - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - class Gcs(BaseModel): + id: str + """Unique identifier for the origin. + + This is generated by ImageKit when you create a new origin. + """ + bucket: str client_email: str = FieldInfo(alias="clientEmail") + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - type: Literal["GCS"] + prefix: str - id: Optional[str] = None - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ + type: Literal["GCS"] base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None +class AzureBlob(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class AzureBlob(BaseModel): account_name: str = FieldInfo(alias="accountName") container: str + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" - type: Literal["AZURE_BLOB"] - - id: Optional[str] = None - """Unique identifier for the origin. + prefix: str - This is generated by ImageKit when you create a new origin. - """ + type: Literal["AZURE_BLOB"] base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - prefix: Optional[str] = None +class AkeneoPim(BaseModel): + id: str + """Unique identifier for the origin. + This is generated by ImageKit when you create a new origin. + """ -class AkeneoPim(BaseModel): base_url: str = FieldInfo(alias="baseUrl") """Akeneo instance base URL.""" + include_canonical_header: bool = FieldInfo(alias="includeCanonicalHeader") + """Whether to send a Canonical header.""" + name: str """Display name of the origin.""" type: Literal["AKENEO_PIM"] - id: Optional[str] = None - """Unique identifier for the origin. - - This is generated by ImageKit when you create a new origin. - """ - base_url_for_canonical_header: Optional[str] = FieldInfo(alias="baseUrlForCanonicalHeader", default=None) """URL used in the Canonical header (if enabled).""" - include_canonical_header: Optional[bool] = FieldInfo(alias="includeCanonicalHeader", default=None) - """Whether to send a Canonical header.""" - -Origin: TypeAlias = Annotated[ +OriginResponse: TypeAlias = Annotated[ Union[S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim], PropertyInfo(discriminator="type"), ] diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekit/types/accounts/origin_update_params.py index 984cdfe..78a8e65 100644 --- a/src/imagekit/types/accounts/origin_update_params.py +++ b/src/imagekit/types/accounts/origin_update_params.py @@ -2,13 +2,220 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing import Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from .origin_param import OriginParam +from ..._utils import PropertyInfo -__all__ = ["OriginUpdateParams"] +__all__ = [ + "OriginUpdateParams", + "Origin", + "OriginS3", + "OriginS3Compatible", + "OriginCloudinaryBackup", + "OriginWebFolder", + "OriginWebProxy", + "OriginGcs", + "OriginAzureBlob", + "OriginAkeneoPim", +] class OriginUpdateParams(TypedDict, total=False): - origin: Required[OriginParam] - """Schema for origin resources.""" + origin: Required[Origin] + """Schema for origin request resources.""" + + +class OriginS3(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class OriginS3Compatible(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + endpoint: Required[str] + """Custom S3-compatible endpoint.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3_COMPATIBLE"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] + """Use path-style S3 URLs?""" + + +class OriginCloudinaryBackup(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["CLOUDINARY_BACKUP"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class OriginWebFolder(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Root URL for the web folder origin.""" + + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_FOLDER"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] + """Forward the Host header to origin?""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class OriginWebProxy(TypedDict, total=False): + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_PROXY"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class OriginGcs(TypedDict, total=False): + bucket: Required[str] + + client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] + + name: Required[str] + """Display name of the origin.""" + + private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] + + type: Required[Literal["GCS"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class OriginAzureBlob(TypedDict, total=False): + account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] + + container: Required[str] + + name: Required[str] + """Display name of the origin.""" + + sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] + + type: Required[Literal["AZURE_BLOB"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class OriginAkeneoPim(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Akeneo instance base URL.""" + + client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] + """Akeneo API client ID.""" + + client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] + """Akeneo API client secret.""" + + name: Required[str] + """Display name of the origin.""" + + password: Required[str] + """Akeneo API password.""" + + type: Required[Literal["AKENEO_PIM"]] + + username: Required[str] + """Akeneo API username.""" + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +Origin: TypeAlias = Union[ + OriginS3, + OriginS3Compatible, + OriginCloudinaryBackup, + OriginWebFolder, + OriginWebProxy, + OriginGcs, + OriginAzureBlob, + OriginAkeneoPim, +] diff --git a/tests/api_resources/accounts/test_origins.py b/tests/api_resources/accounts/test_origins.py index ce2ccfe..3b4a817 100644 --- a/tests/api_resources/accounts/test_origins.py +++ b/tests/api_resources/accounts/test_origins.py @@ -9,7 +9,7 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.accounts import Origin, OriginListResponse +from imagekit.types.accounts import OriginResponse, OriginListResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -29,7 +29,7 @@ def test_method_create(self, client: ImageKit) -> None: "type": "S3", }, ) - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -46,7 +46,7 @@ def test_method_create_with_all_params(self, client: ImageKit) -> None: "prefix": "images", }, ) - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -64,7 +64,7 @@ def test_raw_response_create(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -82,7 +82,7 @@ def test_streaming_response_create(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -99,7 +99,7 @@ def test_method_update(self, client: ImageKit) -> None: "type": "S3", }, ) - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -117,7 +117,7 @@ def test_method_update_with_all_params(self, client: ImageKit) -> None: "prefix": "images", }, ) - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -136,7 +136,7 @@ def test_raw_response_update(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -155,7 +155,7 @@ def test_streaming_response_update(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -250,7 +250,7 @@ def test_method_get(self, client: ImageKit) -> None: origin = client.accounts.origins.get( "id", ) - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -262,7 +262,7 @@ def test_raw_response_get(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -274,7 +274,7 @@ def test_streaming_response_get(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -304,7 +304,7 @@ async def test_method_create(self, async_client: AsyncImageKit) -> None: "type": "S3", }, ) - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -321,7 +321,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncImageKit) "prefix": "images", }, ) - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -339,7 +339,7 @@ async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -357,7 +357,7 @@ async def test_streaming_response_create(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -374,7 +374,7 @@ async def test_method_update(self, async_client: AsyncImageKit) -> None: "type": "S3", }, ) - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -392,7 +392,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncImageKit) "prefix": "images", }, ) - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -411,7 +411,7 @@ async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -430,7 +430,7 @@ async def test_streaming_response_update(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @@ -525,7 +525,7 @@ async def test_method_get(self, async_client: AsyncImageKit) -> None: origin = await async_client.accounts.origins.get( "id", ) - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -537,7 +537,7 @@ async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -549,7 +549,7 @@ async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None assert response.http_request.headers.get("X-Stainless-Lang") == "python" origin = await response.parse() - assert_matches_type(Origin, origin, path=["response"]) + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True From 2b797c45cd3cac423afae136884e7ef2ca0b9d41 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 06:12:08 +0000 Subject: [PATCH 052/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 2 +- src/imagekit/resources/accounts/origins.py | 9 +- src/imagekit/types/accounts/__init__.py | 1 + .../types/accounts/origin_create_params.py | 215 +----------------- .../types/accounts/origin_request_param.py | 208 +++++++++++++++++ .../types/accounts/origin_update_params.py | 215 +----------------- tests/api_resources/accounts/test_origins.py | 5 +- 8 files changed, 228 insertions(+), 429 deletions(-) create mode 100644 src/imagekit/types/accounts/origin_request_param.py diff --git a/.stats.yml b/.stats.yml index 8a42af3..d806113 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-fa82106bb6313906d2eaac167e0ca5f60f12a166c743c00a18c22be0e455c1b6.yml openapi_spec_hash: 8ff6fc6886e8d7a9eee6d45d51e9673c -config_hash: 76b94bb341141f0e9b14cdbb1203b0fa +config_hash: e1442470f0f1b22d8558d6ca9526e0ea diff --git a/api.md b/api.md index 9e93045..3d92539 100644 --- a/api.md +++ b/api.md @@ -171,7 +171,7 @@ Methods: Types: ```python -from imagekit.types.accounts import OriginResponse, OriginListResponse +from imagekit.types.accounts import OriginRequest, OriginResponse, OriginListResponse ``` Methods: diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index 2a78aab..08eca06 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -20,6 +20,7 @@ from ...types.accounts import origin_create_params, origin_update_params from ...types.accounts.origin_response import OriginResponse from ...types.accounts.origin_list_response import OriginListResponse +from ...types.accounts.origin_request_param import OriginRequestParam __all__ = ["OriginsResource", "AsyncOriginsResource"] @@ -47,7 +48,7 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: def create( self, *, - origin: origin_create_params.Origin, + origin: OriginRequestParam, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -87,7 +88,7 @@ def update( self, id: str, *, - origin: origin_update_params.Origin, + origin: OriginRequestParam, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -256,7 +257,7 @@ def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: async def create( self, *, - origin: origin_create_params.Origin, + origin: OriginRequestParam, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -296,7 +297,7 @@ async def update( self, id: str, *, - origin: origin_update_params.Origin, + origin: OriginRequestParam, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, diff --git a/src/imagekit/types/accounts/__init__.py b/src/imagekit/types/accounts/__init__.py index b20d482..0b2b52e 100644 --- a/src/imagekit/types/accounts/__init__.py +++ b/src/imagekit/types/accounts/__init__.py @@ -7,6 +7,7 @@ from .usage_get_response import UsageGetResponse as UsageGetResponse from .origin_create_params import OriginCreateParams as OriginCreateParams from .origin_list_response import OriginListResponse as OriginListResponse +from .origin_request_param import OriginRequestParam as OriginRequestParam from .origin_update_params import OriginUpdateParams as OriginUpdateParams from .url_endpoint_get_response import URLEndpointGetResponse as URLEndpointGetResponse from .url_endpoint_create_params import URLEndpointCreateParams as URLEndpointCreateParams diff --git a/src/imagekit/types/accounts/origin_create_params.py b/src/imagekit/types/accounts/origin_create_params.py index 8299cd9..adb74db 100644 --- a/src/imagekit/types/accounts/origin_create_params.py +++ b/src/imagekit/types/accounts/origin_create_params.py @@ -2,220 +2,13 @@ from __future__ import annotations -from typing import Union -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Required, TypedDict -from ..._utils import PropertyInfo +from .origin_request_param import OriginRequestParam -__all__ = [ - "OriginCreateParams", - "Origin", - "OriginS3", - "OriginS3Compatible", - "OriginCloudinaryBackup", - "OriginWebFolder", - "OriginWebProxy", - "OriginGcs", - "OriginAzureBlob", - "OriginAkeneoPim", -] +__all__ = ["OriginCreateParams"] class OriginCreateParams(TypedDict, total=False): - origin: Required[Origin] + origin: Required[OriginRequestParam] """Schema for origin request resources.""" - - -class OriginS3(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["S3"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class OriginS3Compatible(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - endpoint: Required[str] - """Custom S3-compatible endpoint.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["S3_COMPATIBLE"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] - """Use path-style S3 URLs?""" - - -class OriginCloudinaryBackup(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["CLOUDINARY_BACKUP"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class OriginWebFolder(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Root URL for the web folder origin.""" - - name: Required[str] - """Display name of the origin.""" - - type: Required[Literal["WEB_FOLDER"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] - """Forward the Host header to origin?""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class OriginWebProxy(TypedDict, total=False): - name: Required[str] - """Display name of the origin.""" - - type: Required[Literal["WEB_PROXY"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class OriginGcs(TypedDict, total=False): - bucket: Required[str] - - client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] - - name: Required[str] - """Display name of the origin.""" - - private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] - - type: Required[Literal["GCS"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class OriginAzureBlob(TypedDict, total=False): - account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] - - container: Required[str] - - name: Required[str] - """Display name of the origin.""" - - sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] - - type: Required[Literal["AZURE_BLOB"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class OriginAkeneoPim(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Akeneo instance base URL.""" - - client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] - """Akeneo API client ID.""" - - client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] - """Akeneo API client secret.""" - - name: Required[str] - """Display name of the origin.""" - - password: Required[str] - """Akeneo API password.""" - - type: Required[Literal["AKENEO_PIM"]] - - username: Required[str] - """Akeneo API username.""" - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -Origin: TypeAlias = Union[ - OriginS3, - OriginS3Compatible, - OriginCloudinaryBackup, - OriginWebFolder, - OriginWebProxy, - OriginGcs, - OriginAzureBlob, - OriginAkeneoPim, -] diff --git a/src/imagekit/types/accounts/origin_request_param.py b/src/imagekit/types/accounts/origin_request_param.py new file mode 100644 index 0000000..a2864ad --- /dev/null +++ b/src/imagekit/types/accounts/origin_request_param.py @@ -0,0 +1,208 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from ..._utils import PropertyInfo + +__all__ = [ + "OriginRequestParam", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "Gcs", + "AzureBlob", + "AkeneoPim", +] + + +class S3(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class S3Compatible(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + endpoint: Required[str] + """Custom S3-compatible endpoint.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3_COMPATIBLE"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] + """Use path-style S3 URLs?""" + + +class CloudinaryBackup(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["CLOUDINARY_BACKUP"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class WebFolder(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Root URL for the web folder origin.""" + + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_FOLDER"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] + """Forward the Host header to origin?""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class WebProxy(TypedDict, total=False): + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_PROXY"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class Gcs(TypedDict, total=False): + bucket: Required[str] + + client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] + + name: Required[str] + """Display name of the origin.""" + + private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] + + type: Required[Literal["GCS"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AzureBlob(TypedDict, total=False): + account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] + + container: Required[str] + + name: Required[str] + """Display name of the origin.""" + + sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] + + type: Required[Literal["AZURE_BLOB"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AkeneoPim(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Akeneo instance base URL.""" + + client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] + """Akeneo API client ID.""" + + client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] + """Akeneo API client secret.""" + + name: Required[str] + """Display name of the origin.""" + + password: Required[str] + """Akeneo API password.""" + + type: Required[Literal["AKENEO_PIM"]] + + username: Required[str] + """Akeneo API username.""" + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +OriginRequestParam: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, Gcs, AzureBlob, AkeneoPim +] diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekit/types/accounts/origin_update_params.py index 78a8e65..138bf3c 100644 --- a/src/imagekit/types/accounts/origin_update_params.py +++ b/src/imagekit/types/accounts/origin_update_params.py @@ -2,220 +2,13 @@ from __future__ import annotations -from typing import Union -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Required, TypedDict -from ..._utils import PropertyInfo +from .origin_request_param import OriginRequestParam -__all__ = [ - "OriginUpdateParams", - "Origin", - "OriginS3", - "OriginS3Compatible", - "OriginCloudinaryBackup", - "OriginWebFolder", - "OriginWebProxy", - "OriginGcs", - "OriginAzureBlob", - "OriginAkeneoPim", -] +__all__ = ["OriginUpdateParams"] class OriginUpdateParams(TypedDict, total=False): - origin: Required[Origin] + origin: Required[OriginRequestParam] """Schema for origin request resources.""" - - -class OriginS3(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["S3"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class OriginS3Compatible(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - endpoint: Required[str] - """Custom S3-compatible endpoint.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["S3_COMPATIBLE"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] - """Use path-style S3 URLs?""" - - -class OriginCloudinaryBackup(TypedDict, total=False): - access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] - """Access key for the bucket.""" - - bucket: Required[str] - """S3 bucket name.""" - - name: Required[str] - """Display name of the origin.""" - - secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] - """Secret key for the bucket.""" - - type: Required[Literal["CLOUDINARY_BACKUP"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - """Path prefix inside the bucket.""" - - -class OriginWebFolder(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Root URL for the web folder origin.""" - - name: Required[str] - """Display name of the origin.""" - - type: Required[Literal["WEB_FOLDER"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] - """Forward the Host header to origin?""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class OriginWebProxy(TypedDict, total=False): - name: Required[str] - """Display name of the origin.""" - - type: Required[Literal["WEB_PROXY"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -class OriginGcs(TypedDict, total=False): - bucket: Required[str] - - client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] - - name: Required[str] - """Display name of the origin.""" - - private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] - - type: Required[Literal["GCS"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class OriginAzureBlob(TypedDict, total=False): - account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] - - container: Required[str] - - name: Required[str] - """Display name of the origin.""" - - sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] - - type: Required[Literal["AZURE_BLOB"]] - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - prefix: str - - -class OriginAkeneoPim(TypedDict, total=False): - base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] - """Akeneo instance base URL.""" - - client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] - """Akeneo API client ID.""" - - client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] - """Akeneo API client secret.""" - - name: Required[str] - """Display name of the origin.""" - - password: Required[str] - """Akeneo API password.""" - - type: Required[Literal["AKENEO_PIM"]] - - username: Required[str] - """Akeneo API username.""" - - base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] - """URL used in the Canonical header (if enabled).""" - - include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] - """Whether to send a Canonical header.""" - - -Origin: TypeAlias = Union[ - OriginS3, - OriginS3Compatible, - OriginCloudinaryBackup, - OriginWebFolder, - OriginWebProxy, - OriginGcs, - OriginAzureBlob, - OriginAkeneoPim, -] diff --git a/tests/api_resources/accounts/test_origins.py b/tests/api_resources/accounts/test_origins.py index 3b4a817..ba060f6 100644 --- a/tests/api_resources/accounts/test_origins.py +++ b/tests/api_resources/accounts/test_origins.py @@ -9,7 +9,10 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.accounts import OriginResponse, OriginListResponse +from imagekit.types.accounts import ( + OriginResponse, + OriginListResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") From da6b24e83b6e0c1f5d2bc6103a0ebec5484de18f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 06:14:01 +0000 Subject: [PATCH 053/177] feat(api): manual updates --- .stats.yml | 6 +- api.md | 14 +--- .../resources/accounts/url_endpoints.py | 28 ++++--- src/imagekit/types/accounts/__init__.py | 4 +- .../accounts/url_endpoint_create_response.py | 59 --------------- .../accounts/url_endpoint_list_response.py | 74 ++----------------- ...t_response.py => url_endpoint_response.py} | 4 +- .../accounts/url_endpoint_update_response.py | 59 --------------- .../accounts/test_url_endpoints.py | 48 ++++++------ 9 files changed, 51 insertions(+), 245 deletions(-) delete mode 100644 src/imagekit/types/accounts/url_endpoint_create_response.py rename src/imagekit/types/accounts/{url_endpoint_get_response.py => url_endpoint_response.py} (91%) delete mode 100644 src/imagekit/types/accounts/url_endpoint_update_response.py diff --git a/.stats.yml b/.stats.yml index d806113..e88489f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-fa82106bb6313906d2eaac167e0ca5f60f12a166c743c00a18c22be0e455c1b6.yml -openapi_spec_hash: 8ff6fc6886e8d7a9eee6d45d51e9673c -config_hash: e1442470f0f1b22d8558d6ca9526e0ea +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-547b616849eececf3f5b1ea38ebe1dba718e1877c787e3642b9c91e552548789.yml +openapi_spec_hash: fba0bf8c1ee034067ab6ae93f84abeae +config_hash: befd7c8f04cc5b4992ec11efe0d6934b diff --git a/api.md b/api.md index 3d92539..0dbfc8a 100644 --- a/api.md +++ b/api.md @@ -187,22 +187,16 @@ Methods: Types: ```python -from imagekit.types.accounts import ( - URLEndpoint, - URLEndpointCreateResponse, - URLEndpointUpdateResponse, - URLEndpointListResponse, - URLEndpointGetResponse, -) +from imagekit.types.accounts import URLEndpointRequest, URLEndpointResponse, URLEndpointListResponse ``` Methods: -- client.accounts.url_endpoints.create(\*\*params) -> URLEndpointCreateResponse -- client.accounts.url_endpoints.update(id, \*\*params) -> URLEndpointUpdateResponse +- client.accounts.url_endpoints.create(\*\*params) -> URLEndpointResponse +- client.accounts.url_endpoints.update(id, \*\*params) -> URLEndpointResponse - client.accounts.url_endpoints.list() -> URLEndpointListResponse - client.accounts.url_endpoints.delete(id) -> None -- client.accounts.url_endpoints.get(id) -> URLEndpointGetResponse +- client.accounts.url_endpoints.get(id) -> URLEndpointResponse # Beta diff --git a/src/imagekit/resources/accounts/url_endpoints.py b/src/imagekit/resources/accounts/url_endpoints.py index ce20a62..5c23f50 100644 --- a/src/imagekit/resources/accounts/url_endpoints.py +++ b/src/imagekit/resources/accounts/url_endpoints.py @@ -18,10 +18,8 @@ ) from ..._base_client import make_request_options from ...types.accounts import url_endpoint_create_params, url_endpoint_update_params -from ...types.accounts.url_endpoint_get_response import URLEndpointGetResponse +from ...types.accounts.url_endpoint_response import URLEndpointResponse from ...types.accounts.url_endpoint_list_response import URLEndpointListResponse -from ...types.accounts.url_endpoint_create_response import URLEndpointCreateResponse -from ...types.accounts.url_endpoint_update_response import URLEndpointUpdateResponse __all__ = ["URLEndpointsResource", "AsyncURLEndpointsResource"] @@ -59,7 +57,7 @@ def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> URLEndpointCreateResponse: + ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -99,7 +97,7 @@ def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=URLEndpointCreateResponse, + cast_to=URLEndpointResponse, ) def update( @@ -116,7 +114,7 @@ def update( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> URLEndpointUpdateResponse: + ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -162,7 +160,7 @@ def update( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=URLEndpointUpdateResponse, + cast_to=URLEndpointResponse, ) def list( @@ -240,7 +238,7 @@ def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> URLEndpointGetResponse: + ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -266,7 +264,7 @@ def get( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=URLEndpointGetResponse, + cast_to=URLEndpointResponse, ) @@ -303,7 +301,7 @@ async def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> URLEndpointCreateResponse: + ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -343,7 +341,7 @@ async def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=URLEndpointCreateResponse, + cast_to=URLEndpointResponse, ) async def update( @@ -360,7 +358,7 @@ async def update( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> URLEndpointUpdateResponse: + ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -406,7 +404,7 @@ async def update( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=URLEndpointUpdateResponse, + cast_to=URLEndpointResponse, ) async def list( @@ -484,7 +482,7 @@ async def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> URLEndpointGetResponse: + ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -510,7 +508,7 @@ async def get( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=URLEndpointGetResponse, + cast_to=URLEndpointResponse, ) diff --git a/src/imagekit/types/accounts/__init__.py b/src/imagekit/types/accounts/__init__.py index 0b2b52e..3d713db 100644 --- a/src/imagekit/types/accounts/__init__.py +++ b/src/imagekit/types/accounts/__init__.py @@ -9,9 +9,7 @@ from .origin_list_response import OriginListResponse as OriginListResponse from .origin_request_param import OriginRequestParam as OriginRequestParam from .origin_update_params import OriginUpdateParams as OriginUpdateParams -from .url_endpoint_get_response import URLEndpointGetResponse as URLEndpointGetResponse +from .url_endpoint_response import URLEndpointResponse as URLEndpointResponse from .url_endpoint_create_params import URLEndpointCreateParams as URLEndpointCreateParams from .url_endpoint_list_response import URLEndpointListResponse as URLEndpointListResponse from .url_endpoint_update_params import URLEndpointUpdateParams as URLEndpointUpdateParams -from .url_endpoint_create_response import URLEndpointCreateResponse as URLEndpointCreateResponse -from .url_endpoint_update_response import URLEndpointUpdateResponse as URLEndpointUpdateResponse diff --git a/src/imagekit/types/accounts/url_endpoint_create_response.py b/src/imagekit/types/accounts/url_endpoint_create_response.py deleted file mode 100644 index f8ef98f..0000000 --- a/src/imagekit/types/accounts/url_endpoint_create_response.py +++ /dev/null @@ -1,59 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias - -from pydantic import Field as FieldInfo - -from ..._utils import PropertyInfo -from ..._models import BaseModel - -__all__ = ["URLEndpointCreateResponse", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] - - -class URLRewriterCloudinary(BaseModel): - preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") - """Whether to preserve `/` in the rewritten URL.""" - - type: Literal["CLOUDINARY"] - - -class URLRewriterImgix(BaseModel): - type: Literal["IMGIX"] - - -class URLRewriterAkamai(BaseModel): - type: Literal["AKAMAI"] - - -URLRewriter: TypeAlias = Annotated[ - Union[URLRewriterCloudinary, URLRewriterImgix, URLRewriterAkamai], PropertyInfo(discriminator="type") -] - - -class URLEndpointCreateResponse(BaseModel): - id: str - """Unique identifier for the URL-endpoint. - - This is generated by ImageKit when you create a new URL-endpoint. For the - default URL-endpoint, this is always `default`. - """ - - description: str - """Description of the URL endpoint.""" - - origins: List[str] - """ - Ordered list of origin IDs to try when the file isn’t in the Media Library; - ImageKit checks them in the sequence provided. Origin must be created before it - can be used in a URL endpoint. - """ - - url_prefix: str = FieldInfo(alias="urlPrefix") - """ - Path segment appended to your base URL to form the endpoint (letters, digits, - and hyphens only — or empty for the default endpoint). - """ - - url_rewriter: Optional[URLRewriter] = FieldInfo(alias="urlRewriter", default=None) - """Configuration for third-party URL rewriting.""" diff --git a/src/imagekit/types/accounts/url_endpoint_list_response.py b/src/imagekit/types/accounts/url_endpoint_list_response.py index addbb17..a51a8df 100644 --- a/src/imagekit/types/accounts/url_endpoint_list_response.py +++ b/src/imagekit/types/accounts/url_endpoint_list_response.py @@ -1,74 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias +from typing import List +from typing_extensions import TypeAlias -from pydantic import Field as FieldInfo +from .url_endpoint_response import URLEndpointResponse -from ..._utils import PropertyInfo -from ..._models import BaseModel +__all__ = ["URLEndpointListResponse"] -__all__ = [ - "URLEndpointListResponse", - "URLEndpointListResponseItem", - "URLEndpointListResponseItemURLRewriter", - "URLEndpointListResponseItemURLRewriterCloudinary", - "URLEndpointListResponseItemURLRewriterImgix", - "URLEndpointListResponseItemURLRewriterAkamai", -] - - -class URLEndpointListResponseItemURLRewriterCloudinary(BaseModel): - preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") - """Whether to preserve `/` in the rewritten URL.""" - - type: Literal["CLOUDINARY"] - - -class URLEndpointListResponseItemURLRewriterImgix(BaseModel): - type: Literal["IMGIX"] - - -class URLEndpointListResponseItemURLRewriterAkamai(BaseModel): - type: Literal["AKAMAI"] - - -URLEndpointListResponseItemURLRewriter: TypeAlias = Annotated[ - Union[ - URLEndpointListResponseItemURLRewriterCloudinary, - URLEndpointListResponseItemURLRewriterImgix, - URLEndpointListResponseItemURLRewriterAkamai, - ], - PropertyInfo(discriminator="type"), -] - - -class URLEndpointListResponseItem(BaseModel): - id: str - """Unique identifier for the URL-endpoint. - - This is generated by ImageKit when you create a new URL-endpoint. For the - default URL-endpoint, this is always `default`. - """ - - description: str - """Description of the URL endpoint.""" - - origins: List[str] - """ - Ordered list of origin IDs to try when the file isn’t in the Media Library; - ImageKit checks them in the sequence provided. Origin must be created before it - can be used in a URL endpoint. - """ - - url_prefix: str = FieldInfo(alias="urlPrefix") - """ - Path segment appended to your base URL to form the endpoint (letters, digits, - and hyphens only — or empty for the default endpoint). - """ - - url_rewriter: Optional[URLEndpointListResponseItemURLRewriter] = FieldInfo(alias="urlRewriter", default=None) - """Configuration for third-party URL rewriting.""" - - -URLEndpointListResponse: TypeAlias = List[URLEndpointListResponseItem] +URLEndpointListResponse: TypeAlias = List[URLEndpointResponse] diff --git a/src/imagekit/types/accounts/url_endpoint_get_response.py b/src/imagekit/types/accounts/url_endpoint_response.py similarity index 91% rename from src/imagekit/types/accounts/url_endpoint_get_response.py rename to src/imagekit/types/accounts/url_endpoint_response.py index 85c1c27..c868c7c 100644 --- a/src/imagekit/types/accounts/url_endpoint_get_response.py +++ b/src/imagekit/types/accounts/url_endpoint_response.py @@ -8,7 +8,7 @@ from ..._utils import PropertyInfo from ..._models import BaseModel -__all__ = ["URLEndpointGetResponse", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] +__all__ = ["URLEndpointResponse", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] class URLRewriterCloudinary(BaseModel): @@ -31,7 +31,7 @@ class URLRewriterAkamai(BaseModel): ] -class URLEndpointGetResponse(BaseModel): +class URLEndpointResponse(BaseModel): id: str """Unique identifier for the URL-endpoint. diff --git a/src/imagekit/types/accounts/url_endpoint_update_response.py b/src/imagekit/types/accounts/url_endpoint_update_response.py deleted file mode 100644 index 99e9bbb..0000000 --- a/src/imagekit/types/accounts/url_endpoint_update_response.py +++ /dev/null @@ -1,59 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias - -from pydantic import Field as FieldInfo - -from ..._utils import PropertyInfo -from ..._models import BaseModel - -__all__ = ["URLEndpointUpdateResponse", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] - - -class URLRewriterCloudinary(BaseModel): - preserve_asset_delivery_types: bool = FieldInfo(alias="preserveAssetDeliveryTypes") - """Whether to preserve `/` in the rewritten URL.""" - - type: Literal["CLOUDINARY"] - - -class URLRewriterImgix(BaseModel): - type: Literal["IMGIX"] - - -class URLRewriterAkamai(BaseModel): - type: Literal["AKAMAI"] - - -URLRewriter: TypeAlias = Annotated[ - Union[URLRewriterCloudinary, URLRewriterImgix, URLRewriterAkamai], PropertyInfo(discriminator="type") -] - - -class URLEndpointUpdateResponse(BaseModel): - id: str - """Unique identifier for the URL-endpoint. - - This is generated by ImageKit when you create a new URL-endpoint. For the - default URL-endpoint, this is always `default`. - """ - - description: str - """Description of the URL endpoint.""" - - origins: List[str] - """ - Ordered list of origin IDs to try when the file isn’t in the Media Library; - ImageKit checks them in the sequence provided. Origin must be created before it - can be used in a URL endpoint. - """ - - url_prefix: str = FieldInfo(alias="urlPrefix") - """ - Path segment appended to your base URL to form the endpoint (letters, digits, - and hyphens only — or empty for the default endpoint). - """ - - url_rewriter: Optional[URLRewriter] = FieldInfo(alias="urlRewriter", default=None) - """Configuration for third-party URL rewriting.""" diff --git a/tests/api_resources/accounts/test_url_endpoints.py b/tests/api_resources/accounts/test_url_endpoints.py index b84517e..714a7c0 100644 --- a/tests/api_resources/accounts/test_url_endpoints.py +++ b/tests/api_resources/accounts/test_url_endpoints.py @@ -10,10 +10,8 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type from imagekit.types.accounts import ( - URLEndpointGetResponse, + URLEndpointResponse, URLEndpointListResponse, - URLEndpointCreateResponse, - URLEndpointUpdateResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -28,7 +26,7 @@ def test_method_create(self, client: ImageKit) -> None: url_endpoint = client.accounts.url_endpoints.create( description="My custom URL endpoint", ) - assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -42,7 +40,7 @@ def test_method_create_with_all_params(self, client: ImageKit) -> None: "preserve_asset_delivery_types": True, }, ) - assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -54,7 +52,7 @@ def test_raw_response_create(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = response.parse() - assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -66,7 +64,7 @@ def test_streaming_response_create(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = response.parse() - assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) assert cast(Any, response.is_closed) is True @@ -77,7 +75,7 @@ def test_method_update(self, client: ImageKit) -> None: id="id", description="My custom URL endpoint", ) - assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -92,7 +90,7 @@ def test_method_update_with_all_params(self, client: ImageKit) -> None: "preserve_asset_delivery_types": True, }, ) - assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -105,7 +103,7 @@ def test_raw_response_update(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = response.parse() - assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -118,7 +116,7 @@ def test_streaming_response_update(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = response.parse() - assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) assert cast(Any, response.is_closed) is True @@ -207,7 +205,7 @@ def test_method_get(self, client: ImageKit) -> None: url_endpoint = client.accounts.url_endpoints.get( "id", ) - assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -219,7 +217,7 @@ def test_raw_response_get(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = response.parse() - assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -231,7 +229,7 @@ def test_streaming_response_get(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = response.parse() - assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) assert cast(Any, response.is_closed) is True @@ -255,7 +253,7 @@ async def test_method_create(self, async_client: AsyncImageKit) -> None: url_endpoint = await async_client.accounts.url_endpoints.create( description="My custom URL endpoint", ) - assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -269,7 +267,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncImageKit) "preserve_asset_delivery_types": True, }, ) - assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -281,7 +279,7 @@ async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = await response.parse() - assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -293,7 +291,7 @@ async def test_streaming_response_create(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = await response.parse() - assert_matches_type(URLEndpointCreateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) assert cast(Any, response.is_closed) is True @@ -304,7 +302,7 @@ async def test_method_update(self, async_client: AsyncImageKit) -> None: id="id", description="My custom URL endpoint", ) - assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -319,7 +317,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncImageKit) "preserve_asset_delivery_types": True, }, ) - assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -332,7 +330,7 @@ async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = await response.parse() - assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -345,7 +343,7 @@ async def test_streaming_response_update(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = await response.parse() - assert_matches_type(URLEndpointUpdateResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) assert cast(Any, response.is_closed) is True @@ -434,7 +432,7 @@ async def test_method_get(self, async_client: AsyncImageKit) -> None: url_endpoint = await async_client.accounts.url_endpoints.get( "id", ) - assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -446,7 +444,7 @@ async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = await response.parse() - assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -458,7 +456,7 @@ async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None assert response.http_request.headers.get("X-Stainless-Lang") == "python" url_endpoint = await response.parse() - assert_matches_type(URLEndpointGetResponse, url_endpoint, path=["response"]) + assert_matches_type(URLEndpointResponse, url_endpoint, path=["response"]) assert cast(Any, response.is_closed) is True From 16b7f8a9bac6459b6a5d92860ff70477cf6d69b3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 06:22:01 +0000 Subject: [PATCH 054/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 11 +- src/imagekit/resources/files/metadata.py | 19 +- src/imagekit/types/__init__.py | 1 + .../types/beta/v2/file_upload_response.py | 179 +---------------- src/imagekit/types/file_upload_response.py | 179 +---------------- src/imagekit/types/files/__init__.py | 2 - .../files/metadata_get_from_url_response.py | 181 ------------------ .../metadata_get_response.py => metadata.py} | 6 +- tests/api_resources/files/test_metadata.py | 26 +-- 10 files changed, 34 insertions(+), 572 deletions(-) delete mode 100644 src/imagekit/types/files/metadata_get_from_url_response.py rename src/imagekit/types/{files/metadata_get_response.py => metadata.py} (96%) diff --git a/.stats.yml b/.stats.yml index e88489f..eae8704 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-547b616849eececf3f5b1ea38ebe1dba718e1877c787e3642b9c91e552548789.yml openapi_spec_hash: fba0bf8c1ee034067ab6ae93f84abeae -config_hash: befd7c8f04cc5b4992ec11efe0d6934b +config_hash: 659d086a034de739b7423470b2c13ae0 diff --git a/api.md b/api.md index 0dbfc8a..c66da88 100644 --- a/api.md +++ b/api.md @@ -25,6 +25,7 @@ Types: from imagekit.types import ( File, Folder, + Metadata, FileUpdateResponse, FileCopyResponse, FileMoveResponse, @@ -80,16 +81,10 @@ Methods: ## Metadata -Types: - -```python -from imagekit.types.files import MetadataGetResponse, MetadataGetFromURLResponse -``` - Methods: -- client.files.metadata.get(file_id) -> MetadataGetResponse -- client.files.metadata.get_from_url(\*\*params) -> MetadataGetFromURLResponse +- client.files.metadata.get(file_id) -> Metadata +- client.files.metadata.get_from_url(\*\*params) -> Metadata # Assets diff --git a/src/imagekit/resources/files/metadata.py b/src/imagekit/resources/files/metadata.py index c6e5035..9432b0c 100644 --- a/src/imagekit/resources/files/metadata.py +++ b/src/imagekit/resources/files/metadata.py @@ -16,8 +16,7 @@ ) from ...types.files import metadata_get_from_url_params from ..._base_client import make_request_options -from ...types.files.metadata_get_response import MetadataGetResponse -from ...types.files.metadata_get_from_url_response import MetadataGetFromURLResponse +from ...types.metadata import Metadata __all__ = ["MetadataResource", "AsyncMetadataResource"] @@ -52,7 +51,7 @@ def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> MetadataGetResponse: + ) -> Metadata: """ You can programmatically get image EXIF, pHash, and other metadata for uploaded files in the ImageKit.io media library using this API. @@ -76,7 +75,7 @@ def get( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=MetadataGetResponse, + cast_to=Metadata, ) def get_from_url( @@ -89,7 +88,7 @@ def get_from_url( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> MetadataGetFromURLResponse: + ) -> Metadata: """ Get image EXIF, pHash, and other metadata from ImageKit.io powered remote URL using this API. @@ -115,7 +114,7 @@ def get_from_url( timeout=timeout, query=maybe_transform({"url": url}, metadata_get_from_url_params.MetadataGetFromURLParams), ), - cast_to=MetadataGetFromURLResponse, + cast_to=Metadata, ) @@ -149,7 +148,7 @@ async def get( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> MetadataGetResponse: + ) -> Metadata: """ You can programmatically get image EXIF, pHash, and other metadata for uploaded files in the ImageKit.io media library using this API. @@ -173,7 +172,7 @@ async def get( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=MetadataGetResponse, + cast_to=Metadata, ) async def get_from_url( @@ -186,7 +185,7 @@ async def get_from_url( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> MetadataGetFromURLResponse: + ) -> Metadata: """ Get image EXIF, pHash, and other metadata from ImageKit.io powered remote URL using this API. @@ -212,7 +211,7 @@ async def get_from_url( timeout=timeout, query=await async_maybe_transform({"url": url}, metadata_get_from_url_params.MetadataGetFromURLParams), ), - cast_to=MetadataGetFromURLResponse, + cast_to=Metadata, ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 5c759c7..e076245 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -4,6 +4,7 @@ from .file import File as File from .folder import Folder as Folder +from .metadata import Metadata as Metadata from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams from .asset_list_params import AssetListParams as AssetListParams diff --git a/src/imagekit/types/beta/v2/file_upload_response.py b/src/imagekit/types/beta/v2/file_upload_response.py index 05d1d6e..75c3109 100644 --- a/src/imagekit/types/beta/v2/file_upload_response.py +++ b/src/imagekit/types/beta/v2/file_upload_response.py @@ -6,20 +6,9 @@ from pydantic import Field as FieldInfo from ...._models import BaseModel +from ...metadata import Metadata -__all__ = [ - "FileUploadResponse", - "AITag", - "ExtensionStatus", - "Metadata", - "MetadataExif", - "MetadataExifExif", - "MetadataExifGps", - "MetadataExifImage", - "MetadataExifInteroperability", - "MetadataExifThumbnail", - "VersionInfo", -] +__all__ = ["FileUploadResponse", "AITag", "ExtensionStatus", "VersionInfo"] class AITag(BaseModel): @@ -49,170 +38,6 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) -class MetadataExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class MetadataExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class MetadataExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class MetadataExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class MetadataExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class MetadataExif(BaseModel): - exif: Optional[MetadataExifExif] = None - """Object containing Exif details.""" - - gps: Optional[MetadataExifGps] = None - """Object containing GPS information.""" - - image: Optional[MetadataExifImage] = None - """Object containing EXIF image information.""" - - interoperability: Optional[MetadataExifInteroperability] = None - """JSON object.""" - - makernote: Optional[Dict[str, object]] = None - - thumbnail: Optional[MetadataExifThumbnail] = None - """Object containing Thumbnail information.""" - - -class Metadata(BaseModel): - audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) - """The audio codec used in the video (only for video).""" - - bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) - """The bit rate of the video in kbps (only for video).""" - - density: Optional[int] = None - """The density of the image in DPI.""" - - duration: Optional[int] = None - """The duration of the video in seconds (only for video).""" - - exif: Optional[MetadataExif] = None - - format: Optional[str] = None - """The format of the file (e.g., 'jpg', 'mp4').""" - - has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) - """Indicates if the image has a color profile.""" - - has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) - """Indicates if the image contains transparent areas.""" - - height: Optional[int] = None - """The height of the image or video in pixels.""" - - p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) - """Perceptual hash of the image.""" - - quality: Optional[int] = None - """The quality indicator of the image.""" - - size: Optional[int] = None - """The file size in bytes.""" - - video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) - """The video codec used in the video (only for video).""" - - width: Optional[int] = None - """The width of the image or video in pixels.""" - - class VersionInfo(BaseModel): id: Optional[str] = None """Unique identifier of the file version.""" diff --git a/src/imagekit/types/file_upload_response.py b/src/imagekit/types/file_upload_response.py index 8e0883b..094d561 100644 --- a/src/imagekit/types/file_upload_response.py +++ b/src/imagekit/types/file_upload_response.py @@ -6,20 +6,9 @@ from pydantic import Field as FieldInfo from .._models import BaseModel +from .metadata import Metadata -__all__ = [ - "FileUploadResponse", - "AITag", - "ExtensionStatus", - "Metadata", - "MetadataExif", - "MetadataExifExif", - "MetadataExifGps", - "MetadataExifImage", - "MetadataExifInteroperability", - "MetadataExifThumbnail", - "VersionInfo", -] +__all__ = ["FileUploadResponse", "AITag", "ExtensionStatus", "VersionInfo"] class AITag(BaseModel): @@ -49,170 +38,6 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) -class MetadataExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class MetadataExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class MetadataExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class MetadataExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class MetadataExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class MetadataExif(BaseModel): - exif: Optional[MetadataExifExif] = None - """Object containing Exif details.""" - - gps: Optional[MetadataExifGps] = None - """Object containing GPS information.""" - - image: Optional[MetadataExifImage] = None - """Object containing EXIF image information.""" - - interoperability: Optional[MetadataExifInteroperability] = None - """JSON object.""" - - makernote: Optional[Dict[str, object]] = None - - thumbnail: Optional[MetadataExifThumbnail] = None - """Object containing Thumbnail information.""" - - -class Metadata(BaseModel): - audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) - """The audio codec used in the video (only for video).""" - - bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) - """The bit rate of the video in kbps (only for video).""" - - density: Optional[int] = None - """The density of the image in DPI.""" - - duration: Optional[int] = None - """The duration of the video in seconds (only for video).""" - - exif: Optional[MetadataExif] = None - - format: Optional[str] = None - """The format of the file (e.g., 'jpg', 'mp4').""" - - has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) - """Indicates if the image has a color profile.""" - - has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) - """Indicates if the image contains transparent areas.""" - - height: Optional[int] = None - """The height of the image or video in pixels.""" - - p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) - """Perceptual hash of the image.""" - - quality: Optional[int] = None - """The quality indicator of the image.""" - - size: Optional[int] = None - """The file size in bytes.""" - - video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) - """The video codec used in the video (only for video).""" - - width: Optional[int] = None - """The width of the image or video in pixels.""" - - class VersionInfo(BaseModel): id: Optional[str] = None """Unique identifier of the file version.""" diff --git a/src/imagekit/types/files/__init__.py b/src/imagekit/types/files/__init__.py index b6dd7da..b46129a 100644 --- a/src/imagekit/types/files/__init__.py +++ b/src/imagekit/types/files/__init__.py @@ -5,7 +5,6 @@ from .bulk_delete_params import BulkDeleteParams as BulkDeleteParams from .bulk_add_tags_params import BulkAddTagsParams as BulkAddTagsParams from .bulk_delete_response import BulkDeleteResponse as BulkDeleteResponse -from .metadata_get_response import MetadataGetResponse as MetadataGetResponse from .version_list_response import VersionListResponse as VersionListResponse from .bulk_add_tags_response import BulkAddTagsResponse as BulkAddTagsResponse from .bulk_remove_tags_params import BulkRemoveTagsParams as BulkRemoveTagsParams @@ -14,4 +13,3 @@ from .bulk_remove_ai_tags_params import BulkRemoveAITagsParams as BulkRemoveAITagsParams from .bulk_remove_ai_tags_response import BulkRemoveAITagsResponse as BulkRemoveAITagsResponse from .metadata_get_from_url_params import MetadataGetFromURLParams as MetadataGetFromURLParams -from .metadata_get_from_url_response import MetadataGetFromURLResponse as MetadataGetFromURLResponse diff --git a/src/imagekit/types/files/metadata_get_from_url_response.py b/src/imagekit/types/files/metadata_get_from_url_response.py deleted file mode 100644 index 47b1bcd..0000000 --- a/src/imagekit/types/files/metadata_get_from_url_response.py +++ /dev/null @@ -1,181 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, List, Optional - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = [ - "MetadataGetFromURLResponse", - "Exif", - "ExifExif", - "ExifGps", - "ExifImage", - "ExifInteroperability", - "ExifThumbnail", -] - - -class ExifExif(BaseModel): - aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) - - color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) - - create_date: Optional[str] = FieldInfo(alias="CreateDate", default=None) - - custom_rendered: Optional[int] = FieldInfo(alias="CustomRendered", default=None) - - date_time_original: Optional[str] = FieldInfo(alias="DateTimeOriginal", default=None) - - exif_image_height: Optional[int] = FieldInfo(alias="ExifImageHeight", default=None) - - exif_image_width: Optional[int] = FieldInfo(alias="ExifImageWidth", default=None) - - exif_version: Optional[str] = FieldInfo(alias="ExifVersion", default=None) - - exposure_compensation: Optional[float] = FieldInfo(alias="ExposureCompensation", default=None) - - exposure_mode: Optional[int] = FieldInfo(alias="ExposureMode", default=None) - - exposure_program: Optional[int] = FieldInfo(alias="ExposureProgram", default=None) - - exposure_time: Optional[float] = FieldInfo(alias="ExposureTime", default=None) - - flash: Optional[int] = FieldInfo(alias="Flash", default=None) - - flashpix_version: Optional[str] = FieldInfo(alias="FlashpixVersion", default=None) - - f_number: Optional[float] = FieldInfo(alias="FNumber", default=None) - - focal_length: Optional[int] = FieldInfo(alias="FocalLength", default=None) - - focal_plane_resolution_unit: Optional[int] = FieldInfo(alias="FocalPlaneResolutionUnit", default=None) - - focal_plane_x_resolution: Optional[float] = FieldInfo(alias="FocalPlaneXResolution", default=None) - - focal_plane_y_resolution: Optional[float] = FieldInfo(alias="FocalPlaneYResolution", default=None) - - interop_offset: Optional[int] = FieldInfo(alias="InteropOffset", default=None) - - iso: Optional[int] = FieldInfo(alias="ISO", default=None) - - metering_mode: Optional[int] = FieldInfo(alias="MeteringMode", default=None) - - scene_capture_type: Optional[int] = FieldInfo(alias="SceneCaptureType", default=None) - - shutter_speed_value: Optional[float] = FieldInfo(alias="ShutterSpeedValue", default=None) - - sub_sec_time: Optional[str] = FieldInfo(alias="SubSecTime", default=None) - - white_balance: Optional[int] = FieldInfo(alias="WhiteBalance", default=None) - - -class ExifGps(BaseModel): - gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) - - -class ExifImage(BaseModel): - exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) - - gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) - - make: Optional[str] = FieldInfo(alias="Make", default=None) - - model: Optional[str] = FieldInfo(alias="Model", default=None) - - modify_date: Optional[str] = FieldInfo(alias="ModifyDate", default=None) - - orientation: Optional[int] = FieldInfo(alias="Orientation", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - software: Optional[str] = FieldInfo(alias="Software", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_cb_cr_positioning: Optional[int] = FieldInfo(alias="YCbCrPositioning", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class ExifInteroperability(BaseModel): - interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) - - interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) - - -class ExifThumbnail(BaseModel): - compression: Optional[int] = FieldInfo(alias="Compression", default=None) - - resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) - - thumbnail_length: Optional[int] = FieldInfo(alias="ThumbnailLength", default=None) - - thumbnail_offset: Optional[int] = FieldInfo(alias="ThumbnailOffset", default=None) - - x_resolution: Optional[int] = FieldInfo(alias="XResolution", default=None) - - y_resolution: Optional[int] = FieldInfo(alias="YResolution", default=None) - - -class Exif(BaseModel): - exif: Optional[ExifExif] = None - """Object containing Exif details.""" - - gps: Optional[ExifGps] = None - """Object containing GPS information.""" - - image: Optional[ExifImage] = None - """Object containing EXIF image information.""" - - interoperability: Optional[ExifInteroperability] = None - """JSON object.""" - - makernote: Optional[Dict[str, object]] = None - - thumbnail: Optional[ExifThumbnail] = None - """Object containing Thumbnail information.""" - - -class MetadataGetFromURLResponse(BaseModel): - audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) - """The audio codec used in the video (only for video).""" - - bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) - """The bit rate of the video in kbps (only for video).""" - - density: Optional[int] = None - """The density of the image in DPI.""" - - duration: Optional[int] = None - """The duration of the video in seconds (only for video).""" - - exif: Optional[Exif] = None - - format: Optional[str] = None - """The format of the file (e.g., 'jpg', 'mp4').""" - - has_color_profile: Optional[bool] = FieldInfo(alias="hasColorProfile", default=None) - """Indicates if the image has a color profile.""" - - has_transparency: Optional[bool] = FieldInfo(alias="hasTransparency", default=None) - """Indicates if the image contains transparent areas.""" - - height: Optional[int] = None - """The height of the image or video in pixels.""" - - p_hash: Optional[str] = FieldInfo(alias="pHash", default=None) - """Perceptual hash of the image.""" - - quality: Optional[int] = None - """The quality indicator of the image.""" - - size: Optional[int] = None - """The file size in bytes.""" - - video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) - """The video codec used in the video (only for video).""" - - width: Optional[int] = None - """The width of the image or video in pixels.""" diff --git a/src/imagekit/types/files/metadata_get_response.py b/src/imagekit/types/metadata.py similarity index 96% rename from src/imagekit/types/files/metadata_get_response.py rename to src/imagekit/types/metadata.py index d5a3cbf..85bb814 100644 --- a/src/imagekit/types/files/metadata_get_response.py +++ b/src/imagekit/types/metadata.py @@ -4,9 +4,9 @@ from pydantic import Field as FieldInfo -from ..._models import BaseModel +from .._models import BaseModel -__all__ = ["MetadataGetResponse", "Exif", "ExifExif", "ExifGps", "ExifImage", "ExifInteroperability", "ExifThumbnail"] +__all__ = ["Metadata", "Exif", "ExifExif", "ExifGps", "ExifImage", "ExifInteroperability", "ExifThumbnail"] class ExifExif(BaseModel): @@ -130,7 +130,7 @@ class Exif(BaseModel): """Object containing Thumbnail information.""" -class MetadataGetResponse(BaseModel): +class Metadata(BaseModel): audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) """The audio codec used in the video (only for video).""" diff --git a/tests/api_resources/files/test_metadata.py b/tests/api_resources/files/test_metadata.py index 76d23e5..dc0d9f4 100644 --- a/tests/api_resources/files/test_metadata.py +++ b/tests/api_resources/files/test_metadata.py @@ -9,7 +9,7 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.files import MetadataGetResponse, MetadataGetFromURLResponse +from imagekit.types import Metadata base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -23,7 +23,7 @@ def test_method_get(self, client: ImageKit) -> None: metadata = client.files.metadata.get( "fileId", ) - assert_matches_type(MetadataGetResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -35,7 +35,7 @@ def test_raw_response_get(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = response.parse() - assert_matches_type(MetadataGetResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -47,7 +47,7 @@ def test_streaming_response_get(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = response.parse() - assert_matches_type(MetadataGetResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) assert cast(Any, response.is_closed) is True @@ -65,7 +65,7 @@ def test_method_get_from_url(self, client: ImageKit) -> None: metadata = client.files.metadata.get_from_url( url="https://example.com", ) - assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -77,7 +77,7 @@ def test_raw_response_get_from_url(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = response.parse() - assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -89,7 +89,7 @@ def test_streaming_response_get_from_url(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = response.parse() - assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) assert cast(Any, response.is_closed) is True @@ -105,7 +105,7 @@ async def test_method_get(self, async_client: AsyncImageKit) -> None: metadata = await async_client.files.metadata.get( "fileId", ) - assert_matches_type(MetadataGetResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -117,7 +117,7 @@ async def test_raw_response_get(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = await response.parse() - assert_matches_type(MetadataGetResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -129,7 +129,7 @@ async def test_streaming_response_get(self, async_client: AsyncImageKit) -> None assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = await response.parse() - assert_matches_type(MetadataGetResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) assert cast(Any, response.is_closed) is True @@ -147,7 +147,7 @@ async def test_method_get_from_url(self, async_client: AsyncImageKit) -> None: metadata = await async_client.files.metadata.get_from_url( url="https://example.com", ) - assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -159,7 +159,7 @@ async def test_raw_response_get_from_url(self, async_client: AsyncImageKit) -> N assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = await response.parse() - assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -171,6 +171,6 @@ async def test_streaming_response_get_from_url(self, async_client: AsyncImageKit assert response.http_request.headers.get("X-Stainless-Lang") == "python" metadata = await response.parse() - assert_matches_type(MetadataGetFromURLResponse, metadata, path=["response"]) + assert_matches_type(Metadata, metadata, path=["response"]) assert cast(Any, response.is_closed) is True From 45543e501c30e3929e78a7324e38531c8970d9fd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 06:22:43 +0000 Subject: [PATCH 055/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index eae8704..b0b132c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-547b616849eececf3f5b1ea38ebe1dba718e1877c787e3642b9c91e552548789.yml openapi_spec_hash: fba0bf8c1ee034067ab6ae93f84abeae -config_hash: 659d086a034de739b7423470b2c13ae0 +config_hash: 90f5a16140d721a24bffafbc30abaf35 From 5231495169f91e36cb02737fce79d5c7abb41d78 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 06:44:29 +0000 Subject: [PATCH 056/177] feat(api): manual updates --- .stats.yml | 6 +++--- api.md | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index b0b132c..67dc438 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-547b616849eececf3f5b1ea38ebe1dba718e1877c787e3642b9c91e552548789.yml -openapi_spec_hash: fba0bf8c1ee034067ab6ae93f84abeae -config_hash: 90f5a16140d721a24bffafbc30abaf35 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-ef47bed4a4585d2bdb4308a8710d748625a33548279a7b5ba04bbea0a0bbe1b8.yml +openapi_spec_hash: e64e91aa1603678f705d1ef4817f3304 +config_hash: 3e8cbbe505aa1a6dd7a72728dbf8fd4a diff --git a/api.md b/api.md index c66da88..edcfb44 100644 --- a/api.md +++ b/api.md @@ -23,6 +23,7 @@ Types: ```python from imagekit.types import ( + AsyncBulkJobResponse, File, Folder, Metadata, From 01879ee95a21b83794e6c3a4cc48cff2a5b3f4ac Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 06:48:26 +0000 Subject: [PATCH 057/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 67dc438..8c084b5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-ef47bed4a4585d2bdb4308a8710d748625a33548279a7b5ba04bbea0a0bbe1b8.yml openapi_spec_hash: e64e91aa1603678f705d1ef4817f3304 -config_hash: 3e8cbbe505aa1a6dd7a72728dbf8fd4a +config_hash: 9f3ce6ee05ee57f8d3f0330a5d18be26 diff --git a/api.md b/api.md index edcfb44..c0fb196 100644 --- a/api.md +++ b/api.md @@ -23,7 +23,6 @@ Types: ```python from imagekit.types import ( - AsyncBulkJobResponse, File, Folder, Metadata, @@ -120,6 +119,7 @@ Types: ```python from imagekit.types import ( + AsyncBulkJobResponse, FolderCreateResponse, FolderDeleteResponse, FolderCopyResponse, From cca2791c42c1fd9dcc82833f5116b4194ad40ed4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 06:56:17 +0000 Subject: [PATCH 058/177] feat(api): manual updates --- .stats.yml | 4 +- api.md | 15 ++---- src/imagekit/resources/folders/folders.py | 28 +++++------ src/imagekit/types/__init__.py | 4 +- ...response.py => async_bulk_job_response.py} | 8 ++-- src/imagekit/types/folder_move_response.py | 17 ------- src/imagekit/types/folder_rename_response.py | 17 ------- tests/api_resources/test_folders.py | 48 +++++++++---------- 8 files changed, 46 insertions(+), 95 deletions(-) rename src/imagekit/types/{folder_copy_response.py => async_bulk_job_response.py} (62%) delete mode 100644 src/imagekit/types/folder_move_response.py delete mode 100644 src/imagekit/types/folder_rename_response.py diff --git a/.stats.yml b/.stats.yml index 8c084b5..a43e2d2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-ef47bed4a4585d2bdb4308a8710d748625a33548279a7b5ba04bbea0a0bbe1b8.yml -openapi_spec_hash: e64e91aa1603678f705d1ef4817f3304 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-76121f82e0f399831eff2cf350f6f7737d8e22b996b22f5a5ca88fdf73c8a7fc.yml +openapi_spec_hash: 0913383eddc12609ad59e29d68dc6154 config_hash: 9f3ce6ee05ee57f8d3f0330a5d18be26 diff --git a/api.md b/api.md index c0fb196..befc3d8 100644 --- a/api.md +++ b/api.md @@ -118,23 +118,16 @@ Methods: Types: ```python -from imagekit.types import ( - AsyncBulkJobResponse, - FolderCreateResponse, - FolderDeleteResponse, - FolderCopyResponse, - FolderMoveResponse, - FolderRenameResponse, -) +from imagekit.types import AsyncBulkJobResponse, FolderCreateResponse, FolderDeleteResponse ``` Methods: - client.folders.create(\*\*params) -> FolderCreateResponse - client.folders.delete(\*\*params) -> FolderDeleteResponse -- client.folders.copy(\*\*params) -> FolderCopyResponse -- client.folders.move(\*\*params) -> FolderMoveResponse -- client.folders.rename(\*\*params) -> FolderRenameResponse +- client.folders.copy(\*\*params) -> AsyncBulkJobResponse +- client.folders.move(\*\*params) -> AsyncBulkJobResponse +- client.folders.rename(\*\*params) -> AsyncBulkJobResponse ## Job diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekit/resources/folders/folders.py index b0e322d..ba214db 100644 --- a/src/imagekit/resources/folders/folders.py +++ b/src/imagekit/resources/folders/folders.py @@ -30,11 +30,9 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options -from ...types.folder_copy_response import FolderCopyResponse -from ...types.folder_move_response import FolderMoveResponse from ...types.folder_create_response import FolderCreateResponse from ...types.folder_delete_response import FolderDeleteResponse -from ...types.folder_rename_response import FolderRenameResponse +from ...types.async_bulk_job_response import AsyncBulkJobResponse __all__ = ["FoldersResource", "AsyncFoldersResource"] @@ -166,7 +164,7 @@ def copy( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FolderCopyResponse: + ) -> AsyncBulkJobResponse: """This will copy one folder into another. The selected folder, its nested folders, @@ -206,7 +204,7 @@ def copy( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FolderCopyResponse, + cast_to=AsyncBulkJobResponse, ) def move( @@ -220,7 +218,7 @@ def move( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FolderMoveResponse: + ) -> AsyncBulkJobResponse: """This will move one folder into another. The selected folder, its nested folders, @@ -254,7 +252,7 @@ def move( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FolderMoveResponse, + cast_to=AsyncBulkJobResponse, ) def rename( @@ -269,7 +267,7 @@ def rename( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FolderRenameResponse: + ) -> AsyncBulkJobResponse: """This API allows you to rename an existing folder. The folder and all its nested @@ -322,7 +320,7 @@ def rename( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FolderRenameResponse, + cast_to=AsyncBulkJobResponse, ) @@ -453,7 +451,7 @@ async def copy( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FolderCopyResponse: + ) -> AsyncBulkJobResponse: """This will copy one folder into another. The selected folder, its nested folders, @@ -493,7 +491,7 @@ async def copy( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FolderCopyResponse, + cast_to=AsyncBulkJobResponse, ) async def move( @@ -507,7 +505,7 @@ async def move( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FolderMoveResponse: + ) -> AsyncBulkJobResponse: """This will move one folder into another. The selected folder, its nested folders, @@ -541,7 +539,7 @@ async def move( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FolderMoveResponse, + cast_to=AsyncBulkJobResponse, ) async def rename( @@ -556,7 +554,7 @@ async def rename( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FolderRenameResponse: + ) -> AsyncBulkJobResponse: """This API allows you to rename an existing folder. The folder and all its nested @@ -609,7 +607,7 @@ async def rename( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=FolderRenameResponse, + cast_to=AsyncBulkJobResponse, ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index e076245..ca94d3e 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -19,16 +19,14 @@ from .file_rename_response import FileRenameResponse as FileRenameResponse from .file_update_response import FileUpdateResponse as FileUpdateResponse from .file_upload_response import FileUploadResponse as FileUploadResponse -from .folder_copy_response import FolderCopyResponse as FolderCopyResponse from .folder_create_params import FolderCreateParams as FolderCreateParams from .folder_delete_params import FolderDeleteParams as FolderDeleteParams -from .folder_move_response import FolderMoveResponse as FolderMoveResponse from .folder_rename_params import FolderRenameParams as FolderRenameParams from .unwrap_webhook_event import UnwrapWebhookEvent as UnwrapWebhookEvent from .custom_metadata_field import CustomMetadataField as CustomMetadataField from .folder_create_response import FolderCreateResponse as FolderCreateResponse from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse -from .folder_rename_response import FolderRenameResponse as FolderRenameResponse +from .async_bulk_job_response import AsyncBulkJobResponse as AsyncBulkJobResponse from .unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent as UnsafeUnwrapWebhookEvent from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams diff --git a/src/imagekit/types/folder_copy_response.py b/src/imagekit/types/async_bulk_job_response.py similarity index 62% rename from src/imagekit/types/folder_copy_response.py rename to src/imagekit/types/async_bulk_job_response.py index 4e2f5ab..cb4eb26 100644 --- a/src/imagekit/types/folder_copy_response.py +++ b/src/imagekit/types/async_bulk_job_response.py @@ -1,16 +1,14 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from pydantic import Field as FieldInfo from .._models import BaseModel -__all__ = ["FolderCopyResponse"] +__all__ = ["AsyncBulkJobResponse"] -class FolderCopyResponse(BaseModel): - job_id: Optional[str] = FieldInfo(alias="jobId", default=None) +class AsyncBulkJobResponse(BaseModel): + job_id: str = FieldInfo(alias="jobId") """Unique identifier of the bulk job. This can be used to check the status of the bulk job. diff --git a/src/imagekit/types/folder_move_response.py b/src/imagekit/types/folder_move_response.py deleted file mode 100644 index a2d1a6f..0000000 --- a/src/imagekit/types/folder_move_response.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["FolderMoveResponse"] - - -class FolderMoveResponse(BaseModel): - job_id: Optional[str] = FieldInfo(alias="jobId", default=None) - """Unique identifier of the bulk job. - - This can be used to check the status of the bulk job. - """ diff --git a/src/imagekit/types/folder_rename_response.py b/src/imagekit/types/folder_rename_response.py deleted file mode 100644 index b693ea0..0000000 --- a/src/imagekit/types/folder_rename_response.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["FolderRenameResponse"] - - -class FolderRenameResponse(BaseModel): - job_id: Optional[str] = FieldInfo(alias="jobId", default=None) - """Unique identifier of the bulk job. - - This can be used to check the status of the bulk job. - """ diff --git a/tests/api_resources/test_folders.py b/tests/api_resources/test_folders.py index de14df0..d6386e4 100644 --- a/tests/api_resources/test_folders.py +++ b/tests/api_resources/test_folders.py @@ -10,11 +10,9 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type from imagekit.types import ( - FolderCopyResponse, - FolderMoveResponse, + AsyncBulkJobResponse, FolderCreateResponse, FolderDeleteResponse, - FolderRenameResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -101,7 +99,7 @@ def test_method_copy(self, client: ImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(FolderCopyResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -111,7 +109,7 @@ def test_method_copy_with_all_params(self, client: ImageKit) -> None: source_folder_path="/path/of/source/folder", include_versions=True, ) - assert_matches_type(FolderCopyResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -124,7 +122,7 @@ def test_raw_response_copy(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(FolderCopyResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -137,7 +135,7 @@ def test_streaming_response_copy(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(FolderCopyResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -148,7 +146,7 @@ def test_method_move(self, client: ImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(FolderMoveResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -161,7 +159,7 @@ def test_raw_response_move(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(FolderMoveResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -174,7 +172,7 @@ def test_streaming_response_move(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(FolderMoveResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -185,7 +183,7 @@ def test_method_rename(self, client: ImageKit) -> None: folder_path="/path/of/folder", new_folder_name="new-folder-name", ) - assert_matches_type(FolderRenameResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -195,7 +193,7 @@ def test_method_rename_with_all_params(self, client: ImageKit) -> None: new_folder_name="new-folder-name", purge_cache=True, ) - assert_matches_type(FolderRenameResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -208,7 +206,7 @@ def test_raw_response_rename(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(FolderRenameResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -221,7 +219,7 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(FolderRenameResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -309,7 +307,7 @@ async def test_method_copy(self, async_client: AsyncImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(FolderCopyResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -319,7 +317,7 @@ async def test_method_copy_with_all_params(self, async_client: AsyncImageKit) -> source_folder_path="/path/of/source/folder", include_versions=True, ) - assert_matches_type(FolderCopyResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -332,7 +330,7 @@ async def test_raw_response_copy(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(FolderCopyResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -345,7 +343,7 @@ async def test_streaming_response_copy(self, async_client: AsyncImageKit) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(FolderCopyResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -356,7 +354,7 @@ async def test_method_move(self, async_client: AsyncImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(FolderMoveResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -369,7 +367,7 @@ async def test_raw_response_move(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(FolderMoveResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -382,7 +380,7 @@ async def test_streaming_response_move(self, async_client: AsyncImageKit) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(FolderMoveResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -393,7 +391,7 @@ async def test_method_rename(self, async_client: AsyncImageKit) -> None: folder_path="/path/of/folder", new_folder_name="new-folder-name", ) - assert_matches_type(FolderRenameResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -403,7 +401,7 @@ async def test_method_rename_with_all_params(self, async_client: AsyncImageKit) new_folder_name="new-folder-name", purge_cache=True, ) - assert_matches_type(FolderRenameResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -416,7 +414,7 @@ async def test_raw_response_rename(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(FolderRenameResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -429,6 +427,6 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(FolderRenameResponse, folder, path=["response"]) + assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True From 120e0cdf0c7897c693f96557d8cc85f848935025 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 06:58:10 +0000 Subject: [PATCH 059/177] feat(api): manual updates --- .stats.yml | 6 +-- api.md | 8 ++-- src/imagekit/resources/folders/folders.py | 26 +++++------ src/imagekit/types/__init__.py | 2 +- ...c_bulk_job_response.py => job_response.py} | 4 +- tests/api_resources/test_folders.py | 46 +++++++++---------- 6 files changed, 46 insertions(+), 46 deletions(-) rename src/imagekit/types/{async_bulk_job_response.py => job_response.py} (80%) diff --git a/.stats.yml b/.stats.yml index a43e2d2..8cb350c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-76121f82e0f399831eff2cf350f6f7737d8e22b996b22f5a5ca88fdf73c8a7fc.yml -openapi_spec_hash: 0913383eddc12609ad59e29d68dc6154 -config_hash: 9f3ce6ee05ee57f8d3f0330a5d18be26 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-6fee8f335061dc7a308b9a2712dce5a1c16c81125f71e00dba3e4759a39d7bf0.yml +openapi_spec_hash: 205e083e0ab6b49d5bc8a2e5b323610b +config_hash: f7c2f1f50b841dabc54904c2e05f21c5 diff --git a/api.md b/api.md index befc3d8..5dc6d1b 100644 --- a/api.md +++ b/api.md @@ -118,16 +118,16 @@ Methods: Types: ```python -from imagekit.types import AsyncBulkJobResponse, FolderCreateResponse, FolderDeleteResponse +from imagekit.types import JobResponse, FolderCreateResponse, FolderDeleteResponse ``` Methods: - client.folders.create(\*\*params) -> FolderCreateResponse - client.folders.delete(\*\*params) -> FolderDeleteResponse -- client.folders.copy(\*\*params) -> AsyncBulkJobResponse -- client.folders.move(\*\*params) -> AsyncBulkJobResponse -- client.folders.rename(\*\*params) -> AsyncBulkJobResponse +- client.folders.copy(\*\*params) -> JobResponse +- client.folders.move(\*\*params) -> JobResponse +- client.folders.rename(\*\*params) -> JobResponse ## Job diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekit/resources/folders/folders.py index ba214db..743d706 100644 --- a/src/imagekit/resources/folders/folders.py +++ b/src/imagekit/resources/folders/folders.py @@ -30,9 +30,9 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options +from ...types.job_response import JobResponse from ...types.folder_create_response import FolderCreateResponse from ...types.folder_delete_response import FolderDeleteResponse -from ...types.async_bulk_job_response import AsyncBulkJobResponse __all__ = ["FoldersResource", "AsyncFoldersResource"] @@ -164,7 +164,7 @@ def copy( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AsyncBulkJobResponse: + ) -> JobResponse: """This will copy one folder into another. The selected folder, its nested folders, @@ -204,7 +204,7 @@ def copy( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AsyncBulkJobResponse, + cast_to=JobResponse, ) def move( @@ -218,7 +218,7 @@ def move( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AsyncBulkJobResponse: + ) -> JobResponse: """This will move one folder into another. The selected folder, its nested folders, @@ -252,7 +252,7 @@ def move( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AsyncBulkJobResponse, + cast_to=JobResponse, ) def rename( @@ -267,7 +267,7 @@ def rename( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AsyncBulkJobResponse: + ) -> JobResponse: """This API allows you to rename an existing folder. The folder and all its nested @@ -320,7 +320,7 @@ def rename( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AsyncBulkJobResponse, + cast_to=JobResponse, ) @@ -451,7 +451,7 @@ async def copy( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AsyncBulkJobResponse: + ) -> JobResponse: """This will copy one folder into another. The selected folder, its nested folders, @@ -491,7 +491,7 @@ async def copy( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AsyncBulkJobResponse, + cast_to=JobResponse, ) async def move( @@ -505,7 +505,7 @@ async def move( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AsyncBulkJobResponse: + ) -> JobResponse: """This will move one folder into another. The selected folder, its nested folders, @@ -539,7 +539,7 @@ async def move( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AsyncBulkJobResponse, + cast_to=JobResponse, ) async def rename( @@ -554,7 +554,7 @@ async def rename( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AsyncBulkJobResponse: + ) -> JobResponse: """This API allows you to rename an existing folder. The folder and all its nested @@ -607,7 +607,7 @@ async def rename( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AsyncBulkJobResponse, + cast_to=JobResponse, ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index ca94d3e..a6fd14b 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -5,6 +5,7 @@ from .file import File as File from .folder import Folder as Folder from .metadata import Metadata as Metadata +from .job_response import JobResponse as JobResponse from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams from .asset_list_params import AssetListParams as AssetListParams @@ -26,7 +27,6 @@ from .custom_metadata_field import CustomMetadataField as CustomMetadataField from .folder_create_response import FolderCreateResponse as FolderCreateResponse from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse -from .async_bulk_job_response import AsyncBulkJobResponse as AsyncBulkJobResponse from .unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent as UnsafeUnwrapWebhookEvent from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams diff --git a/src/imagekit/types/async_bulk_job_response.py b/src/imagekit/types/job_response.py similarity index 80% rename from src/imagekit/types/async_bulk_job_response.py rename to src/imagekit/types/job_response.py index cb4eb26..ed8041e 100644 --- a/src/imagekit/types/async_bulk_job_response.py +++ b/src/imagekit/types/job_response.py @@ -4,10 +4,10 @@ from .._models import BaseModel -__all__ = ["AsyncBulkJobResponse"] +__all__ = ["JobResponse"] -class AsyncBulkJobResponse(BaseModel): +class JobResponse(BaseModel): job_id: str = FieldInfo(alias="jobId") """Unique identifier of the bulk job. diff --git a/tests/api_resources/test_folders.py b/tests/api_resources/test_folders.py index d6386e4..f005351 100644 --- a/tests/api_resources/test_folders.py +++ b/tests/api_resources/test_folders.py @@ -10,7 +10,7 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type from imagekit.types import ( - AsyncBulkJobResponse, + JobResponse, FolderCreateResponse, FolderDeleteResponse, ) @@ -99,7 +99,7 @@ def test_method_copy(self, client: ImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -109,7 +109,7 @@ def test_method_copy_with_all_params(self, client: ImageKit) -> None: source_folder_path="/path/of/source/folder", include_versions=True, ) - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -122,7 +122,7 @@ def test_raw_response_copy(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -135,7 +135,7 @@ def test_streaming_response_copy(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -146,7 +146,7 @@ def test_method_move(self, client: ImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -159,7 +159,7 @@ def test_raw_response_move(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -172,7 +172,7 @@ def test_streaming_response_move(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -183,7 +183,7 @@ def test_method_rename(self, client: ImageKit) -> None: folder_path="/path/of/folder", new_folder_name="new-folder-name", ) - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -193,7 +193,7 @@ def test_method_rename_with_all_params(self, client: ImageKit) -> None: new_folder_name="new-folder-name", purge_cache=True, ) - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -206,7 +206,7 @@ def test_raw_response_rename(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -219,7 +219,7 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -307,7 +307,7 @@ async def test_method_copy(self, async_client: AsyncImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -317,7 +317,7 @@ async def test_method_copy_with_all_params(self, async_client: AsyncImageKit) -> source_folder_path="/path/of/source/folder", include_versions=True, ) - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -330,7 +330,7 @@ async def test_raw_response_copy(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -343,7 +343,7 @@ async def test_streaming_response_copy(self, async_client: AsyncImageKit) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -354,7 +354,7 @@ async def test_method_move(self, async_client: AsyncImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -367,7 +367,7 @@ async def test_raw_response_move(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -380,7 +380,7 @@ async def test_streaming_response_move(self, async_client: AsyncImageKit) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -391,7 +391,7 @@ async def test_method_rename(self, async_client: AsyncImageKit) -> None: folder_path="/path/of/folder", new_folder_name="new-folder-name", ) - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -401,7 +401,7 @@ async def test_method_rename_with_all_params(self, async_client: AsyncImageKit) new_folder_name="new-folder-name", purge_cache=True, ) - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -414,7 +414,7 @@ async def test_raw_response_rename(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -427,6 +427,6 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(AsyncBulkJobResponse, folder, path=["response"]) + assert_matches_type(JobResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True From dd062e7fe2e659011a15c86ea9652abd7c7ec0ed Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 07:03:05 +0000 Subject: [PATCH 060/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 14 ++++-- src/imagekit/resources/folders/folders.py | 28 ++++++----- src/imagekit/types/__init__.py | 4 +- ...ob_response.py => folder_copy_response.py} | 4 +- src/imagekit/types/folder_move_response.py | 15 ++++++ src/imagekit/types/folder_rename_response.py | 15 ++++++ tests/api_resources/test_folders.py | 48 ++++++++++--------- 8 files changed, 86 insertions(+), 44 deletions(-) rename src/imagekit/types/{job_response.py => folder_copy_response.py} (81%) create mode 100644 src/imagekit/types/folder_move_response.py create mode 100644 src/imagekit/types/folder_rename_response.py diff --git a/.stats.yml b/.stats.yml index 8cb350c..f16eca0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-6fee8f335061dc7a308b9a2712dce5a1c16c81125f71e00dba3e4759a39d7bf0.yml openapi_spec_hash: 205e083e0ab6b49d5bc8a2e5b323610b -config_hash: f7c2f1f50b841dabc54904c2e05f21c5 +config_hash: 90f5a16140d721a24bffafbc30abaf35 diff --git a/api.md b/api.md index 5dc6d1b..c66da88 100644 --- a/api.md +++ b/api.md @@ -118,16 +118,22 @@ Methods: Types: ```python -from imagekit.types import JobResponse, FolderCreateResponse, FolderDeleteResponse +from imagekit.types import ( + FolderCreateResponse, + FolderDeleteResponse, + FolderCopyResponse, + FolderMoveResponse, + FolderRenameResponse, +) ``` Methods: - client.folders.create(\*\*params) -> FolderCreateResponse - client.folders.delete(\*\*params) -> FolderDeleteResponse -- client.folders.copy(\*\*params) -> JobResponse -- client.folders.move(\*\*params) -> JobResponse -- client.folders.rename(\*\*params) -> JobResponse +- client.folders.copy(\*\*params) -> FolderCopyResponse +- client.folders.move(\*\*params) -> FolderMoveResponse +- client.folders.rename(\*\*params) -> FolderRenameResponse ## Job diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekit/resources/folders/folders.py index 743d706..b0e322d 100644 --- a/src/imagekit/resources/folders/folders.py +++ b/src/imagekit/resources/folders/folders.py @@ -30,9 +30,11 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options -from ...types.job_response import JobResponse +from ...types.folder_copy_response import FolderCopyResponse +from ...types.folder_move_response import FolderMoveResponse from ...types.folder_create_response import FolderCreateResponse from ...types.folder_delete_response import FolderDeleteResponse +from ...types.folder_rename_response import FolderRenameResponse __all__ = ["FoldersResource", "AsyncFoldersResource"] @@ -164,7 +166,7 @@ def copy( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> JobResponse: + ) -> FolderCopyResponse: """This will copy one folder into another. The selected folder, its nested folders, @@ -204,7 +206,7 @@ def copy( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=JobResponse, + cast_to=FolderCopyResponse, ) def move( @@ -218,7 +220,7 @@ def move( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> JobResponse: + ) -> FolderMoveResponse: """This will move one folder into another. The selected folder, its nested folders, @@ -252,7 +254,7 @@ def move( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=JobResponse, + cast_to=FolderMoveResponse, ) def rename( @@ -267,7 +269,7 @@ def rename( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> JobResponse: + ) -> FolderRenameResponse: """This API allows you to rename an existing folder. The folder and all its nested @@ -320,7 +322,7 @@ def rename( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=JobResponse, + cast_to=FolderRenameResponse, ) @@ -451,7 +453,7 @@ async def copy( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> JobResponse: + ) -> FolderCopyResponse: """This will copy one folder into another. The selected folder, its nested folders, @@ -491,7 +493,7 @@ async def copy( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=JobResponse, + cast_to=FolderCopyResponse, ) async def move( @@ -505,7 +507,7 @@ async def move( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> JobResponse: + ) -> FolderMoveResponse: """This will move one folder into another. The selected folder, its nested folders, @@ -539,7 +541,7 @@ async def move( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=JobResponse, + cast_to=FolderMoveResponse, ) async def rename( @@ -554,7 +556,7 @@ async def rename( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> JobResponse: + ) -> FolderRenameResponse: """This API allows you to rename an existing folder. The folder and all its nested @@ -607,7 +609,7 @@ async def rename( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=JobResponse, + cast_to=FolderRenameResponse, ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index a6fd14b..e076245 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -5,7 +5,6 @@ from .file import File as File from .folder import Folder as Folder from .metadata import Metadata as Metadata -from .job_response import JobResponse as JobResponse from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams from .asset_list_params import AssetListParams as AssetListParams @@ -20,13 +19,16 @@ from .file_rename_response import FileRenameResponse as FileRenameResponse from .file_update_response import FileUpdateResponse as FileUpdateResponse from .file_upload_response import FileUploadResponse as FileUploadResponse +from .folder_copy_response import FolderCopyResponse as FolderCopyResponse from .folder_create_params import FolderCreateParams as FolderCreateParams from .folder_delete_params import FolderDeleteParams as FolderDeleteParams +from .folder_move_response import FolderMoveResponse as FolderMoveResponse from .folder_rename_params import FolderRenameParams as FolderRenameParams from .unwrap_webhook_event import UnwrapWebhookEvent as UnwrapWebhookEvent from .custom_metadata_field import CustomMetadataField as CustomMetadataField from .folder_create_response import FolderCreateResponse as FolderCreateResponse from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse +from .folder_rename_response import FolderRenameResponse as FolderRenameResponse from .unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent as UnsafeUnwrapWebhookEvent from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams diff --git a/src/imagekit/types/job_response.py b/src/imagekit/types/folder_copy_response.py similarity index 81% rename from src/imagekit/types/job_response.py rename to src/imagekit/types/folder_copy_response.py index ed8041e..6ca3b1a 100644 --- a/src/imagekit/types/job_response.py +++ b/src/imagekit/types/folder_copy_response.py @@ -4,10 +4,10 @@ from .._models import BaseModel -__all__ = ["JobResponse"] +__all__ = ["FolderCopyResponse"] -class JobResponse(BaseModel): +class FolderCopyResponse(BaseModel): job_id: str = FieldInfo(alias="jobId") """Unique identifier of the bulk job. diff --git a/src/imagekit/types/folder_move_response.py b/src/imagekit/types/folder_move_response.py new file mode 100644 index 0000000..a2ff321 --- /dev/null +++ b/src/imagekit/types/folder_move_response.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["FolderMoveResponse"] + + +class FolderMoveResponse(BaseModel): + job_id: str = FieldInfo(alias="jobId") + """Unique identifier of the bulk job. + + This can be used to check the status of the bulk job. + """ diff --git a/src/imagekit/types/folder_rename_response.py b/src/imagekit/types/folder_rename_response.py new file mode 100644 index 0000000..f6b4d37 --- /dev/null +++ b/src/imagekit/types/folder_rename_response.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["FolderRenameResponse"] + + +class FolderRenameResponse(BaseModel): + job_id: str = FieldInfo(alias="jobId") + """Unique identifier of the bulk job. + + This can be used to check the status of the bulk job. + """ diff --git a/tests/api_resources/test_folders.py b/tests/api_resources/test_folders.py index f005351..de14df0 100644 --- a/tests/api_resources/test_folders.py +++ b/tests/api_resources/test_folders.py @@ -10,9 +10,11 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type from imagekit.types import ( - JobResponse, + FolderCopyResponse, + FolderMoveResponse, FolderCreateResponse, FolderDeleteResponse, + FolderRenameResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -99,7 +101,7 @@ def test_method_copy(self, client: ImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -109,7 +111,7 @@ def test_method_copy_with_all_params(self, client: ImageKit) -> None: source_folder_path="/path/of/source/folder", include_versions=True, ) - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -122,7 +124,7 @@ def test_raw_response_copy(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -135,7 +137,7 @@ def test_streaming_response_copy(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -146,7 +148,7 @@ def test_method_move(self, client: ImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderMoveResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -159,7 +161,7 @@ def test_raw_response_move(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderMoveResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -172,7 +174,7 @@ def test_streaming_response_move(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderMoveResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -183,7 +185,7 @@ def test_method_rename(self, client: ImageKit) -> None: folder_path="/path/of/folder", new_folder_name="new-folder-name", ) - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -193,7 +195,7 @@ def test_method_rename_with_all_params(self, client: ImageKit) -> None: new_folder_name="new-folder-name", purge_cache=True, ) - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -206,7 +208,7 @@ def test_raw_response_rename(self, client: ImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -219,7 +221,7 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -307,7 +309,7 @@ async def test_method_copy(self, async_client: AsyncImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -317,7 +319,7 @@ async def test_method_copy_with_all_params(self, async_client: AsyncImageKit) -> source_folder_path="/path/of/source/folder", include_versions=True, ) - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -330,7 +332,7 @@ async def test_raw_response_copy(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -343,7 +345,7 @@ async def test_streaming_response_copy(self, async_client: AsyncImageKit) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderCopyResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -354,7 +356,7 @@ async def test_method_move(self, async_client: AsyncImageKit) -> None: destination_path="/path/of/destination/folder", source_folder_path="/path/of/source/folder", ) - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderMoveResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -367,7 +369,7 @@ async def test_raw_response_move(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderMoveResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -380,7 +382,7 @@ async def test_streaming_response_move(self, async_client: AsyncImageKit) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderMoveResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True @@ -391,7 +393,7 @@ async def test_method_rename(self, async_client: AsyncImageKit) -> None: folder_path="/path/of/folder", new_folder_name="new-folder-name", ) - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -401,7 +403,7 @@ async def test_method_rename_with_all_params(self, async_client: AsyncImageKit) new_folder_name="new-folder-name", purge_cache=True, ) - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -414,7 +416,7 @@ async def test_raw_response_rename(self, async_client: AsyncImageKit) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize @@ -427,6 +429,6 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" folder = await response.parse() - assert_matches_type(JobResponse, folder, path=["response"]) + assert_matches_type(FolderRenameResponse, folder, path=["response"]) assert cast(Any, response.is_closed) is True From 34a15ca357a7b98d7101ef61a9204e19544b80cc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 07:09:44 +0000 Subject: [PATCH 061/177] feat(api): manual updates --- .stats.yml | 4 ++-- src/imagekit/types/folders/job_get_response.py | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.stats.yml b/.stats.yml index f16eca0..5d95bc6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-6fee8f335061dc7a308b9a2712dce5a1c16c81125f71e00dba3e4759a39d7bf0.yml -openapi_spec_hash: 205e083e0ab6b49d5bc8a2e5b323610b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-e9ae4f96eddf09567444c458e190ab6f96d0f1e1aa594793466c78791330ffde.yml +openapi_spec_hash: 88836566c32f51ff2bf66404e8b8f40e config_hash: 90f5a16140d721a24bffafbc30abaf35 diff --git a/src/imagekit/types/folders/job_get_response.py b/src/imagekit/types/folders/job_get_response.py index d63f771..17a11ef 100644 --- a/src/imagekit/types/folders/job_get_response.py +++ b/src/imagekit/types/folders/job_get_response.py @@ -1,6 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional +from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -20,11 +21,8 @@ class JobGetResponse(BaseModel): API request. """ - status: Optional[str] = None - """Status of the bulk job. Possible values - `Pending`, `Completed`.""" + status: Optional[Literal["Pending", "Completed"]] = None + """Status of the bulk job.""" - type: Optional[str] = None - """Type of the bulk job. - - Possible values - `COPY_FOLDER`, `MOVE_FOLDER`, `RENAME_FOLDER`. - """ + type: Optional[Literal["COPY_FOLDER", "MOVE_FOLDER", "RENAME_FOLDER"]] = None + """Type of the bulk job.""" From e6ed2e7dab524880008bf4492a31f38e9069d47e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 07:15:13 +0000 Subject: [PATCH 062/177] feat(api): manual updates --- .stats.yml | 4 ++-- src/imagekit/types/beta/v2/file_upload_response.py | 6 ++++++ src/imagekit/types/file.py | 6 ++++++ src/imagekit/types/file_upload_response.py | 6 ++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5d95bc6..7fff3c2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-e9ae4f96eddf09567444c458e190ab6f96d0f1e1aa594793466c78791330ffde.yml -openapi_spec_hash: 88836566c32f51ff2bf66404e8b8f40e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-64e7f6a89ec59f5801a735655ff564f48bab5be2c4d8c1146a27cdab70538945.yml +openapi_spec_hash: 581fefcb95712f716fa46f84469e6655 config_hash: 90f5a16140d721a24bffafbc30abaf35 diff --git a/src/imagekit/types/beta/v2/file_upload_response.py b/src/imagekit/types/beta/v2/file_upload_response.py index 75c3109..82a4813 100644 --- a/src/imagekit/types/beta/v2/file_upload_response.py +++ b/src/imagekit/types/beta/v2/file_upload_response.py @@ -73,6 +73,12 @@ class FileUploadResponse(BaseModel): `responseFields` in API request to get the value of this field. """ + description: Optional[str] = None + """Optional text to describe the contents of the file. + + Can be set by the user or the ai-auto-description extension. + """ + duration: Optional[int] = None """The duration of the video in seconds (only for video).""" diff --git a/src/imagekit/types/file.py b/src/imagekit/types/file.py index b674d06..69b0b39 100644 --- a/src/imagekit/types/file.py +++ b/src/imagekit/types/file.py @@ -49,6 +49,12 @@ class File(BaseModel): custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) """An object with custom metadata for the file.""" + description: Optional[str] = None + """Optional text to describe the contents of the file. + + Can be set by the user or the ai-auto-description extension. + """ + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) """Unique identifier of the asset.""" diff --git a/src/imagekit/types/file_upload_response.py b/src/imagekit/types/file_upload_response.py index 094d561..02d9a29 100644 --- a/src/imagekit/types/file_upload_response.py +++ b/src/imagekit/types/file_upload_response.py @@ -73,6 +73,12 @@ class FileUploadResponse(BaseModel): `responseFields` in API request to get the value of this field. """ + description: Optional[str] = None + """Optional text to describe the contents of the file. + + Can be set by the user or the ai-auto-description extension. + """ + duration: Optional[int] = None """The duration of the video in seconds (only for video).""" From 2adcad294d6af29ca0872f980bf8c4a2ca974764 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 07:20:46 +0000 Subject: [PATCH 063/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7fff3c2..b8f03de 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-64e7f6a89ec59f5801a735655ff564f48bab5be2c4d8c1146a27cdab70538945.yml -openapi_spec_hash: 581fefcb95712f716fa46f84469e6655 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-53f7c35748f9b41bb07f888796c7417ea84e5e63ab0e9e2aa4a8d64e48713b24.yml +openapi_spec_hash: 098ce74bcff31c61870e3d0ce357814b config_hash: 90f5a16140d721a24bffafbc30abaf35 From 7a799a2d6688a921198bddc1f1466be757389923 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 07:26:11 +0000 Subject: [PATCH 064/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 14 +++++++++----- src/imagekit/resources/files/files.py | 2 +- src/imagekit/resources/files/versions.py | 2 +- src/imagekit/types/__init__.py | 3 +-- src/imagekit/types/asset_list_response.py | 4 ++-- src/imagekit/types/file_update_response.py | 2 +- src/imagekit/types/files/version_list_response.py | 2 +- src/imagekit/types/shared/__init__.py | 4 ++++ src/imagekit/types/{ => shared}/file.py | 2 +- src/imagekit/types/{ => shared}/folder.py | 2 +- tests/api_resources/files/test_versions.py | 2 +- tests/api_resources/test_files.py | 2 +- 13 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 src/imagekit/types/shared/__init__.py rename src/imagekit/types/{ => shared}/file.py (99%) rename src/imagekit/types/{ => shared}/folder.py (97%) diff --git a/.stats.yml b/.stats.yml index b8f03de..cb0d8e1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-53f7c35748f9b41bb07f888796c7417ea84e5e63ab0e9e2aa4a8d64e48713b24.yml openapi_spec_hash: 098ce74bcff31c61870e3d0ce357814b -config_hash: 90f5a16140d721a24bffafbc30abaf35 +config_hash: b8c48b915f11a452e84fafc0e851a772 diff --git a/api.md b/api.md index c66da88..d40864d 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,9 @@ +# Shared Types + +```python +from imagekit.types import File, Folder +``` + # CustomMetadataFields Types: @@ -23,8 +29,6 @@ Types: ```python from imagekit.types import ( - File, - Folder, Metadata, FileUpdateResponse, FileCopyResponse, @@ -39,7 +43,7 @@ Methods: - client.files.update(file_id, \*\*params) -> FileUpdateResponse - client.files.delete(file_id) -> None - client.files.copy(\*\*params) -> FileCopyResponse -- client.files.get(file_id) -> File +- client.files.get(file_id) -> File - client.files.move(\*\*params) -> FileMoveResponse - client.files.rename(\*\*params) -> FileRenameResponse - client.files.upload(\*\*params) -> FileUploadResponse @@ -76,8 +80,8 @@ Methods: - client.files.versions.list(file_id) -> VersionListResponse - client.files.versions.delete(version_id, \*, file_id) -> VersionDeleteResponse -- client.files.versions.get(version_id, \*, file_id) -> File -- client.files.versions.restore(version_id, \*, file_id) -> File +- client.files.versions.get(version_id, \*, file_id) -> File +- client.files.versions.restore(version_id, \*, file_id) -> File ## Metadata diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 58b4d98..1fb2e55 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -42,8 +42,8 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ...types.file import File from ..._base_client import make_request_options +from ...types.shared.file import File from ...types.file_copy_response import FileCopyResponse from ...types.file_move_response import FileMoveResponse from ...types.file_rename_response import FileRenameResponse diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py index 09b473e..5da2c7e 100644 --- a/src/imagekit/resources/files/versions.py +++ b/src/imagekit/resources/files/versions.py @@ -13,8 +13,8 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ...types.file import File from ..._base_client import make_request_options +from ...types.shared.file import File from ...types.files.version_list_response import VersionListResponse from ...types.files.version_delete_response import VersionDeleteResponse diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index e076245..6ccfc84 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -2,8 +2,7 @@ from __future__ import annotations -from .file import File as File -from .folder import Folder as Folder +from .shared import File as File, Folder as Folder from .metadata import Metadata as Metadata from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams diff --git a/src/imagekit/types/asset_list_response.py b/src/imagekit/types/asset_list_response.py index 00596e2..a9b5873 100644 --- a/src/imagekit/types/asset_list_response.py +++ b/src/imagekit/types/asset_list_response.py @@ -3,8 +3,8 @@ from typing import List, Union from typing_extensions import TypeAlias -from .file import File -from .folder import Folder +from .shared.file import File +from .shared.folder import Folder __all__ = ["AssetListResponse", "AssetListResponseItem"] diff --git a/src/imagekit/types/file_update_response.py b/src/imagekit/types/file_update_response.py index 34b9731..9f4d8c6 100644 --- a/src/imagekit/types/file_update_response.py +++ b/src/imagekit/types/file_update_response.py @@ -5,8 +5,8 @@ from pydantic import Field as FieldInfo -from .file import File from .._models import BaseModel +from .shared.file import File __all__ = ["FileUpdateResponse", "FileUpdateResponseExtensionStatus"] diff --git a/src/imagekit/types/files/version_list_response.py b/src/imagekit/types/files/version_list_response.py index 6d0c3f0..a606130 100644 --- a/src/imagekit/types/files/version_list_response.py +++ b/src/imagekit/types/files/version_list_response.py @@ -3,7 +3,7 @@ from typing import List from typing_extensions import TypeAlias -from ..file import File +from ..shared.file import File __all__ = ["VersionListResponse"] diff --git a/src/imagekit/types/shared/__init__.py b/src/imagekit/types/shared/__init__.py new file mode 100644 index 0000000..0b423b7 --- /dev/null +++ b/src/imagekit/types/shared/__init__.py @@ -0,0 +1,4 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .file import File as File +from .folder import Folder as Folder diff --git a/src/imagekit/types/file.py b/src/imagekit/types/shared/file.py similarity index 99% rename from src/imagekit/types/file.py rename to src/imagekit/types/shared/file.py index 69b0b39..3227129 100644 --- a/src/imagekit/types/file.py +++ b/src/imagekit/types/shared/file.py @@ -6,7 +6,7 @@ from pydantic import Field as FieldInfo -from .._models import BaseModel +from ..._models import BaseModel __all__ = ["File", "AITag", "VersionInfo"] diff --git a/src/imagekit/types/folder.py b/src/imagekit/types/shared/folder.py similarity index 97% rename from src/imagekit/types/folder.py rename to src/imagekit/types/shared/folder.py index 17b7287..053884b 100644 --- a/src/imagekit/types/folder.py +++ b/src/imagekit/types/shared/folder.py @@ -6,7 +6,7 @@ from pydantic import Field as FieldInfo -from .._models import BaseModel +from ..._models import BaseModel __all__ = ["Folder"] diff --git a/tests/api_resources/files/test_versions.py b/tests/api_resources/files/test_versions.py index 1d0121d..3570a9a 100644 --- a/tests/api_resources/files/test_versions.py +++ b/tests/api_resources/files/test_versions.py @@ -9,8 +9,8 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types import File from imagekit.types.files import VersionListResponse, VersionDeleteResponse +from imagekit.types.shared import File base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 94de220..a49f255 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -10,13 +10,13 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type from imagekit.types import ( - File, FileCopyResponse, FileMoveResponse, FileRenameResponse, FileUpdateResponse, FileUploadResponse, ) +from imagekit.types.shared import File base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") From 583d87dc37ddda9947206cef8dac1c783594ce39 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 07:32:40 +0000 Subject: [PATCH 065/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 14 +++++--------- src/imagekit/resources/files/files.py | 2 +- src/imagekit/resources/files/versions.py | 2 +- src/imagekit/types/__init__.py | 3 ++- src/imagekit/types/asset_list_response.py | 4 ++-- src/imagekit/types/{shared => }/file.py | 2 +- src/imagekit/types/file_update_response.py | 2 +- src/imagekit/types/files/version_list_response.py | 2 +- src/imagekit/types/{shared => }/folder.py | 2 +- src/imagekit/types/shared/__init__.py | 4 ---- tests/api_resources/files/test_versions.py | 2 +- tests/api_resources/test_files.py | 2 +- 13 files changed, 18 insertions(+), 25 deletions(-) rename src/imagekit/types/{shared => }/file.py (99%) rename src/imagekit/types/{shared => }/folder.py (97%) delete mode 100644 src/imagekit/types/shared/__init__.py diff --git a/.stats.yml b/.stats.yml index cb0d8e1..b8f03de 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-53f7c35748f9b41bb07f888796c7417ea84e5e63ab0e9e2aa4a8d64e48713b24.yml openapi_spec_hash: 098ce74bcff31c61870e3d0ce357814b -config_hash: b8c48b915f11a452e84fafc0e851a772 +config_hash: 90f5a16140d721a24bffafbc30abaf35 diff --git a/api.md b/api.md index d40864d..c66da88 100644 --- a/api.md +++ b/api.md @@ -1,9 +1,3 @@ -# Shared Types - -```python -from imagekit.types import File, Folder -``` - # CustomMetadataFields Types: @@ -29,6 +23,8 @@ Types: ```python from imagekit.types import ( + File, + Folder, Metadata, FileUpdateResponse, FileCopyResponse, @@ -43,7 +39,7 @@ Methods: - client.files.update(file_id, \*\*params) -> FileUpdateResponse - client.files.delete(file_id) -> None - client.files.copy(\*\*params) -> FileCopyResponse -- client.files.get(file_id) -> File +- client.files.get(file_id) -> File - client.files.move(\*\*params) -> FileMoveResponse - client.files.rename(\*\*params) -> FileRenameResponse - client.files.upload(\*\*params) -> FileUploadResponse @@ -80,8 +76,8 @@ Methods: - client.files.versions.list(file_id) -> VersionListResponse - client.files.versions.delete(version_id, \*, file_id) -> VersionDeleteResponse -- client.files.versions.get(version_id, \*, file_id) -> File -- client.files.versions.restore(version_id, \*, file_id) -> File +- client.files.versions.get(version_id, \*, file_id) -> File +- client.files.versions.restore(version_id, \*, file_id) -> File ## Metadata diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 1fb2e55..58b4d98 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -42,8 +42,8 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) +from ...types.file import File from ..._base_client import make_request_options -from ...types.shared.file import File from ...types.file_copy_response import FileCopyResponse from ...types.file_move_response import FileMoveResponse from ...types.file_rename_response import FileRenameResponse diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py index 5da2c7e..09b473e 100644 --- a/src/imagekit/resources/files/versions.py +++ b/src/imagekit/resources/files/versions.py @@ -13,8 +13,8 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) +from ...types.file import File from ..._base_client import make_request_options -from ...types.shared.file import File from ...types.files.version_list_response import VersionListResponse from ...types.files.version_delete_response import VersionDeleteResponse diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 6ccfc84..e076245 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -2,7 +2,8 @@ from __future__ import annotations -from .shared import File as File, Folder as Folder +from .file import File as File +from .folder import Folder as Folder from .metadata import Metadata as Metadata from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams diff --git a/src/imagekit/types/asset_list_response.py b/src/imagekit/types/asset_list_response.py index a9b5873..00596e2 100644 --- a/src/imagekit/types/asset_list_response.py +++ b/src/imagekit/types/asset_list_response.py @@ -3,8 +3,8 @@ from typing import List, Union from typing_extensions import TypeAlias -from .shared.file import File -from .shared.folder import Folder +from .file import File +from .folder import Folder __all__ = ["AssetListResponse", "AssetListResponseItem"] diff --git a/src/imagekit/types/shared/file.py b/src/imagekit/types/file.py similarity index 99% rename from src/imagekit/types/shared/file.py rename to src/imagekit/types/file.py index 3227129..69b0b39 100644 --- a/src/imagekit/types/shared/file.py +++ b/src/imagekit/types/file.py @@ -6,7 +6,7 @@ from pydantic import Field as FieldInfo -from ..._models import BaseModel +from .._models import BaseModel __all__ = ["File", "AITag", "VersionInfo"] diff --git a/src/imagekit/types/file_update_response.py b/src/imagekit/types/file_update_response.py index 9f4d8c6..34b9731 100644 --- a/src/imagekit/types/file_update_response.py +++ b/src/imagekit/types/file_update_response.py @@ -5,8 +5,8 @@ from pydantic import Field as FieldInfo +from .file import File from .._models import BaseModel -from .shared.file import File __all__ = ["FileUpdateResponse", "FileUpdateResponseExtensionStatus"] diff --git a/src/imagekit/types/files/version_list_response.py b/src/imagekit/types/files/version_list_response.py index a606130..6d0c3f0 100644 --- a/src/imagekit/types/files/version_list_response.py +++ b/src/imagekit/types/files/version_list_response.py @@ -3,7 +3,7 @@ from typing import List from typing_extensions import TypeAlias -from ..shared.file import File +from ..file import File __all__ = ["VersionListResponse"] diff --git a/src/imagekit/types/shared/folder.py b/src/imagekit/types/folder.py similarity index 97% rename from src/imagekit/types/shared/folder.py rename to src/imagekit/types/folder.py index 053884b..17b7287 100644 --- a/src/imagekit/types/shared/folder.py +++ b/src/imagekit/types/folder.py @@ -6,7 +6,7 @@ from pydantic import Field as FieldInfo -from ..._models import BaseModel +from .._models import BaseModel __all__ = ["Folder"] diff --git a/src/imagekit/types/shared/__init__.py b/src/imagekit/types/shared/__init__.py deleted file mode 100644 index 0b423b7..0000000 --- a/src/imagekit/types/shared/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .file import File as File -from .folder import Folder as Folder diff --git a/tests/api_resources/files/test_versions.py b/tests/api_resources/files/test_versions.py index 3570a9a..1d0121d 100644 --- a/tests/api_resources/files/test_versions.py +++ b/tests/api_resources/files/test_versions.py @@ -9,8 +9,8 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type +from imagekit.types import File from imagekit.types.files import VersionListResponse, VersionDeleteResponse -from imagekit.types.shared import File base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index a49f255..94de220 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -10,13 +10,13 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type from imagekit.types import ( + File, FileCopyResponse, FileMoveResponse, FileRenameResponse, FileUpdateResponse, FileUploadResponse, ) -from imagekit.types.shared import File base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") From 6e13573024093f56723f0f390aacfe38e76125d4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 07:48:43 +0000 Subject: [PATCH 066/177] feat(api): manual updates --- .stats.yml | 4 ++-- tests/api_resources/beta/v2/test_files.py | 2 ++ tests/api_resources/test_files.py | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b8f03de..82cd02a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-53f7c35748f9b41bb07f888796c7417ea84e5e63ab0e9e2aa4a8d64e48713b24.yml -openapi_spec_hash: 098ce74bcff31c61870e3d0ce357814b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-e798e75f763868cfd2babe250a0d880a651b19f9e1b9a3b567d629eea9893147.yml +openapi_spec_hash: 45341845beb1363b7dcb4050934b9cf0 config_hash: 90f5a16140d721a24bffafbc30abaf35 diff --git a/tests/api_resources/beta/v2/test_files.py b/tests/api_resources/beta/v2/test_files.py index 8efb5e8..e5757ff 100644 --- a/tests/api_resources/beta/v2/test_files.py +++ b/tests/api_resources/beta/v2/test_files.py @@ -55,6 +55,7 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: "min_confidence": 95, "name": "google-auto-tagging", }, + {"name": "ai-auto-description"}, ], folder="folder", is_private_file=True, @@ -156,6 +157,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) "min_confidence": 95, "name": "google-auto-tagging", }, + {"name": "ai-auto-description"}, ], folder="folder", is_private_file=True, diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 94de220..f639534 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -361,6 +361,7 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: "min_confidence": 95, "name": "google-auto-tagging", }, + {"name": "ai-auto-description"}, ], folder="folder", is_private_file=True, @@ -763,6 +764,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) "min_confidence": 95, "name": "google-auto-tagging", }, + {"name": "ai-auto-description"}, ], folder="folder", is_private_file=True, From dcb0b04d8cf0ba8ec4bc2d9f0b306346c434ffb4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 26 Aug 2025 03:27:36 +0000 Subject: [PATCH 067/177] chore(internal): change ci workflow machines --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 366eea7..7658728 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,7 +42,7 @@ jobs: permissions: contents: read id-token: write - runs-on: depot-ubuntu-24.04 + runs-on: ${{ github.repository == 'stainless-sdks/imagekit-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - uses: actions/checkout@v4 From 4e80f28e8fb5145e6e990622d2c59d93f801b94e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 26 Aug 2025 12:23:48 +0000 Subject: [PATCH 068/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 82cd02a..2feea33 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-e798e75f763868cfd2babe250a0d880a651b19f9e1b9a3b567d629eea9893147.yml openapi_spec_hash: 45341845beb1363b7dcb4050934b9cf0 -config_hash: 90f5a16140d721a24bffafbc30abaf35 +config_hash: d1c62fed14fedf6774ac70983dc71d68 From 23b38454bade79b4f4100f549b1f0bf71a9a216b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 04:05:19 +0000 Subject: [PATCH 069/177] fix: avoid newer type syntax --- src/imagekit/_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imagekit/_models.py b/src/imagekit/_models.py index b8387ce..92f7c10 100644 --- a/src/imagekit/_models.py +++ b/src/imagekit/_models.py @@ -304,7 +304,7 @@ def model_dump( exclude_none=exclude_none, ) - return cast(dict[str, Any], json_safe(dumped)) if mode == "json" else dumped + return cast("dict[str, Any]", json_safe(dumped)) if mode == "json" else dumped @override def model_dump_json( From aefff48f294362ed88b6893d7bc1626dfdbee023 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 04:12:40 +0000 Subject: [PATCH 070/177] chore(internal): update pyright exclude list --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index c3c06b5..354f999 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -149,6 +149,7 @@ exclude = [ "_dev", ".venv", ".nox", + ".git", ] reportImplicitOverride = true From e706d42099303f0b2a6c1da7f1f6fd3598e14d16 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 14:56:28 +0000 Subject: [PATCH 071/177] feat(api): add models back to Webhooks --- .stats.yml | 2 +- api.md | 9 +- src/imagekit/types/__init__.py | 12 +- .../types/unsafe_unwrap_webhook_event.py | 8 +- src/imagekit/types/unwrap_webhook_event.py | 8 +- ...=> video_transformation_accepted_event.py} | 4 +- ..._transformation_accepted_webhook_event1.py | 73 ------------ ...py => video_transformation_error_event.py} | 4 +- ...deo_transformation_error_webhook_event1.py | 80 -------------- ...py => video_transformation_ready_event.py} | 4 +- ...deo_transformation_ready_webhook_event1.py | 104 ------------------ 11 files changed, 21 insertions(+), 287 deletions(-) rename src/imagekit/types/{video_transformation_accepted_webhook_event.py => video_transformation_accepted_event.py} (93%) delete mode 100644 src/imagekit/types/video_transformation_accepted_webhook_event1.py rename src/imagekit/types/{video_transformation_error_webhook_event.py => video_transformation_error_event.py} (94%) delete mode 100644 src/imagekit/types/video_transformation_error_webhook_event1.py rename src/imagekit/types/{video_transformation_ready_webhook_event.py => video_transformation_ready_event.py} (95%) delete mode 100644 src/imagekit/types/video_transformation_ready_webhook_event1.py diff --git a/.stats.yml b/.stats.yml index 2feea33..aa083b7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-e798e75f763868cfd2babe250a0d880a651b19f9e1b9a3b567d629eea9893147.yml openapi_spec_hash: 45341845beb1363b7dcb4050934b9cf0 -config_hash: d1c62fed14fedf6774ac70983dc71d68 +config_hash: 128de0925828937e2ae36770e7f6029a diff --git a/api.md b/api.md index c66da88..db5cdbe 100644 --- a/api.md +++ b/api.md @@ -215,12 +215,9 @@ Types: ```python from imagekit.types import ( - VideoTransformationAcceptedWebhookEvent, - VideoTransformationReadyWebhookEvent, - VideoTransformationErrorWebhookEvent, - VideoTransformationAcceptedWebhookEvent, - VideoTransformationReadyWebhookEvent, - VideoTransformationErrorWebhookEvent, + VideoTransformationAcceptedEvent, + VideoTransformationErrorEvent, + VideoTransformationReadyEvent, UnsafeUnwrapWebhookEvent, UnwrapWebhookEvent, ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index e076245..3ec2095 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -30,19 +30,13 @@ from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse from .folder_rename_response import FolderRenameResponse as FolderRenameResponse from .unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent as UnsafeUnwrapWebhookEvent +from .video_transformation_error_event import VideoTransformationErrorEvent as VideoTransformationErrorEvent +from .video_transformation_ready_event import VideoTransformationReadyEvent as VideoTransformationReadyEvent from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams from .custom_metadata_field_list_response import CustomMetadataFieldListResponse as CustomMetadataFieldListResponse from .custom_metadata_field_update_params import CustomMetadataFieldUpdateParams as CustomMetadataFieldUpdateParams +from .video_transformation_accepted_event import VideoTransformationAcceptedEvent as VideoTransformationAcceptedEvent from .custom_metadata_field_delete_response import ( CustomMetadataFieldDeleteResponse as CustomMetadataFieldDeleteResponse, ) -from .video_transformation_error_webhook_event import ( - VideoTransformationErrorWebhookEvent as VideoTransformationErrorWebhookEvent, -) -from .video_transformation_ready_webhook_event import ( - VideoTransformationReadyWebhookEvent as VideoTransformationReadyWebhookEvent, -) -from .video_transformation_accepted_webhook_event import ( - VideoTransformationAcceptedWebhookEvent as VideoTransformationAcceptedWebhookEvent, -) diff --git a/src/imagekit/types/unsafe_unwrap_webhook_event.py b/src/imagekit/types/unsafe_unwrap_webhook_event.py index eb7cc05..89566bf 100644 --- a/src/imagekit/types/unsafe_unwrap_webhook_event.py +++ b/src/imagekit/types/unsafe_unwrap_webhook_event.py @@ -3,12 +3,12 @@ from typing import Union from typing_extensions import TypeAlias -from .video_transformation_error_webhook_event import VideoTransformationErrorWebhookEvent -from .video_transformation_ready_webhook_event import VideoTransformationReadyWebhookEvent -from .video_transformation_accepted_webhook_event import VideoTransformationAcceptedWebhookEvent +from .video_transformation_error_event import VideoTransformationErrorEvent +from .video_transformation_ready_event import VideoTransformationReadyEvent +from .video_transformation_accepted_event import VideoTransformationAcceptedEvent __all__ = ["UnsafeUnwrapWebhookEvent"] UnsafeUnwrapWebhookEvent: TypeAlias = Union[ - VideoTransformationAcceptedWebhookEvent, VideoTransformationReadyWebhookEvent, VideoTransformationErrorWebhookEvent + VideoTransformationAcceptedEvent, VideoTransformationReadyEvent, VideoTransformationErrorEvent ] diff --git a/src/imagekit/types/unwrap_webhook_event.py b/src/imagekit/types/unwrap_webhook_event.py index b87f119..3ede6e2 100644 --- a/src/imagekit/types/unwrap_webhook_event.py +++ b/src/imagekit/types/unwrap_webhook_event.py @@ -3,12 +3,12 @@ from typing import Union from typing_extensions import TypeAlias -from .video_transformation_error_webhook_event import VideoTransformationErrorWebhookEvent -from .video_transformation_ready_webhook_event import VideoTransformationReadyWebhookEvent -from .video_transformation_accepted_webhook_event import VideoTransformationAcceptedWebhookEvent +from .video_transformation_error_event import VideoTransformationErrorEvent +from .video_transformation_ready_event import VideoTransformationReadyEvent +from .video_transformation_accepted_event import VideoTransformationAcceptedEvent __all__ = ["UnwrapWebhookEvent"] UnwrapWebhookEvent: TypeAlias = Union[ - VideoTransformationAcceptedWebhookEvent, VideoTransformationReadyWebhookEvent, VideoTransformationErrorWebhookEvent + VideoTransformationAcceptedEvent, VideoTransformationReadyEvent, VideoTransformationErrorEvent ] diff --git a/src/imagekit/types/video_transformation_accepted_webhook_event.py b/src/imagekit/types/video_transformation_accepted_event.py similarity index 93% rename from src/imagekit/types/video_transformation_accepted_webhook_event.py rename to src/imagekit/types/video_transformation_accepted_event.py index 58dc145..35683e2 100644 --- a/src/imagekit/types/video_transformation_accepted_webhook_event.py +++ b/src/imagekit/types/video_transformation_accepted_event.py @@ -7,7 +7,7 @@ from .._models import BaseModel __all__ = [ - "VideoTransformationAcceptedWebhookEvent", + "VideoTransformationAcceptedEvent", "Data", "DataAsset", "DataTransformation", @@ -60,7 +60,7 @@ class Request(BaseModel): """User-Agent header of the originating request.""" -class VideoTransformationAcceptedWebhookEvent(BaseModel): +class VideoTransformationAcceptedEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/video_transformation_accepted_webhook_event1.py b/src/imagekit/types/video_transformation_accepted_webhook_event1.py deleted file mode 100644 index 58dc145..0000000 --- a/src/imagekit/types/video_transformation_accepted_webhook_event1.py +++ /dev/null @@ -1,73 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = [ - "VideoTransformationAcceptedWebhookEvent", - "Data", - "DataAsset", - "DataTransformation", - "DataTransformationOptions", - "Request", -] - - -class DataAsset(BaseModel): - url: str - """Source asset URL.""" - - -class DataTransformationOptions(BaseModel): - audio_codec: Optional[Literal["aac", "opus"]] = None - - auto_rotate: Optional[bool] = None - - format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None - - quality: Optional[int] = None - - stream_protocol: Optional[Literal["HLS", "DASH"]] = None - - variants: Optional[List[str]] = None - - video_codec: Optional[Literal["h264", "vp9"]] = None - - -class DataTransformation(BaseModel): - type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] - - options: Optional[DataTransformationOptions] = None - - -class Data(BaseModel): - asset: DataAsset - - transformation: DataTransformation - - -class Request(BaseModel): - url: str - """URL of the submitted request.""" - - x_request_id: str - """Unique ID for the originating request.""" - - user_agent: Optional[str] = None - """User-Agent header of the originating request.""" - - -class VideoTransformationAcceptedWebhookEvent(BaseModel): - id: str - """Unique identifier for the event.""" - - created_at: datetime - - data: Data - - request: Request - - type: Literal["video.transformation.accepted"] diff --git a/src/imagekit/types/video_transformation_error_webhook_event.py b/src/imagekit/types/video_transformation_error_event.py similarity index 94% rename from src/imagekit/types/video_transformation_error_webhook_event.py rename to src/imagekit/types/video_transformation_error_event.py index ce29cc9..1060e20 100644 --- a/src/imagekit/types/video_transformation_error_webhook_event.py +++ b/src/imagekit/types/video_transformation_error_event.py @@ -7,7 +7,7 @@ from .._models import BaseModel __all__ = [ - "VideoTransformationErrorWebhookEvent", + "VideoTransformationErrorEvent", "Data", "DataAsset", "DataTransformation", @@ -67,7 +67,7 @@ class Request(BaseModel): """User-Agent header of the originating request.""" -class VideoTransformationErrorWebhookEvent(BaseModel): +class VideoTransformationErrorEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/video_transformation_error_webhook_event1.py b/src/imagekit/types/video_transformation_error_webhook_event1.py deleted file mode 100644 index ce29cc9..0000000 --- a/src/imagekit/types/video_transformation_error_webhook_event1.py +++ /dev/null @@ -1,80 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = [ - "VideoTransformationErrorWebhookEvent", - "Data", - "DataAsset", - "DataTransformation", - "DataTransformationError", - "DataTransformationOptions", - "Request", -] - - -class DataAsset(BaseModel): - url: str - """Source asset URL.""" - - -class DataTransformationError(BaseModel): - reason: Literal["encoding_failed", "download_failed", "internal_server_error"] - - -class DataTransformationOptions(BaseModel): - audio_codec: Optional[Literal["aac", "opus"]] = None - - auto_rotate: Optional[bool] = None - - format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None - - quality: Optional[int] = None - - stream_protocol: Optional[Literal["HLS", "DASH"]] = None - - variants: Optional[List[str]] = None - - video_codec: Optional[Literal["h264", "vp9"]] = None - - -class DataTransformation(BaseModel): - type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] - - error: Optional[DataTransformationError] = None - - options: Optional[DataTransformationOptions] = None - - -class Data(BaseModel): - asset: DataAsset - - transformation: DataTransformation - - -class Request(BaseModel): - url: str - """URL of the submitted request.""" - - x_request_id: str - """Unique ID for the originating request.""" - - user_agent: Optional[str] = None - """User-Agent header of the originating request.""" - - -class VideoTransformationErrorWebhookEvent(BaseModel): - id: str - """Unique identifier for the event.""" - - created_at: datetime - - data: Data - - request: Request - - type: Literal["video.transformation.error"] diff --git a/src/imagekit/types/video_transformation_ready_webhook_event.py b/src/imagekit/types/video_transformation_ready_event.py similarity index 95% rename from src/imagekit/types/video_transformation_ready_webhook_event.py rename to src/imagekit/types/video_transformation_ready_event.py index 6935733..f73cdf5 100644 --- a/src/imagekit/types/video_transformation_ready_webhook_event.py +++ b/src/imagekit/types/video_transformation_ready_event.py @@ -7,7 +7,7 @@ from .._models import BaseModel __all__ = [ - "VideoTransformationReadyWebhookEvent", + "VideoTransformationReadyEvent", "Data", "DataAsset", "DataTransformation", @@ -89,7 +89,7 @@ class Timings(BaseModel): """Milliseconds spent encoding.""" -class VideoTransformationReadyWebhookEvent(BaseModel): +class VideoTransformationReadyEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/video_transformation_ready_webhook_event1.py b/src/imagekit/types/video_transformation_ready_webhook_event1.py deleted file mode 100644 index 6935733..0000000 --- a/src/imagekit/types/video_transformation_ready_webhook_event1.py +++ /dev/null @@ -1,104 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = [ - "VideoTransformationReadyWebhookEvent", - "Data", - "DataAsset", - "DataTransformation", - "DataTransformationOptions", - "DataTransformationOutput", - "DataTransformationOutputVideoMetadata", - "Request", - "Timings", -] - - -class DataAsset(BaseModel): - url: str - """Source asset URL.""" - - -class DataTransformationOptions(BaseModel): - audio_codec: Optional[Literal["aac", "opus"]] = None - - auto_rotate: Optional[bool] = None - - format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None - - quality: Optional[int] = None - - stream_protocol: Optional[Literal["HLS", "DASH"]] = None - - variants: Optional[List[str]] = None - - video_codec: Optional[Literal["h264", "vp9"]] = None - - -class DataTransformationOutputVideoMetadata(BaseModel): - bitrate: int - - duration: float - - height: int - - width: int - - -class DataTransformationOutput(BaseModel): - url: str - - video_metadata: Optional[DataTransformationOutputVideoMetadata] = None - - -class DataTransformation(BaseModel): - type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] - - options: Optional[DataTransformationOptions] = None - - output: Optional[DataTransformationOutput] = None - - -class Data(BaseModel): - asset: DataAsset - - transformation: DataTransformation - - -class Request(BaseModel): - url: str - """URL of the submitted request.""" - - x_request_id: str - """Unique ID for the originating request.""" - - user_agent: Optional[str] = None - """User-Agent header of the originating request.""" - - -class Timings(BaseModel): - download_duration: Optional[int] = None - """Milliseconds spent downloading the source.""" - - encoding_duration: Optional[int] = None - """Milliseconds spent encoding.""" - - -class VideoTransformationReadyWebhookEvent(BaseModel): - id: str - """Unique identifier for the event.""" - - created_at: datetime - - data: Data - - request: Request - - type: Literal["video.transformation.ready"] - - timings: Optional[Timings] = None From 999ee9b013a95b3fa6b182c05f904ac02ee143b1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 04:54:15 +0000 Subject: [PATCH 072/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index aa083b7..211c282 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-e798e75f763868cfd2babe250a0d880a651b19f9e1b9a3b567d629eea9893147.yml openapi_spec_hash: 45341845beb1363b7dcb4050934b9cf0 -config_hash: 128de0925828937e2ae36770e7f6029a +config_hash: 62e43a8e96bb82f754e37a0e0c264f1e From f76b1190c7749aa0db583ac476241d02b993eb5d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 05:08:42 +0000 Subject: [PATCH 073/177] feat(api): manual updates --- .stats.yml | 6 +- api.md | 9 +- src/imagekit/resources/files/files.py | 8 +- src/imagekit/types/__init__.py | 12 +- .../types/unsafe_unwrap_webhook_event.py | 8 +- src/imagekit/types/unwrap_webhook_event.py | 8 +- ..._transformation_accepted_webhook_event.py} | 4 +- ..._transformation_accepted_webhook_event1.py | 73 ++++++++++++ ...deo_transformation_error_webhook_event.py} | 4 +- ...deo_transformation_error_webhook_event1.py | 80 ++++++++++++++ ...deo_transformation_ready_webhook_event.py} | 4 +- ...deo_transformation_ready_webhook_event1.py | 104 ++++++++++++++++++ 12 files changed, 293 insertions(+), 27 deletions(-) rename src/imagekit/types/{video_transformation_accepted_event.py => video_transformation_accepted_webhook_event.py} (93%) create mode 100644 src/imagekit/types/video_transformation_accepted_webhook_event1.py rename src/imagekit/types/{video_transformation_error_event.py => video_transformation_error_webhook_event.py} (94%) create mode 100644 src/imagekit/types/video_transformation_error_webhook_event1.py rename src/imagekit/types/{video_transformation_ready_event.py => video_transformation_ready_webhook_event.py} (95%) create mode 100644 src/imagekit/types/video_transformation_ready_webhook_event1.py diff --git a/.stats.yml b/.stats.yml index 211c282..2ec886b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-e798e75f763868cfd2babe250a0d880a651b19f9e1b9a3b567d629eea9893147.yml -openapi_spec_hash: 45341845beb1363b7dcb4050934b9cf0 -config_hash: 62e43a8e96bb82f754e37a0e0c264f1e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-863564701f791fdf016f7321fce445de5e368c474b06b135aaac16214f4f6416.yml +openapi_spec_hash: e3bb05601081de07084edf79cf3a2d63 +config_hash: 4947aef92e0f986b21a473329de4a647 diff --git a/api.md b/api.md index db5cdbe..c66da88 100644 --- a/api.md +++ b/api.md @@ -215,9 +215,12 @@ Types: ```python from imagekit.types import ( - VideoTransformationAcceptedEvent, - VideoTransformationErrorEvent, - VideoTransformationReadyEvent, + VideoTransformationAcceptedWebhookEvent, + VideoTransformationReadyWebhookEvent, + VideoTransformationErrorWebhookEvent, + VideoTransformationAcceptedWebhookEvent, + VideoTransformationReadyWebhookEvent, + VideoTransformationErrorWebhookEvent, UnsafeUnwrapWebhookEvent, UnwrapWebhookEvent, ) diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 58b4d98..7d58b56 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -412,8 +412,8 @@ def upload( """ ImageKit.io allows you to upload files directly from both the server and client sides. For server-side uploads, private API key authentication is used. For - client-side uploads, generate a one-time `token`, `signature`, and `expiration` - from your secure backend using private API. + client-side uploads, generate a one-time `token`, `signature`, and `expire` from + your secure backend using private API. [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) about how to implement client-side file upload. @@ -983,8 +983,8 @@ async def upload( """ ImageKit.io allows you to upload files directly from both the server and client sides. For server-side uploads, private API key authentication is used. For - client-side uploads, generate a one-time `token`, `signature`, and `expiration` - from your secure backend using private API. + client-side uploads, generate a one-time `token`, `signature`, and `expire` from + your secure backend using private API. [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) about how to implement client-side file upload. diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 3ec2095..e076245 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -30,13 +30,19 @@ from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse from .folder_rename_response import FolderRenameResponse as FolderRenameResponse from .unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent as UnsafeUnwrapWebhookEvent -from .video_transformation_error_event import VideoTransformationErrorEvent as VideoTransformationErrorEvent -from .video_transformation_ready_event import VideoTransformationReadyEvent as VideoTransformationReadyEvent from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams from .custom_metadata_field_list_response import CustomMetadataFieldListResponse as CustomMetadataFieldListResponse from .custom_metadata_field_update_params import CustomMetadataFieldUpdateParams as CustomMetadataFieldUpdateParams -from .video_transformation_accepted_event import VideoTransformationAcceptedEvent as VideoTransformationAcceptedEvent from .custom_metadata_field_delete_response import ( CustomMetadataFieldDeleteResponse as CustomMetadataFieldDeleteResponse, ) +from .video_transformation_error_webhook_event import ( + VideoTransformationErrorWebhookEvent as VideoTransformationErrorWebhookEvent, +) +from .video_transformation_ready_webhook_event import ( + VideoTransformationReadyWebhookEvent as VideoTransformationReadyWebhookEvent, +) +from .video_transformation_accepted_webhook_event import ( + VideoTransformationAcceptedWebhookEvent as VideoTransformationAcceptedWebhookEvent, +) diff --git a/src/imagekit/types/unsafe_unwrap_webhook_event.py b/src/imagekit/types/unsafe_unwrap_webhook_event.py index 89566bf..eb7cc05 100644 --- a/src/imagekit/types/unsafe_unwrap_webhook_event.py +++ b/src/imagekit/types/unsafe_unwrap_webhook_event.py @@ -3,12 +3,12 @@ from typing import Union from typing_extensions import TypeAlias -from .video_transformation_error_event import VideoTransformationErrorEvent -from .video_transformation_ready_event import VideoTransformationReadyEvent -from .video_transformation_accepted_event import VideoTransformationAcceptedEvent +from .video_transformation_error_webhook_event import VideoTransformationErrorWebhookEvent +from .video_transformation_ready_webhook_event import VideoTransformationReadyWebhookEvent +from .video_transformation_accepted_webhook_event import VideoTransformationAcceptedWebhookEvent __all__ = ["UnsafeUnwrapWebhookEvent"] UnsafeUnwrapWebhookEvent: TypeAlias = Union[ - VideoTransformationAcceptedEvent, VideoTransformationReadyEvent, VideoTransformationErrorEvent + VideoTransformationAcceptedWebhookEvent, VideoTransformationReadyWebhookEvent, VideoTransformationErrorWebhookEvent ] diff --git a/src/imagekit/types/unwrap_webhook_event.py b/src/imagekit/types/unwrap_webhook_event.py index 3ede6e2..b87f119 100644 --- a/src/imagekit/types/unwrap_webhook_event.py +++ b/src/imagekit/types/unwrap_webhook_event.py @@ -3,12 +3,12 @@ from typing import Union from typing_extensions import TypeAlias -from .video_transformation_error_event import VideoTransformationErrorEvent -from .video_transformation_ready_event import VideoTransformationReadyEvent -from .video_transformation_accepted_event import VideoTransformationAcceptedEvent +from .video_transformation_error_webhook_event import VideoTransformationErrorWebhookEvent +from .video_transformation_ready_webhook_event import VideoTransformationReadyWebhookEvent +from .video_transformation_accepted_webhook_event import VideoTransformationAcceptedWebhookEvent __all__ = ["UnwrapWebhookEvent"] UnwrapWebhookEvent: TypeAlias = Union[ - VideoTransformationAcceptedEvent, VideoTransformationReadyEvent, VideoTransformationErrorEvent + VideoTransformationAcceptedWebhookEvent, VideoTransformationReadyWebhookEvent, VideoTransformationErrorWebhookEvent ] diff --git a/src/imagekit/types/video_transformation_accepted_event.py b/src/imagekit/types/video_transformation_accepted_webhook_event.py similarity index 93% rename from src/imagekit/types/video_transformation_accepted_event.py rename to src/imagekit/types/video_transformation_accepted_webhook_event.py index 35683e2..58dc145 100644 --- a/src/imagekit/types/video_transformation_accepted_event.py +++ b/src/imagekit/types/video_transformation_accepted_webhook_event.py @@ -7,7 +7,7 @@ from .._models import BaseModel __all__ = [ - "VideoTransformationAcceptedEvent", + "VideoTransformationAcceptedWebhookEvent", "Data", "DataAsset", "DataTransformation", @@ -60,7 +60,7 @@ class Request(BaseModel): """User-Agent header of the originating request.""" -class VideoTransformationAcceptedEvent(BaseModel): +class VideoTransformationAcceptedWebhookEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/video_transformation_accepted_webhook_event1.py b/src/imagekit/types/video_transformation_accepted_webhook_event1.py new file mode 100644 index 0000000..58dc145 --- /dev/null +++ b/src/imagekit/types/video_transformation_accepted_webhook_event1.py @@ -0,0 +1,73 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = [ + "VideoTransformationAcceptedWebhookEvent", + "Data", + "DataAsset", + "DataTransformation", + "DataTransformationOptions", + "Request", +] + + +class DataAsset(BaseModel): + url: str + """Source asset URL.""" + + +class DataTransformationOptions(BaseModel): + audio_codec: Optional[Literal["aac", "opus"]] = None + + auto_rotate: Optional[bool] = None + + format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + + quality: Optional[int] = None + + stream_protocol: Optional[Literal["HLS", "DASH"]] = None + + variants: Optional[List[str]] = None + + video_codec: Optional[Literal["h264", "vp9"]] = None + + +class DataTransformation(BaseModel): + type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + + options: Optional[DataTransformationOptions] = None + + +class Data(BaseModel): + asset: DataAsset + + transformation: DataTransformation + + +class Request(BaseModel): + url: str + """URL of the submitted request.""" + + x_request_id: str + """Unique ID for the originating request.""" + + user_agent: Optional[str] = None + """User-Agent header of the originating request.""" + + +class VideoTransformationAcceptedWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + + data: Data + + request: Request + + type: Literal["video.transformation.accepted"] diff --git a/src/imagekit/types/video_transformation_error_event.py b/src/imagekit/types/video_transformation_error_webhook_event.py similarity index 94% rename from src/imagekit/types/video_transformation_error_event.py rename to src/imagekit/types/video_transformation_error_webhook_event.py index 1060e20..ce29cc9 100644 --- a/src/imagekit/types/video_transformation_error_event.py +++ b/src/imagekit/types/video_transformation_error_webhook_event.py @@ -7,7 +7,7 @@ from .._models import BaseModel __all__ = [ - "VideoTransformationErrorEvent", + "VideoTransformationErrorWebhookEvent", "Data", "DataAsset", "DataTransformation", @@ -67,7 +67,7 @@ class Request(BaseModel): """User-Agent header of the originating request.""" -class VideoTransformationErrorEvent(BaseModel): +class VideoTransformationErrorWebhookEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/video_transformation_error_webhook_event1.py b/src/imagekit/types/video_transformation_error_webhook_event1.py new file mode 100644 index 0000000..ce29cc9 --- /dev/null +++ b/src/imagekit/types/video_transformation_error_webhook_event1.py @@ -0,0 +1,80 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = [ + "VideoTransformationErrorWebhookEvent", + "Data", + "DataAsset", + "DataTransformation", + "DataTransformationError", + "DataTransformationOptions", + "Request", +] + + +class DataAsset(BaseModel): + url: str + """Source asset URL.""" + + +class DataTransformationError(BaseModel): + reason: Literal["encoding_failed", "download_failed", "internal_server_error"] + + +class DataTransformationOptions(BaseModel): + audio_codec: Optional[Literal["aac", "opus"]] = None + + auto_rotate: Optional[bool] = None + + format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + + quality: Optional[int] = None + + stream_protocol: Optional[Literal["HLS", "DASH"]] = None + + variants: Optional[List[str]] = None + + video_codec: Optional[Literal["h264", "vp9"]] = None + + +class DataTransformation(BaseModel): + type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + + error: Optional[DataTransformationError] = None + + options: Optional[DataTransformationOptions] = None + + +class Data(BaseModel): + asset: DataAsset + + transformation: DataTransformation + + +class Request(BaseModel): + url: str + """URL of the submitted request.""" + + x_request_id: str + """Unique ID for the originating request.""" + + user_agent: Optional[str] = None + """User-Agent header of the originating request.""" + + +class VideoTransformationErrorWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + + data: Data + + request: Request + + type: Literal["video.transformation.error"] diff --git a/src/imagekit/types/video_transformation_ready_event.py b/src/imagekit/types/video_transformation_ready_webhook_event.py similarity index 95% rename from src/imagekit/types/video_transformation_ready_event.py rename to src/imagekit/types/video_transformation_ready_webhook_event.py index f73cdf5..6935733 100644 --- a/src/imagekit/types/video_transformation_ready_event.py +++ b/src/imagekit/types/video_transformation_ready_webhook_event.py @@ -7,7 +7,7 @@ from .._models import BaseModel __all__ = [ - "VideoTransformationReadyEvent", + "VideoTransformationReadyWebhookEvent", "Data", "DataAsset", "DataTransformation", @@ -89,7 +89,7 @@ class Timings(BaseModel): """Milliseconds spent encoding.""" -class VideoTransformationReadyEvent(BaseModel): +class VideoTransformationReadyWebhookEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/video_transformation_ready_webhook_event1.py b/src/imagekit/types/video_transformation_ready_webhook_event1.py new file mode 100644 index 0000000..6935733 --- /dev/null +++ b/src/imagekit/types/video_transformation_ready_webhook_event1.py @@ -0,0 +1,104 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = [ + "VideoTransformationReadyWebhookEvent", + "Data", + "DataAsset", + "DataTransformation", + "DataTransformationOptions", + "DataTransformationOutput", + "DataTransformationOutputVideoMetadata", + "Request", + "Timings", +] + + +class DataAsset(BaseModel): + url: str + """Source asset URL.""" + + +class DataTransformationOptions(BaseModel): + audio_codec: Optional[Literal["aac", "opus"]] = None + + auto_rotate: Optional[bool] = None + + format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + + quality: Optional[int] = None + + stream_protocol: Optional[Literal["HLS", "DASH"]] = None + + variants: Optional[List[str]] = None + + video_codec: Optional[Literal["h264", "vp9"]] = None + + +class DataTransformationOutputVideoMetadata(BaseModel): + bitrate: int + + duration: float + + height: int + + width: int + + +class DataTransformationOutput(BaseModel): + url: str + + video_metadata: Optional[DataTransformationOutputVideoMetadata] = None + + +class DataTransformation(BaseModel): + type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + + options: Optional[DataTransformationOptions] = None + + output: Optional[DataTransformationOutput] = None + + +class Data(BaseModel): + asset: DataAsset + + transformation: DataTransformation + + +class Request(BaseModel): + url: str + """URL of the submitted request.""" + + x_request_id: str + """Unique ID for the originating request.""" + + user_agent: Optional[str] = None + """User-Agent header of the originating request.""" + + +class Timings(BaseModel): + download_duration: Optional[int] = None + """Milliseconds spent downloading the source.""" + + encoding_duration: Optional[int] = None + """Milliseconds spent encoding.""" + + +class VideoTransformationReadyWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + + data: Data + + request: Request + + type: Literal["video.transformation.ready"] + + timings: Optional[Timings] = None From eacb3a87febaeefaa84fa7174cfddf026aba3414 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 05:11:03 +0000 Subject: [PATCH 074/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 9 +- src/imagekit/types/__init__.py | 12 +- .../types/unsafe_unwrap_webhook_event.py | 8 +- src/imagekit/types/unwrap_webhook_event.py | 8 +- ...=> video_transformation_accepted_event.py} | 4 +- ..._transformation_accepted_webhook_event1.py | 73 ------------ ...py => video_transformation_error_event.py} | 4 +- ...deo_transformation_error_webhook_event1.py | 80 -------------- ...py => video_transformation_ready_event.py} | 4 +- ...deo_transformation_ready_webhook_event1.py | 104 ------------------ 11 files changed, 21 insertions(+), 287 deletions(-) rename src/imagekit/types/{video_transformation_accepted_webhook_event.py => video_transformation_accepted_event.py} (93%) delete mode 100644 src/imagekit/types/video_transformation_accepted_webhook_event1.py rename src/imagekit/types/{video_transformation_error_webhook_event.py => video_transformation_error_event.py} (94%) delete mode 100644 src/imagekit/types/video_transformation_error_webhook_event1.py rename src/imagekit/types/{video_transformation_ready_webhook_event.py => video_transformation_ready_event.py} (95%) delete mode 100644 src/imagekit/types/video_transformation_ready_webhook_event1.py diff --git a/.stats.yml b/.stats.yml index 2ec886b..f8ab83a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-863564701f791fdf016f7321fce445de5e368c474b06b135aaac16214f4f6416.yml openapi_spec_hash: e3bb05601081de07084edf79cf3a2d63 -config_hash: 4947aef92e0f986b21a473329de4a647 +config_hash: d6fc50026fa9ef4b444d43c07c2c70a6 diff --git a/api.md b/api.md index c66da88..db5cdbe 100644 --- a/api.md +++ b/api.md @@ -215,12 +215,9 @@ Types: ```python from imagekit.types import ( - VideoTransformationAcceptedWebhookEvent, - VideoTransformationReadyWebhookEvent, - VideoTransformationErrorWebhookEvent, - VideoTransformationAcceptedWebhookEvent, - VideoTransformationReadyWebhookEvent, - VideoTransformationErrorWebhookEvent, + VideoTransformationAcceptedEvent, + VideoTransformationErrorEvent, + VideoTransformationReadyEvent, UnsafeUnwrapWebhookEvent, UnwrapWebhookEvent, ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index e076245..3ec2095 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -30,19 +30,13 @@ from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse from .folder_rename_response import FolderRenameResponse as FolderRenameResponse from .unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent as UnsafeUnwrapWebhookEvent +from .video_transformation_error_event import VideoTransformationErrorEvent as VideoTransformationErrorEvent +from .video_transformation_ready_event import VideoTransformationReadyEvent as VideoTransformationReadyEvent from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams from .custom_metadata_field_list_response import CustomMetadataFieldListResponse as CustomMetadataFieldListResponse from .custom_metadata_field_update_params import CustomMetadataFieldUpdateParams as CustomMetadataFieldUpdateParams +from .video_transformation_accepted_event import VideoTransformationAcceptedEvent as VideoTransformationAcceptedEvent from .custom_metadata_field_delete_response import ( CustomMetadataFieldDeleteResponse as CustomMetadataFieldDeleteResponse, ) -from .video_transformation_error_webhook_event import ( - VideoTransformationErrorWebhookEvent as VideoTransformationErrorWebhookEvent, -) -from .video_transformation_ready_webhook_event import ( - VideoTransformationReadyWebhookEvent as VideoTransformationReadyWebhookEvent, -) -from .video_transformation_accepted_webhook_event import ( - VideoTransformationAcceptedWebhookEvent as VideoTransformationAcceptedWebhookEvent, -) diff --git a/src/imagekit/types/unsafe_unwrap_webhook_event.py b/src/imagekit/types/unsafe_unwrap_webhook_event.py index eb7cc05..89566bf 100644 --- a/src/imagekit/types/unsafe_unwrap_webhook_event.py +++ b/src/imagekit/types/unsafe_unwrap_webhook_event.py @@ -3,12 +3,12 @@ from typing import Union from typing_extensions import TypeAlias -from .video_transformation_error_webhook_event import VideoTransformationErrorWebhookEvent -from .video_transformation_ready_webhook_event import VideoTransformationReadyWebhookEvent -from .video_transformation_accepted_webhook_event import VideoTransformationAcceptedWebhookEvent +from .video_transformation_error_event import VideoTransformationErrorEvent +from .video_transformation_ready_event import VideoTransformationReadyEvent +from .video_transformation_accepted_event import VideoTransformationAcceptedEvent __all__ = ["UnsafeUnwrapWebhookEvent"] UnsafeUnwrapWebhookEvent: TypeAlias = Union[ - VideoTransformationAcceptedWebhookEvent, VideoTransformationReadyWebhookEvent, VideoTransformationErrorWebhookEvent + VideoTransformationAcceptedEvent, VideoTransformationReadyEvent, VideoTransformationErrorEvent ] diff --git a/src/imagekit/types/unwrap_webhook_event.py b/src/imagekit/types/unwrap_webhook_event.py index b87f119..3ede6e2 100644 --- a/src/imagekit/types/unwrap_webhook_event.py +++ b/src/imagekit/types/unwrap_webhook_event.py @@ -3,12 +3,12 @@ from typing import Union from typing_extensions import TypeAlias -from .video_transformation_error_webhook_event import VideoTransformationErrorWebhookEvent -from .video_transformation_ready_webhook_event import VideoTransformationReadyWebhookEvent -from .video_transformation_accepted_webhook_event import VideoTransformationAcceptedWebhookEvent +from .video_transformation_error_event import VideoTransformationErrorEvent +from .video_transformation_ready_event import VideoTransformationReadyEvent +from .video_transformation_accepted_event import VideoTransformationAcceptedEvent __all__ = ["UnwrapWebhookEvent"] UnwrapWebhookEvent: TypeAlias = Union[ - VideoTransformationAcceptedWebhookEvent, VideoTransformationReadyWebhookEvent, VideoTransformationErrorWebhookEvent + VideoTransformationAcceptedEvent, VideoTransformationReadyEvent, VideoTransformationErrorEvent ] diff --git a/src/imagekit/types/video_transformation_accepted_webhook_event.py b/src/imagekit/types/video_transformation_accepted_event.py similarity index 93% rename from src/imagekit/types/video_transformation_accepted_webhook_event.py rename to src/imagekit/types/video_transformation_accepted_event.py index 58dc145..35683e2 100644 --- a/src/imagekit/types/video_transformation_accepted_webhook_event.py +++ b/src/imagekit/types/video_transformation_accepted_event.py @@ -7,7 +7,7 @@ from .._models import BaseModel __all__ = [ - "VideoTransformationAcceptedWebhookEvent", + "VideoTransformationAcceptedEvent", "Data", "DataAsset", "DataTransformation", @@ -60,7 +60,7 @@ class Request(BaseModel): """User-Agent header of the originating request.""" -class VideoTransformationAcceptedWebhookEvent(BaseModel): +class VideoTransformationAcceptedEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/video_transformation_accepted_webhook_event1.py b/src/imagekit/types/video_transformation_accepted_webhook_event1.py deleted file mode 100644 index 58dc145..0000000 --- a/src/imagekit/types/video_transformation_accepted_webhook_event1.py +++ /dev/null @@ -1,73 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = [ - "VideoTransformationAcceptedWebhookEvent", - "Data", - "DataAsset", - "DataTransformation", - "DataTransformationOptions", - "Request", -] - - -class DataAsset(BaseModel): - url: str - """Source asset URL.""" - - -class DataTransformationOptions(BaseModel): - audio_codec: Optional[Literal["aac", "opus"]] = None - - auto_rotate: Optional[bool] = None - - format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None - - quality: Optional[int] = None - - stream_protocol: Optional[Literal["HLS", "DASH"]] = None - - variants: Optional[List[str]] = None - - video_codec: Optional[Literal["h264", "vp9"]] = None - - -class DataTransformation(BaseModel): - type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] - - options: Optional[DataTransformationOptions] = None - - -class Data(BaseModel): - asset: DataAsset - - transformation: DataTransformation - - -class Request(BaseModel): - url: str - """URL of the submitted request.""" - - x_request_id: str - """Unique ID for the originating request.""" - - user_agent: Optional[str] = None - """User-Agent header of the originating request.""" - - -class VideoTransformationAcceptedWebhookEvent(BaseModel): - id: str - """Unique identifier for the event.""" - - created_at: datetime - - data: Data - - request: Request - - type: Literal["video.transformation.accepted"] diff --git a/src/imagekit/types/video_transformation_error_webhook_event.py b/src/imagekit/types/video_transformation_error_event.py similarity index 94% rename from src/imagekit/types/video_transformation_error_webhook_event.py rename to src/imagekit/types/video_transformation_error_event.py index ce29cc9..1060e20 100644 --- a/src/imagekit/types/video_transformation_error_webhook_event.py +++ b/src/imagekit/types/video_transformation_error_event.py @@ -7,7 +7,7 @@ from .._models import BaseModel __all__ = [ - "VideoTransformationErrorWebhookEvent", + "VideoTransformationErrorEvent", "Data", "DataAsset", "DataTransformation", @@ -67,7 +67,7 @@ class Request(BaseModel): """User-Agent header of the originating request.""" -class VideoTransformationErrorWebhookEvent(BaseModel): +class VideoTransformationErrorEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/video_transformation_error_webhook_event1.py b/src/imagekit/types/video_transformation_error_webhook_event1.py deleted file mode 100644 index ce29cc9..0000000 --- a/src/imagekit/types/video_transformation_error_webhook_event1.py +++ /dev/null @@ -1,80 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = [ - "VideoTransformationErrorWebhookEvent", - "Data", - "DataAsset", - "DataTransformation", - "DataTransformationError", - "DataTransformationOptions", - "Request", -] - - -class DataAsset(BaseModel): - url: str - """Source asset URL.""" - - -class DataTransformationError(BaseModel): - reason: Literal["encoding_failed", "download_failed", "internal_server_error"] - - -class DataTransformationOptions(BaseModel): - audio_codec: Optional[Literal["aac", "opus"]] = None - - auto_rotate: Optional[bool] = None - - format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None - - quality: Optional[int] = None - - stream_protocol: Optional[Literal["HLS", "DASH"]] = None - - variants: Optional[List[str]] = None - - video_codec: Optional[Literal["h264", "vp9"]] = None - - -class DataTransformation(BaseModel): - type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] - - error: Optional[DataTransformationError] = None - - options: Optional[DataTransformationOptions] = None - - -class Data(BaseModel): - asset: DataAsset - - transformation: DataTransformation - - -class Request(BaseModel): - url: str - """URL of the submitted request.""" - - x_request_id: str - """Unique ID for the originating request.""" - - user_agent: Optional[str] = None - """User-Agent header of the originating request.""" - - -class VideoTransformationErrorWebhookEvent(BaseModel): - id: str - """Unique identifier for the event.""" - - created_at: datetime - - data: Data - - request: Request - - type: Literal["video.transformation.error"] diff --git a/src/imagekit/types/video_transformation_ready_webhook_event.py b/src/imagekit/types/video_transformation_ready_event.py similarity index 95% rename from src/imagekit/types/video_transformation_ready_webhook_event.py rename to src/imagekit/types/video_transformation_ready_event.py index 6935733..f73cdf5 100644 --- a/src/imagekit/types/video_transformation_ready_webhook_event.py +++ b/src/imagekit/types/video_transformation_ready_event.py @@ -7,7 +7,7 @@ from .._models import BaseModel __all__ = [ - "VideoTransformationReadyWebhookEvent", + "VideoTransformationReadyEvent", "Data", "DataAsset", "DataTransformation", @@ -89,7 +89,7 @@ class Timings(BaseModel): """Milliseconds spent encoding.""" -class VideoTransformationReadyWebhookEvent(BaseModel): +class VideoTransformationReadyEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/video_transformation_ready_webhook_event1.py b/src/imagekit/types/video_transformation_ready_webhook_event1.py deleted file mode 100644 index 6935733..0000000 --- a/src/imagekit/types/video_transformation_ready_webhook_event1.py +++ /dev/null @@ -1,104 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = [ - "VideoTransformationReadyWebhookEvent", - "Data", - "DataAsset", - "DataTransformation", - "DataTransformationOptions", - "DataTransformationOutput", - "DataTransformationOutputVideoMetadata", - "Request", - "Timings", -] - - -class DataAsset(BaseModel): - url: str - """Source asset URL.""" - - -class DataTransformationOptions(BaseModel): - audio_codec: Optional[Literal["aac", "opus"]] = None - - auto_rotate: Optional[bool] = None - - format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None - - quality: Optional[int] = None - - stream_protocol: Optional[Literal["HLS", "DASH"]] = None - - variants: Optional[List[str]] = None - - video_codec: Optional[Literal["h264", "vp9"]] = None - - -class DataTransformationOutputVideoMetadata(BaseModel): - bitrate: int - - duration: float - - height: int - - width: int - - -class DataTransformationOutput(BaseModel): - url: str - - video_metadata: Optional[DataTransformationOutputVideoMetadata] = None - - -class DataTransformation(BaseModel): - type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] - - options: Optional[DataTransformationOptions] = None - - output: Optional[DataTransformationOutput] = None - - -class Data(BaseModel): - asset: DataAsset - - transformation: DataTransformation - - -class Request(BaseModel): - url: str - """URL of the submitted request.""" - - x_request_id: str - """Unique ID for the originating request.""" - - user_agent: Optional[str] = None - """User-Agent header of the originating request.""" - - -class Timings(BaseModel): - download_duration: Optional[int] = None - """Milliseconds spent downloading the source.""" - - encoding_duration: Optional[int] = None - """Milliseconds spent encoding.""" - - -class VideoTransformationReadyWebhookEvent(BaseModel): - id: str - """Unique identifier for the event.""" - - created_at: datetime - - data: Data - - request: Request - - type: Literal["video.transformation.ready"] - - timings: Optional[Timings] = None From 249375348417c1816e244fb5e75736d5a196e9b1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 10:33:23 +0000 Subject: [PATCH 075/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f8ab83a..5d98704 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-863564701f791fdf016f7321fce445de5e368c474b06b135aaac16214f4f6416.yml -openapi_spec_hash: e3bb05601081de07084edf79cf3a2d63 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-5b571c1f83e65c8209d9e4d82e89f62e958a852d1f3ccdb9e8137292079bb18f.yml +openapi_spec_hash: e67360f0b45cace9f1cbfa280982b56c config_hash: d6fc50026fa9ef4b444d43c07c2c70a6 From de7c5272e5147dbfa19ee6c3d7d305967c9d4ccc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 10:41:47 +0000 Subject: [PATCH 076/177] feat(api): manual updates --- .stats.yml | 6 +- api.md | 23 ++ src/imagekit/types/__init__.py | 31 ++ src/imagekit/types/shared/__init__.py | 18 + src/imagekit/types/shared/base_overlay.py | 24 ++ src/imagekit/types/shared/image_overlay.py | 45 +++ src/imagekit/types/shared/overlay.py | 31 ++ src/imagekit/types/shared/overlay_position.py | 41 +++ src/imagekit/types/shared/overlay_timing.py | 43 +++ .../types/shared/solid_color_overlay.py | 37 ++ .../solid_color_overlay_transformation.py | 37 ++ src/imagekit/types/shared/src_options.py | 58 ++++ .../types/shared/streaming_resolution.py | 7 + src/imagekit/types/shared/subtitle_overlay.py | 38 ++ .../shared/subtitle_overlay_transformation.py | 40 +++ src/imagekit/types/shared/text_overlay.py | 41 +++ .../shared/text_overlay_transformation.py | 95 +++++ src/imagekit/types/shared/transformation.py | 324 ++++++++++++++++++ .../types/shared/transformation_position.py | 7 + src/imagekit/types/shared/video_overlay.py | 45 +++ 20 files changed, 988 insertions(+), 3 deletions(-) create mode 100644 src/imagekit/types/shared/__init__.py create mode 100644 src/imagekit/types/shared/base_overlay.py create mode 100644 src/imagekit/types/shared/image_overlay.py create mode 100644 src/imagekit/types/shared/overlay.py create mode 100644 src/imagekit/types/shared/overlay_position.py create mode 100644 src/imagekit/types/shared/overlay_timing.py create mode 100644 src/imagekit/types/shared/solid_color_overlay.py create mode 100644 src/imagekit/types/shared/solid_color_overlay_transformation.py create mode 100644 src/imagekit/types/shared/src_options.py create mode 100644 src/imagekit/types/shared/streaming_resolution.py create mode 100644 src/imagekit/types/shared/subtitle_overlay.py create mode 100644 src/imagekit/types/shared/subtitle_overlay_transformation.py create mode 100644 src/imagekit/types/shared/text_overlay.py create mode 100644 src/imagekit/types/shared/text_overlay_transformation.py create mode 100644 src/imagekit/types/shared/transformation.py create mode 100644 src/imagekit/types/shared/transformation_position.py create mode 100644 src/imagekit/types/shared/video_overlay.py diff --git a/.stats.yml b/.stats.yml index 5d98704..64418ba 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-5b571c1f83e65c8209d9e4d82e89f62e958a852d1f3ccdb9e8137292079bb18f.yml -openapi_spec_hash: e67360f0b45cace9f1cbfa280982b56c -config_hash: d6fc50026fa9ef4b444d43c07c2c70a6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-f3bff3868f6fb17535ab409692a079b9187de5922d7f04578082ea44680d28db.yml +openapi_spec_hash: 00e12ee294dedaf7afab030d42178bf2 +config_hash: 1dd1a96eff228aa2567b9973c36f5593 diff --git a/api.md b/api.md index db5cdbe..f8d9403 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,26 @@ +# Shared Types + +```python +from imagekit.types import ( + BaseOverlay, + ImageOverlay, + Overlay, + OverlayPosition, + OverlayTiming, + SolidColorOverlay, + SolidColorOverlayTransformation, + SrcOptions, + StreamingResolution, + SubtitleOverlay, + SubtitleOverlayTransformation, + TextOverlay, + TextOverlayTransformation, + Transformation, + TransformationPosition, + VideoOverlay, +) +``` + # CustomMetadataFields Types: diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 3ec2095..b19183e 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -2,8 +2,28 @@ from __future__ import annotations +from . import shared +from .. import _compat from .file import File as File from .folder import Folder as Folder +from .shared import ( + Overlay as Overlay, + SrcOptions as SrcOptions, + BaseOverlay as BaseOverlay, + TextOverlay as TextOverlay, + ImageOverlay as ImageOverlay, + VideoOverlay as VideoOverlay, + OverlayTiming as OverlayTiming, + Transformation as Transformation, + OverlayPosition as OverlayPosition, + SubtitleOverlay as SubtitleOverlay, + SolidColorOverlay as SolidColorOverlay, + StreamingResolution as StreamingResolution, + TransformationPosition as TransformationPosition, + TextOverlayTransformation as TextOverlayTransformation, + SubtitleOverlayTransformation as SubtitleOverlayTransformation, + SolidColorOverlayTransformation as SolidColorOverlayTransformation, +) from .metadata import Metadata as Metadata from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams @@ -40,3 +60,14 @@ from .custom_metadata_field_delete_response import ( CustomMetadataFieldDeleteResponse as CustomMetadataFieldDeleteResponse, ) + +# Rebuild cyclical models only after all modules are imported. +# This ensures that, when building the deferred (due to cyclical references) model schema, +# Pydantic can resolve the necessary references. +# See: https://github.com/pydantic/pydantic/issues/11250 for more context. +if _compat.PYDANTIC_V2: + shared.src_options.SrcOptions.model_rebuild(_parent_namespace_depth=0) + shared.transformation.Transformation.model_rebuild(_parent_namespace_depth=0) +else: + shared.src_options.SrcOptions.update_forward_refs() # type: ignore + shared.transformation.Transformation.update_forward_refs() # type: ignore diff --git a/src/imagekit/types/shared/__init__.py b/src/imagekit/types/shared/__init__.py new file mode 100644 index 0000000..794a18b --- /dev/null +++ b/src/imagekit/types/shared/__init__.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .overlay import Overlay as Overlay +from .src_options import SrcOptions as SrcOptions +from .base_overlay import BaseOverlay as BaseOverlay +from .text_overlay import TextOverlay as TextOverlay +from .image_overlay import ImageOverlay as ImageOverlay +from .video_overlay import VideoOverlay as VideoOverlay +from .overlay_timing import OverlayTiming as OverlayTiming +from .transformation import Transformation as Transformation +from .overlay_position import OverlayPosition as OverlayPosition +from .subtitle_overlay import SubtitleOverlay as SubtitleOverlay +from .solid_color_overlay import SolidColorOverlay as SolidColorOverlay +from .streaming_resolution import StreamingResolution as StreamingResolution +from .transformation_position import TransformationPosition as TransformationPosition +from .text_overlay_transformation import TextOverlayTransformation as TextOverlayTransformation +from .subtitle_overlay_transformation import SubtitleOverlayTransformation as SubtitleOverlayTransformation +from .solid_color_overlay_transformation import SolidColorOverlayTransformation as SolidColorOverlayTransformation diff --git a/src/imagekit/types/shared/base_overlay.py b/src/imagekit/types/shared/base_overlay.py new file mode 100644 index 0000000..ec53108 --- /dev/null +++ b/src/imagekit/types/shared/base_overlay.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import TYPE_CHECKING, Dict, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from .overlay_timing import OverlayTiming +from .overlay_position import OverlayPosition + +__all__ = ["BaseOverlay"] + + +class BaseOverlay(BaseModel): + position: Optional[OverlayPosition] = None + + timing: Optional[OverlayTiming] = None + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/image_overlay.py b/src/imagekit/types/shared/image_overlay.py new file mode 100644 index 0000000..3482c80 --- /dev/null +++ b/src/imagekit/types/shared/image_overlay.py @@ -0,0 +1,45 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Dict, List, Optional +from typing_extensions import Literal, override + +from pydantic import Field as FieldInfo + +from .base_overlay import BaseOverlay + +__all__ = ["ImageOverlay"] + + +class ImageOverlay(BaseOverlay): + input: str + """Specifies the relative path to the image used as an overlay.""" + + type: Literal["image"] + + encoding: Optional[Literal["auto", "plain", "base64"]] = None + """ + The input path can be included in the layer as either `i-{input}` or + `ie-{base64_encoded_input}`. By default, the SDK determines the appropriate + format automatically. To always use base64 encoding (`ie-{base64}`), set this + parameter to `base64`. To always use plain text (`i-{input}`), set it to + `plain`. + """ + + transformation: Optional[List["Transformation"]] = None + """Array of transformations to be applied to the overlay image. + + Supported transformations depends on the base/parent asset. + """ + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + @override + def __getattr__(self, attr: str) -> str: ... + + +from .transformation import Transformation diff --git a/src/imagekit/types/shared/overlay.py b/src/imagekit/types/shared/overlay.py new file mode 100644 index 0000000..00e685a --- /dev/null +++ b/src/imagekit/types/shared/overlay.py @@ -0,0 +1,31 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Union +from typing_extensions import Annotated, TypeAlias, TypeAliasType + +from ..._utils import PropertyInfo +from ..._compat import PYDANTIC_V2 +from .text_overlay import TextOverlay +from .subtitle_overlay import SubtitleOverlay +from .solid_color_overlay import SolidColorOverlay + +__all__ = ["Overlay"] + +if TYPE_CHECKING or PYDANTIC_V2: + Overlay = TypeAliasType( + "Overlay", + Annotated[ + Union[TextOverlay, "ImageOverlay", "VideoOverlay", SubtitleOverlay, SolidColorOverlay], + PropertyInfo(discriminator="type"), + ], + ) +else: + Overlay: TypeAlias = Annotated[ + Union[TextOverlay, "ImageOverlay", "VideoOverlay", SubtitleOverlay, SolidColorOverlay], + PropertyInfo(discriminator="type"), + ] + +from .image_overlay import ImageOverlay +from .video_overlay import VideoOverlay diff --git a/src/imagekit/types/shared/overlay_position.py b/src/imagekit/types/shared/overlay_position.py new file mode 100644 index 0000000..49b733b --- /dev/null +++ b/src/imagekit/types/shared/overlay_position.py @@ -0,0 +1,41 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import TYPE_CHECKING, Dict, Union, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["OverlayPosition"] + + +class OverlayPosition(BaseModel): + focus: Optional[ + Literal["center", "top", "left", "bottom", "right", "top_left", "top_right", "bottom_left", "bottom_right"] + ] = None + """ + Specifies the position of the overlay relative to the parent image or video. + Maps to `lfo` in the URL. + """ + + x: Union[float, str, None] = None + """ + Specifies the x-coordinate of the top-left corner of the base asset where the + overlay's top-left corner will be positioned. It also accepts arithmetic + expressions such as `bw_mul_0.4` or `bw_sub_cw`. Maps to `lx` in the URL. + """ + + y: Union[float, str, None] = None + """ + Specifies the y-coordinate of the top-left corner of the base asset where the + overlay's top-left corner will be positioned. It also accepts arithmetic + expressions such as `bh_mul_0.4` or `bh_sub_ch`. Maps to `ly` in the URL. + """ + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/overlay_timing.py b/src/imagekit/types/shared/overlay_timing.py new file mode 100644 index 0000000..4274490 --- /dev/null +++ b/src/imagekit/types/shared/overlay_timing.py @@ -0,0 +1,43 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import TYPE_CHECKING, Dict, Union + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["OverlayTiming"] + + +class OverlayTiming(BaseModel): + duration: Union[float, str, None] = None + """ + Specifies the duration (in seconds) during which the overlay should appear on + the base video. Accepts a positive number up to two decimal places (e.g., `20` + or `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. + Applies only if the base asset is a video. Maps to `ldu` in the URL. + """ + + end: Union[float, str, None] = None + """ + Specifies the end time (in seconds) for when the overlay should disappear from + the base video. If both end and duration are provided, duration is ignored. + Accepts a positive number up to two decimal places (e.g., `20` or `20.50`) and + arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. Applies only if + the base asset is a video. Maps to `leo` in the URL. + """ + + start: Union[float, str, None] = None + """ + Specifies the start time (in seconds) for when the overlay should appear on the + base video. Accepts a positive number up to two decimal places (e.g., `20` or + `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. + Applies only if the base asset is a video. Maps to `lso` in the URL. + """ + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/solid_color_overlay.py b/src/imagekit/types/shared/solid_color_overlay.py new file mode 100644 index 0000000..a213fa2 --- /dev/null +++ b/src/imagekit/types/shared/solid_color_overlay.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import TYPE_CHECKING, Dict, List, Optional +from typing_extensions import Literal, override + +from pydantic import Field as FieldInfo + +from .base_overlay import BaseOverlay +from .solid_color_overlay_transformation import SolidColorOverlayTransformation + +__all__ = ["SolidColorOverlay"] + + +class SolidColorOverlay(BaseOverlay): + color: str + """ + Specifies the color of the block using an RGB hex code (e.g., `FF0000`), an RGBA + code (e.g., `FFAABB50`), or a color name (e.g., `red`). If an 8-character value + is provided, the last two characters represent the opacity level (from `00` for + 0.00 to `99` for 0.99). + """ + + type: Literal["solidColor"] + + transformation: Optional[List[SolidColorOverlayTransformation]] = None + """Control width and height of the solid color overlay. + + Supported transformations depend on the base/parent asset. + """ + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + @override + def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/solid_color_overlay_transformation.py b/src/imagekit/types/shared/solid_color_overlay_transformation.py new file mode 100644 index 0000000..16992e0 --- /dev/null +++ b/src/imagekit/types/shared/solid_color_overlay_transformation.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import TYPE_CHECKING, Dict, Union, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["SolidColorOverlayTransformation"] + + +class SolidColorOverlayTransformation(BaseModel): + alpha: Optional[float] = None + """Alpha transparency level""" + + background: Optional[str] = None + """Background color""" + + gradient: Union[Literal[True], str, None] = None + """Gradient effect for the overlay""" + + height: Union[float, str, None] = None + """Height of the solid color overlay""" + + radius: Union[float, Literal["max"], None] = None + """Corner radius of the solid color overlay""" + + width: Union[float, str, None] = None + """Width of the solid color overlay""" + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/src_options.py b/src/imagekit/types/shared/src_options.py new file mode 100644 index 0000000..f1a0432 --- /dev/null +++ b/src/imagekit/types/shared/src_options.py @@ -0,0 +1,58 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Dict, List, Union, Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from .transformation_position import TransformationPosition + +__all__ = ["SrcOptions"] + + +class SrcOptions(BaseModel): + src: str + """Accepts a relative or absolute path of the resource. + + If a relative path is provided, it is appended to the `urlEndpoint`. If an + absolute path is provided, `urlEndpoint` is ignored. + """ + + url_endpoint: str = FieldInfo(alias="urlEndpoint") + """ + Get your urlEndpoint from the + [ImageKit dashboard](https://imagekit.io/dashboard/url-endpoints). + """ + + query_parameters: Optional[Dict[str, Union[str, float]]] = FieldInfo(alias="queryParameters", default=None) + """ + These are additional query parameters that you want to add to the final URL. + They can be any query parameters and not necessarily related to ImageKit. This + is especially useful if you want to add a versioning parameter to your URLs. + """ + + transformation: Optional[List["Transformation"]] = None + """An array of objects specifying the transformations to be applied in the URL. + + If more than one transformation is specified, they are applied in the order they + are specified as chained transformations. + """ + + transformation_position: Optional[TransformationPosition] = FieldInfo(alias="transformationPosition", default=None) + """ + By default, the transformation string is added as a query parameter in the URL, + e.g., `?tr=w-100,h-100`. If you want to add the transformation string in the + path of the URL, set this to `path`. + """ + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> str: ... + + +from .transformation import Transformation diff --git a/src/imagekit/types/shared/streaming_resolution.py b/src/imagekit/types/shared/streaming_resolution.py new file mode 100644 index 0000000..6eb3008 --- /dev/null +++ b/src/imagekit/types/shared/streaming_resolution.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["StreamingResolution"] + +StreamingResolution: TypeAlias = Literal["240", "360", "480", "720", "1080", "1440", "2160"] diff --git a/src/imagekit/types/shared/subtitle_overlay.py b/src/imagekit/types/shared/subtitle_overlay.py new file mode 100644 index 0000000..681160d --- /dev/null +++ b/src/imagekit/types/shared/subtitle_overlay.py @@ -0,0 +1,38 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import TYPE_CHECKING, Dict, List, Optional +from typing_extensions import Literal, override + +from pydantic import Field as FieldInfo + +from .base_overlay import BaseOverlay +from .subtitle_overlay_transformation import SubtitleOverlayTransformation + +__all__ = ["SubtitleOverlay"] + + +class SubtitleOverlay(BaseOverlay): + input: str + """Specifies the relative path to the subtitle file used as an overlay.""" + + type: Literal["subtitle"] + + encoding: Optional[Literal["auto", "plain", "base64"]] = None + """ + The input path can be included in the layer as either `i-{input}` or + `ie-{base64_encoded_input}`. By default, the SDK determines the appropriate + format automatically. To always use base64 encoding (`ie-{base64}`), set this + parameter to `base64`. To always use plain text (`i-{input}`), set it to + `plain`. + """ + + transformation: Optional[List[SubtitleOverlayTransformation]] = None + """Control styling of the subtitle.""" + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + @override + def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/subtitle_overlay_transformation.py b/src/imagekit/types/shared/subtitle_overlay_transformation.py new file mode 100644 index 0000000..e439d85 --- /dev/null +++ b/src/imagekit/types/shared/subtitle_overlay_transformation.py @@ -0,0 +1,40 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import TYPE_CHECKING, Dict, Union, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["SubtitleOverlayTransformation"] + + +class SubtitleOverlayTransformation(BaseModel): + background: Optional[str] = None + """Background color for subtitles""" + + color: Optional[str] = None + """Text color for subtitles""" + + font_family: Optional[str] = FieldInfo(alias="fontFamily", default=None) + """Font family for subtitles""" + + font_outline: Optional[str] = FieldInfo(alias="fontOutline", default=None) + """Font outline for subtitles""" + + font_shadow: Optional[str] = FieldInfo(alias="fontShadow", default=None) + """Font shadow for subtitles""" + + font_size: Union[float, str, None] = FieldInfo(alias="fontSize", default=None) + """Font size for subtitles""" + + typography: Optional[Literal["b", "i", "b_i"]] = None + """Typography style for subtitles""" + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/text_overlay.py b/src/imagekit/types/shared/text_overlay.py new file mode 100644 index 0000000..4200ef6 --- /dev/null +++ b/src/imagekit/types/shared/text_overlay.py @@ -0,0 +1,41 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import TYPE_CHECKING, Dict, List, Optional +from typing_extensions import Literal, override + +from pydantic import Field as FieldInfo + +from .base_overlay import BaseOverlay +from .text_overlay_transformation import TextOverlayTransformation + +__all__ = ["TextOverlay"] + + +class TextOverlay(BaseOverlay): + text: str + """Specifies the text to be displayed in the overlay. + + The SDK automatically handles special characters and encoding. + """ + + type: Literal["text"] + + encoding: Optional[Literal["auto", "plain", "base64"]] = None + """ + Text can be included in the layer as either `i-{input}` (plain text) or + `ie-{base64_encoded_input}` (base64). By default, the SDK selects the + appropriate format based on the input text. To always use base64 + (`ie-{base64}`), set this parameter to `base64`. To always use plain text + (`i-{input}`), set it to `plain`. + """ + + transformation: Optional[List[TextOverlayTransformation]] = None + """Control styling of the text overlay.""" + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + @override + def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/text_overlay_transformation.py b/src/imagekit/types/shared/text_overlay_transformation.py new file mode 100644 index 0000000..a48df3c --- /dev/null +++ b/src/imagekit/types/shared/text_overlay_transformation.py @@ -0,0 +1,95 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import TYPE_CHECKING, Dict, Union, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["TextOverlayTransformation"] + + +class TextOverlayTransformation(BaseModel): + alpha: Optional[float] = None + """Specifies the transparency level of the text overlay. + + Accepts integers from `1` to `9`. + """ + + background: Optional[str] = None + """ + Specifies the background color of the text overlay. Accepts an RGB hex code, an + RGBA code, or a color name. + """ + + flip: Optional[Literal["h", "v", "h_v", "v_h"]] = None + """Flip the text overlay horizontally, vertically, or both.""" + + font_color: Optional[str] = FieldInfo(alias="fontColor", default=None) + """Specifies the font color of the overlaid text. + + Accepts an RGB hex code (e.g., `FF0000`), an RGBA code (e.g., `FFAABB50`), or a + color name. + """ + + font_family: Optional[str] = FieldInfo(alias="fontFamily", default=None) + """Specifies the font family of the overlaid text. + + Choose from the supported fonts list or use a custom font. + """ + + font_size: Union[float, str, None] = FieldInfo(alias="fontSize", default=None) + """Specifies the font size of the overlaid text. + + Accepts a numeric value or an arithmetic expression. + """ + + inner_alignment: Optional[Literal["left", "right", "center"]] = FieldInfo(alias="innerAlignment", default=None) + """ + Specifies the inner alignment of the text when width is more than the text + length. + """ + + line_height: Union[float, str, None] = FieldInfo(alias="lineHeight", default=None) + """Specifies the line height of the text overlay.""" + + padding: Union[float, str, None] = None + """ + Specifies the padding around the overlaid text. Can be provided as a single + positive integer or multiple values separated by underscores (following CSS + shorthand order). Arithmetic expressions are also accepted. + """ + + radius: Union[float, Literal["max"], None] = None + """ + Specifies the corner radius of the text overlay. Set to `max` to achieve a + circular or oval shape. + """ + + rotation: Union[float, str, None] = None + """ + Specifies the rotation angle of the text overlay. Accepts a numeric value for + clockwise rotation or a string prefixed with "N" for counter-clockwise rotation. + """ + + typography: Optional[Literal["b", "i", "b_i"]] = None + """ + Specifies the typography style of the text. Supported values: `b` for bold, `i` + for italics, and `b_i` for bold with italics. + """ + + width: Union[float, str, None] = None + """Specifies the maximum width (in pixels) of the overlaid text. + + The text wraps automatically, and arithmetic expressions (e.g., `bw_mul_0.2` or + `bh_div_2`) are supported. Useful when used in conjunction with the + `background`. + """ + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/transformation.py b/src/imagekit/types/shared/transformation.py new file mode 100644 index 0000000..b2cf694 --- /dev/null +++ b/src/imagekit/types/shared/transformation.py @@ -0,0 +1,324 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Dict, List, Union, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from .streaming_resolution import StreamingResolution + +__all__ = ["Transformation"] + + +class Transformation(BaseModel): + ai_change_background: Optional[str] = FieldInfo(alias="aiChangeBackground", default=None) + """Uses AI to change the background. + + Provide a text prompt or a base64-encoded prompt, e.g., `prompt-snow road` or + `prompte-[urlencoded_base64_encoded_text]`. Not supported inside overlay. + """ + + ai_drop_shadow: Union[Literal[True], str, None] = FieldInfo(alias="aiDropShadow", default=None) + """ + Adds an AI-based drop shadow around a foreground object on a transparent or + removed background. Optionally, control the direction, elevation, and saturation + of the light source (e.g., `az-45` to change light direction). Pass `true` for + the default drop shadow, or provide a string for a custom drop shadow. Supported + inside overlay. + """ + + ai_remove_background: Optional[Literal[True]] = FieldInfo(alias="aiRemoveBackground", default=None) + """Applies ImageKit's in-house background removal. Supported inside overlay.""" + + ai_remove_background_external: Optional[Literal[True]] = FieldInfo(alias="aiRemoveBackgroundExternal", default=None) + """Uses third-party background removal. + + Note: It is recommended to use aiRemoveBackground, ImageKit's in-house solution, + which is more cost-effective. Supported inside overlay. + """ + + ai_retouch: Optional[Literal[True]] = FieldInfo(alias="aiRetouch", default=None) + """Performs AI-based retouching to improve faces or product shots. + + Not supported inside overlay. + """ + + ai_upscale: Optional[Literal[True]] = FieldInfo(alias="aiUpscale", default=None) + """Upscales images beyond their original dimensions using AI. + + Not supported inside overlay. + """ + + ai_variation: Optional[Literal[True]] = FieldInfo(alias="aiVariation", default=None) + """Generates a variation of an image using AI. + + This produces a new image with slight variations from the original, such as + changes in color, texture, and other visual elements, while preserving the + structure and essence of the original image. Not supported inside overlay. + """ + + aspect_ratio: Union[float, str, None] = FieldInfo(alias="aspectRatio", default=None) + """Specifies the aspect ratio for the output, e.g., "ar-4-3". + + Typically used with either width or height (but not both). For example: + aspectRatio = `4:3`, `4_3`, or an expression like `iar_div_2`. + """ + + audio_codec: Optional[Literal["aac", "opus", "none"]] = FieldInfo(alias="audioCodec", default=None) + """Specifies the audio codec, e.g., `aac`, `opus`, or `none`.""" + + background: Optional[str] = None + """ + Specifies the background to be used in conjunction with certain cropping + strategies when resizing an image. + + - A solid color: e.g., `red`, `F3F3F3`, `AAFF0010`. + - A blurred background: e.g., `blurred`, `blurred_25_N15`, etc. + - Expand the image boundaries using generative fill: `genfill`. Not supported + inside overlay. Optionally, control the background scene by passing a text + prompt: `genfill[:-prompt-${text}]` or + `genfill[:-prompte-${urlencoded_base64_encoded_text}]`. + """ + + blur: Optional[float] = None + """Specifies the Gaussian blur level. + + Accepts an integer value between 1 and 100, or an expression like `bl-10`. + """ + + border: Optional[str] = None + """Adds a border to the output media. + + Accepts a string in the format `_` (e.g., `5_FFF000` for + a 5px yellow border), or an expression like `ih_div_20_FF00FF`. + """ + + color_profile: Optional[bool] = FieldInfo(alias="colorProfile", default=None) + """Indicates whether the output image should retain the original color profile.""" + + contrast_stretch: Optional[Literal[True]] = FieldInfo(alias="contrastStretch", default=None) + """Automatically enhances the contrast of an image (contrast stretch).""" + + crop: Optional[Literal["force", "at_max", "at_max_enlarge", "at_least", "maintain_ratio"]] = None + """Crop modes for image resizing""" + + crop_mode: Optional[Literal["pad_resize", "extract", "pad_extract"]] = FieldInfo(alias="cropMode", default=None) + """Additional crop modes for image resizing""" + + default_image: Optional[str] = FieldInfo(alias="defaultImage", default=None) + """ + Specifies a fallback image if the resource is not found, e.g., a URL or file + path. + """ + + dpr: Optional[float] = None + """ + Accepts values between 0.1 and 5, or `auto` for automatic device pixel ratio + (DPR) calculation. + """ + + duration: Union[float, str, None] = None + """Specifies the duration (in seconds) for trimming videos, e.g., `5` or `10.5`. + + Typically used with startOffset to indicate the length from the start offset. + Arithmetic expressions are supported. + """ + + end_offset: Union[float, str, None] = FieldInfo(alias="endOffset", default=None) + """Specifies the end offset (in seconds) for trimming videos, e.g., `5` or `10.5`. + + Typically used with startOffset to define a time window. Arithmetic expressions + are supported. + """ + + flip: Optional[Literal["h", "v", "h_v", "v_h"]] = None + """Flips or mirrors an image either horizontally, vertically, or both. + + Acceptable values: `h` (horizontal), `v` (vertical), `h_v` (horizontal and + vertical), or `v_h`. + """ + + focus: Optional[str] = None + """ + This parameter can be used with pad resize, maintain ratio, or extract crop to + modify the padding or cropping behavior. + """ + + format: Optional[Literal["auto", "webp", "jpg", "jpeg", "png", "gif", "svg", "mp4", "webm", "avif", "orig"]] = None + """ + Specifies the output format for images or videos, e.g., `jpg`, `png`, `webp`, + `mp4`, or `auto`. You can also pass `orig` for images to return the original + format. ImageKit automatically delivers images and videos in the optimal format + based on device support unless overridden by the dashboard settings or the + format parameter. + """ + + gradient: Union[Literal[True], str, None] = None + """Creates a linear gradient with two colors. + + Pass `true` for a default gradient, or provide a string for a custom gradient. + """ + + grayscale: Optional[Literal[True]] = None + """Enables a grayscale effect for images.""" + + height: Union[float, str, None] = None + """Specifies the height of the output. + + If a value between 0 and 1 is provided, it is treated as a percentage (e.g., + `0.5` represents 50% of the original height). You can also supply arithmetic + expressions (e.g., `ih_mul_0.5`). + """ + + lossless: Optional[bool] = None + """ + Specifies whether the output image (in JPEG or PNG) should be compressed + losslessly. + """ + + metadata: Optional[bool] = None + """By default, ImageKit removes all metadata during automatic image compression. + + Set this to true to preserve metadata. + """ + + named: Optional[str] = None + """Named transformation reference""" + + opacity: Optional[float] = None + """Specifies the opacity level of the output image.""" + + original: Optional[bool] = None + """If set to true, serves the original file without applying any transformations.""" + + overlay: Optional["Overlay"] = None + """Specifies an overlay to be applied on the parent image or video. + + ImageKit supports overlays including images, text, videos, subtitles, and solid + colors. + """ + + page: Union[float, str, None] = None + """ + Extracts a specific page or frame from multi-page or layered files (PDF, PSD, + AI). For example, specify by number (e.g., `2`), a range (e.g., `3-4` for the + 2nd and 3rd layers), or by name (e.g., `name-layer-4` for a PSD layer). + """ + + progressive: Optional[bool] = None + """Specifies whether the output JPEG image should be rendered progressively. + + Progressive loading begins with a low-quality, pixelated version of the full + image, which gradually improves to provide a faster perceived load time. + """ + + quality: Optional[float] = None + """ + Specifies the quality of the output image for lossy formats such as JPEG, WebP, + and AVIF. A higher quality value results in a larger file size with better + quality, while a lower value produces a smaller file size with reduced quality. + """ + + radius: Union[float, Literal["max"], None] = None + """ + Specifies the corner radius for rounded corners (e.g., 20) or `max` for + circular/oval shapes. + """ + + raw: Optional[str] = None + """Pass any transformation not directly supported by the SDK. + + This transformation string is appended to the URL as provided. + """ + + rotation: Union[float, str, None] = None + """Specifies the rotation angle in degrees. + + Positive values rotate the image clockwise; you can also use, for example, `N40` + for counterclockwise rotation or `auto` to use the orientation specified in the + image's EXIF data. For videos, only the following values are supported: 0, 90, + 180, 270, or 360. + """ + + shadow: Union[Literal[True], str, None] = None + """Adds a shadow beneath solid objects in an image with a transparent background. + + For AI-based drop shadows, refer to aiDropShadow. Pass `true` for a default + shadow, or provide a string for a custom shadow. + """ + + sharpen: Union[Literal[True], float, None] = None + """Sharpens the input image, highlighting edges and finer details. + + Pass `true` for default sharpening, or provide a numeric value for custom + sharpening. + """ + + start_offset: Union[float, str, None] = FieldInfo(alias="startOffset", default=None) + """Specifies the start offset (in seconds) for trimming videos, e.g., `5` or + `10.5`. + + Arithmetic expressions are also supported. + """ + + streaming_resolutions: Optional[List[StreamingResolution]] = FieldInfo(alias="streamingResolutions", default=None) + """ + An array of resolutions for adaptive bitrate streaming, e.g., [`240`, `360`, + `480`, `720`, `1080`]. + """ + + trim: Union[Literal[True], float, None] = None + """Useful for images with a solid or nearly solid background and a central object. + + This parameter trims the background, leaving only the central object in the + output image. + """ + + unsharp_mask: Union[Literal[True], str, None] = FieldInfo(alias="unsharpMask", default=None) + """Applies Unsharp Masking (USM), an image sharpening technique. + + Pass `true` for a default unsharp mask, or provide a string for a custom unsharp + mask. + """ + + video_codec: Optional[Literal["h264", "vp9", "av1", "none"]] = FieldInfo(alias="videoCodec", default=None) + """Specifies the video codec, e.g., `h264`, `vp9`, `av1`, or `none`.""" + + width: Union[float, str, None] = None + """Specifies the width of the output. + + If a value between 0 and 1 is provided, it is treated as a percentage (e.g., + `0.4` represents 40% of the original width). You can also supply arithmetic + expressions (e.g., `iw_div_2`). + """ + + x: Union[float, str, None] = None + """Focus using cropped image coordinates - X coordinate""" + + x_center: Union[float, str, None] = FieldInfo(alias="xCenter", default=None) + """Focus using cropped image coordinates - X center coordinate""" + + y: Union[float, str, None] = None + """Focus using cropped image coordinates - Y coordinate""" + + y_center: Union[float, str, None] = FieldInfo(alias="yCenter", default=None) + """Focus using cropped image coordinates - Y center coordinate""" + + zoom: Optional[float] = None + """ + Accepts a numeric value that determines how much to zoom in or out of the + cropped area. It should be used in conjunction with fo-face or fo-. + """ + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> str: ... + + +from .overlay import Overlay diff --git a/src/imagekit/types/shared/transformation_position.py b/src/imagekit/types/shared/transformation_position.py new file mode 100644 index 0000000..bded9e8 --- /dev/null +++ b/src/imagekit/types/shared/transformation_position.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["TransformationPosition"] + +TransformationPosition: TypeAlias = Literal["path", "query"] diff --git a/src/imagekit/types/shared/video_overlay.py b/src/imagekit/types/shared/video_overlay.py new file mode 100644 index 0000000..f6a712b --- /dev/null +++ b/src/imagekit/types/shared/video_overlay.py @@ -0,0 +1,45 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Dict, List, Optional +from typing_extensions import Literal, override + +from pydantic import Field as FieldInfo + +from .base_overlay import BaseOverlay + +__all__ = ["VideoOverlay"] + + +class VideoOverlay(BaseOverlay): + input: str + """Specifies the relative path to the video used as an overlay.""" + + type: Literal["video"] + + encoding: Optional[Literal["auto", "plain", "base64"]] = None + """ + The input path can be included in the layer as either `i-{input}` or + `ie-{base64_encoded_input}`. By default, the SDK determines the appropriate + format automatically. To always use base64 encoding (`ie-{base64}`), set this + parameter to `base64`. To always use plain text (`i-{input}`), set it to + `plain`. + """ + + transformation: Optional[List["Transformation"]] = None + """Array of transformation to be applied to the overlay video. + + Except `streamingResolutions`, all other video transformations are supported. + """ + + __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + if TYPE_CHECKING: + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + @override + def __getattr__(self, attr: str) -> str: ... + + +from .transformation import Transformation From 2e3b7b594a96d710e15d4cda257f6c74e395120d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 10:55:38 +0000 Subject: [PATCH 077/177] feat(api): manual updates --- .stats.yml | 4 ++-- src/imagekit/types/shared/base_overlay.py | 11 +---------- src/imagekit/types/shared/image_overlay.py | 14 ++------------ src/imagekit/types/shared/overlay_position.py | 11 +---------- src/imagekit/types/shared/overlay_timing.py | 11 +---------- src/imagekit/types/shared/solid_color_overlay.py | 14 ++------------ .../shared/solid_color_overlay_transformation.py | 11 +---------- src/imagekit/types/shared/src_options.py | 11 ++--------- src/imagekit/types/shared/subtitle_overlay.py | 14 ++------------ .../shared/subtitle_overlay_transformation.py | 9 +-------- src/imagekit/types/shared/text_overlay.py | 14 ++------------ .../types/shared/text_overlay_transformation.py | 9 +-------- src/imagekit/types/shared/transformation.py | 9 +-------- src/imagekit/types/shared/video_overlay.py | 14 ++------------ 14 files changed, 21 insertions(+), 135 deletions(-) diff --git a/.stats.yml b/.stats.yml index 64418ba..67507d3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-f3bff3868f6fb17535ab409692a079b9187de5922d7f04578082ea44680d28db.yml -openapi_spec_hash: 00e12ee294dedaf7afab030d42178bf2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-81851750ac0e826623eae52a2361a85e97d1dc39cfcd47adea4b392440c897f1.yml +openapi_spec_hash: b36ee8d65b9b270168076c8d36420dc1 config_hash: 1dd1a96eff228aa2567b9973c36f5593 diff --git a/src/imagekit/types/shared/base_overlay.py b/src/imagekit/types/shared/base_overlay.py index ec53108..fa490a4 100644 --- a/src/imagekit/types/shared/base_overlay.py +++ b/src/imagekit/types/shared/base_overlay.py @@ -1,8 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, Optional - -from pydantic import Field as FieldInfo +from typing import Optional from ..._models import BaseModel from .overlay_timing import OverlayTiming @@ -15,10 +13,3 @@ class BaseOverlay(BaseModel): position: Optional[OverlayPosition] = None timing: Optional[OverlayTiming] = None - - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/image_overlay.py b/src/imagekit/types/shared/image_overlay.py index 3482c80..339cf77 100644 --- a/src/imagekit/types/shared/image_overlay.py +++ b/src/imagekit/types/shared/image_overlay.py @@ -2,10 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Dict, List, Optional -from typing_extensions import Literal, override - -from pydantic import Field as FieldInfo +from typing import List, Optional +from typing_extensions import Literal from .base_overlay import BaseOverlay @@ -33,13 +31,5 @@ class ImageOverlay(BaseOverlay): Supported transformations depends on the base/parent asset. """ - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - @override - def __getattr__(self, attr: str) -> str: ... - from .transformation import Transformation diff --git a/src/imagekit/types/shared/overlay_position.py b/src/imagekit/types/shared/overlay_position.py index 49b733b..288f9fc 100644 --- a/src/imagekit/types/shared/overlay_position.py +++ b/src/imagekit/types/shared/overlay_position.py @@ -1,10 +1,8 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, Union, Optional +from typing import Union, Optional from typing_extensions import Literal -from pydantic import Field as FieldInfo - from ..._models import BaseModel __all__ = ["OverlayPosition"] @@ -32,10 +30,3 @@ class OverlayPosition(BaseModel): overlay's top-left corner will be positioned. It also accepts arithmetic expressions such as `bh_mul_0.4` or `bh_sub_ch`. Maps to `ly` in the URL. """ - - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/overlay_timing.py b/src/imagekit/types/shared/overlay_timing.py index 4274490..f4d9c67 100644 --- a/src/imagekit/types/shared/overlay_timing.py +++ b/src/imagekit/types/shared/overlay_timing.py @@ -1,8 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, Union - -from pydantic import Field as FieldInfo +from typing import Union from ..._models import BaseModel @@ -34,10 +32,3 @@ class OverlayTiming(BaseModel): `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. Applies only if the base asset is a video. Maps to `lso` in the URL. """ - - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/solid_color_overlay.py b/src/imagekit/types/shared/solid_color_overlay.py index a213fa2..d136604 100644 --- a/src/imagekit/types/shared/solid_color_overlay.py +++ b/src/imagekit/types/shared/solid_color_overlay.py @@ -1,9 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, List, Optional -from typing_extensions import Literal, override - -from pydantic import Field as FieldInfo +from typing import List, Optional +from typing_extensions import Literal from .base_overlay import BaseOverlay from .solid_color_overlay_transformation import SolidColorOverlayTransformation @@ -27,11 +25,3 @@ class SolidColorOverlay(BaseOverlay): Supported transformations depend on the base/parent asset. """ - - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - @override - def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/solid_color_overlay_transformation.py b/src/imagekit/types/shared/solid_color_overlay_transformation.py index 16992e0..99df4c7 100644 --- a/src/imagekit/types/shared/solid_color_overlay_transformation.py +++ b/src/imagekit/types/shared/solid_color_overlay_transformation.py @@ -1,10 +1,8 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, Union, Optional +from typing import Union, Optional from typing_extensions import Literal -from pydantic import Field as FieldInfo - from ..._models import BaseModel __all__ = ["SolidColorOverlayTransformation"] @@ -28,10 +26,3 @@ class SolidColorOverlayTransformation(BaseModel): width: Union[float, str, None] = None """Width of the solid color overlay""" - - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/src_options.py b/src/imagekit/types/shared/src_options.py index f1a0432..3476dda 100644 --- a/src/imagekit/types/shared/src_options.py +++ b/src/imagekit/types/shared/src_options.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Dict, List, Union, Optional +from typing import Dict, List, Optional from pydantic import Field as FieldInfo @@ -26,7 +26,7 @@ class SrcOptions(BaseModel): [ImageKit dashboard](https://imagekit.io/dashboard/url-endpoints). """ - query_parameters: Optional[Dict[str, Union[str, float]]] = FieldInfo(alias="queryParameters", default=None) + query_parameters: Optional[Dict[str, str]] = FieldInfo(alias="queryParameters", default=None) """ These are additional query parameters that you want to add to the final URL. They can be any query parameters and not necessarily related to ImageKit. This @@ -47,12 +47,5 @@ class SrcOptions(BaseModel): path of the URL, set this to `path`. """ - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> str: ... - from .transformation import Transformation diff --git a/src/imagekit/types/shared/subtitle_overlay.py b/src/imagekit/types/shared/subtitle_overlay.py index 681160d..ad5b68f 100644 --- a/src/imagekit/types/shared/subtitle_overlay.py +++ b/src/imagekit/types/shared/subtitle_overlay.py @@ -1,9 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, List, Optional -from typing_extensions import Literal, override - -from pydantic import Field as FieldInfo +from typing import List, Optional +from typing_extensions import Literal from .base_overlay import BaseOverlay from .subtitle_overlay_transformation import SubtitleOverlayTransformation @@ -28,11 +26,3 @@ class SubtitleOverlay(BaseOverlay): transformation: Optional[List[SubtitleOverlayTransformation]] = None """Control styling of the subtitle.""" - - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - @override - def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/subtitle_overlay_transformation.py b/src/imagekit/types/shared/subtitle_overlay_transformation.py index e439d85..8bd43ee 100644 --- a/src/imagekit/types/shared/subtitle_overlay_transformation.py +++ b/src/imagekit/types/shared/subtitle_overlay_transformation.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, Union, Optional +from typing import Union, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -31,10 +31,3 @@ class SubtitleOverlayTransformation(BaseModel): typography: Optional[Literal["b", "i", "b_i"]] = None """Typography style for subtitles""" - - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/text_overlay.py b/src/imagekit/types/shared/text_overlay.py index 4200ef6..d779927 100644 --- a/src/imagekit/types/shared/text_overlay.py +++ b/src/imagekit/types/shared/text_overlay.py @@ -1,9 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, List, Optional -from typing_extensions import Literal, override - -from pydantic import Field as FieldInfo +from typing import List, Optional +from typing_extensions import Literal from .base_overlay import BaseOverlay from .text_overlay_transformation import TextOverlayTransformation @@ -31,11 +29,3 @@ class TextOverlay(BaseOverlay): transformation: Optional[List[TextOverlayTransformation]] = None """Control styling of the text overlay.""" - - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - @override - def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/text_overlay_transformation.py b/src/imagekit/types/shared/text_overlay_transformation.py index a48df3c..a09ff7c 100644 --- a/src/imagekit/types/shared/text_overlay_transformation.py +++ b/src/imagekit/types/shared/text_overlay_transformation.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, Union, Optional +from typing import Union, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -86,10 +86,3 @@ class TextOverlayTransformation(BaseModel): `bh_div_2`) are supported. Useful when used in conjunction with the `background`. """ - - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> str: ... diff --git a/src/imagekit/types/shared/transformation.py b/src/imagekit/types/shared/transformation.py index b2cf694..c3b5efa 100644 --- a/src/imagekit/types/shared/transformation.py +++ b/src/imagekit/types/shared/transformation.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Dict, List, Union, Optional +from typing import List, Union, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -313,12 +313,5 @@ class Transformation(BaseModel): cropped area. It should be used in conjunction with fo-face or fo-. """ - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> str: ... - from .overlay import Overlay diff --git a/src/imagekit/types/shared/video_overlay.py b/src/imagekit/types/shared/video_overlay.py index f6a712b..d902468 100644 --- a/src/imagekit/types/shared/video_overlay.py +++ b/src/imagekit/types/shared/video_overlay.py @@ -2,10 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Dict, List, Optional -from typing_extensions import Literal, override - -from pydantic import Field as FieldInfo +from typing import List, Optional +from typing_extensions import Literal from .base_overlay import BaseOverlay @@ -33,13 +31,5 @@ class VideoOverlay(BaseOverlay): Except `streamingResolutions`, all other video transformations are supported. """ - __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - if TYPE_CHECKING: - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - @override - def __getattr__(self, attr: str) -> str: ... - from .transformation import Transformation From 5e59104848cb0cb2dfbbb8fd350d60d59ce85962 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 22:24:40 +0000 Subject: [PATCH 078/177] chore(internal): add Sequence related utils --- src/imagekit/_types.py | 36 ++++++++++++++++++++++++++++++++- src/imagekit/_utils/__init__.py | 1 + src/imagekit/_utils/_typing.py | 5 +++++ tests/utils.py | 10 ++++++++- 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/imagekit/_types.py b/src/imagekit/_types.py index 1a4bc72..62059ad 100644 --- a/src/imagekit/_types.py +++ b/src/imagekit/_types.py @@ -13,10 +13,21 @@ Mapping, TypeVar, Callable, + Iterator, Optional, Sequence, ) -from typing_extensions import Set, Literal, Protocol, TypeAlias, TypedDict, override, runtime_checkable +from typing_extensions import ( + Set, + Literal, + Protocol, + TypeAlias, + TypedDict, + SupportsIndex, + overload, + override, + runtime_checkable, +) import httpx import pydantic @@ -217,3 +228,26 @@ class _GenericAlias(Protocol): class HttpxSendArgs(TypedDict, total=False): auth: httpx.Auth follow_redirects: bool + + +_T_co = TypeVar("_T_co", covariant=True) + + +if TYPE_CHECKING: + # This works because str.__contains__ does not accept object (either in typeshed or at runtime) + # https://github.com/hauntsaninja/useful_types/blob/5e9710f3875107d068e7679fd7fec9cfab0eff3b/useful_types/__init__.py#L285 + class SequenceNotStr(Protocol[_T_co]): + @overload + def __getitem__(self, index: SupportsIndex, /) -> _T_co: ... + @overload + def __getitem__(self, index: slice, /) -> Sequence[_T_co]: ... + def __contains__(self, value: object, /) -> bool: ... + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[_T_co]: ... + def index(self, value: Any, start: int = 0, stop: int = ..., /) -> int: ... + def count(self, value: Any, /) -> int: ... + def __reversed__(self) -> Iterator[_T_co]: ... +else: + # just point this to a normal `Sequence` at runtime to avoid having to special case + # deserializing our custom sequence type + SequenceNotStr = Sequence diff --git a/src/imagekit/_utils/__init__.py b/src/imagekit/_utils/__init__.py index d4fda26..ca547ce 100644 --- a/src/imagekit/_utils/__init__.py +++ b/src/imagekit/_utils/__init__.py @@ -38,6 +38,7 @@ extract_type_arg as extract_type_arg, is_iterable_type as is_iterable_type, is_required_type as is_required_type, + is_sequence_type as is_sequence_type, is_annotated_type as is_annotated_type, is_type_alias_type as is_type_alias_type, strip_annotated_type as strip_annotated_type, diff --git a/src/imagekit/_utils/_typing.py b/src/imagekit/_utils/_typing.py index 1bac954..845cd6b 100644 --- a/src/imagekit/_utils/_typing.py +++ b/src/imagekit/_utils/_typing.py @@ -26,6 +26,11 @@ def is_list_type(typ: type) -> bool: return (get_origin(typ) or typ) == list +def is_sequence_type(typ: type) -> bool: + origin = get_origin(typ) or typ + return origin == typing_extensions.Sequence or origin == typing.Sequence or origin == _c_abc.Sequence + + def is_iterable_type(typ: type) -> bool: """If the given type is `typing.Iterable[T]`""" origin = get_origin(typ) or typ diff --git a/tests/utils.py b/tests/utils.py index 53d5897..eed9080 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -4,7 +4,7 @@ import inspect import traceback import contextlib -from typing import Any, TypeVar, Iterator, cast +from typing import Any, TypeVar, Iterator, Sequence, cast from datetime import date, datetime from typing_extensions import Literal, get_args, get_origin, assert_type @@ -15,6 +15,7 @@ is_list_type, is_union_type, extract_type_arg, + is_sequence_type, is_annotated_type, is_type_alias_type, ) @@ -71,6 +72,13 @@ def assert_matches_type( if is_list_type(type_): return _assert_list_type(type_, value) + if is_sequence_type(type_): + assert isinstance(value, Sequence) + inner_type = get_args(type_)[0] + for entry in value: # type: ignore + assert_type(inner_type, entry) # type: ignore + return + if origin == str: assert isinstance(value, str) elif origin == int: From febb34c5f27d8a84a455f7e89e9be9a43db1967a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 30 Aug 2025 12:52:58 +0000 Subject: [PATCH 079/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 67507d3..c328b0a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-81851750ac0e826623eae52a2361a85e97d1dc39cfcd47adea4b392440c897f1.yml openapi_spec_hash: b36ee8d65b9b270168076c8d36420dc1 -config_hash: 1dd1a96eff228aa2567b9973c36f5593 +config_hash: 93458331374b86a886e325d435070b07 From 029e5bb3b751bca9a01af8e7fa1b735e8eed5f7b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 30 Aug 2025 12:59:28 +0000 Subject: [PATCH 080/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index c328b0a..57157ab 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-81851750ac0e826623eae52a2361a85e97d1dc39cfcd47adea4b392440c897f1.yml openapi_spec_hash: b36ee8d65b9b270168076c8d36420dc1 -config_hash: 93458331374b86a886e325d435070b07 +config_hash: 0388cd86c33cbbc99abfb19c4abb324f From 182e8a2d254e0e7c468449a9c39dfa0abe9f2197 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 30 Aug 2025 13:17:12 +0000 Subject: [PATCH 081/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 57157ab..9af5467 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-81851750ac0e826623eae52a2361a85e97d1dc39cfcd47adea4b392440c897f1.yml openapi_spec_hash: b36ee8d65b9b270168076c8d36420dc1 -config_hash: 0388cd86c33cbbc99abfb19c4abb324f +config_hash: 1335a5f946838eb26cf469ddf59cd223 From 2909548205f7e127ba50f5a0b21eab6d768d211c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 30 Aug 2025 13:21:39 +0000 Subject: [PATCH 082/177] feat(api): manual updates --- .stats.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9af5467..fa65ec9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-81851750ac0e826623eae52a2361a85e97d1dc39cfcd47adea4b392440c897f1.yml openapi_spec_hash: b36ee8d65b9b270168076c8d36420dc1 -config_hash: 1335a5f946838eb26cf469ddf59cd223 +config_hash: 249ee22f294858ab0971b8379f7cb519 diff --git a/README.md b/README.md index e1be54e..2ba13db 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It is generated with [Stainless](https://www.stainless.com/). ## Documentation -The REST API documentation can be found on [imagekit.io](https://imagekit.io). The full API of this library can be found in [api.md](api.md). +The REST API documentation can be found on [imagekit.io](https://imagekit.io/docs). The full API of this library can be found in [api.md](api.md). ## Installation From a8bb46c8fdd33f9a2b34330c4bb1f0b13b2a7f28 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 31 Aug 2025 08:43:35 +0000 Subject: [PATCH 083/177] feat(api): manual updates --- .stats.yml | 4 +- api.md | 8 + src/imagekit/types/__init__.py | 12 + src/imagekit/types/shared/image_overlay.py | 5 +- src/imagekit/types/shared/overlay_position.py | 8 +- .../types/shared/solid_color_overlay.py | 5 +- .../solid_color_overlay_transformation.py | 37 ++- src/imagekit/types/shared/src_options.py | 6 +- src/imagekit/types/shared/subtitle_overlay.py | 6 +- .../shared/subtitle_overlay_transformation.py | 60 ++++- src/imagekit/types/shared/text_overlay.py | 6 +- .../shared/text_overlay_transformation.py | 25 ++- src/imagekit/types/shared/transformation.py | 211 +++++++++++++----- src/imagekit/types/shared/video_overlay.py | 1 + .../types/unsafe_unwrap_webhook_event.py | 12 +- src/imagekit/types/unwrap_webhook_event.py | 12 +- ...load_post_transform_error_webhook_event.py | 75 +++++++ ...oad_post_transform_error_webhook_event1.py | 75 +++++++ ...ad_post_transform_success_webhook_event.py | 54 +++++ ...d_post_transform_success_webhook_event1.py | 54 +++++ ...pload_pre_transform_error_webhook_event.py | 49 ++++ ...load_pre_transform_error_webhook_event1.py | 49 ++++ ...oad_pre_transform_success_webhook_event.py | 203 +++++++++++++++++ ...ad_pre_transform_success_webhook_event1.py | 203 +++++++++++++++++ .../video_transformation_accepted_event.py | 27 ++- .../types/video_transformation_error_event.py | 33 ++- .../types/video_transformation_ready_event.py | 41 +++- 27 files changed, 1182 insertions(+), 99 deletions(-) create mode 100644 src/imagekit/types/upload_post_transform_error_webhook_event.py create mode 100644 src/imagekit/types/upload_post_transform_error_webhook_event1.py create mode 100644 src/imagekit/types/upload_post_transform_success_webhook_event.py create mode 100644 src/imagekit/types/upload_post_transform_success_webhook_event1.py create mode 100644 src/imagekit/types/upload_pre_transform_error_webhook_event.py create mode 100644 src/imagekit/types/upload_pre_transform_error_webhook_event1.py create mode 100644 src/imagekit/types/upload_pre_transform_success_webhook_event.py create mode 100644 src/imagekit/types/upload_pre_transform_success_webhook_event1.py diff --git a/.stats.yml b/.stats.yml index fa65ec9..caed6f5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-81851750ac0e826623eae52a2361a85e97d1dc39cfcd47adea4b392440c897f1.yml -openapi_spec_hash: b36ee8d65b9b270168076c8d36420dc1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0cdbdd05084a8219bc003a34670472f198cf91e5f6402cede2cb1094b7bfd98d.yml +openapi_spec_hash: d337c89146f41fa215560bb5aef2e4ec config_hash: 249ee22f294858ab0971b8379f7cb519 diff --git a/api.md b/api.md index f8d9403..1d64a23 100644 --- a/api.md +++ b/api.md @@ -241,6 +241,14 @@ from imagekit.types import ( VideoTransformationAcceptedEvent, VideoTransformationErrorEvent, VideoTransformationReadyEvent, + UploadPreTransformSuccessWebhookEvent, + UploadPreTransformErrorWebhookEvent, + UploadPostTransformSuccessWebhookEvent, + UploadPostTransformErrorWebhookEvent, + UploadPreTransformSuccessWebhookEvent, + UploadPreTransformErrorWebhookEvent, + UploadPostTransformSuccessWebhookEvent, + UploadPostTransformErrorWebhookEvent, UnsafeUnwrapWebhookEvent, UnwrapWebhookEvent, ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index b19183e..01aa820 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -60,6 +60,18 @@ from .custom_metadata_field_delete_response import ( CustomMetadataFieldDeleteResponse as CustomMetadataFieldDeleteResponse, ) +from .upload_pre_transform_error_webhook_event import ( + UploadPreTransformErrorWebhookEvent as UploadPreTransformErrorWebhookEvent, +) +from .upload_post_transform_error_webhook_event import ( + UploadPostTransformErrorWebhookEvent as UploadPostTransformErrorWebhookEvent, +) +from .upload_pre_transform_success_webhook_event import ( + UploadPreTransformSuccessWebhookEvent as UploadPreTransformSuccessWebhookEvent, +) +from .upload_post_transform_success_webhook_event import ( + UploadPostTransformSuccessWebhookEvent as UploadPostTransformSuccessWebhookEvent, +) # Rebuild cyclical models only after all modules are imported. # This ensures that, when building the deferred (due to cyclical references) model schema, diff --git a/src/imagekit/types/shared/image_overlay.py b/src/imagekit/types/shared/image_overlay.py index 339cf77..178864c 100644 --- a/src/imagekit/types/shared/image_overlay.py +++ b/src/imagekit/types/shared/image_overlay.py @@ -28,7 +28,10 @@ class ImageOverlay(BaseOverlay): transformation: Optional[List["Transformation"]] = None """Array of transformations to be applied to the overlay image. - Supported transformations depends on the base/parent asset. + Supported transformations depends on the base/parent asset. See overlays on + [Images](https://imagekit.io/docs/add-overlays-on-images#list-of-supported-image-transformations-in-image-layers) + and + [Videos](https://imagekit.io/docs/add-overlays-on-videos#list-of-transformations-supported-on-image-overlay). """ diff --git a/src/imagekit/types/shared/overlay_position.py b/src/imagekit/types/shared/overlay_position.py index 288f9fc..a6fe5f8 100644 --- a/src/imagekit/types/shared/overlay_position.py +++ b/src/imagekit/types/shared/overlay_position.py @@ -21,12 +21,16 @@ class OverlayPosition(BaseModel): """ Specifies the x-coordinate of the top-left corner of the base asset where the overlay's top-left corner will be positioned. It also accepts arithmetic - expressions such as `bw_mul_0.4` or `bw_sub_cw`. Maps to `lx` in the URL. + expressions such as `bw_mul_0.4` or `bw_sub_cw`. Maps to `lx` in the URL. Learn + about + [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). """ y: Union[float, str, None] = None """ Specifies the y-coordinate of the top-left corner of the base asset where the overlay's top-left corner will be positioned. It also accepts arithmetic - expressions such as `bh_mul_0.4` or `bh_sub_ch`. Maps to `ly` in the URL. + expressions such as `bh_mul_0.4` or `bh_sub_ch`. Maps to `ly` in the URL. Learn + about + [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). """ diff --git a/src/imagekit/types/shared/solid_color_overlay.py b/src/imagekit/types/shared/solid_color_overlay.py index d136604..49c11a9 100644 --- a/src/imagekit/types/shared/solid_color_overlay.py +++ b/src/imagekit/types/shared/solid_color_overlay.py @@ -23,5 +23,8 @@ class SolidColorOverlay(BaseOverlay): transformation: Optional[List[SolidColorOverlayTransformation]] = None """Control width and height of the solid color overlay. - Supported transformations depend on the base/parent asset. + Supported transformations depend on the base/parent asset. See overlays on + [Images](https://imagekit.io/docs/add-overlays-on-images#apply-transformation-on-solid-color-overlay) + and + [Videos](https://imagekit.io/docs/add-overlays-on-videos#apply-transformations-on-solid-color-block-overlay). """ diff --git a/src/imagekit/types/shared/solid_color_overlay_transformation.py b/src/imagekit/types/shared/solid_color_overlay_transformation.py index 99df4c7..4e0f173 100644 --- a/src/imagekit/types/shared/solid_color_overlay_transformation.py +++ b/src/imagekit/types/shared/solid_color_overlay_transformation.py @@ -10,19 +10,44 @@ class SolidColorOverlayTransformation(BaseModel): alpha: Optional[float] = None - """Alpha transparency level""" + """Specifies the transparency level of the solid color overlay. + + Accepts integers from `1` to `9`. + """ background: Optional[str] = None - """Background color""" + """Specifies the background color of the solid color overlay. + + Accepts an RGB hex code (e.g., `FF0000`), an RGBA code (e.g., `FFAABB50`), or a + color name. + """ gradient: Union[Literal[True], str, None] = None - """Gradient effect for the overlay""" + """Creates a linear gradient with two colors. + + Pass `true` for a default gradient, or provide a string for a custom gradient. + Only works if the base asset is an image. See + [gradient](https://imagekit.io/docs/effects-and-enhancements#gradient---e-gradient). + """ height: Union[float, str, None] = None - """Height of the solid color overlay""" + """Controls the height of the solid color overlay. + + Accepts a numeric value or an arithmetic expression. Learn about + [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + """ radius: Union[float, Literal["max"], None] = None - """Corner radius of the solid color overlay""" + """Specifies the corner radius of the solid color overlay. + + Set to `max` for circular or oval shape. See + [radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). + """ width: Union[float, str, None] = None - """Width of the solid color overlay""" + """Controls the width of the solid color overlay. + + Accepts a numeric value or an arithmetic expression (e.g., `bw_mul_0.2` or + `bh_div_2`). Learn about + [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + """ diff --git a/src/imagekit/types/shared/src_options.py b/src/imagekit/types/shared/src_options.py index 3476dda..6e30fcd 100644 --- a/src/imagekit/types/shared/src_options.py +++ b/src/imagekit/types/shared/src_options.py @@ -37,14 +37,16 @@ class SrcOptions(BaseModel): """An array of objects specifying the transformations to be applied in the URL. If more than one transformation is specified, they are applied in the order they - are specified as chained transformations. + are specified as chained transformations. See + [Chained transformations](https://imagekit.io/docs/transformations#chained-transformations). """ transformation_position: Optional[TransformationPosition] = FieldInfo(alias="transformationPosition", default=None) """ By default, the transformation string is added as a query parameter in the URL, e.g., `?tr=w-100,h-100`. If you want to add the transformation string in the - path of the URL, set this to `path`. + path of the URL, set this to `path`. Learn more in the + [Transformations guide](https://imagekit.io/docs/transformations). """ diff --git a/src/imagekit/types/shared/subtitle_overlay.py b/src/imagekit/types/shared/subtitle_overlay.py index ad5b68f..f44f3c4 100644 --- a/src/imagekit/types/shared/subtitle_overlay.py +++ b/src/imagekit/types/shared/subtitle_overlay.py @@ -25,4 +25,8 @@ class SubtitleOverlay(BaseOverlay): """ transformation: Optional[List[SubtitleOverlayTransformation]] = None - """Control styling of the subtitle.""" + """Control styling of the subtitle. + + See + [Styling subtitles](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer). + """ diff --git a/src/imagekit/types/shared/subtitle_overlay_transformation.py b/src/imagekit/types/shared/subtitle_overlay_transformation.py index 8bd43ee..fb692be 100644 --- a/src/imagekit/types/shared/subtitle_overlay_transformation.py +++ b/src/imagekit/types/shared/subtitle_overlay_transformation.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Union, Optional +from typing import Optional from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -12,22 +12,64 @@ class SubtitleOverlayTransformation(BaseModel): background: Optional[str] = None - """Background color for subtitles""" + """ + Specifies the subtitle background color using a standard color name, an RGB + color code (e.g., FF0000), or an RGBA color code (e.g., FFAABB50). + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ color: Optional[str] = None - """Text color for subtitles""" + """ + Sets the font color of the subtitle text using a standard color name, an RGB + color code (e.g., FF0000), or an RGBA color code (e.g., FFAABB50). + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ font_family: Optional[str] = FieldInfo(alias="fontFamily", default=None) - """Font family for subtitles""" + """Font family for subtitles. + + Refer to the + [supported fonts](https://imagekit.io/docs/add-overlays-on-images#supported-text-font-list). + """ font_outline: Optional[str] = FieldInfo(alias="fontOutline", default=None) - """Font outline for subtitles""" + """Sets the font outline of the subtitle text. + + Requires the outline width (an integer) and the outline color (as an RGB color + code, RGBA color code, or standard web color name) separated by an underscore. + Example: `fol-2_blue` (outline width of 2px and outline color blue), + `fol-2_A1CCDD` (outline width of 2px and outline color `#A1CCDD`) and + `fol-2_A1CCDD50` (outline width of 2px and outline color `#A1CCDD` at 50% + opacity). + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ font_shadow: Optional[str] = FieldInfo(alias="fontShadow", default=None) - """Font shadow for subtitles""" + """Sets the font shadow for the subtitle text. - font_size: Union[float, str, None] = FieldInfo(alias="fontSize", default=None) - """Font size for subtitles""" + Requires the shadow color (as an RGB color code, RGBA color code, or standard + web color name) and shadow indent (an integer) separated by an underscore. + Example: `fsh-blue_2` (shadow color blue, indent of 2px), `fsh-A1CCDD_3` (shadow + color `#A1CCDD`, indent of 3px), `fsh-A1CCDD50_3` (shadow color `#A1CCDD` at 50% + opacity, indent of 3px). + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ + + font_size: Optional[float] = FieldInfo(alias="fontSize", default=None) + """Sets the font size of subtitle text. + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ typography: Optional[Literal["b", "i", "b_i"]] = None - """Typography style for subtitles""" + """Sets the typography style of the subtitle text. + + Supports values are `b` for bold, `i` for italics, and `b_i` for bold with + italics. + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ diff --git a/src/imagekit/types/shared/text_overlay.py b/src/imagekit/types/shared/text_overlay.py index d779927..b156834 100644 --- a/src/imagekit/types/shared/text_overlay.py +++ b/src/imagekit/types/shared/text_overlay.py @@ -28,4 +28,8 @@ class TextOverlay(BaseOverlay): """ transformation: Optional[List[TextOverlayTransformation]] = None - """Control styling of the text overlay.""" + """Control styling of the text overlay. + + See + [Text overlays](https://imagekit.io/docs/add-overlays-on-images#text-overlay). + """ diff --git a/src/imagekit/types/shared/text_overlay_transformation.py b/src/imagekit/types/shared/text_overlay_transformation.py index a09ff7c..8aa0711 100644 --- a/src/imagekit/types/shared/text_overlay_transformation.py +++ b/src/imagekit/types/shared/text_overlay_transformation.py @@ -36,7 +36,10 @@ class TextOverlayTransformation(BaseModel): font_family: Optional[str] = FieldInfo(alias="fontFamily", default=None) """Specifies the font family of the overlaid text. - Choose from the supported fonts list or use a custom font. + Choose from the supported fonts list or use a custom font. See + [Supported fonts](https://imagekit.io/docs/add-overlays-on-images#supported-text-font-list) + and + [Custom font](https://imagekit.io/docs/add-overlays-on-images#change-font-family-in-text-overlay). """ font_size: Union[float, str, None] = FieldInfo(alias="fontSize", default=None) @@ -52,7 +55,12 @@ class TextOverlayTransformation(BaseModel): """ line_height: Union[float, str, None] = FieldInfo(alias="lineHeight", default=None) - """Specifies the line height of the text overlay.""" + """Specifies the line height of the text overlay. + + Accepts integer values representing line height in points. It can also accept + [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations) + such as `bw_mul_0.2`, or `bh_div_20`. + """ padding: Union[float, str, None] = None """ @@ -73,10 +81,12 @@ class TextOverlayTransformation(BaseModel): clockwise rotation or a string prefixed with "N" for counter-clockwise rotation. """ - typography: Optional[Literal["b", "i", "b_i"]] = None - """ - Specifies the typography style of the text. Supported values: `b` for bold, `i` - for italics, and `b_i` for bold with italics. + typography: Optional[str] = None + """Specifies the typography style of the text. Supported values: + + - Single styles: `b` (bold), `i` (italic), `strikethrough`. + - Combinations: Any combination separated by underscores, e.g., `b_i`, + `b_i_strikethrough`. """ width: Union[float, str, None] = None @@ -84,5 +94,6 @@ class TextOverlayTransformation(BaseModel): The text wraps automatically, and arithmetic expressions (e.g., `bw_mul_0.2` or `bh_div_2`) are supported. Useful when used in conjunction with the - `background`. + `background`. Learn about + [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). """ diff --git a/src/imagekit/types/shared/transformation.py b/src/imagekit/types/shared/transformation.py index c3b5efa..970d9e9 100644 --- a/src/imagekit/types/shared/transformation.py +++ b/src/imagekit/types/shared/transformation.py @@ -18,7 +18,8 @@ class Transformation(BaseModel): """Uses AI to change the background. Provide a text prompt or a base64-encoded prompt, e.g., `prompt-snow road` or - `prompte-[urlencoded_base64_encoded_text]`. Not supported inside overlay. + `prompte-[urlencoded_base64_encoded_text]`. Not supported inside overlay. See + [AI Change Background](https://imagekit.io/docs/ai-transformations#change-background-e-changebg). """ ai_drop_shadow: Union[Literal[True], str, None] = FieldInfo(alias="aiDropShadow", default=None) @@ -27,29 +28,45 @@ class Transformation(BaseModel): removed background. Optionally, control the direction, elevation, and saturation of the light source (e.g., `az-45` to change light direction). Pass `true` for the default drop shadow, or provide a string for a custom drop shadow. Supported - inside overlay. + inside overlay. See + [AI Drop Shadow](https://imagekit.io/docs/ai-transformations#ai-drop-shadow-e-dropshadow). + """ + + ai_edit: Optional[str] = FieldInfo(alias="aiEdit", default=None) + """Uses AI to edit images based on a text prompt. + + Provide a text prompt or a base64-encoded prompt, e.g., `prompt-snow road` or + `prompte-[urlencoded_base64_encoded_text]`. Not supported inside overlay. + See [AI Edit](https://imagekit.io/docs/ai-transformations#edit-image-e-edit). """ ai_remove_background: Optional[Literal[True]] = FieldInfo(alias="aiRemoveBackground", default=None) - """Applies ImageKit's in-house background removal. Supported inside overlay.""" + """Applies ImageKit's in-house background removal. + + Supported inside overlay. See + [AI Background Removal](https://imagekit.io/docs/ai-transformations#imagekit-background-removal-e-bgremove). + """ ai_remove_background_external: Optional[Literal[True]] = FieldInfo(alias="aiRemoveBackgroundExternal", default=None) """Uses third-party background removal. Note: It is recommended to use aiRemoveBackground, ImageKit's in-house solution, - which is more cost-effective. Supported inside overlay. + which is more cost-effective. Supported inside overlay. See + [External Background Removal](https://imagekit.io/docs/ai-transformations#background-removal-e-removedotbg). """ ai_retouch: Optional[Literal[True]] = FieldInfo(alias="aiRetouch", default=None) """Performs AI-based retouching to improve faces or product shots. - Not supported inside overlay. + Not supported inside overlay. See + [AI Retouch](https://imagekit.io/docs/ai-transformations#retouch-e-retouch). """ ai_upscale: Optional[Literal[True]] = FieldInfo(alias="aiUpscale", default=None) """Upscales images beyond their original dimensions using AI. - Not supported inside overlay. + Not supported inside overlay. See + [AI Upscale](https://imagekit.io/docs/ai-transformations#upscale-e-upscale). """ ai_variation: Optional[Literal[True]] = FieldInfo(alias="aiVariation", default=None) @@ -57,94 +74,129 @@ class Transformation(BaseModel): This produces a new image with slight variations from the original, such as changes in color, texture, and other visual elements, while preserving the - structure and essence of the original image. Not supported inside overlay. + structure and essence of the original image. Not supported inside overlay. See + [AI Generate Variations](https://imagekit.io/docs/ai-transformations#generate-variations-of-an-image-e-genvar). """ aspect_ratio: Union[float, str, None] = FieldInfo(alias="aspectRatio", default=None) """Specifies the aspect ratio for the output, e.g., "ar-4-3". Typically used with either width or height (but not both). For example: - aspectRatio = `4:3`, `4_3`, or an expression like `iar_div_2`. + aspectRatio = `4:3`, `4_3`, or an expression like `iar_div_2`. See + [Image resize and crop – Aspect ratio](https://imagekit.io/docs/image-resize-and-crop#aspect-ratio---ar). """ audio_codec: Optional[Literal["aac", "opus", "none"]] = FieldInfo(alias="audioCodec", default=None) - """Specifies the audio codec, e.g., `aac`, `opus`, or `none`.""" + """Specifies the audio codec, e.g., `aac`, `opus`, or `none`. + + See [Audio codec](https://imagekit.io/docs/video-optimization#audio-codec---ac). + """ background: Optional[str] = None """ Specifies the background to be used in conjunction with certain cropping strategies when resizing an image. - - A solid color: e.g., `red`, `F3F3F3`, `AAFF0010`. - - A blurred background: e.g., `blurred`, `blurred_25_N15`, etc. + - A solid color: e.g., `red`, `F3F3F3`, `AAFF0010`. See + [Solid color background](https://imagekit.io/docs/effects-and-enhancements#solid-color-background). + - A blurred background: e.g., `blurred`, `blurred_25_N15`, etc. See + [Blurred background](https://imagekit.io/docs/effects-and-enhancements#blurred-background). - Expand the image boundaries using generative fill: `genfill`. Not supported inside overlay. Optionally, control the background scene by passing a text prompt: `genfill[:-prompt-${text}]` or - `genfill[:-prompte-${urlencoded_base64_encoded_text}]`. + `genfill[:-prompte-${urlencoded_base64_encoded_text}]`. See + [Generative fill background](https://imagekit.io/docs/ai-transformations#generative-fill-bg-genfill). """ blur: Optional[float] = None """Specifies the Gaussian blur level. - Accepts an integer value between 1 and 100, or an expression like `bl-10`. + Accepts an integer value between 1 and 100, or an expression like `bl-10`. See + [Blur](https://imagekit.io/docs/effects-and-enhancements#blur---bl). """ border: Optional[str] = None """Adds a border to the output media. Accepts a string in the format `_` (e.g., `5_FFF000` for - a 5px yellow border), or an expression like `ih_div_20_FF00FF`. + a 5px yellow border), or an expression like `ih_div_20_FF00FF`. See + [Border](https://imagekit.io/docs/effects-and-enhancements#border---b). """ color_profile: Optional[bool] = FieldInfo(alias="colorProfile", default=None) - """Indicates whether the output image should retain the original color profile.""" + """ + Indicates whether the output image should retain the original color profile. See + [Color profile](https://imagekit.io/docs/image-optimization#color-profile---cp). + """ contrast_stretch: Optional[Literal[True]] = FieldInfo(alias="contrastStretch", default=None) - """Automatically enhances the contrast of an image (contrast stretch).""" + """ + Automatically enhances the contrast of an image (contrast stretch). See + [Contrast Stretch](https://imagekit.io/docs/effects-and-enhancements#contrast-stretch---e-contrast). + """ crop: Optional[Literal["force", "at_max", "at_max_enlarge", "at_least", "maintain_ratio"]] = None - """Crop modes for image resizing""" + """Crop modes for image resizing. + + See + [Crop modes & focus](https://imagekit.io/docs/image-resize-and-crop#crop-crop-modes--focus). + """ crop_mode: Optional[Literal["pad_resize", "extract", "pad_extract"]] = FieldInfo(alias="cropMode", default=None) - """Additional crop modes for image resizing""" + """Additional crop modes for image resizing. + + See + [Crop modes & focus](https://imagekit.io/docs/image-resize-and-crop#crop-crop-modes--focus). + """ default_image: Optional[str] = FieldInfo(alias="defaultImage", default=None) """ Specifies a fallback image if the resource is not found, e.g., a URL or file - path. + path. See + [Default image](https://imagekit.io/docs/image-transformation#default-image---di). """ dpr: Optional[float] = None """ Accepts values between 0.1 and 5, or `auto` for automatic device pixel ratio - (DPR) calculation. + (DPR) calculation. See + [DPR](https://imagekit.io/docs/image-resize-and-crop#dpr---dpr). """ duration: Union[float, str, None] = None """Specifies the duration (in seconds) for trimming videos, e.g., `5` or `10.5`. Typically used with startOffset to indicate the length from the start offset. - Arithmetic expressions are supported. + Arithmetic expressions are supported. See + [Trim videos – Duration](https://imagekit.io/docs/trim-videos#duration---du). """ end_offset: Union[float, str, None] = FieldInfo(alias="endOffset", default=None) """Specifies the end offset (in seconds) for trimming videos, e.g., `5` or `10.5`. Typically used with startOffset to define a time window. Arithmetic expressions - are supported. + are supported. See + [Trim videos – End offset](https://imagekit.io/docs/trim-videos#end-offset---eo). """ flip: Optional[Literal["h", "v", "h_v", "v_h"]] = None """Flips or mirrors an image either horizontally, vertically, or both. Acceptable values: `h` (horizontal), `v` (vertical), `h_v` (horizontal and - vertical), or `v_h`. + vertical), or `v_h`. See + [Flip](https://imagekit.io/docs/effects-and-enhancements#flip---fl). """ focus: Optional[str] = None """ - This parameter can be used with pad resize, maintain ratio, or extract crop to - modify the padding or cropping behavior. + Refines padding and cropping behavior for pad resize, maintain ratio, and + extract crop modes. Supports manual positions and coordinate-based focus. With + AI-based cropping, you can automatically keep key subjects in frame—such as + faces or detected objects (e.g., `fo-face`, `fo-person`, `fo-car`)— while + resizing. + + - See [Focus](https://imagekit.io/docs/image-resize-and-crop#focus---fo). + - [Object aware cropping](https://imagekit.io/docs/image-resize-and-crop#object-aware-cropping---fo-object-name) """ format: Optional[Literal["auto", "webp", "jpg", "jpeg", "png", "gif", "svg", "mp4", "webm", "avif", "orig"]] = None @@ -153,66 +205,92 @@ class Transformation(BaseModel): `mp4`, or `auto`. You can also pass `orig` for images to return the original format. ImageKit automatically delivers images and videos in the optimal format based on device support unless overridden by the dashboard settings or the - format parameter. + format parameter. See + [Image format](https://imagekit.io/docs/image-optimization#format---f) and + [Video format](https://imagekit.io/docs/video-optimization#format---f). """ gradient: Union[Literal[True], str, None] = None """Creates a linear gradient with two colors. Pass `true` for a default gradient, or provide a string for a custom gradient. + See + [Gradient](https://imagekit.io/docs/effects-and-enhancements#gradient---e-gradient). """ grayscale: Optional[Literal[True]] = None - """Enables a grayscale effect for images.""" + """Enables a grayscale effect for images. + + See + [Grayscale](https://imagekit.io/docs/effects-and-enhancements#grayscale---e-grayscale). + """ height: Union[float, str, None] = None """Specifies the height of the output. If a value between 0 and 1 is provided, it is treated as a percentage (e.g., `0.5` represents 50% of the original height). You can also supply arithmetic - expressions (e.g., `ih_mul_0.5`). + expressions (e.g., `ih_mul_0.5`). Height transformation – + [Images](https://imagekit.io/docs/image-resize-and-crop#height---h) · + [Videos](https://imagekit.io/docs/video-resize-and-crop#height---h) """ lossless: Optional[bool] = None """ Specifies whether the output image (in JPEG or PNG) should be compressed - losslessly. + losslessly. See + [Lossless compression](https://imagekit.io/docs/image-optimization#lossless-webp-and-png---lo). """ metadata: Optional[bool] = None """By default, ImageKit removes all metadata during automatic image compression. - Set this to true to preserve metadata. + Set this to true to preserve metadata. See + [Image metadata](https://imagekit.io/docs/image-optimization#image-metadata---md). """ named: Optional[str] = None - """Named transformation reference""" + """Named transformation reference. + + See + [Named transformations](https://imagekit.io/docs/transformations#named-transformations). + """ opacity: Optional[float] = None - """Specifies the opacity level of the output image.""" + """Specifies the opacity level of the output image. + + See [Opacity](https://imagekit.io/docs/effects-and-enhancements#opacity---o). + """ original: Optional[bool] = None - """If set to true, serves the original file without applying any transformations.""" + """ + If set to true, serves the original file without applying any transformations. + See + [Deliver original file as-is](https://imagekit.io/docs/core-delivery-features#deliver-original-file-as-is---orig-true). + """ overlay: Optional["Overlay"] = None """Specifies an overlay to be applied on the parent image or video. ImageKit supports overlays including images, text, videos, subtitles, and solid - colors. + colors. See + [Overlay using layers](https://imagekit.io/docs/transformations#overlay-using-layers). """ page: Union[float, str, None] = None """ Extracts a specific page or frame from multi-page or layered files (PDF, PSD, AI). For example, specify by number (e.g., `2`), a range (e.g., `3-4` for the - 2nd and 3rd layers), or by name (e.g., `name-layer-4` for a PSD layer). + 2nd and 3rd layers), or by name (e.g., `name-layer-4` for a PSD layer). See + [Thumbnail extraction](https://imagekit.io/docs/vector-and-animated-images#get-thumbnail-from-psd-pdf-ai-eps-and-animated-files). """ progressive: Optional[bool] = None """Specifies whether the output JPEG image should be rendered progressively. Progressive loading begins with a low-quality, pixelated version of the full - image, which gradually improves to provide a faster perceived load time. + image, which gradually improves to provide a faster perceived load time. See + [Progressive images](https://imagekit.io/docs/image-optimization#progressive-image---pr). """ quality: Optional[float] = None @@ -220,12 +298,14 @@ class Transformation(BaseModel): Specifies the quality of the output image for lossy formats such as JPEG, WebP, and AVIF. A higher quality value results in a larger file size with better quality, while a lower value produces a smaller file size with reduced quality. + See [Quality](https://imagekit.io/docs/image-optimization#quality---q). """ radius: Union[float, Literal["max"], None] = None """ - Specifies the corner radius for rounded corners (e.g., 20) or `max` for - circular/oval shapes. + Specifies the corner radius for rounded corners (e.g., 20) or `max` for circular + or oval shape. See + [Radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). """ raw: Optional[str] = None @@ -240,77 +320,106 @@ class Transformation(BaseModel): Positive values rotate the image clockwise; you can also use, for example, `N40` for counterclockwise rotation or `auto` to use the orientation specified in the image's EXIF data. For videos, only the following values are supported: 0, 90, - 180, 270, or 360. + 180, 270, or 360. See + [Rotate](https://imagekit.io/docs/effects-and-enhancements#rotate---rt). """ shadow: Union[Literal[True], str, None] = None """Adds a shadow beneath solid objects in an image with a transparent background. For AI-based drop shadows, refer to aiDropShadow. Pass `true` for a default - shadow, or provide a string for a custom shadow. + shadow, or provide a string for a custom shadow. See + [Shadow](https://imagekit.io/docs/effects-and-enhancements#shadow---e-shadow). """ sharpen: Union[Literal[True], float, None] = None """Sharpens the input image, highlighting edges and finer details. Pass `true` for default sharpening, or provide a numeric value for custom - sharpening. + sharpening. See + [Sharpen](https://imagekit.io/docs/effects-and-enhancements#sharpen---e-sharpen). """ start_offset: Union[float, str, None] = FieldInfo(alias="startOffset", default=None) """Specifies the start offset (in seconds) for trimming videos, e.g., `5` or `10.5`. - Arithmetic expressions are also supported. + Arithmetic expressions are also supported. See + [Trim videos – Start offset](https://imagekit.io/docs/trim-videos#start-offset---so). """ streaming_resolutions: Optional[List[StreamingResolution]] = FieldInfo(alias="streamingResolutions", default=None) """ An array of resolutions for adaptive bitrate streaming, e.g., [`240`, `360`, - `480`, `720`, `1080`]. + `480`, `720`, `1080`]. See + [Adaptive Bitrate Streaming](https://imagekit.io/docs/adaptive-bitrate-streaming). """ trim: Union[Literal[True], float, None] = None """Useful for images with a solid or nearly solid background and a central object. This parameter trims the background, leaving only the central object in the - output image. + output image. See + [Trim edges](https://imagekit.io/docs/effects-and-enhancements#trim-edges---t). """ unsharp_mask: Union[Literal[True], str, None] = FieldInfo(alias="unsharpMask", default=None) """Applies Unsharp Masking (USM), an image sharpening technique. Pass `true` for a default unsharp mask, or provide a string for a custom unsharp - mask. + mask. See + [Unsharp Mask](https://imagekit.io/docs/effects-and-enhancements#unsharp-mask---e-usm). """ video_codec: Optional[Literal["h264", "vp9", "av1", "none"]] = FieldInfo(alias="videoCodec", default=None) - """Specifies the video codec, e.g., `h264`, `vp9`, `av1`, or `none`.""" + """Specifies the video codec, e.g., `h264`, `vp9`, `av1`, or `none`. + + See [Video codec](https://imagekit.io/docs/video-optimization#video-codec---vc). + """ width: Union[float, str, None] = None """Specifies the width of the output. If a value between 0 and 1 is provided, it is treated as a percentage (e.g., `0.4` represents 40% of the original width). You can also supply arithmetic - expressions (e.g., `iw_div_2`). + expressions (e.g., `iw_div_2`). Width transformation – + [Images](https://imagekit.io/docs/image-resize-and-crop#width---w) · + [Videos](https://imagekit.io/docs/video-resize-and-crop#width---w) """ x: Union[float, str, None] = None - """Focus using cropped image coordinates - X coordinate""" + """Focus using cropped image coordinates - X coordinate. + + See + [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + """ x_center: Union[float, str, None] = FieldInfo(alias="xCenter", default=None) - """Focus using cropped image coordinates - X center coordinate""" + """Focus using cropped image coordinates - X center coordinate. + + See + [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + """ y: Union[float, str, None] = None - """Focus using cropped image coordinates - Y coordinate""" + """Focus using cropped image coordinates - Y coordinate. + + See + [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + """ y_center: Union[float, str, None] = FieldInfo(alias="yCenter", default=None) - """Focus using cropped image coordinates - Y center coordinate""" + """Focus using cropped image coordinates - Y center coordinate. + + See + [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + """ zoom: Optional[float] = None """ Accepts a numeric value that determines how much to zoom in or out of the cropped area. It should be used in conjunction with fo-face or fo-. + See [Zoom](https://imagekit.io/docs/image-resize-and-crop#zoom---z). """ diff --git a/src/imagekit/types/shared/video_overlay.py b/src/imagekit/types/shared/video_overlay.py index d902468..3cc64c6 100644 --- a/src/imagekit/types/shared/video_overlay.py +++ b/src/imagekit/types/shared/video_overlay.py @@ -29,6 +29,7 @@ class VideoOverlay(BaseOverlay): """Array of transformation to be applied to the overlay video. Except `streamingResolutions`, all other video transformations are supported. + See [Video transformations](https://imagekit.io/docs/video-transformation). """ diff --git a/src/imagekit/types/unsafe_unwrap_webhook_event.py b/src/imagekit/types/unsafe_unwrap_webhook_event.py index 89566bf..d90d1c0 100644 --- a/src/imagekit/types/unsafe_unwrap_webhook_event.py +++ b/src/imagekit/types/unsafe_unwrap_webhook_event.py @@ -6,9 +6,19 @@ from .video_transformation_error_event import VideoTransformationErrorEvent from .video_transformation_ready_event import VideoTransformationReadyEvent from .video_transformation_accepted_event import VideoTransformationAcceptedEvent +from .upload_pre_transform_error_webhook_event import UploadPreTransformErrorWebhookEvent +from .upload_post_transform_error_webhook_event import UploadPostTransformErrorWebhookEvent +from .upload_pre_transform_success_webhook_event import UploadPreTransformSuccessWebhookEvent +from .upload_post_transform_success_webhook_event import UploadPostTransformSuccessWebhookEvent __all__ = ["UnsafeUnwrapWebhookEvent"] UnsafeUnwrapWebhookEvent: TypeAlias = Union[ - VideoTransformationAcceptedEvent, VideoTransformationReadyEvent, VideoTransformationErrorEvent + VideoTransformationAcceptedEvent, + VideoTransformationReadyEvent, + VideoTransformationErrorEvent, + UploadPreTransformSuccessWebhookEvent, + UploadPreTransformErrorWebhookEvent, + UploadPostTransformSuccessWebhookEvent, + UploadPostTransformErrorWebhookEvent, ] diff --git a/src/imagekit/types/unwrap_webhook_event.py b/src/imagekit/types/unwrap_webhook_event.py index 3ede6e2..ad62f96 100644 --- a/src/imagekit/types/unwrap_webhook_event.py +++ b/src/imagekit/types/unwrap_webhook_event.py @@ -6,9 +6,19 @@ from .video_transformation_error_event import VideoTransformationErrorEvent from .video_transformation_ready_event import VideoTransformationReadyEvent from .video_transformation_accepted_event import VideoTransformationAcceptedEvent +from .upload_pre_transform_error_webhook_event import UploadPreTransformErrorWebhookEvent +from .upload_post_transform_error_webhook_event import UploadPostTransformErrorWebhookEvent +from .upload_pre_transform_success_webhook_event import UploadPreTransformSuccessWebhookEvent +from .upload_post_transform_success_webhook_event import UploadPostTransformSuccessWebhookEvent __all__ = ["UnwrapWebhookEvent"] UnwrapWebhookEvent: TypeAlias = Union[ - VideoTransformationAcceptedEvent, VideoTransformationReadyEvent, VideoTransformationErrorEvent + VideoTransformationAcceptedEvent, + VideoTransformationReadyEvent, + VideoTransformationErrorEvent, + UploadPreTransformSuccessWebhookEvent, + UploadPreTransformErrorWebhookEvent, + UploadPostTransformSuccessWebhookEvent, + UploadPostTransformErrorWebhookEvent, ] diff --git a/src/imagekit/types/upload_post_transform_error_webhook_event.py b/src/imagekit/types/upload_post_transform_error_webhook_event.py new file mode 100644 index 0000000..3e48ae2 --- /dev/null +++ b/src/imagekit/types/upload_post_transform_error_webhook_event.py @@ -0,0 +1,75 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = [ + "UploadPostTransformErrorWebhookEvent", + "Data", + "DataTransformation", + "DataTransformationError", + "Request", + "RequestTransformation", +] + + +class DataTransformationError(BaseModel): + reason: str + """Reason for the post-transformation failure.""" + + +class DataTransformation(BaseModel): + error: DataTransformationError + + +class Data(BaseModel): + file_id: str = FieldInfo(alias="fileId") + """Unique identifier of the originally uploaded file.""" + + name: str + """Name of the file.""" + + path: str + """Path of the file.""" + + transformation: DataTransformation + + url: str + """URL of the attempted post-transformation.""" + + +class RequestTransformation(BaseModel): + type: Literal["transformation", "abs", "gif-to-video", "thumbnail"] + """Type of the requested post-transformation.""" + + protocol: Optional[Literal["hls", "dash"]] = None + """Only applicable if transformation type is 'abs'. Streaming protocol used.""" + + value: Optional[str] = None + """Value for the requested transformation type.""" + + +class Request(BaseModel): + transformation: RequestTransformation + + x_request_id: str + """Unique identifier for the originating request.""" + + +class UploadPostTransformErrorWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + """Timestamp of when the event occurred in ISO8601 format.""" + + data: Data + + request: Request + + type: Literal["upload.post-transform.error"] diff --git a/src/imagekit/types/upload_post_transform_error_webhook_event1.py b/src/imagekit/types/upload_post_transform_error_webhook_event1.py new file mode 100644 index 0000000..3e48ae2 --- /dev/null +++ b/src/imagekit/types/upload_post_transform_error_webhook_event1.py @@ -0,0 +1,75 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = [ + "UploadPostTransformErrorWebhookEvent", + "Data", + "DataTransformation", + "DataTransformationError", + "Request", + "RequestTransformation", +] + + +class DataTransformationError(BaseModel): + reason: str + """Reason for the post-transformation failure.""" + + +class DataTransformation(BaseModel): + error: DataTransformationError + + +class Data(BaseModel): + file_id: str = FieldInfo(alias="fileId") + """Unique identifier of the originally uploaded file.""" + + name: str + """Name of the file.""" + + path: str + """Path of the file.""" + + transformation: DataTransformation + + url: str + """URL of the attempted post-transformation.""" + + +class RequestTransformation(BaseModel): + type: Literal["transformation", "abs", "gif-to-video", "thumbnail"] + """Type of the requested post-transformation.""" + + protocol: Optional[Literal["hls", "dash"]] = None + """Only applicable if transformation type is 'abs'. Streaming protocol used.""" + + value: Optional[str] = None + """Value for the requested transformation type.""" + + +class Request(BaseModel): + transformation: RequestTransformation + + x_request_id: str + """Unique identifier for the originating request.""" + + +class UploadPostTransformErrorWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + """Timestamp of when the event occurred in ISO8601 format.""" + + data: Data + + request: Request + + type: Literal["upload.post-transform.error"] diff --git a/src/imagekit/types/upload_post_transform_success_webhook_event.py b/src/imagekit/types/upload_post_transform_success_webhook_event.py new file mode 100644 index 0000000..3aed297 --- /dev/null +++ b/src/imagekit/types/upload_post_transform_success_webhook_event.py @@ -0,0 +1,54 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["UploadPostTransformSuccessWebhookEvent", "Data", "Request", "RequestTransformation"] + + +class Data(BaseModel): + file_id: str = FieldInfo(alias="fileId") + """Unique identifier of the originally uploaded file.""" + + name: str + """Name of the file.""" + + url: str + """URL of the generated post-transformation.""" + + +class RequestTransformation(BaseModel): + type: Literal["transformation", "abs", "gif-to-video", "thumbnail"] + """Type of the requested post-transformation.""" + + protocol: Optional[Literal["hls", "dash"]] = None + """Only applicable if transformation type is 'abs'. Streaming protocol used.""" + + value: Optional[str] = None + """Value for the requested transformation type.""" + + +class Request(BaseModel): + transformation: RequestTransformation + + x_request_id: str + """Unique identifier for the originating request.""" + + +class UploadPostTransformSuccessWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + """Timestamp of when the event occurred in ISO8601 format.""" + + data: Data + + request: Request + + type: Literal["upload.post-transform.success"] diff --git a/src/imagekit/types/upload_post_transform_success_webhook_event1.py b/src/imagekit/types/upload_post_transform_success_webhook_event1.py new file mode 100644 index 0000000..3aed297 --- /dev/null +++ b/src/imagekit/types/upload_post_transform_success_webhook_event1.py @@ -0,0 +1,54 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["UploadPostTransformSuccessWebhookEvent", "Data", "Request", "RequestTransformation"] + + +class Data(BaseModel): + file_id: str = FieldInfo(alias="fileId") + """Unique identifier of the originally uploaded file.""" + + name: str + """Name of the file.""" + + url: str + """URL of the generated post-transformation.""" + + +class RequestTransformation(BaseModel): + type: Literal["transformation", "abs", "gif-to-video", "thumbnail"] + """Type of the requested post-transformation.""" + + protocol: Optional[Literal["hls", "dash"]] = None + """Only applicable if transformation type is 'abs'. Streaming protocol used.""" + + value: Optional[str] = None + """Value for the requested transformation type.""" + + +class Request(BaseModel): + transformation: RequestTransformation + + x_request_id: str + """Unique identifier for the originating request.""" + + +class UploadPostTransformSuccessWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + """Timestamp of when the event occurred in ISO8601 format.""" + + data: Data + + request: Request + + type: Literal["upload.post-transform.success"] diff --git a/src/imagekit/types/upload_pre_transform_error_webhook_event.py b/src/imagekit/types/upload_pre_transform_error_webhook_event.py new file mode 100644 index 0000000..c0b1d14 --- /dev/null +++ b/src/imagekit/types/upload_pre_transform_error_webhook_event.py @@ -0,0 +1,49 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["UploadPreTransformErrorWebhookEvent", "Data", "DataTransformation", "DataTransformationError", "Request"] + + +class DataTransformationError(BaseModel): + reason: str + """Reason for the pre-transformation failure.""" + + +class DataTransformation(BaseModel): + error: DataTransformationError + + +class Data(BaseModel): + name: str + """Name of the file.""" + + path: str + """Path of the file.""" + + transformation: DataTransformation + + +class Request(BaseModel): + transformation: str + """The requested pre-transformation string.""" + + x_request_id: str + """Unique identifier for the originating request.""" + + +class UploadPreTransformErrorWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + """Timestamp of when the event occurred in ISO8601 format.""" + + data: Data + + request: Request + + type: Literal["upload.pre-transform.error"] diff --git a/src/imagekit/types/upload_pre_transform_error_webhook_event1.py b/src/imagekit/types/upload_pre_transform_error_webhook_event1.py new file mode 100644 index 0000000..c0b1d14 --- /dev/null +++ b/src/imagekit/types/upload_pre_transform_error_webhook_event1.py @@ -0,0 +1,49 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["UploadPreTransformErrorWebhookEvent", "Data", "DataTransformation", "DataTransformationError", "Request"] + + +class DataTransformationError(BaseModel): + reason: str + """Reason for the pre-transformation failure.""" + + +class DataTransformation(BaseModel): + error: DataTransformationError + + +class Data(BaseModel): + name: str + """Name of the file.""" + + path: str + """Path of the file.""" + + transformation: DataTransformation + + +class Request(BaseModel): + transformation: str + """The requested pre-transformation string.""" + + x_request_id: str + """Unique identifier for the originating request.""" + + +class UploadPreTransformErrorWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + """Timestamp of when the event occurred in ISO8601 format.""" + + data: Data + + request: Request + + type: Literal["upload.pre-transform.error"] diff --git a/src/imagekit/types/upload_pre_transform_success_webhook_event.py b/src/imagekit/types/upload_pre_transform_success_webhook_event.py new file mode 100644 index 0000000..3d500ab --- /dev/null +++ b/src/imagekit/types/upload_pre_transform_success_webhook_event.py @@ -0,0 +1,203 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel +from .metadata import Metadata + +__all__ = [ + "UploadPreTransformSuccessWebhookEvent", + "Data", + "DataAITag", + "DataExtensionStatus", + "DataVersionInfo", + "Request", +] + + +class DataAITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Array of `AITags` associated with the image. + + If no `AITags` are set, it will be null. These tags can be added using the + `google-auto-tagging` or `aws-auto-tagging` extensions. + """ + + +class DataExtensionStatus(BaseModel): + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="aws-auto-tagging", default=None + ) + + google_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="google-auto-tagging", default=None + ) + + remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) + + +class DataVersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class Data(BaseModel): + ai_tags: Optional[List[DataAITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the uploaded file by auto tagging.""" + + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """ + Value of custom coordinates associated with the image in the format + `x,y,width,height`. If `customCoordinates` are not defined, then it is `null`. + Send `customCoordinates` in `responseFields` in API request to get the value of + this field. + """ + + custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) + """A key-value data associated with the asset. + + Use `responseField` in API request to get `customMetadata` in the upload API + response. Before setting any custom metadata on an asset, you have to create the + field using custom metadata fields API. Send `customMetadata` in + `responseFields` in API request to get the value of this field. + """ + + description: Optional[str] = None + """Optional text to describe the contents of the file. + + Can be set by the user or the ai-auto-description extension. + """ + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + embedded_metadata: Optional[Dict[str, object]] = FieldInfo(alias="embeddedMetadata", default=None) + """Consolidated embedded metadata associated with the file. + + It includes exif, iptc, and xmp data. Send `embeddedMetadata` in + `responseFields` in API request to get embeddedMetadata in the upload API + response. + """ + + extension_status: Optional[DataExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) + """ + Extension names with their processing status at the time of completion of the + request. It could have one of the following status values: + + `success`: The extension has been successfully applied. `failed`: The extension + has failed and will not be retried. `pending`: The extension will finish + processing in some time. On completion, the final status (success / failed) will + be sent to the `webhookUrl` provided. + + If no extension was requested, then this parameter is not returned. + """ + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique fileId. + + Store this fileld in your database, as this will be used to perform update + action on this file. + """ + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """The relative path of the file in the media library e.g. + + `/marketing-assets/new-banner.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the uploaded file. Possible values are `image`, `non-image`.""" + + height: Optional[float] = None + """Height of the image in pixels (Only for images)""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Is the file marked as private. + + It can be either `true` or `false`. Send `isPrivateFile` in `responseFields` in + API request to get the value of this field. + """ + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Is the file published or in draft state. + + It can be either `true` or `false`. Send `isPublished` in `responseFields` in + API request to get the value of this field. + """ + + metadata: Optional[Metadata] = None + """Legacy metadata. + + Send `metadata` in `responseFields` in API request to get metadata in the upload + API response. + """ + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the image file in Bytes.""" + + tags: Optional[List[str]] = None + """The array of tags associated with the asset. + + If no tags are set, it will be `null`. Send `tags` in `responseFields` in API + request to get the value of this field. + """ + + thumbnail_url: Optional[str] = FieldInfo(alias="thumbnailUrl", default=None) + """In the case of an image, a small thumbnail URL.""" + + url: Optional[str] = None + """A publicly accessible URL of the file.""" + + version_info: Optional[DataVersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object containing the file or file version's `id` (versionId) and `name`.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[float] = None + """Width of the image in pixels (Only for Images)""" + + +class Request(BaseModel): + transformation: str + """The requested pre-transformation string.""" + + x_request_id: str + """Unique identifier for the originating request.""" + + +class UploadPreTransformSuccessWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + """Timestamp of when the event occurred in ISO8601 format.""" + + data: Data + """Object containing details of a successful upload.""" + + request: Request + + type: Literal["upload.pre-transform.success"] diff --git a/src/imagekit/types/upload_pre_transform_success_webhook_event1.py b/src/imagekit/types/upload_pre_transform_success_webhook_event1.py new file mode 100644 index 0000000..3d500ab --- /dev/null +++ b/src/imagekit/types/upload_pre_transform_success_webhook_event1.py @@ -0,0 +1,203 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel +from .metadata import Metadata + +__all__ = [ + "UploadPreTransformSuccessWebhookEvent", + "Data", + "DataAITag", + "DataExtensionStatus", + "DataVersionInfo", + "Request", +] + + +class DataAITag(BaseModel): + confidence: Optional[float] = None + """Confidence score of the tag.""" + + name: Optional[str] = None + """Name of the tag.""" + + source: Optional[str] = None + """Array of `AITags` associated with the image. + + If no `AITags` are set, it will be null. These tags can be added using the + `google-auto-tagging` or `aws-auto-tagging` extensions. + """ + + +class DataExtensionStatus(BaseModel): + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="aws-auto-tagging", default=None + ) + + google_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="google-auto-tagging", default=None + ) + + remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) + + +class DataVersionInfo(BaseModel): + id: Optional[str] = None + """Unique identifier of the file version.""" + + name: Optional[str] = None + """Name of the file version.""" + + +class Data(BaseModel): + ai_tags: Optional[List[DataAITag]] = FieldInfo(alias="AITags", default=None) + """An array of tags assigned to the uploaded file by auto tagging.""" + + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) + """The audio codec used in the video (only for video).""" + + bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) + """The bit rate of the video in kbps (only for video).""" + + custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) + """ + Value of custom coordinates associated with the image in the format + `x,y,width,height`. If `customCoordinates` are not defined, then it is `null`. + Send `customCoordinates` in `responseFields` in API request to get the value of + this field. + """ + + custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) + """A key-value data associated with the asset. + + Use `responseField` in API request to get `customMetadata` in the upload API + response. Before setting any custom metadata on an asset, you have to create the + field using custom metadata fields API. Send `customMetadata` in + `responseFields` in API request to get the value of this field. + """ + + description: Optional[str] = None + """Optional text to describe the contents of the file. + + Can be set by the user or the ai-auto-description extension. + """ + + duration: Optional[int] = None + """The duration of the video in seconds (only for video).""" + + embedded_metadata: Optional[Dict[str, object]] = FieldInfo(alias="embeddedMetadata", default=None) + """Consolidated embedded metadata associated with the file. + + It includes exif, iptc, and xmp data. Send `embeddedMetadata` in + `responseFields` in API request to get embeddedMetadata in the upload API + response. + """ + + extension_status: Optional[DataExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) + """ + Extension names with their processing status at the time of completion of the + request. It could have one of the following status values: + + `success`: The extension has been successfully applied. `failed`: The extension + has failed and will not be retried. `pending`: The extension will finish + processing in some time. On completion, the final status (success / failed) will + be sent to the `webhookUrl` provided. + + If no extension was requested, then this parameter is not returned. + """ + + file_id: Optional[str] = FieldInfo(alias="fileId", default=None) + """Unique fileId. + + Store this fileld in your database, as this will be used to perform update + action on this file. + """ + + file_path: Optional[str] = FieldInfo(alias="filePath", default=None) + """The relative path of the file in the media library e.g. + + `/marketing-assets/new-banner.jpg`. + """ + + file_type: Optional[str] = FieldInfo(alias="fileType", default=None) + """Type of the uploaded file. Possible values are `image`, `non-image`.""" + + height: Optional[float] = None + """Height of the image in pixels (Only for images)""" + + is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) + """Is the file marked as private. + + It can be either `true` or `false`. Send `isPrivateFile` in `responseFields` in + API request to get the value of this field. + """ + + is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) + """Is the file published or in draft state. + + It can be either `true` or `false`. Send `isPublished` in `responseFields` in + API request to get the value of this field. + """ + + metadata: Optional[Metadata] = None + """Legacy metadata. + + Send `metadata` in `responseFields` in API request to get metadata in the upload + API response. + """ + + name: Optional[str] = None + """Name of the asset.""" + + size: Optional[float] = None + """Size of the image file in Bytes.""" + + tags: Optional[List[str]] = None + """The array of tags associated with the asset. + + If no tags are set, it will be `null`. Send `tags` in `responseFields` in API + request to get the value of this field. + """ + + thumbnail_url: Optional[str] = FieldInfo(alias="thumbnailUrl", default=None) + """In the case of an image, a small thumbnail URL.""" + + url: Optional[str] = None + """A publicly accessible URL of the file.""" + + version_info: Optional[DataVersionInfo] = FieldInfo(alias="versionInfo", default=None) + """An object containing the file or file version's `id` (versionId) and `name`.""" + + video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) + """The video codec used in the video (only for video).""" + + width: Optional[float] = None + """Width of the image in pixels (Only for Images)""" + + +class Request(BaseModel): + transformation: str + """The requested pre-transformation string.""" + + x_request_id: str + """Unique identifier for the originating request.""" + + +class UploadPreTransformSuccessWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + created_at: datetime + """Timestamp of when the event occurred in ISO8601 format.""" + + data: Data + """Object containing details of a successful upload.""" + + request: Request + + type: Literal["upload.pre-transform.success"] diff --git a/src/imagekit/types/video_transformation_accepted_event.py b/src/imagekit/types/video_transformation_accepted_event.py index 35683e2..f193e52 100644 --- a/src/imagekit/types/video_transformation_accepted_event.py +++ b/src/imagekit/types/video_transformation_accepted_event.py @@ -18,46 +18,63 @@ class DataAsset(BaseModel): url: str - """Source asset URL.""" + """URL to download or access the source video file.""" class DataTransformationOptions(BaseModel): audio_codec: Optional[Literal["aac", "opus"]] = None + """Audio codec used for encoding (aac or opus).""" auto_rotate: Optional[bool] = None + """Whether to automatically rotate the video based on metadata.""" format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + """Output format for the transformed video or thumbnail.""" quality: Optional[int] = None + """Quality setting for the output video.""" stream_protocol: Optional[Literal["HLS", "DASH"]] = None + """Streaming protocol for adaptive bitrate streaming.""" variants: Optional[List[str]] = None + """Array of quality representations for adaptive bitrate streaming.""" video_codec: Optional[Literal["h264", "vp9"]] = None + """Video codec used for encoding (h264 or vp9).""" class DataTransformation(BaseModel): type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + """Type of video transformation: + + - `video-transformation`: Standard video processing (resize, format conversion, + etc.) + - `gif-to-video`: Convert animated GIF to video format + - `video-thumbnail`: Generate thumbnail image from video + """ options: Optional[DataTransformationOptions] = None + """Configuration options for video transformations.""" class Data(BaseModel): asset: DataAsset + """Information about the source video asset being transformed.""" transformation: DataTransformation + """Base information about a video transformation request.""" class Request(BaseModel): url: str - """URL of the submitted request.""" + """Full URL of the transformation request that was submitted.""" x_request_id: str - """Unique ID for the originating request.""" + """Unique identifier for the originating transformation request.""" user_agent: Optional[str] = None - """User-Agent header of the originating request.""" + """User-Agent header from the original request that triggered the transformation.""" class VideoTransformationAcceptedEvent(BaseModel): @@ -65,9 +82,11 @@ class VideoTransformationAcceptedEvent(BaseModel): """Unique identifier for the event.""" created_at: datetime + """Timestamp when the event was created in ISO8601 format.""" data: Data request: Request + """Information about the original request that triggered the video transformation.""" type: Literal["video.transformation.accepted"] diff --git a/src/imagekit/types/video_transformation_error_event.py b/src/imagekit/types/video_transformation_error_event.py index 1060e20..7206a1c 100644 --- a/src/imagekit/types/video_transformation_error_event.py +++ b/src/imagekit/types/video_transformation_error_event.py @@ -19,52 +19,75 @@ class DataAsset(BaseModel): url: str - """Source asset URL.""" + """URL to download or access the source video file.""" class DataTransformationError(BaseModel): reason: Literal["encoding_failed", "download_failed", "internal_server_error"] + """Specific reason for the transformation failure: + + - `encoding_failed`: Error during video encoding process + - `download_failed`: Could not download source video + - `internal_server_error`: Unexpected server error + """ class DataTransformationOptions(BaseModel): audio_codec: Optional[Literal["aac", "opus"]] = None + """Audio codec used for encoding (aac or opus).""" auto_rotate: Optional[bool] = None + """Whether to automatically rotate the video based on metadata.""" format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + """Output format for the transformed video or thumbnail.""" quality: Optional[int] = None + """Quality setting for the output video.""" stream_protocol: Optional[Literal["HLS", "DASH"]] = None + """Streaming protocol for adaptive bitrate streaming.""" variants: Optional[List[str]] = None + """Array of quality representations for adaptive bitrate streaming.""" video_codec: Optional[Literal["h264", "vp9"]] = None + """Video codec used for encoding (h264 or vp9).""" class DataTransformation(BaseModel): type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + """Type of video transformation: + + - `video-transformation`: Standard video processing (resize, format conversion, + etc.) + - `gif-to-video`: Convert animated GIF to video format + - `video-thumbnail`: Generate thumbnail image from video + """ error: Optional[DataTransformationError] = None + """Details about the transformation error.""" options: Optional[DataTransformationOptions] = None + """Configuration options for video transformations.""" class Data(BaseModel): asset: DataAsset + """Information about the source video asset being transformed.""" transformation: DataTransformation class Request(BaseModel): url: str - """URL of the submitted request.""" + """Full URL of the transformation request that was submitted.""" x_request_id: str - """Unique ID for the originating request.""" + """Unique identifier for the originating transformation request.""" user_agent: Optional[str] = None - """User-Agent header of the originating request.""" + """User-Agent header from the original request that triggered the transformation.""" class VideoTransformationErrorEvent(BaseModel): @@ -72,9 +95,11 @@ class VideoTransformationErrorEvent(BaseModel): """Unique identifier for the event.""" created_at: datetime + """Timestamp when the event was created in ISO8601 format.""" data: Data request: Request + """Information about the original request that triggered the video transformation.""" type: Literal["video.transformation.error"] diff --git a/src/imagekit/types/video_transformation_ready_event.py b/src/imagekit/types/video_transformation_ready_event.py index f73cdf5..3e25102 100644 --- a/src/imagekit/types/video_transformation_ready_event.py +++ b/src/imagekit/types/video_transformation_ready_event.py @@ -21,72 +21,98 @@ class DataAsset(BaseModel): url: str - """Source asset URL.""" + """URL to download or access the source video file.""" class DataTransformationOptions(BaseModel): audio_codec: Optional[Literal["aac", "opus"]] = None + """Audio codec used for encoding (aac or opus).""" auto_rotate: Optional[bool] = None + """Whether to automatically rotate the video based on metadata.""" format: Optional[Literal["mp4", "webm", "jpg", "png", "webp"]] = None + """Output format for the transformed video or thumbnail.""" quality: Optional[int] = None + """Quality setting for the output video.""" stream_protocol: Optional[Literal["HLS", "DASH"]] = None + """Streaming protocol for adaptive bitrate streaming.""" variants: Optional[List[str]] = None + """Array of quality representations for adaptive bitrate streaming.""" video_codec: Optional[Literal["h264", "vp9"]] = None + """Video codec used for encoding (h264 or vp9).""" class DataTransformationOutputVideoMetadata(BaseModel): bitrate: int + """Bitrate of the output video in bits per second.""" duration: float + """Duration of the output video in seconds.""" height: int + """Height of the output video in pixels.""" width: int + """Width of the output video in pixels.""" class DataTransformationOutput(BaseModel): url: str + """URL to access the transformed video.""" video_metadata: Optional[DataTransformationOutputVideoMetadata] = None + """Metadata of the output video file.""" class DataTransformation(BaseModel): type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] + """Type of video transformation: + + - `video-transformation`: Standard video processing (resize, format conversion, + etc.) + - `gif-to-video`: Convert animated GIF to video format + - `video-thumbnail`: Generate thumbnail image from video + """ options: Optional[DataTransformationOptions] = None + """Configuration options for video transformations.""" output: Optional[DataTransformationOutput] = None + """Information about the transformed output video.""" class Data(BaseModel): asset: DataAsset + """Information about the source video asset being transformed.""" transformation: DataTransformation class Request(BaseModel): url: str - """URL of the submitted request.""" + """Full URL of the transformation request that was submitted.""" x_request_id: str - """Unique ID for the originating request.""" + """Unique identifier for the originating transformation request.""" user_agent: Optional[str] = None - """User-Agent header of the originating request.""" + """User-Agent header from the original request that triggered the transformation.""" class Timings(BaseModel): download_duration: Optional[int] = None - """Milliseconds spent downloading the source.""" + """ + Time spent downloading the source video from your origin or media library, in + milliseconds. + """ encoding_duration: Optional[int] = None - """Milliseconds spent encoding.""" + """Time spent encoding the video, in milliseconds.""" class VideoTransformationReadyEvent(BaseModel): @@ -94,11 +120,14 @@ class VideoTransformationReadyEvent(BaseModel): """Unique identifier for the event.""" created_at: datetime + """Timestamp when the event was created in ISO8601 format.""" data: Data request: Request + """Information about the original request that triggered the video transformation.""" type: Literal["video.transformation.ready"] timings: Optional[Timings] = None + """Performance metrics for the transformation process.""" From a1912099c0949809ceac844fb84276fe9e4ed9c7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 31 Aug 2025 08:48:43 +0000 Subject: [PATCH 084/177] feat(api): manual updates --- .stats.yml | 4 ++-- src/imagekit/types/video_transformation_accepted_event.py | 4 ++-- src/imagekit/types/video_transformation_error_event.py | 4 ++-- src/imagekit/types/video_transformation_ready_event.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index caed6f5..66a8df1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0cdbdd05084a8219bc003a34670472f198cf91e5f6402cede2cb1094b7bfd98d.yml -openapi_spec_hash: d337c89146f41fa215560bb5aef2e4ec +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-a49f0e337789b1a4368194ed004ac4c1b0c0cd2ce4344e14546422632242d897.yml +openapi_spec_hash: a7f3999c6227aac108cd80253ffc7730 config_hash: 249ee22f294858ab0971b8379f7cb519 diff --git a/src/imagekit/types/video_transformation_accepted_event.py b/src/imagekit/types/video_transformation_accepted_event.py index f193e52..2176808 100644 --- a/src/imagekit/types/video_transformation_accepted_event.py +++ b/src/imagekit/types/video_transformation_accepted_event.py @@ -40,8 +40,8 @@ class DataTransformationOptions(BaseModel): variants: Optional[List[str]] = None """Array of quality representations for adaptive bitrate streaming.""" - video_codec: Optional[Literal["h264", "vp9"]] = None - """Video codec used for encoding (h264 or vp9).""" + video_codec: Optional[Literal["h264", "vp9", "av1"]] = None + """Video codec used for encoding (h264, vp9, or av1).""" class DataTransformation(BaseModel): diff --git a/src/imagekit/types/video_transformation_error_event.py b/src/imagekit/types/video_transformation_error_event.py index 7206a1c..244d20f 100644 --- a/src/imagekit/types/video_transformation_error_event.py +++ b/src/imagekit/types/video_transformation_error_event.py @@ -51,8 +51,8 @@ class DataTransformationOptions(BaseModel): variants: Optional[List[str]] = None """Array of quality representations for adaptive bitrate streaming.""" - video_codec: Optional[Literal["h264", "vp9"]] = None - """Video codec used for encoding (h264 or vp9).""" + video_codec: Optional[Literal["h264", "vp9", "av1"]] = None + """Video codec used for encoding (h264, vp9, or av1).""" class DataTransformation(BaseModel): diff --git a/src/imagekit/types/video_transformation_ready_event.py b/src/imagekit/types/video_transformation_ready_event.py index 3e25102..e962bf8 100644 --- a/src/imagekit/types/video_transformation_ready_event.py +++ b/src/imagekit/types/video_transformation_ready_event.py @@ -43,8 +43,8 @@ class DataTransformationOptions(BaseModel): variants: Optional[List[str]] = None """Array of quality representations for adaptive bitrate streaming.""" - video_codec: Optional[Literal["h264", "vp9"]] = None - """Video codec used for encoding (h264 or vp9).""" + video_codec: Optional[Literal["h264", "vp9", "av1"]] = None + """Video codec used for encoding (h264, vp9, or av1).""" class DataTransformationOutputVideoMetadata(BaseModel): From c5b6c4c0b27085ef13b09ecc4445c2dbc7dfb346 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 05:26:04 +0000 Subject: [PATCH 085/177] feat(api): add signed URL options with expiration settings to enhance security features --- .stats.yml | 4 ++-- src/imagekit/types/shared/src_options.py | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 66a8df1..cb2a397 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-a49f0e337789b1a4368194ed004ac4c1b0c0cd2ce4344e14546422632242d897.yml -openapi_spec_hash: a7f3999c6227aac108cd80253ffc7730 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d857341f30517b11df568dd6c5a0e9dea3a854930f7f6583718114d311f2d5ee.yml +openapi_spec_hash: db94bfd556220d6244a1b2bbae9d7d00 config_hash: 249ee22f294858ab0971b8379f7cb519 diff --git a/src/imagekit/types/shared/src_options.py b/src/imagekit/types/shared/src_options.py index 6e30fcd..981860d 100644 --- a/src/imagekit/types/shared/src_options.py +++ b/src/imagekit/types/shared/src_options.py @@ -26,6 +26,20 @@ class SrcOptions(BaseModel): [ImageKit dashboard](https://imagekit.io/dashboard/url-endpoints). """ + expires_in: Optional[float] = FieldInfo(alias="expiresIn", default=None) + """When you want the signed URL to expire, specified in seconds. + + If `expiresIn` is anything above 0, the URL will always be signed even if + `signed` is set to false. If not specified and `signed` is `true`, the signed + URL will not expire (valid indefinitely). + + Example: Setting `expiresIn: 3600` will make the URL expire 1 hour from + generation time. After the expiry time, the signed URL will no longer be valid + and ImageKit will return a 401 Unauthorized status code. + + [Learn more](https://imagekit.io/docs/media-delivery-basic-security#how-to-generate-signed-urls). + """ + query_parameters: Optional[Dict[str, str]] = FieldInfo(alias="queryParameters", default=None) """ These are additional query parameters that you want to add to the final URL. @@ -33,6 +47,16 @@ class SrcOptions(BaseModel): is especially useful if you want to add a versioning parameter to your URLs. """ + signed: Optional[bool] = None + """Whether to sign the URL or not. + + Set this to `true` if you want to generate a signed URL. If `signed` is `true` + and `expiresIn` is not specified, the signed URL will not expire (valid + indefinitely). Note: If `expiresIn` is set to any value above 0, the URL will + always be signed regardless of this setting. + [Learn more](https://imagekit.io/docs/media-delivery-basic-security#how-to-generate-signed-urls). + """ + transformation: Optional[List["Transformation"]] = None """An array of objects specifying the transformations to be applied in the URL. From cc76268a6604efd515e132e049cf230964011bb9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 08:31:37 +0000 Subject: [PATCH 086/177] feat(api): add new webhook events for upload transformations to enhance event tracking --- .stats.yml | 2 +- api.md | 12 +- src/imagekit/types/__init__.py | 16 +- .../types/unsafe_unwrap_webhook_event.py | 16 +- src/imagekit/types/unwrap_webhook_event.py | 16 +- ...y => upload_post_transform_error_event.py} | 4 +- ...oad_post_transform_error_webhook_event1.py | 75 ------- ...=> upload_post_transform_success_event.py} | 4 +- ...d_post_transform_success_webhook_event1.py | 54 ----- ...py => upload_pre_transform_error_event.py} | 4 +- ...load_pre_transform_error_webhook_event1.py | 49 ----- ... => upload_pre_transform_success_event.py} | 11 +- ...ad_pre_transform_success_webhook_event1.py | 203 ------------------ 13 files changed, 33 insertions(+), 433 deletions(-) rename src/imagekit/types/{upload_post_transform_error_webhook_event.py => upload_post_transform_error_event.py} (94%) delete mode 100644 src/imagekit/types/upload_post_transform_error_webhook_event1.py rename src/imagekit/types/{upload_post_transform_success_webhook_event.py => upload_post_transform_success_event.py} (89%) delete mode 100644 src/imagekit/types/upload_post_transform_success_webhook_event1.py rename src/imagekit/types/{upload_pre_transform_error_webhook_event.py => upload_pre_transform_error_event.py} (84%) delete mode 100644 src/imagekit/types/upload_pre_transform_error_webhook_event1.py rename src/imagekit/types/{upload_pre_transform_success_webhook_event.py => upload_pre_transform_success_event.py} (96%) delete mode 100644 src/imagekit/types/upload_pre_transform_success_webhook_event1.py diff --git a/.stats.yml b/.stats.yml index cb2a397..6bb89db 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d857341f30517b11df568dd6c5a0e9dea3a854930f7f6583718114d311f2d5ee.yml openapi_spec_hash: db94bfd556220d6244a1b2bbae9d7d00 -config_hash: 249ee22f294858ab0971b8379f7cb519 +config_hash: 4ef178e13ecfdb97211f284f13a21e83 diff --git a/api.md b/api.md index 1d64a23..5cb14f5 100644 --- a/api.md +++ b/api.md @@ -238,17 +238,13 @@ Types: ```python from imagekit.types import ( + UploadPostTransformErrorEvent, + UploadPostTransformSuccessEvent, + UploadPreTransformErrorEvent, + UploadPreTransformSuccessEvent, VideoTransformationAcceptedEvent, VideoTransformationErrorEvent, VideoTransformationReadyEvent, - UploadPreTransformSuccessWebhookEvent, - UploadPreTransformErrorWebhookEvent, - UploadPostTransformSuccessWebhookEvent, - UploadPostTransformErrorWebhookEvent, - UploadPreTransformSuccessWebhookEvent, - UploadPreTransformErrorWebhookEvent, - UploadPostTransformSuccessWebhookEvent, - UploadPostTransformErrorWebhookEvent, UnsafeUnwrapWebhookEvent, UnwrapWebhookEvent, ) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 01aa820..8af42ff 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -50,28 +50,20 @@ from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse from .folder_rename_response import FolderRenameResponse as FolderRenameResponse from .unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent as UnsafeUnwrapWebhookEvent +from .upload_pre_transform_error_event import UploadPreTransformErrorEvent as UploadPreTransformErrorEvent from .video_transformation_error_event import VideoTransformationErrorEvent as VideoTransformationErrorEvent from .video_transformation_ready_event import VideoTransformationReadyEvent as VideoTransformationReadyEvent from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams +from .upload_post_transform_error_event import UploadPostTransformErrorEvent as UploadPostTransformErrorEvent +from .upload_pre_transform_success_event import UploadPreTransformSuccessEvent as UploadPreTransformSuccessEvent from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams from .custom_metadata_field_list_response import CustomMetadataFieldListResponse as CustomMetadataFieldListResponse from .custom_metadata_field_update_params import CustomMetadataFieldUpdateParams as CustomMetadataFieldUpdateParams +from .upload_post_transform_success_event import UploadPostTransformSuccessEvent as UploadPostTransformSuccessEvent from .video_transformation_accepted_event import VideoTransformationAcceptedEvent as VideoTransformationAcceptedEvent from .custom_metadata_field_delete_response import ( CustomMetadataFieldDeleteResponse as CustomMetadataFieldDeleteResponse, ) -from .upload_pre_transform_error_webhook_event import ( - UploadPreTransformErrorWebhookEvent as UploadPreTransformErrorWebhookEvent, -) -from .upload_post_transform_error_webhook_event import ( - UploadPostTransformErrorWebhookEvent as UploadPostTransformErrorWebhookEvent, -) -from .upload_pre_transform_success_webhook_event import ( - UploadPreTransformSuccessWebhookEvent as UploadPreTransformSuccessWebhookEvent, -) -from .upload_post_transform_success_webhook_event import ( - UploadPostTransformSuccessWebhookEvent as UploadPostTransformSuccessWebhookEvent, -) # Rebuild cyclical models only after all modules are imported. # This ensures that, when building the deferred (due to cyclical references) model schema, diff --git a/src/imagekit/types/unsafe_unwrap_webhook_event.py b/src/imagekit/types/unsafe_unwrap_webhook_event.py index d90d1c0..c04c98a 100644 --- a/src/imagekit/types/unsafe_unwrap_webhook_event.py +++ b/src/imagekit/types/unsafe_unwrap_webhook_event.py @@ -3,13 +3,13 @@ from typing import Union from typing_extensions import TypeAlias +from .upload_pre_transform_error_event import UploadPreTransformErrorEvent from .video_transformation_error_event import VideoTransformationErrorEvent from .video_transformation_ready_event import VideoTransformationReadyEvent +from .upload_post_transform_error_event import UploadPostTransformErrorEvent +from .upload_pre_transform_success_event import UploadPreTransformSuccessEvent +from .upload_post_transform_success_event import UploadPostTransformSuccessEvent from .video_transformation_accepted_event import VideoTransformationAcceptedEvent -from .upload_pre_transform_error_webhook_event import UploadPreTransformErrorWebhookEvent -from .upload_post_transform_error_webhook_event import UploadPostTransformErrorWebhookEvent -from .upload_pre_transform_success_webhook_event import UploadPreTransformSuccessWebhookEvent -from .upload_post_transform_success_webhook_event import UploadPostTransformSuccessWebhookEvent __all__ = ["UnsafeUnwrapWebhookEvent"] @@ -17,8 +17,8 @@ VideoTransformationAcceptedEvent, VideoTransformationReadyEvent, VideoTransformationErrorEvent, - UploadPreTransformSuccessWebhookEvent, - UploadPreTransformErrorWebhookEvent, - UploadPostTransformSuccessWebhookEvent, - UploadPostTransformErrorWebhookEvent, + UploadPreTransformSuccessEvent, + UploadPreTransformErrorEvent, + UploadPostTransformSuccessEvent, + UploadPostTransformErrorEvent, ] diff --git a/src/imagekit/types/unwrap_webhook_event.py b/src/imagekit/types/unwrap_webhook_event.py index ad62f96..dddf005 100644 --- a/src/imagekit/types/unwrap_webhook_event.py +++ b/src/imagekit/types/unwrap_webhook_event.py @@ -3,13 +3,13 @@ from typing import Union from typing_extensions import TypeAlias +from .upload_pre_transform_error_event import UploadPreTransformErrorEvent from .video_transformation_error_event import VideoTransformationErrorEvent from .video_transformation_ready_event import VideoTransformationReadyEvent +from .upload_post_transform_error_event import UploadPostTransformErrorEvent +from .upload_pre_transform_success_event import UploadPreTransformSuccessEvent +from .upload_post_transform_success_event import UploadPostTransformSuccessEvent from .video_transformation_accepted_event import VideoTransformationAcceptedEvent -from .upload_pre_transform_error_webhook_event import UploadPreTransformErrorWebhookEvent -from .upload_post_transform_error_webhook_event import UploadPostTransformErrorWebhookEvent -from .upload_pre_transform_success_webhook_event import UploadPreTransformSuccessWebhookEvent -from .upload_post_transform_success_webhook_event import UploadPostTransformSuccessWebhookEvent __all__ = ["UnwrapWebhookEvent"] @@ -17,8 +17,8 @@ VideoTransformationAcceptedEvent, VideoTransformationReadyEvent, VideoTransformationErrorEvent, - UploadPreTransformSuccessWebhookEvent, - UploadPreTransformErrorWebhookEvent, - UploadPostTransformSuccessWebhookEvent, - UploadPostTransformErrorWebhookEvent, + UploadPreTransformSuccessEvent, + UploadPreTransformErrorEvent, + UploadPostTransformSuccessEvent, + UploadPostTransformErrorEvent, ] diff --git a/src/imagekit/types/upload_post_transform_error_webhook_event.py b/src/imagekit/types/upload_post_transform_error_event.py similarity index 94% rename from src/imagekit/types/upload_post_transform_error_webhook_event.py rename to src/imagekit/types/upload_post_transform_error_event.py index 3e48ae2..1c85408 100644 --- a/src/imagekit/types/upload_post_transform_error_webhook_event.py +++ b/src/imagekit/types/upload_post_transform_error_event.py @@ -9,7 +9,7 @@ from .._models import BaseModel __all__ = [ - "UploadPostTransformErrorWebhookEvent", + "UploadPostTransformErrorEvent", "Data", "DataTransformation", "DataTransformationError", @@ -61,7 +61,7 @@ class Request(BaseModel): """Unique identifier for the originating request.""" -class UploadPostTransformErrorWebhookEvent(BaseModel): +class UploadPostTransformErrorEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/upload_post_transform_error_webhook_event1.py b/src/imagekit/types/upload_post_transform_error_webhook_event1.py deleted file mode 100644 index 3e48ae2..0000000 --- a/src/imagekit/types/upload_post_transform_error_webhook_event1.py +++ /dev/null @@ -1,75 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = [ - "UploadPostTransformErrorWebhookEvent", - "Data", - "DataTransformation", - "DataTransformationError", - "Request", - "RequestTransformation", -] - - -class DataTransformationError(BaseModel): - reason: str - """Reason for the post-transformation failure.""" - - -class DataTransformation(BaseModel): - error: DataTransformationError - - -class Data(BaseModel): - file_id: str = FieldInfo(alias="fileId") - """Unique identifier of the originally uploaded file.""" - - name: str - """Name of the file.""" - - path: str - """Path of the file.""" - - transformation: DataTransformation - - url: str - """URL of the attempted post-transformation.""" - - -class RequestTransformation(BaseModel): - type: Literal["transformation", "abs", "gif-to-video", "thumbnail"] - """Type of the requested post-transformation.""" - - protocol: Optional[Literal["hls", "dash"]] = None - """Only applicable if transformation type is 'abs'. Streaming protocol used.""" - - value: Optional[str] = None - """Value for the requested transformation type.""" - - -class Request(BaseModel): - transformation: RequestTransformation - - x_request_id: str - """Unique identifier for the originating request.""" - - -class UploadPostTransformErrorWebhookEvent(BaseModel): - id: str - """Unique identifier for the event.""" - - created_at: datetime - """Timestamp of when the event occurred in ISO8601 format.""" - - data: Data - - request: Request - - type: Literal["upload.post-transform.error"] diff --git a/src/imagekit/types/upload_post_transform_success_webhook_event.py b/src/imagekit/types/upload_post_transform_success_event.py similarity index 89% rename from src/imagekit/types/upload_post_transform_success_webhook_event.py rename to src/imagekit/types/upload_post_transform_success_event.py index 3aed297..aab063a 100644 --- a/src/imagekit/types/upload_post_transform_success_webhook_event.py +++ b/src/imagekit/types/upload_post_transform_success_event.py @@ -8,7 +8,7 @@ from .._models import BaseModel -__all__ = ["UploadPostTransformSuccessWebhookEvent", "Data", "Request", "RequestTransformation"] +__all__ = ["UploadPostTransformSuccessEvent", "Data", "Request", "RequestTransformation"] class Data(BaseModel): @@ -40,7 +40,7 @@ class Request(BaseModel): """Unique identifier for the originating request.""" -class UploadPostTransformSuccessWebhookEvent(BaseModel): +class UploadPostTransformSuccessEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/upload_post_transform_success_webhook_event1.py b/src/imagekit/types/upload_post_transform_success_webhook_event1.py deleted file mode 100644 index 3aed297..0000000 --- a/src/imagekit/types/upload_post_transform_success_webhook_event1.py +++ /dev/null @@ -1,54 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["UploadPostTransformSuccessWebhookEvent", "Data", "Request", "RequestTransformation"] - - -class Data(BaseModel): - file_id: str = FieldInfo(alias="fileId") - """Unique identifier of the originally uploaded file.""" - - name: str - """Name of the file.""" - - url: str - """URL of the generated post-transformation.""" - - -class RequestTransformation(BaseModel): - type: Literal["transformation", "abs", "gif-to-video", "thumbnail"] - """Type of the requested post-transformation.""" - - protocol: Optional[Literal["hls", "dash"]] = None - """Only applicable if transformation type is 'abs'. Streaming protocol used.""" - - value: Optional[str] = None - """Value for the requested transformation type.""" - - -class Request(BaseModel): - transformation: RequestTransformation - - x_request_id: str - """Unique identifier for the originating request.""" - - -class UploadPostTransformSuccessWebhookEvent(BaseModel): - id: str - """Unique identifier for the event.""" - - created_at: datetime - """Timestamp of when the event occurred in ISO8601 format.""" - - data: Data - - request: Request - - type: Literal["upload.post-transform.success"] diff --git a/src/imagekit/types/upload_pre_transform_error_webhook_event.py b/src/imagekit/types/upload_pre_transform_error_event.py similarity index 84% rename from src/imagekit/types/upload_pre_transform_error_webhook_event.py rename to src/imagekit/types/upload_pre_transform_error_event.py index c0b1d14..7691de7 100644 --- a/src/imagekit/types/upload_pre_transform_error_webhook_event.py +++ b/src/imagekit/types/upload_pre_transform_error_event.py @@ -5,7 +5,7 @@ from .._models import BaseModel -__all__ = ["UploadPreTransformErrorWebhookEvent", "Data", "DataTransformation", "DataTransformationError", "Request"] +__all__ = ["UploadPreTransformErrorEvent", "Data", "DataTransformation", "DataTransformationError", "Request"] class DataTransformationError(BaseModel): @@ -35,7 +35,7 @@ class Request(BaseModel): """Unique identifier for the originating request.""" -class UploadPreTransformErrorWebhookEvent(BaseModel): +class UploadPreTransformErrorEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/upload_pre_transform_error_webhook_event1.py b/src/imagekit/types/upload_pre_transform_error_webhook_event1.py deleted file mode 100644 index c0b1d14..0000000 --- a/src/imagekit/types/upload_pre_transform_error_webhook_event1.py +++ /dev/null @@ -1,49 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from datetime import datetime -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = ["UploadPreTransformErrorWebhookEvent", "Data", "DataTransformation", "DataTransformationError", "Request"] - - -class DataTransformationError(BaseModel): - reason: str - """Reason for the pre-transformation failure.""" - - -class DataTransformation(BaseModel): - error: DataTransformationError - - -class Data(BaseModel): - name: str - """Name of the file.""" - - path: str - """Path of the file.""" - - transformation: DataTransformation - - -class Request(BaseModel): - transformation: str - """The requested pre-transformation string.""" - - x_request_id: str - """Unique identifier for the originating request.""" - - -class UploadPreTransformErrorWebhookEvent(BaseModel): - id: str - """Unique identifier for the event.""" - - created_at: datetime - """Timestamp of when the event occurred in ISO8601 format.""" - - data: Data - - request: Request - - type: Literal["upload.pre-transform.error"] diff --git a/src/imagekit/types/upload_pre_transform_success_webhook_event.py b/src/imagekit/types/upload_pre_transform_success_event.py similarity index 96% rename from src/imagekit/types/upload_pre_transform_success_webhook_event.py rename to src/imagekit/types/upload_pre_transform_success_event.py index 3d500ab..8e377e4 100644 --- a/src/imagekit/types/upload_pre_transform_success_webhook_event.py +++ b/src/imagekit/types/upload_pre_transform_success_event.py @@ -9,14 +9,7 @@ from .._models import BaseModel from .metadata import Metadata -__all__ = [ - "UploadPreTransformSuccessWebhookEvent", - "Data", - "DataAITag", - "DataExtensionStatus", - "DataVersionInfo", - "Request", -] +__all__ = ["UploadPreTransformSuccessEvent", "Data", "DataAITag", "DataExtensionStatus", "DataVersionInfo", "Request"] class DataAITag(BaseModel): @@ -188,7 +181,7 @@ class Request(BaseModel): """Unique identifier for the originating request.""" -class UploadPreTransformSuccessWebhookEvent(BaseModel): +class UploadPreTransformSuccessEvent(BaseModel): id: str """Unique identifier for the event.""" diff --git a/src/imagekit/types/upload_pre_transform_success_webhook_event1.py b/src/imagekit/types/upload_pre_transform_success_webhook_event1.py deleted file mode 100644 index 3d500ab..0000000 --- a/src/imagekit/types/upload_pre_transform_success_webhook_event1.py +++ /dev/null @@ -1,203 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel -from .metadata import Metadata - -__all__ = [ - "UploadPreTransformSuccessWebhookEvent", - "Data", - "DataAITag", - "DataExtensionStatus", - "DataVersionInfo", - "Request", -] - - -class DataAITag(BaseModel): - confidence: Optional[float] = None - """Confidence score of the tag.""" - - name: Optional[str] = None - """Name of the tag.""" - - source: Optional[str] = None - """Array of `AITags` associated with the image. - - If no `AITags` are set, it will be null. These tags can be added using the - `google-auto-tagging` or `aws-auto-tagging` extensions. - """ - - -class DataExtensionStatus(BaseModel): - aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( - alias="aws-auto-tagging", default=None - ) - - google_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( - alias="google-auto-tagging", default=None - ) - - remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) - - -class DataVersionInfo(BaseModel): - id: Optional[str] = None - """Unique identifier of the file version.""" - - name: Optional[str] = None - """Name of the file version.""" - - -class Data(BaseModel): - ai_tags: Optional[List[DataAITag]] = FieldInfo(alias="AITags", default=None) - """An array of tags assigned to the uploaded file by auto tagging.""" - - audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) - """The audio codec used in the video (only for video).""" - - bit_rate: Optional[int] = FieldInfo(alias="bitRate", default=None) - """The bit rate of the video in kbps (only for video).""" - - custom_coordinates: Optional[str] = FieldInfo(alias="customCoordinates", default=None) - """ - Value of custom coordinates associated with the image in the format - `x,y,width,height`. If `customCoordinates` are not defined, then it is `null`. - Send `customCoordinates` in `responseFields` in API request to get the value of - this field. - """ - - custom_metadata: Optional[Dict[str, object]] = FieldInfo(alias="customMetadata", default=None) - """A key-value data associated with the asset. - - Use `responseField` in API request to get `customMetadata` in the upload API - response. Before setting any custom metadata on an asset, you have to create the - field using custom metadata fields API. Send `customMetadata` in - `responseFields` in API request to get the value of this field. - """ - - description: Optional[str] = None - """Optional text to describe the contents of the file. - - Can be set by the user or the ai-auto-description extension. - """ - - duration: Optional[int] = None - """The duration of the video in seconds (only for video).""" - - embedded_metadata: Optional[Dict[str, object]] = FieldInfo(alias="embeddedMetadata", default=None) - """Consolidated embedded metadata associated with the file. - - It includes exif, iptc, and xmp data. Send `embeddedMetadata` in - `responseFields` in API request to get embeddedMetadata in the upload API - response. - """ - - extension_status: Optional[DataExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) - """ - Extension names with their processing status at the time of completion of the - request. It could have one of the following status values: - - `success`: The extension has been successfully applied. `failed`: The extension - has failed and will not be retried. `pending`: The extension will finish - processing in some time. On completion, the final status (success / failed) will - be sent to the `webhookUrl` provided. - - If no extension was requested, then this parameter is not returned. - """ - - file_id: Optional[str] = FieldInfo(alias="fileId", default=None) - """Unique fileId. - - Store this fileld in your database, as this will be used to perform update - action on this file. - """ - - file_path: Optional[str] = FieldInfo(alias="filePath", default=None) - """The relative path of the file in the media library e.g. - - `/marketing-assets/new-banner.jpg`. - """ - - file_type: Optional[str] = FieldInfo(alias="fileType", default=None) - """Type of the uploaded file. Possible values are `image`, `non-image`.""" - - height: Optional[float] = None - """Height of the image in pixels (Only for images)""" - - is_private_file: Optional[bool] = FieldInfo(alias="isPrivateFile", default=None) - """Is the file marked as private. - - It can be either `true` or `false`. Send `isPrivateFile` in `responseFields` in - API request to get the value of this field. - """ - - is_published: Optional[bool] = FieldInfo(alias="isPublished", default=None) - """Is the file published or in draft state. - - It can be either `true` or `false`. Send `isPublished` in `responseFields` in - API request to get the value of this field. - """ - - metadata: Optional[Metadata] = None - """Legacy metadata. - - Send `metadata` in `responseFields` in API request to get metadata in the upload - API response. - """ - - name: Optional[str] = None - """Name of the asset.""" - - size: Optional[float] = None - """Size of the image file in Bytes.""" - - tags: Optional[List[str]] = None - """The array of tags associated with the asset. - - If no tags are set, it will be `null`. Send `tags` in `responseFields` in API - request to get the value of this field. - """ - - thumbnail_url: Optional[str] = FieldInfo(alias="thumbnailUrl", default=None) - """In the case of an image, a small thumbnail URL.""" - - url: Optional[str] = None - """A publicly accessible URL of the file.""" - - version_info: Optional[DataVersionInfo] = FieldInfo(alias="versionInfo", default=None) - """An object containing the file or file version's `id` (versionId) and `name`.""" - - video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) - """The video codec used in the video (only for video).""" - - width: Optional[float] = None - """Width of the image in pixels (Only for Images)""" - - -class Request(BaseModel): - transformation: str - """The requested pre-transformation string.""" - - x_request_id: str - """Unique identifier for the originating request.""" - - -class UploadPreTransformSuccessWebhookEvent(BaseModel): - id: str - """Unique identifier for the event.""" - - created_at: datetime - """Timestamp of when the event occurred in ISO8601 format.""" - - data: Data - """Object containing details of a successful upload.""" - - request: Request - - type: Literal["upload.pre-transform.success"] From 167eaee4ca1209060ddfc46e18c828b3ab5f1a36 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 10:25:52 +0000 Subject: [PATCH 087/177] feat(api): add ai-auto-description field with status options to components schema --- .stats.yml | 4 ++-- src/imagekit/types/beta/v2/file_upload_response.py | 4 ++++ src/imagekit/types/file_upload_response.py | 4 ++++ src/imagekit/types/upload_pre_transform_success_event.py | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6bb89db..bd62087 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d857341f30517b11df568dd6c5a0e9dea3a854930f7f6583718114d311f2d5ee.yml -openapi_spec_hash: db94bfd556220d6244a1b2bbae9d7d00 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3d7da4b8ef2ed30aa32c4fb3e98e498e67402e91aaa5fd4c628fc080bfe82ea1.yml +openapi_spec_hash: aaa50fcbccec6f2cf1165f34bc6ac886 config_hash: 4ef178e13ecfdb97211f284f13a21e83 diff --git a/src/imagekit/types/beta/v2/file_upload_response.py b/src/imagekit/types/beta/v2/file_upload_response.py index 82a4813..08f6ceb 100644 --- a/src/imagekit/types/beta/v2/file_upload_response.py +++ b/src/imagekit/types/beta/v2/file_upload_response.py @@ -27,6 +27,10 @@ class AITag(BaseModel): class ExtensionStatus(BaseModel): + ai_auto_description: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="ai-auto-description", default=None + ) + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( alias="aws-auto-tagging", default=None ) diff --git a/src/imagekit/types/file_upload_response.py b/src/imagekit/types/file_upload_response.py index 02d9a29..56a1098 100644 --- a/src/imagekit/types/file_upload_response.py +++ b/src/imagekit/types/file_upload_response.py @@ -27,6 +27,10 @@ class AITag(BaseModel): class ExtensionStatus(BaseModel): + ai_auto_description: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="ai-auto-description", default=None + ) + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( alias="aws-auto-tagging", default=None ) diff --git a/src/imagekit/types/upload_pre_transform_success_event.py b/src/imagekit/types/upload_pre_transform_success_event.py index 8e377e4..d37813e 100644 --- a/src/imagekit/types/upload_pre_transform_success_event.py +++ b/src/imagekit/types/upload_pre_transform_success_event.py @@ -28,6 +28,10 @@ class DataAITag(BaseModel): class DataExtensionStatus(BaseModel): + ai_auto_description: Optional[Literal["success", "pending", "failed"]] = FieldInfo( + alias="ai-auto-description", default=None + ) + aws_auto_tagging: Optional[Literal["success", "pending", "failed"]] = FieldInfo( alias="aws-auto-tagging", default=None ) From 214fa7caac19d90b60bac34033d27cc6aadacd96 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 10:52:59 +0000 Subject: [PATCH 088/177] feat(docs): improve descriptions for private API key and password fields in client settings --- .stats.yml | 2 +- README.md | 8 ++++++-- src/imagekit/_client.py | 8 ++++---- tests/test_client.py | 4 ++-- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.stats.yml b/.stats.yml index bd62087..a4e72d0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3d7da4b8ef2ed30aa32c4fb3e98e498e67402e91aaa5fd4c628fc080bfe82ea1.yml openapi_spec_hash: aaa50fcbccec6f2cf1165f34bc6ac886 -config_hash: 4ef178e13ecfdb97211f284f13a21e83 +config_hash: 7218b2df6efd609f88bac0ac591a70e9 diff --git a/README.md b/README.md index 2ba13db..d2b9990 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,9 @@ client = ImageKit( private_api_key=os.environ.get( "IMAGEKIT_PRIVATE_API_KEY" ), # This is the default and can be omitted - password=os.environ.get("ORG_MY_PASSWORD_TOKEN"), # This is the default and can be omitted + password=os.environ.get( + "OPTIONAL_IMAGEKIT_IGNORES_THIS" + ), # This is the default and can be omitted ) response = client.files.upload( @@ -63,7 +65,9 @@ client = AsyncImageKit( private_api_key=os.environ.get( "IMAGEKIT_PRIVATE_API_KEY" ), # This is the default and can be omitted - password=os.environ.get("ORG_MY_PASSWORD_TOKEN"), # This is the default and can be omitted + password=os.environ.get( + "OPTIONAL_IMAGEKIT_IGNORES_THIS" + ), # This is the default and can be omitted ) diff --git a/src/imagekit/_client.py b/src/imagekit/_client.py index 4478350..978b38b 100644 --- a/src/imagekit/_client.py +++ b/src/imagekit/_client.py @@ -93,7 +93,7 @@ def __init__( This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `private_api_key` from `IMAGEKIT_PRIVATE_API_KEY` - - `password` from `ORG_MY_PASSWORD_TOKEN` + - `password` from `OPTIONAL_IMAGEKIT_IGNORES_THIS` """ if private_api_key is None: private_api_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") @@ -104,7 +104,7 @@ def __init__( self.private_api_key = private_api_key if password is None: - password = os.environ.get("ORG_MY_PASSWORD_TOKEN") or "does_not_matter" + password = os.environ.get("OPTIONAL_IMAGEKIT_IGNORES_THIS") or "do_not_set" self.password = password if base_url is None: @@ -302,7 +302,7 @@ def __init__( This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `private_api_key` from `IMAGEKIT_PRIVATE_API_KEY` - - `password` from `ORG_MY_PASSWORD_TOKEN` + - `password` from `OPTIONAL_IMAGEKIT_IGNORES_THIS` """ if private_api_key is None: private_api_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") @@ -313,7 +313,7 @@ def __init__( self.private_api_key = private_api_key if password is None: - password = os.environ.get("ORG_MY_PASSWORD_TOKEN") or "does_not_matter" + password = os.environ.get("OPTIONAL_IMAGEKIT_IGNORES_THIS") or "do_not_set" self.password = password if base_url is None: diff --git a/tests/test_client.py b/tests/test_client.py index c11dc77..ddb5db7 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -384,7 +384,7 @@ def test_validate_headers(self) -> None: with update_env( **{ "IMAGEKIT_PRIVATE_API_KEY": Omit(), - "ORG_MY_PASSWORD_TOKEN": Omit(), + "OPTIONAL_IMAGEKIT_IGNORES_THIS": Omit(), } ): client2 = ImageKit( @@ -1277,7 +1277,7 @@ def test_validate_headers(self) -> None: with update_env( **{ "IMAGEKIT_PRIVATE_API_KEY": Omit(), - "ORG_MY_PASSWORD_TOKEN": Omit(), + "OPTIONAL_IMAGEKIT_IGNORES_THIS": Omit(), } ): client2 = AsyncImageKit( From bc287431a207cae655a6007cd2ace9b726807486 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 12:44:48 +0000 Subject: [PATCH 089/177] chore: update SDK settings --- .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 | 14 ++-- bin/check-release-environment | 21 ++++++ pyproject.toml | 6 +- release-please-config.json | 66 +++++++++++++++++++ src/imagekit/_files.py | 2 +- src/imagekit/_version.py | 2 +- src/imagekit/resources/accounts/accounts.py | 8 +-- src/imagekit/resources/accounts/origins.py | 8 +-- .../resources/accounts/url_endpoints.py | 8 +-- src/imagekit/resources/accounts/usage.py | 8 +-- src/imagekit/resources/assets.py | 8 +-- src/imagekit/resources/beta/beta.py | 8 +-- src/imagekit/resources/beta/v2/files.py | 8 +-- src/imagekit/resources/beta/v2/v2.py | 8 +-- src/imagekit/resources/cache/cache.py | 8 +-- src/imagekit/resources/cache/invalidation.py | 8 +-- .../resources/custom_metadata_fields.py | 8 +-- src/imagekit/resources/files/bulk.py | 8 +-- src/imagekit/resources/files/files.py | 8 +-- src/imagekit/resources/files/metadata.py | 8 +-- src/imagekit/resources/files/versions.py | 8 +-- src/imagekit/resources/folders/folders.py | 8 +-- src/imagekit/resources/folders/job.py | 8 +-- 28 files changed, 225 insertions(+), 83 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..08adafc --- /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/imagekit-developer/imagekit-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.44.0' + RYE_INSTALL_OPTION: '--yes' + + - name: Publish to PyPI + run: | + bash ./bin/publish-pypi + env: + PYPI_TOKEN: ${{ secrets.IMAGE_KIT_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..c36a89d --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,21 @@ +name: Release Doctor +on: + pull_request: + branches: + - master + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'imagekit-developer/imagekit-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.IMAGE_KIT_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..1332969 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1" +} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index a4e72d0..93aeb61 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3d7da4b8ef2ed30aa32c4fb3e98e498e67402e91aaa5fd4c628fc080bfe82ea1.yml openapi_spec_hash: aaa50fcbccec6f2cf1165f34bc6ac886 -config_hash: 7218b2df6efd609f88bac0ac591a70e9 +config_hash: af15f7df8a4590c14cdce4460983aba6 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a133f19..cf4695d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,7 +62,7 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git +$ pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git ``` Alternatively, you can build from source and install the wheel file: @@ -120,7 +120,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/imagekit-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/imagekit-developer/imagekit-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 d2b9990..19cc02b 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ The REST API documentation can be found on [imagekit.io](https://imagekit.io/doc ## Installation ```sh -# install from this staging repo -pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git +# install from the production repo +pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git ``` > [!NOTE] @@ -91,8 +91,8 @@ By default, the async client uses `httpx` for HTTP requests. However, for improv You can enable this by installing `aiohttp`: ```sh -# install from this staging repo -pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/stainless-sdks/imagekit-python.git' +# install from the production repo +pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git' ``` Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: @@ -317,9 +317,9 @@ file = response.parse() # get the object that `files.upload()` would have retur print(file.video_codec) ``` -These methods return an [`APIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekit/_response.py) object. +These methods return an [`APIResponse`](https://github.com/imagekit-developer/imagekit-python/tree/master/src/imagekit/_response.py) object. -The async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekit/_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/imagekit-developer/imagekit-python/tree/master/src/imagekit/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. #### `.with_streaming_response` @@ -426,7 +426,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/imagekit-python/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/imagekit-developer/imagekit-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..b845b0f --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +errors=() + +if [ -z "${PYPI_TOKEN}" ]; then + errors+=("The 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 354f999..f3403c4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,8 +35,8 @@ classifiers = [ ] [project.urls] -Homepage = "https://github.com/stainless-sdks/imagekit-python" -Repository = "https://github.com/stainless-sdks/imagekit-python" +Homepage = "https://github.com/imagekit-developer/imagekit-python" +Repository = "https://github.com/imagekit-developer/imagekit-python" [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] @@ -126,7 +126,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/imagekit-python/tree/main/\g<2>)' +replacement = '[\1](https://github.com/imagekit-developer/imagekit-python/tree/master/\g<2>)' [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..48e2b41 --- /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/imagekit/_version.py" + ] +} \ No newline at end of file diff --git a/src/imagekit/_files.py b/src/imagekit/_files.py index 3cf7941..331bc44 100644 --- a/src/imagekit/_files.py +++ b/src/imagekit/_files.py @@ -34,7 +34,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None: if not is_file_content(obj): prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" raise RuntimeError( - f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/stainless-sdks/imagekit-python/tree/main#file-uploads" + f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/imagekit-developer/imagekit-python/tree/master#file-uploads" ) from None diff --git a/src/imagekit/_version.py b/src/imagekit/_version.py index 3eb6f6a..e521ae3 100644 --- a/src/imagekit/_version.py +++ b/src/imagekit/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "imagekit" -__version__ = "0.0.1" +__version__ = "0.0.1" # x-release-please-version diff --git a/src/imagekit/resources/accounts/accounts.py b/src/imagekit/resources/accounts/accounts.py index dba376c..461e8cf 100644 --- a/src/imagekit/resources/accounts/accounts.py +++ b/src/imagekit/resources/accounts/accounts.py @@ -51,7 +51,7 @@ def with_raw_response(self) -> AccountsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AccountsResourceWithRawResponse(self) @@ -60,7 +60,7 @@ def with_streaming_response(self) -> AccountsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AccountsResourceWithStreamingResponse(self) @@ -84,7 +84,7 @@ def with_raw_response(self) -> AsyncAccountsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncAccountsResourceWithRawResponse(self) @@ -93,7 +93,7 @@ def with_streaming_response(self) -> AsyncAccountsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncAccountsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index 08eca06..c036f03 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -32,7 +32,7 @@ def with_raw_response(self) -> OriginsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return OriginsResourceWithRawResponse(self) @@ -41,7 +41,7 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return OriginsResourceWithStreamingResponse(self) @@ -241,7 +241,7 @@ def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncOriginsResourceWithRawResponse(self) @@ -250,7 +250,7 @@ def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncOriginsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/url_endpoints.py b/src/imagekit/resources/accounts/url_endpoints.py index 5c23f50..890a63f 100644 --- a/src/imagekit/resources/accounts/url_endpoints.py +++ b/src/imagekit/resources/accounts/url_endpoints.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> URLEndpointsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return URLEndpointsResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> URLEndpointsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return URLEndpointsResourceWithStreamingResponse(self) @@ -275,7 +275,7 @@ def with_raw_response(self) -> AsyncURLEndpointsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncURLEndpointsResourceWithRawResponse(self) @@ -284,7 +284,7 @@ def with_streaming_response(self) -> AsyncURLEndpointsResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncURLEndpointsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/usage.py b/src/imagekit/resources/accounts/usage.py index 0b9b9de..3e0fd41 100644 --- a/src/imagekit/resources/accounts/usage.py +++ b/src/imagekit/resources/accounts/usage.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> UsageResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return UsageResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> UsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return UsageResourceWithStreamingResponse(self) @@ -104,7 +104,7 @@ def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncUsageResourceWithRawResponse(self) @@ -113,7 +113,7 @@ def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncUsageResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/assets.py b/src/imagekit/resources/assets.py index f2b124c..51173fa 100644 --- a/src/imagekit/resources/assets.py +++ b/src/imagekit/resources/assets.py @@ -30,7 +30,7 @@ def with_raw_response(self) -> AssetsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AssetsResourceWithRawResponse(self) @@ -39,7 +39,7 @@ def with_streaming_response(self) -> AssetsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AssetsResourceWithStreamingResponse(self) @@ -163,7 +163,7 @@ def with_raw_response(self) -> AsyncAssetsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncAssetsResourceWithRawResponse(self) @@ -172,7 +172,7 @@ def with_streaming_response(self) -> AsyncAssetsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncAssetsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/beta.py b/src/imagekit/resources/beta/beta.py index e37c117..01e43aa 100644 --- a/src/imagekit/resources/beta/beta.py +++ b/src/imagekit/resources/beta/beta.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> BetaResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return BetaResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> BetaResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return BetaResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncBetaResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncBetaResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncBetaResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncBetaResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index 7d5074a..6242db3 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> FilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) @@ -283,7 +283,7 @@ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @@ -292,7 +292,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/v2/v2.py b/src/imagekit/resources/beta/v2/v2.py index f552e26..2fb9830 100644 --- a/src/imagekit/resources/beta/v2/v2.py +++ b/src/imagekit/resources/beta/v2/v2.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> V2ResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return V2ResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> V2ResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return V2ResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncV2ResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncV2ResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncV2ResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncV2ResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/cache/cache.py b/src/imagekit/resources/cache/cache.py index 47016b0..936b39f 100644 --- a/src/imagekit/resources/cache/cache.py +++ b/src/imagekit/resources/cache/cache.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> CacheResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return CacheResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> CacheResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return CacheResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncCacheResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncCacheResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncCacheResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncCacheResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/cache/invalidation.py b/src/imagekit/resources/cache/invalidation.py index 48d9a2c..a1c83d7 100644 --- a/src/imagekit/resources/cache/invalidation.py +++ b/src/imagekit/resources/cache/invalidation.py @@ -29,7 +29,7 @@ def with_raw_response(self) -> InvalidationResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return InvalidationResourceWithRawResponse(self) @@ -38,7 +38,7 @@ def with_streaming_response(self) -> InvalidationResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return InvalidationResourceWithStreamingResponse(self) @@ -120,7 +120,7 @@ def with_raw_response(self) -> AsyncInvalidationResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncInvalidationResourceWithRawResponse(self) @@ -129,7 +129,7 @@ def with_streaming_response(self) -> AsyncInvalidationResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncInvalidationResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py index 5c745ea..94f4eb5 100644 --- a/src/imagekit/resources/custom_metadata_fields.py +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -34,7 +34,7 @@ def with_raw_response(self) -> CustomMetadataFieldsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return CustomMetadataFieldsResourceWithRawResponse(self) @@ -43,7 +43,7 @@ def with_streaming_response(self) -> CustomMetadataFieldsResourceWithStreamingRe """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return CustomMetadataFieldsResourceWithStreamingResponse(self) @@ -238,7 +238,7 @@ def with_raw_response(self) -> AsyncCustomMetadataFieldsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncCustomMetadataFieldsResourceWithRawResponse(self) @@ -247,7 +247,7 @@ def with_streaming_response(self) -> AsyncCustomMetadataFieldsResourceWithStream """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncCustomMetadataFieldsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/bulk.py b/src/imagekit/resources/files/bulk.py index 1ba19cf..a84becb 100644 --- a/src/imagekit/resources/files/bulk.py +++ b/src/imagekit/resources/files/bulk.py @@ -33,7 +33,7 @@ def with_raw_response(self) -> BulkResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return BulkResourceWithRawResponse(self) @@ -42,7 +42,7 @@ def with_streaming_response(self) -> BulkResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return BulkResourceWithStreamingResponse(self) @@ -229,7 +229,7 @@ def with_raw_response(self) -> AsyncBulkResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncBulkResourceWithRawResponse(self) @@ -238,7 +238,7 @@ def with_streaming_response(self) -> AsyncBulkResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncBulkResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 7d58b56..12ef720 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -72,7 +72,7 @@ def with_raw_response(self) -> FilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @@ -81,7 +81,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) @@ -643,7 +643,7 @@ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @@ -652,7 +652,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/metadata.py b/src/imagekit/resources/files/metadata.py index 9432b0c..e68348a 100644 --- a/src/imagekit/resources/files/metadata.py +++ b/src/imagekit/resources/files/metadata.py @@ -28,7 +28,7 @@ def with_raw_response(self) -> MetadataResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return MetadataResourceWithRawResponse(self) @@ -37,7 +37,7 @@ def with_streaming_response(self) -> MetadataResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return MetadataResourceWithStreamingResponse(self) @@ -125,7 +125,7 @@ def with_raw_response(self) -> AsyncMetadataResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncMetadataResourceWithRawResponse(self) @@ -134,7 +134,7 @@ def with_streaming_response(self) -> AsyncMetadataResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncMetadataResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py index 09b473e..77c22c3 100644 --- a/src/imagekit/resources/files/versions.py +++ b/src/imagekit/resources/files/versions.py @@ -28,7 +28,7 @@ def with_raw_response(self) -> VersionsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return VersionsResourceWithRawResponse(self) @@ -37,7 +37,7 @@ def with_streaming_response(self) -> VersionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return VersionsResourceWithStreamingResponse(self) @@ -194,7 +194,7 @@ def with_raw_response(self) -> AsyncVersionsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncVersionsResourceWithRawResponse(self) @@ -203,7 +203,7 @@ def with_streaming_response(self) -> AsyncVersionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncVersionsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekit/resources/folders/folders.py index b0e322d..7b71a40 100644 --- a/src/imagekit/resources/folders/folders.py +++ b/src/imagekit/resources/folders/folders.py @@ -50,7 +50,7 @@ def with_raw_response(self) -> FoldersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return FoldersResourceWithRawResponse(self) @@ -59,7 +59,7 @@ def with_streaming_response(self) -> FoldersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return FoldersResourceWithStreamingResponse(self) @@ -337,7 +337,7 @@ def with_raw_response(self) -> AsyncFoldersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFoldersResourceWithRawResponse(self) @@ -346,7 +346,7 @@ def with_streaming_response(self) -> AsyncFoldersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncFoldersResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/folders/job.py b/src/imagekit/resources/folders/job.py index d051b7f..c76445f 100644 --- a/src/imagekit/resources/folders/job.py +++ b/src/imagekit/resources/folders/job.py @@ -26,7 +26,7 @@ def with_raw_response(self) -> JobResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return JobResourceWithRawResponse(self) @@ -35,7 +35,7 @@ def with_streaming_response(self) -> JobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return JobResourceWithStreamingResponse(self) @@ -80,7 +80,7 @@ def with_raw_response(self) -> AsyncJobResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncJobResourceWithRawResponse(self) @@ -89,7 +89,7 @@ def with_streaming_response(self) -> AsyncJobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncJobResourceWithStreamingResponse(self) From f0519d6c477cadb96871403fa67b9d8caf693ea4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 13:05:48 +0000 Subject: [PATCH 090/177] feat(api): manual updates --- .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 | 14 ++-- bin/check-release-environment | 21 ------ pyproject.toml | 7 +- release-please-config.json | 66 ------------------- requirements-dev.lock | 13 ---- requirements.lock | 16 ----- src/imagekit/__init__.py | 2 - src/imagekit/_exceptions.py | 4 -- src/imagekit/_files.py | 2 +- src/imagekit/_version.py | 2 +- src/imagekit/resources/accounts/accounts.py | 8 +-- src/imagekit/resources/accounts/origins.py | 8 +-- .../resources/accounts/url_endpoints.py | 8 +-- src/imagekit/resources/accounts/usage.py | 8 +-- src/imagekit/resources/assets.py | 8 +-- src/imagekit/resources/beta/beta.py | 8 +-- src/imagekit/resources/beta/v2/files.py | 8 +-- src/imagekit/resources/beta/v2/v2.py | 8 +-- src/imagekit/resources/cache/cache.py | 8 +-- src/imagekit/resources/cache/invalidation.py | 8 +-- .../resources/custom_metadata_fields.py | 8 +-- src/imagekit/resources/files/bulk.py | 8 +-- src/imagekit/resources/files/files.py | 8 +-- src/imagekit/resources/files/metadata.py | 8 +-- src/imagekit/resources/files/versions.py | 8 +-- src/imagekit/resources/folders/folders.py | 8 +-- src/imagekit/resources/folders/job.py | 8 +-- src/imagekit/resources/webhooks.py | 41 +----------- tests/api_resources/test_webhooks.py | 60 ----------------- 34 files changed, 86 insertions(+), 359 deletions(-) delete mode 100644 .github/workflows/publish-pypi.yml delete mode 100644 .github/workflows/release-doctor.yml delete mode 100644 .release-please-manifest.json delete mode 100644 bin/check-release-environment delete mode 100644 release-please-config.json diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml deleted file mode 100644 index 08adafc..0000000 --- a/.github/workflows/publish-pypi.yml +++ /dev/null @@ -1,31 +0,0 @@ -# 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/imagekit-developer/imagekit-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.44.0' - RYE_INSTALL_OPTION: '--yes' - - - name: Publish to PyPI - run: | - bash ./bin/publish-pypi - env: - PYPI_TOKEN: ${{ secrets.IMAGE_KIT_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml deleted file mode 100644 index c36a89d..0000000 --- a/.github/workflows/release-doctor.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Release Doctor -on: - pull_request: - branches: - - master - workflow_dispatch: - -jobs: - release_doctor: - name: release doctor - runs-on: ubuntu-latest - if: github.repository == 'imagekit-developer/imagekit-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.IMAGE_KIT_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json deleted file mode 100644 index 1332969..0000000 --- a/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "0.0.1" -} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 93aeb61..8599545 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3d7da4b8ef2ed30aa32c4fb3e98e498e67402e91aaa5fd4c628fc080bfe82ea1.yml openapi_spec_hash: aaa50fcbccec6f2cf1165f34bc6ac886 -config_hash: af15f7df8a4590c14cdce4460983aba6 +config_hash: 84bf9f929b0248a6cdf2d526331ed8eb diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf4695d..a133f19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,7 +62,7 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git +$ pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git ``` Alternatively, you can build from source and install the wheel file: @@ -120,7 +120,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/imagekit-developer/imagekit-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/stainless-sdks/imagekit-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 19cc02b..d2b9990 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ The REST API documentation can be found on [imagekit.io](https://imagekit.io/doc ## Installation ```sh -# install from the production repo -pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git +# install from this staging repo +pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git ``` > [!NOTE] @@ -91,8 +91,8 @@ By default, the async client uses `httpx` for HTTP requests. However, for improv You can enable this by installing `aiohttp`: ```sh -# install from the production repo -pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git' +# install from this staging repo +pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/stainless-sdks/imagekit-python.git' ``` Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: @@ -317,9 +317,9 @@ file = response.parse() # get the object that `files.upload()` would have retur print(file.video_codec) ``` -These methods return an [`APIResponse`](https://github.com/imagekit-developer/imagekit-python/tree/master/src/imagekit/_response.py) object. +These methods return an [`APIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekit/_response.py) object. -The async client returns an [`AsyncAPIResponse`](https://github.com/imagekit-developer/imagekit-python/tree/master/src/imagekit/_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/stainless-sdks/imagekit-python/tree/main/src/imagekit/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. #### `.with_streaming_response` @@ -426,7 +426,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/imagekit-developer/imagekit-python/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/imagekit-python/issues) with questions, bugs, or suggestions. ### Determining the installed version diff --git a/bin/check-release-environment b/bin/check-release-environment deleted file mode 100644 index b845b0f..0000000 --- a/bin/check-release-environment +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -errors=() - -if [ -z "${PYPI_TOKEN}" ]; then - errors+=("The 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 f3403c4..3168617 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,12 +35,11 @@ classifiers = [ ] [project.urls] -Homepage = "https://github.com/imagekit-developer/imagekit-python" -Repository = "https://github.com/imagekit-developer/imagekit-python" +Homepage = "https://github.com/stainless-sdks/imagekit-python" +Repository = "https://github.com/stainless-sdks/imagekit-python" [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] -webhooks = ["standardwebhooks"] [tool.rye] managed = true @@ -126,7 +125,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/imagekit-developer/imagekit-python/tree/master/\g<2>)' +replacement = '[\1](https://github.com/stainless-sdks/imagekit-python/tree/main/\g<2>)' [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/release-please-config.json b/release-please-config.json deleted file mode 100644 index 48e2b41..0000000 --- a/release-please-config.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "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/imagekit/_version.py" - ] -} \ No newline at end of file diff --git a/requirements-dev.lock b/requirements-dev.lock index 396ac99..2d04bf1 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -28,14 +28,11 @@ async-timeout==5.0.1 # via aiohttp attrs==25.3.0 # via aiohttp - # via standardwebhooks certifi==2023.7.22 # via httpcore # via httpx colorlog==6.7.0 # via nox -deprecated==1.2.18 - # via standardwebhooks dirty-equals==0.6.0 distlib==0.3.7 # via virtualenv @@ -59,7 +56,6 @@ httpx==0.28.1 # via httpx-aiohttp # via imagekit # via respx - # via standardwebhooks httpx-aiohttp==0.1.8 # via imagekit idna==3.4 @@ -106,7 +102,6 @@ pytest==8.3.3 pytest-asyncio==0.24.0 pytest-xdist==3.7.0 python-dateutil==2.8.2 - # via standardwebhooks # via time-machine pytz==2023.3.post1 # via dirty-equals @@ -120,16 +115,10 @@ six==1.16.0 sniffio==1.3.0 # via anyio # via imagekit -standardwebhooks==1.0.0 - # via imagekit time-machine==2.9.0 tomli==2.0.2 # via mypy # via pytest -types-deprecated==1.2.15.20250304 - # via standardwebhooks -types-python-dateutil==2.9.0.20250822 - # via standardwebhooks typing-extensions==4.12.2 # via anyio # via imagekit @@ -140,8 +129,6 @@ typing-extensions==4.12.2 # via pyright virtualenv==20.24.5 # via nox -wrapt==1.17.3 - # via deprecated yarl==1.20.0 # via aiohttp zipp==3.17.0 diff --git a/requirements.lock b/requirements.lock index a922302..85ed03b 100644 --- a/requirements.lock +++ b/requirements.lock @@ -26,12 +26,9 @@ async-timeout==5.0.1 # via aiohttp attrs==25.3.0 # via aiohttp - # via standardwebhooks certifi==2023.7.22 # via httpcore # via httpx -deprecated==1.2.18 - # via standardwebhooks distro==1.8.0 # via imagekit exceptiongroup==1.2.2 @@ -46,7 +43,6 @@ httpcore==1.0.9 httpx==0.28.1 # via httpx-aiohttp # via imagekit - # via standardwebhooks httpx-aiohttp==0.1.8 # via imagekit idna==3.4 @@ -63,26 +59,14 @@ pydantic==2.10.3 # via imagekit pydantic-core==2.27.1 # via pydantic -python-dateutil==2.9.0.post0 - # via standardwebhooks -six==1.17.0 - # via python-dateutil sniffio==1.3.0 # via anyio # via imagekit -standardwebhooks==1.0.0 - # via imagekit -types-deprecated==1.2.15.20250304 - # via standardwebhooks -types-python-dateutil==2.9.0.20250822 - # via standardwebhooks typing-extensions==4.12.2 # via anyio # via imagekit # via multidict # via pydantic # via pydantic-core -wrapt==1.17.3 - # via deprecated yarl==1.20.0 # via aiohttp diff --git a/src/imagekit/__init__.py b/src/imagekit/__init__.py index 43d69f6..07a48e8 100644 --- a/src/imagekit/__init__.py +++ b/src/imagekit/__init__.py @@ -34,7 +34,6 @@ InternalServerError, PermissionDeniedError, UnprocessableEntityError, - APIWebhookValidationError, APIResponseValidationError, ) from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient @@ -56,7 +55,6 @@ "APITimeoutError", "APIConnectionError", "APIResponseValidationError", - "APIWebhookValidationError", "BadRequestError", "AuthenticationError", "PermissionDeniedError", diff --git a/src/imagekit/_exceptions.py b/src/imagekit/_exceptions.py index 364ab5a..990ca06 100644 --- a/src/imagekit/_exceptions.py +++ b/src/imagekit/_exceptions.py @@ -54,10 +54,6 @@ def __init__(self, response: httpx.Response, body: object | None, *, message: st self.status_code = response.status_code -class APIWebhookValidationError(APIError): - pass - - class APIStatusError(APIError): """Raised when an API response has a status code of 4xx or 5xx.""" diff --git a/src/imagekit/_files.py b/src/imagekit/_files.py index 331bc44..3cf7941 100644 --- a/src/imagekit/_files.py +++ b/src/imagekit/_files.py @@ -34,7 +34,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None: if not is_file_content(obj): prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" raise RuntimeError( - f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/imagekit-developer/imagekit-python/tree/master#file-uploads" + f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/stainless-sdks/imagekit-python/tree/main#file-uploads" ) from None diff --git a/src/imagekit/_version.py b/src/imagekit/_version.py index e521ae3..3eb6f6a 100644 --- a/src/imagekit/_version.py +++ b/src/imagekit/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "imagekit" -__version__ = "0.0.1" # x-release-please-version +__version__ = "0.0.1" diff --git a/src/imagekit/resources/accounts/accounts.py b/src/imagekit/resources/accounts/accounts.py index 461e8cf..dba376c 100644 --- a/src/imagekit/resources/accounts/accounts.py +++ b/src/imagekit/resources/accounts/accounts.py @@ -51,7 +51,7 @@ def with_raw_response(self) -> AccountsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AccountsResourceWithRawResponse(self) @@ -60,7 +60,7 @@ def with_streaming_response(self) -> AccountsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AccountsResourceWithStreamingResponse(self) @@ -84,7 +84,7 @@ def with_raw_response(self) -> AsyncAccountsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncAccountsResourceWithRawResponse(self) @@ -93,7 +93,7 @@ def with_streaming_response(self) -> AsyncAccountsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncAccountsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index c036f03..08eca06 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -32,7 +32,7 @@ def with_raw_response(self) -> OriginsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return OriginsResourceWithRawResponse(self) @@ -41,7 +41,7 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return OriginsResourceWithStreamingResponse(self) @@ -241,7 +241,7 @@ def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncOriginsResourceWithRawResponse(self) @@ -250,7 +250,7 @@ def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncOriginsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/url_endpoints.py b/src/imagekit/resources/accounts/url_endpoints.py index 890a63f..5c23f50 100644 --- a/src/imagekit/resources/accounts/url_endpoints.py +++ b/src/imagekit/resources/accounts/url_endpoints.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> URLEndpointsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return URLEndpointsResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> URLEndpointsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return URLEndpointsResourceWithStreamingResponse(self) @@ -275,7 +275,7 @@ def with_raw_response(self) -> AsyncURLEndpointsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncURLEndpointsResourceWithRawResponse(self) @@ -284,7 +284,7 @@ def with_streaming_response(self) -> AsyncURLEndpointsResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncURLEndpointsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/usage.py b/src/imagekit/resources/accounts/usage.py index 3e0fd41..0b9b9de 100644 --- a/src/imagekit/resources/accounts/usage.py +++ b/src/imagekit/resources/accounts/usage.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> UsageResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return UsageResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> UsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return UsageResourceWithStreamingResponse(self) @@ -104,7 +104,7 @@ def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncUsageResourceWithRawResponse(self) @@ -113,7 +113,7 @@ def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncUsageResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/assets.py b/src/imagekit/resources/assets.py index 51173fa..f2b124c 100644 --- a/src/imagekit/resources/assets.py +++ b/src/imagekit/resources/assets.py @@ -30,7 +30,7 @@ def with_raw_response(self) -> AssetsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AssetsResourceWithRawResponse(self) @@ -39,7 +39,7 @@ def with_streaming_response(self) -> AssetsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AssetsResourceWithStreamingResponse(self) @@ -163,7 +163,7 @@ def with_raw_response(self) -> AsyncAssetsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncAssetsResourceWithRawResponse(self) @@ -172,7 +172,7 @@ def with_streaming_response(self) -> AsyncAssetsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncAssetsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/beta.py b/src/imagekit/resources/beta/beta.py index 01e43aa..e37c117 100644 --- a/src/imagekit/resources/beta/beta.py +++ b/src/imagekit/resources/beta/beta.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> BetaResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return BetaResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> BetaResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return BetaResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncBetaResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncBetaResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncBetaResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncBetaResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index 6242db3..7d5074a 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> FilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) @@ -283,7 +283,7 @@ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @@ -292,7 +292,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/v2/v2.py b/src/imagekit/resources/beta/v2/v2.py index 2fb9830..f552e26 100644 --- a/src/imagekit/resources/beta/v2/v2.py +++ b/src/imagekit/resources/beta/v2/v2.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> V2ResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return V2ResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> V2ResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return V2ResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncV2ResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncV2ResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncV2ResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncV2ResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/cache/cache.py b/src/imagekit/resources/cache/cache.py index 936b39f..47016b0 100644 --- a/src/imagekit/resources/cache/cache.py +++ b/src/imagekit/resources/cache/cache.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> CacheResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return CacheResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> CacheResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return CacheResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncCacheResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncCacheResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncCacheResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncCacheResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/cache/invalidation.py b/src/imagekit/resources/cache/invalidation.py index a1c83d7..48d9a2c 100644 --- a/src/imagekit/resources/cache/invalidation.py +++ b/src/imagekit/resources/cache/invalidation.py @@ -29,7 +29,7 @@ def with_raw_response(self) -> InvalidationResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return InvalidationResourceWithRawResponse(self) @@ -38,7 +38,7 @@ def with_streaming_response(self) -> InvalidationResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return InvalidationResourceWithStreamingResponse(self) @@ -120,7 +120,7 @@ def with_raw_response(self) -> AsyncInvalidationResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncInvalidationResourceWithRawResponse(self) @@ -129,7 +129,7 @@ def with_streaming_response(self) -> AsyncInvalidationResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncInvalidationResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py index 94f4eb5..5c745ea 100644 --- a/src/imagekit/resources/custom_metadata_fields.py +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -34,7 +34,7 @@ def with_raw_response(self) -> CustomMetadataFieldsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return CustomMetadataFieldsResourceWithRawResponse(self) @@ -43,7 +43,7 @@ def with_streaming_response(self) -> CustomMetadataFieldsResourceWithStreamingRe """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return CustomMetadataFieldsResourceWithStreamingResponse(self) @@ -238,7 +238,7 @@ def with_raw_response(self) -> AsyncCustomMetadataFieldsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncCustomMetadataFieldsResourceWithRawResponse(self) @@ -247,7 +247,7 @@ def with_streaming_response(self) -> AsyncCustomMetadataFieldsResourceWithStream """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncCustomMetadataFieldsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/bulk.py b/src/imagekit/resources/files/bulk.py index a84becb..1ba19cf 100644 --- a/src/imagekit/resources/files/bulk.py +++ b/src/imagekit/resources/files/bulk.py @@ -33,7 +33,7 @@ def with_raw_response(self) -> BulkResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return BulkResourceWithRawResponse(self) @@ -42,7 +42,7 @@ def with_streaming_response(self) -> BulkResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return BulkResourceWithStreamingResponse(self) @@ -229,7 +229,7 @@ def with_raw_response(self) -> AsyncBulkResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncBulkResourceWithRawResponse(self) @@ -238,7 +238,7 @@ def with_streaming_response(self) -> AsyncBulkResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncBulkResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 12ef720..7d58b56 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -72,7 +72,7 @@ def with_raw_response(self) -> FilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @@ -81,7 +81,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) @@ -643,7 +643,7 @@ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @@ -652,7 +652,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/metadata.py b/src/imagekit/resources/files/metadata.py index e68348a..9432b0c 100644 --- a/src/imagekit/resources/files/metadata.py +++ b/src/imagekit/resources/files/metadata.py @@ -28,7 +28,7 @@ def with_raw_response(self) -> MetadataResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return MetadataResourceWithRawResponse(self) @@ -37,7 +37,7 @@ def with_streaming_response(self) -> MetadataResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return MetadataResourceWithStreamingResponse(self) @@ -125,7 +125,7 @@ def with_raw_response(self) -> AsyncMetadataResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncMetadataResourceWithRawResponse(self) @@ -134,7 +134,7 @@ def with_streaming_response(self) -> AsyncMetadataResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncMetadataResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py index 77c22c3..09b473e 100644 --- a/src/imagekit/resources/files/versions.py +++ b/src/imagekit/resources/files/versions.py @@ -28,7 +28,7 @@ def with_raw_response(self) -> VersionsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return VersionsResourceWithRawResponse(self) @@ -37,7 +37,7 @@ def with_streaming_response(self) -> VersionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return VersionsResourceWithStreamingResponse(self) @@ -194,7 +194,7 @@ def with_raw_response(self) -> AsyncVersionsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncVersionsResourceWithRawResponse(self) @@ -203,7 +203,7 @@ def with_streaming_response(self) -> AsyncVersionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncVersionsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekit/resources/folders/folders.py index 7b71a40..b0e322d 100644 --- a/src/imagekit/resources/folders/folders.py +++ b/src/imagekit/resources/folders/folders.py @@ -50,7 +50,7 @@ def with_raw_response(self) -> FoldersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return FoldersResourceWithRawResponse(self) @@ -59,7 +59,7 @@ def with_streaming_response(self) -> FoldersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return FoldersResourceWithStreamingResponse(self) @@ -337,7 +337,7 @@ def with_raw_response(self) -> AsyncFoldersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFoldersResourceWithRawResponse(self) @@ -346,7 +346,7 @@ def with_streaming_response(self) -> AsyncFoldersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncFoldersResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/folders/job.py b/src/imagekit/resources/folders/job.py index c76445f..d051b7f 100644 --- a/src/imagekit/resources/folders/job.py +++ b/src/imagekit/resources/folders/job.py @@ -26,7 +26,7 @@ def with_raw_response(self) -> JobResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return JobResourceWithRawResponse(self) @@ -35,7 +35,7 @@ def with_streaming_response(self) -> JobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return JobResourceWithStreamingResponse(self) @@ -80,7 +80,7 @@ def with_raw_response(self) -> AsyncJobResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncJobResourceWithRawResponse(self) @@ -89,7 +89,7 @@ def with_streaming_response(self) -> AsyncJobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncJobResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/webhooks.py b/src/imagekit/resources/webhooks.py index dce279e..b2254f3 100644 --- a/src/imagekit/resources/webhooks.py +++ b/src/imagekit/resources/webhooks.py @@ -3,11 +3,10 @@ from __future__ import annotations import json -from typing import Mapping, cast +from typing import cast from .._models import construct_type from .._resource import SyncAPIResource, AsyncAPIResource -from .._exceptions import ImageKitError from ..types.unwrap_webhook_event import UnwrapWebhookEvent from ..types.unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent @@ -24,24 +23,7 @@ def unsafe_unwrap(self, payload: str) -> UnsafeUnwrapWebhookEvent: ), ) - def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | None = None) -> UnwrapWebhookEvent: - try: - from standardwebhooks import Webhook - except ImportError as exc: - raise ImageKitError("You need to install `imagekit[webhooks]` to use this method") from exc - - if key is None: - key = self._client.private_api_key - if key is None: - raise ValueError( - "Cannot verify a webhook without a key on either the client's private_api_key or passed in as an argument" - ) - - if not isinstance(headers, dict): - headers = dict(headers) - - Webhook(key).verify(payload, headers) - + def unwrap(self, payload: str) -> UnwrapWebhookEvent: return cast( UnwrapWebhookEvent, construct_type( @@ -61,24 +43,7 @@ def unsafe_unwrap(self, payload: str) -> UnsafeUnwrapWebhookEvent: ), ) - def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | None = None) -> UnwrapWebhookEvent: - try: - from standardwebhooks import Webhook - except ImportError as exc: - raise ImageKitError("You need to install `imagekit[webhooks]` to use this method") from exc - - if key is None: - key = self._client.private_api_key - if key is None: - raise ValueError( - "Cannot verify a webhook without a key on either the client's private_api_key or passed in as an argument" - ) - - if not isinstance(headers, dict): - headers = dict(headers) - - Webhook(key).verify(payload, headers) - + def unwrap(self, payload: str) -> UnwrapWebhookEvent: return cast( UnwrapWebhookEvent, construct_type( diff --git a/tests/api_resources/test_webhooks.py b/tests/api_resources/test_webhooks.py index d12bd64..543805d 100644 --- a/tests/api_resources/test_webhooks.py +++ b/tests/api_resources/test_webhooks.py @@ -3,12 +3,8 @@ from __future__ import annotations import os -from datetime import datetime, timezone import pytest -import standardwebhooks - -from imagekit import ImageKit base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -16,64 +12,8 @@ class TestWebhooks: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - def test_method_unwrap(self, client: ImageKit) -> None: - key = b"secret" - hook = standardwebhooks.Webhook(key) - - data = """{"id":"id","created_at":"2019-12-27T18:11:19.117Z","data":{"asset":{"url":"https://example.com"},"transformation":{"type":"video-transformation","options":{"audio_codec":"aac","auto_rotate":true,"format":"mp4","quality":0,"stream_protocol":"HLS","variants":["string"],"video_codec":"h264"}}},"request":{"url":"https://example.com","x_request_id":"x_request_id","user_agent":"user_agent"},"type":"video.transformation.accepted"}""" - msg_id = "1" - timestamp = datetime.now(tz=timezone.utc) - sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data) - headers = { - "webhook-id": msg_id, - "webhook-timestamp": str(int(timestamp.timestamp())), - "webhook-signature": sig, - } - - try: - _ = client.webhooks.unwrap(data, headers=headers, key=key) - except standardwebhooks.WebhookVerificationError as e: - raise AssertionError("Failed to unwrap valid webhook") from e - - bad_headers = [ - {**headers, "webhook-signature": hook.sign(msg_id=msg_id, timestamp=timestamp, data="xxx")}, - {**headers, "webhook-id": "bad"}, - {**headers, "webhook-timestamp": "0"}, - ] - for bad_header in bad_headers: - with pytest.raises(standardwebhooks.WebhookVerificationError): - _ = client.webhooks.unwrap(data, headers=bad_header, key=key) - class TestAsyncWebhooks: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - - def test_method_unwrap(self, client: ImageKit) -> None: - key = b"secret" - hook = standardwebhooks.Webhook(key) - - data = """{"id":"id","created_at":"2019-12-27T18:11:19.117Z","data":{"asset":{"url":"https://example.com"},"transformation":{"type":"video-transformation","options":{"audio_codec":"aac","auto_rotate":true,"format":"mp4","quality":0,"stream_protocol":"HLS","variants":["string"],"video_codec":"h264"}}},"request":{"url":"https://example.com","x_request_id":"x_request_id","user_agent":"user_agent"},"type":"video.transformation.accepted"}""" - msg_id = "1" - timestamp = datetime.now(tz=timezone.utc) - sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data) - headers = { - "webhook-id": msg_id, - "webhook-timestamp": str(int(timestamp.timestamp())), - "webhook-signature": sig, - } - - try: - _ = client.webhooks.unwrap(data, headers=headers, key=key) - except standardwebhooks.WebhookVerificationError as e: - raise AssertionError("Failed to unwrap valid webhook") from e - - bad_headers = [ - {**headers, "webhook-signature": hook.sign(msg_id=msg_id, timestamp=timestamp, data="xxx")}, - {**headers, "webhook-id": "bad"}, - {**headers, "webhook-timestamp": "0"}, - ] - for bad_header in bad_headers: - with pytest.raises(standardwebhooks.WebhookVerificationError): - _ = client.webhooks.unwrap(data, headers=bad_header, key=key) From d68b09d739c233a644db8930b766d6459bdf09e0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 13:12:39 +0000 Subject: [PATCH 091/177] feat(api): manual updates --- .stats.yml | 2 +- pyproject.toml | 1 + requirements-dev.lock | 13 ++++++ requirements.lock | 16 ++++++++ src/imagekit/__init__.py | 2 + src/imagekit/_client.py | 18 +++++++++ src/imagekit/_exceptions.py | 4 ++ src/imagekit/resources/webhooks.py | 41 +++++++++++++++++-- tests/api_resources/test_webhooks.py | 60 ++++++++++++++++++++++++++++ 9 files changed, 153 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8599545..2863770 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3d7da4b8ef2ed30aa32c4fb3e98e498e67402e91aaa5fd4c628fc080bfe82ea1.yml openapi_spec_hash: aaa50fcbccec6f2cf1165f34bc6ac886 -config_hash: 84bf9f929b0248a6cdf2d526331ed8eb +config_hash: 0f760028496146ece9431573b1ab0e46 diff --git a/pyproject.toml b/pyproject.toml index 3168617..354f999 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ Repository = "https://github.com/stainless-sdks/imagekit-python" [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] +webhooks = ["standardwebhooks"] [tool.rye] managed = true diff --git a/requirements-dev.lock b/requirements-dev.lock index 2d04bf1..396ac99 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -28,11 +28,14 @@ async-timeout==5.0.1 # via aiohttp attrs==25.3.0 # via aiohttp + # via standardwebhooks certifi==2023.7.22 # via httpcore # via httpx colorlog==6.7.0 # via nox +deprecated==1.2.18 + # via standardwebhooks dirty-equals==0.6.0 distlib==0.3.7 # via virtualenv @@ -56,6 +59,7 @@ httpx==0.28.1 # via httpx-aiohttp # via imagekit # via respx + # via standardwebhooks httpx-aiohttp==0.1.8 # via imagekit idna==3.4 @@ -102,6 +106,7 @@ pytest==8.3.3 pytest-asyncio==0.24.0 pytest-xdist==3.7.0 python-dateutil==2.8.2 + # via standardwebhooks # via time-machine pytz==2023.3.post1 # via dirty-equals @@ -115,10 +120,16 @@ six==1.16.0 sniffio==1.3.0 # via anyio # via imagekit +standardwebhooks==1.0.0 + # via imagekit time-machine==2.9.0 tomli==2.0.2 # via mypy # via pytest +types-deprecated==1.2.15.20250304 + # via standardwebhooks +types-python-dateutil==2.9.0.20250822 + # via standardwebhooks typing-extensions==4.12.2 # via anyio # via imagekit @@ -129,6 +140,8 @@ typing-extensions==4.12.2 # via pyright virtualenv==20.24.5 # via nox +wrapt==1.17.3 + # via deprecated yarl==1.20.0 # via aiohttp zipp==3.17.0 diff --git a/requirements.lock b/requirements.lock index 85ed03b..a922302 100644 --- a/requirements.lock +++ b/requirements.lock @@ -26,9 +26,12 @@ async-timeout==5.0.1 # via aiohttp attrs==25.3.0 # via aiohttp + # via standardwebhooks certifi==2023.7.22 # via httpcore # via httpx +deprecated==1.2.18 + # via standardwebhooks distro==1.8.0 # via imagekit exceptiongroup==1.2.2 @@ -43,6 +46,7 @@ httpcore==1.0.9 httpx==0.28.1 # via httpx-aiohttp # via imagekit + # via standardwebhooks httpx-aiohttp==0.1.8 # via imagekit idna==3.4 @@ -59,14 +63,26 @@ pydantic==2.10.3 # via imagekit pydantic-core==2.27.1 # via pydantic +python-dateutil==2.9.0.post0 + # via standardwebhooks +six==1.17.0 + # via python-dateutil sniffio==1.3.0 # via anyio # via imagekit +standardwebhooks==1.0.0 + # via imagekit +types-deprecated==1.2.15.20250304 + # via standardwebhooks +types-python-dateutil==2.9.0.20250822 + # via standardwebhooks typing-extensions==4.12.2 # via anyio # via imagekit # via multidict # via pydantic # via pydantic-core +wrapt==1.17.3 + # via deprecated yarl==1.20.0 # via aiohttp diff --git a/src/imagekit/__init__.py b/src/imagekit/__init__.py index 07a48e8..43d69f6 100644 --- a/src/imagekit/__init__.py +++ b/src/imagekit/__init__.py @@ -34,6 +34,7 @@ InternalServerError, PermissionDeniedError, UnprocessableEntityError, + APIWebhookValidationError, APIResponseValidationError, ) from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient @@ -55,6 +56,7 @@ "APITimeoutError", "APIConnectionError", "APIResponseValidationError", + "APIWebhookValidationError", "BadRequestError", "AuthenticationError", "PermissionDeniedError", diff --git a/src/imagekit/_client.py b/src/imagekit/_client.py index 978b38b..6166974 100644 --- a/src/imagekit/_client.py +++ b/src/imagekit/_client.py @@ -64,12 +64,14 @@ class ImageKit(SyncAPIClient): # client options private_api_key: str password: str | None + webhook_secret: str | None def __init__( self, *, private_api_key: str | None = None, password: str | None = None, + webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, @@ -94,6 +96,7 @@ def __init__( This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `private_api_key` from `IMAGEKIT_PRIVATE_API_KEY` - `password` from `OPTIONAL_IMAGEKIT_IGNORES_THIS` + - `webhook_secret` from `IMAGEKIT_WEBHOOK_SECRET` """ if private_api_key is None: private_api_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") @@ -107,6 +110,10 @@ def __init__( password = os.environ.get("OPTIONAL_IMAGEKIT_IGNORES_THIS") or "do_not_set" self.password = password + if webhook_secret is None: + webhook_secret = os.environ.get("IMAGEKIT_WEBHOOK_SECRET") + self.webhook_secret = webhook_secret + if base_url is None: base_url = os.environ.get("IMAGE_KIT_BASE_URL") self._base_url_overridden = base_url is not None @@ -174,6 +181,7 @@ def copy( *, private_api_key: str | None = None, password: str | None = None, + webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.Client | None = None, @@ -209,6 +217,7 @@ def copy( client = self.__class__( private_api_key=private_api_key or self.private_api_key, password=password or self.password, + webhook_secret=webhook_secret or self.webhook_secret, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, @@ -273,12 +282,14 @@ class AsyncImageKit(AsyncAPIClient): # client options private_api_key: str password: str | None + webhook_secret: str | None def __init__( self, *, private_api_key: str | None = None, password: str | None = None, + webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, @@ -303,6 +314,7 @@ def __init__( This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `private_api_key` from `IMAGEKIT_PRIVATE_API_KEY` - `password` from `OPTIONAL_IMAGEKIT_IGNORES_THIS` + - `webhook_secret` from `IMAGEKIT_WEBHOOK_SECRET` """ if private_api_key is None: private_api_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") @@ -316,6 +328,10 @@ def __init__( password = os.environ.get("OPTIONAL_IMAGEKIT_IGNORES_THIS") or "do_not_set" self.password = password + if webhook_secret is None: + webhook_secret = os.environ.get("IMAGEKIT_WEBHOOK_SECRET") + self.webhook_secret = webhook_secret + if base_url is None: base_url = os.environ.get("IMAGE_KIT_BASE_URL") self._base_url_overridden = base_url is not None @@ -383,6 +399,7 @@ def copy( *, private_api_key: str | None = None, password: str | None = None, + webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.AsyncClient | None = None, @@ -418,6 +435,7 @@ def copy( client = self.__class__( private_api_key=private_api_key or self.private_api_key, password=password or self.password, + webhook_secret=webhook_secret or self.webhook_secret, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, diff --git a/src/imagekit/_exceptions.py b/src/imagekit/_exceptions.py index 990ca06..364ab5a 100644 --- a/src/imagekit/_exceptions.py +++ b/src/imagekit/_exceptions.py @@ -54,6 +54,10 @@ def __init__(self, response: httpx.Response, body: object | None, *, message: st self.status_code = response.status_code +class APIWebhookValidationError(APIError): + pass + + class APIStatusError(APIError): """Raised when an API response has a status code of 4xx or 5xx.""" diff --git a/src/imagekit/resources/webhooks.py b/src/imagekit/resources/webhooks.py index b2254f3..7c5ed39 100644 --- a/src/imagekit/resources/webhooks.py +++ b/src/imagekit/resources/webhooks.py @@ -3,10 +3,11 @@ from __future__ import annotations import json -from typing import cast +from typing import Mapping, cast from .._models import construct_type from .._resource import SyncAPIResource, AsyncAPIResource +from .._exceptions import ImageKitError from ..types.unwrap_webhook_event import UnwrapWebhookEvent from ..types.unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent @@ -23,7 +24,24 @@ def unsafe_unwrap(self, payload: str) -> UnsafeUnwrapWebhookEvent: ), ) - def unwrap(self, payload: str) -> UnwrapWebhookEvent: + def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | None = None) -> UnwrapWebhookEvent: + try: + from standardwebhooks import Webhook + except ImportError as exc: + raise ImageKitError("You need to install `imagekit[webhooks]` to use this method") from exc + + if key is None: + key = self._client.webhook_secret + if key is None: + raise ValueError( + "Cannot verify a webhook without a key on either the client's webhook_secret or passed in as an argument" + ) + + if not isinstance(headers, dict): + headers = dict(headers) + + Webhook(key).verify(payload, headers) + return cast( UnwrapWebhookEvent, construct_type( @@ -43,7 +61,24 @@ def unsafe_unwrap(self, payload: str) -> UnsafeUnwrapWebhookEvent: ), ) - def unwrap(self, payload: str) -> UnwrapWebhookEvent: + def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | None = None) -> UnwrapWebhookEvent: + try: + from standardwebhooks import Webhook + except ImportError as exc: + raise ImageKitError("You need to install `imagekit[webhooks]` to use this method") from exc + + if key is None: + key = self._client.webhook_secret + if key is None: + raise ValueError( + "Cannot verify a webhook without a key on either the client's webhook_secret or passed in as an argument" + ) + + if not isinstance(headers, dict): + headers = dict(headers) + + Webhook(key).verify(payload, headers) + return cast( UnwrapWebhookEvent, construct_type( diff --git a/tests/api_resources/test_webhooks.py b/tests/api_resources/test_webhooks.py index 543805d..d12bd64 100644 --- a/tests/api_resources/test_webhooks.py +++ b/tests/api_resources/test_webhooks.py @@ -3,8 +3,12 @@ from __future__ import annotations import os +from datetime import datetime, timezone import pytest +import standardwebhooks + +from imagekit import ImageKit base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -12,8 +16,64 @@ class TestWebhooks: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + def test_method_unwrap(self, client: ImageKit) -> None: + key = b"secret" + hook = standardwebhooks.Webhook(key) + + data = """{"id":"id","created_at":"2019-12-27T18:11:19.117Z","data":{"asset":{"url":"https://example.com"},"transformation":{"type":"video-transformation","options":{"audio_codec":"aac","auto_rotate":true,"format":"mp4","quality":0,"stream_protocol":"HLS","variants":["string"],"video_codec":"h264"}}},"request":{"url":"https://example.com","x_request_id":"x_request_id","user_agent":"user_agent"},"type":"video.transformation.accepted"}""" + msg_id = "1" + timestamp = datetime.now(tz=timezone.utc) + sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data) + headers = { + "webhook-id": msg_id, + "webhook-timestamp": str(int(timestamp.timestamp())), + "webhook-signature": sig, + } + + try: + _ = client.webhooks.unwrap(data, headers=headers, key=key) + except standardwebhooks.WebhookVerificationError as e: + raise AssertionError("Failed to unwrap valid webhook") from e + + bad_headers = [ + {**headers, "webhook-signature": hook.sign(msg_id=msg_id, timestamp=timestamp, data="xxx")}, + {**headers, "webhook-id": "bad"}, + {**headers, "webhook-timestamp": "0"}, + ] + for bad_header in bad_headers: + with pytest.raises(standardwebhooks.WebhookVerificationError): + _ = client.webhooks.unwrap(data, headers=bad_header, key=key) + class TestAsyncWebhooks: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) + + def test_method_unwrap(self, client: ImageKit) -> None: + key = b"secret" + hook = standardwebhooks.Webhook(key) + + data = """{"id":"id","created_at":"2019-12-27T18:11:19.117Z","data":{"asset":{"url":"https://example.com"},"transformation":{"type":"video-transformation","options":{"audio_codec":"aac","auto_rotate":true,"format":"mp4","quality":0,"stream_protocol":"HLS","variants":["string"],"video_codec":"h264"}}},"request":{"url":"https://example.com","x_request_id":"x_request_id","user_agent":"user_agent"},"type":"video.transformation.accepted"}""" + msg_id = "1" + timestamp = datetime.now(tz=timezone.utc) + sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data) + headers = { + "webhook-id": msg_id, + "webhook-timestamp": str(int(timestamp.timestamp())), + "webhook-signature": sig, + } + + try: + _ = client.webhooks.unwrap(data, headers=headers, key=key) + except standardwebhooks.WebhookVerificationError as e: + raise AssertionError("Failed to unwrap valid webhook") from e + + bad_headers = [ + {**headers, "webhook-signature": hook.sign(msg_id=msg_id, timestamp=timestamp, data="xxx")}, + {**headers, "webhook-id": "bad"}, + {**headers, "webhook-timestamp": "0"}, + ] + for bad_header in bad_headers: + with pytest.raises(standardwebhooks.WebhookVerificationError): + _ = client.webhooks.unwrap(data, headers=bad_header, key=key) From eae851701547921a81e37eb550c752afb82cf647 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 13:49:44 +0000 Subject: [PATCH 092/177] chore: update SDK settings --- .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 | 14 ++-- bin/check-release-environment | 21 ++++++ pyproject.toml | 6 +- release-please-config.json | 66 +++++++++++++++++++ src/imagekit/_files.py | 2 +- src/imagekit/_version.py | 2 +- src/imagekit/resources/accounts/accounts.py | 8 +-- src/imagekit/resources/accounts/origins.py | 8 +-- .../resources/accounts/url_endpoints.py | 8 +-- src/imagekit/resources/accounts/usage.py | 8 +-- src/imagekit/resources/assets.py | 8 +-- src/imagekit/resources/beta/beta.py | 8 +-- src/imagekit/resources/beta/v2/files.py | 8 +-- src/imagekit/resources/beta/v2/v2.py | 8 +-- src/imagekit/resources/cache/cache.py | 8 +-- src/imagekit/resources/cache/invalidation.py | 8 +-- .../resources/custom_metadata_fields.py | 8 +-- src/imagekit/resources/files/bulk.py | 8 +-- src/imagekit/resources/files/files.py | 8 +-- src/imagekit/resources/files/metadata.py | 8 +-- src/imagekit/resources/files/versions.py | 8 +-- src/imagekit/resources/folders/folders.py | 8 +-- src/imagekit/resources/folders/job.py | 8 +-- 28 files changed, 225 insertions(+), 83 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..08adafc --- /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/imagekit-developer/imagekit-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.44.0' + RYE_INSTALL_OPTION: '--yes' + + - name: Publish to PyPI + run: | + bash ./bin/publish-pypi + env: + PYPI_TOKEN: ${{ secrets.IMAGE_KIT_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..c36a89d --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,21 @@ +name: Release Doctor +on: + pull_request: + branches: + - master + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'imagekit-developer/imagekit-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.IMAGE_KIT_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..1332969 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1" +} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 2863770..ad85869 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3d7da4b8ef2ed30aa32c4fb3e98e498e67402e91aaa5fd4c628fc080bfe82ea1.yml openapi_spec_hash: aaa50fcbccec6f2cf1165f34bc6ac886 -config_hash: 0f760028496146ece9431573b1ab0e46 +config_hash: cf9d50fe62973f4e91ef65c147aabcc1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a133f19..cf4695d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,7 +62,7 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git +$ pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git ``` Alternatively, you can build from source and install the wheel file: @@ -120,7 +120,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/imagekit-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/imagekit-developer/imagekit-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 d2b9990..19cc02b 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ The REST API documentation can be found on [imagekit.io](https://imagekit.io/doc ## Installation ```sh -# install from this staging repo -pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git +# install from the production repo +pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git ``` > [!NOTE] @@ -91,8 +91,8 @@ By default, the async client uses `httpx` for HTTP requests. However, for improv You can enable this by installing `aiohttp`: ```sh -# install from this staging repo -pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/stainless-sdks/imagekit-python.git' +# install from the production repo +pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git' ``` Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: @@ -317,9 +317,9 @@ file = response.parse() # get the object that `files.upload()` would have retur print(file.video_codec) ``` -These methods return an [`APIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekit/_response.py) object. +These methods return an [`APIResponse`](https://github.com/imagekit-developer/imagekit-python/tree/master/src/imagekit/_response.py) object. -The async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekit/_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/imagekit-developer/imagekit-python/tree/master/src/imagekit/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. #### `.with_streaming_response` @@ -426,7 +426,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/imagekit-python/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/imagekit-developer/imagekit-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..b845b0f --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +errors=() + +if [ -z "${PYPI_TOKEN}" ]; then + errors+=("The 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 354f999..f3403c4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,8 +35,8 @@ classifiers = [ ] [project.urls] -Homepage = "https://github.com/stainless-sdks/imagekit-python" -Repository = "https://github.com/stainless-sdks/imagekit-python" +Homepage = "https://github.com/imagekit-developer/imagekit-python" +Repository = "https://github.com/imagekit-developer/imagekit-python" [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] @@ -126,7 +126,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/imagekit-python/tree/main/\g<2>)' +replacement = '[\1](https://github.com/imagekit-developer/imagekit-python/tree/master/\g<2>)' [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..48e2b41 --- /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/imagekit/_version.py" + ] +} \ No newline at end of file diff --git a/src/imagekit/_files.py b/src/imagekit/_files.py index 3cf7941..331bc44 100644 --- a/src/imagekit/_files.py +++ b/src/imagekit/_files.py @@ -34,7 +34,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None: if not is_file_content(obj): prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" raise RuntimeError( - f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/stainless-sdks/imagekit-python/tree/main#file-uploads" + f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/imagekit-developer/imagekit-python/tree/master#file-uploads" ) from None diff --git a/src/imagekit/_version.py b/src/imagekit/_version.py index 3eb6f6a..e521ae3 100644 --- a/src/imagekit/_version.py +++ b/src/imagekit/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "imagekit" -__version__ = "0.0.1" +__version__ = "0.0.1" # x-release-please-version diff --git a/src/imagekit/resources/accounts/accounts.py b/src/imagekit/resources/accounts/accounts.py index dba376c..461e8cf 100644 --- a/src/imagekit/resources/accounts/accounts.py +++ b/src/imagekit/resources/accounts/accounts.py @@ -51,7 +51,7 @@ def with_raw_response(self) -> AccountsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AccountsResourceWithRawResponse(self) @@ -60,7 +60,7 @@ def with_streaming_response(self) -> AccountsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AccountsResourceWithStreamingResponse(self) @@ -84,7 +84,7 @@ def with_raw_response(self) -> AsyncAccountsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncAccountsResourceWithRawResponse(self) @@ -93,7 +93,7 @@ def with_streaming_response(self) -> AsyncAccountsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncAccountsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index 08eca06..c036f03 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -32,7 +32,7 @@ def with_raw_response(self) -> OriginsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return OriginsResourceWithRawResponse(self) @@ -41,7 +41,7 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return OriginsResourceWithStreamingResponse(self) @@ -241,7 +241,7 @@ def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncOriginsResourceWithRawResponse(self) @@ -250,7 +250,7 @@ def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncOriginsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/url_endpoints.py b/src/imagekit/resources/accounts/url_endpoints.py index 5c23f50..890a63f 100644 --- a/src/imagekit/resources/accounts/url_endpoints.py +++ b/src/imagekit/resources/accounts/url_endpoints.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> URLEndpointsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return URLEndpointsResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> URLEndpointsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return URLEndpointsResourceWithStreamingResponse(self) @@ -275,7 +275,7 @@ def with_raw_response(self) -> AsyncURLEndpointsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncURLEndpointsResourceWithRawResponse(self) @@ -284,7 +284,7 @@ def with_streaming_response(self) -> AsyncURLEndpointsResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncURLEndpointsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/usage.py b/src/imagekit/resources/accounts/usage.py index 0b9b9de..3e0fd41 100644 --- a/src/imagekit/resources/accounts/usage.py +++ b/src/imagekit/resources/accounts/usage.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> UsageResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return UsageResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> UsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return UsageResourceWithStreamingResponse(self) @@ -104,7 +104,7 @@ def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncUsageResourceWithRawResponse(self) @@ -113,7 +113,7 @@ def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncUsageResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/assets.py b/src/imagekit/resources/assets.py index f2b124c..51173fa 100644 --- a/src/imagekit/resources/assets.py +++ b/src/imagekit/resources/assets.py @@ -30,7 +30,7 @@ def with_raw_response(self) -> AssetsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AssetsResourceWithRawResponse(self) @@ -39,7 +39,7 @@ def with_streaming_response(self) -> AssetsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AssetsResourceWithStreamingResponse(self) @@ -163,7 +163,7 @@ def with_raw_response(self) -> AsyncAssetsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncAssetsResourceWithRawResponse(self) @@ -172,7 +172,7 @@ def with_streaming_response(self) -> AsyncAssetsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncAssetsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/beta.py b/src/imagekit/resources/beta/beta.py index e37c117..01e43aa 100644 --- a/src/imagekit/resources/beta/beta.py +++ b/src/imagekit/resources/beta/beta.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> BetaResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return BetaResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> BetaResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return BetaResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncBetaResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncBetaResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncBetaResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncBetaResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index 7d5074a..6242db3 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> FilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) @@ -283,7 +283,7 @@ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @@ -292,7 +292,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/v2/v2.py b/src/imagekit/resources/beta/v2/v2.py index f552e26..2fb9830 100644 --- a/src/imagekit/resources/beta/v2/v2.py +++ b/src/imagekit/resources/beta/v2/v2.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> V2ResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return V2ResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> V2ResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return V2ResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncV2ResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncV2ResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncV2ResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncV2ResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/cache/cache.py b/src/imagekit/resources/cache/cache.py index 47016b0..936b39f 100644 --- a/src/imagekit/resources/cache/cache.py +++ b/src/imagekit/resources/cache/cache.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> CacheResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return CacheResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> CacheResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return CacheResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncCacheResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncCacheResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncCacheResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncCacheResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/cache/invalidation.py b/src/imagekit/resources/cache/invalidation.py index 48d9a2c..a1c83d7 100644 --- a/src/imagekit/resources/cache/invalidation.py +++ b/src/imagekit/resources/cache/invalidation.py @@ -29,7 +29,7 @@ def with_raw_response(self) -> InvalidationResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return InvalidationResourceWithRawResponse(self) @@ -38,7 +38,7 @@ def with_streaming_response(self) -> InvalidationResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return InvalidationResourceWithStreamingResponse(self) @@ -120,7 +120,7 @@ def with_raw_response(self) -> AsyncInvalidationResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncInvalidationResourceWithRawResponse(self) @@ -129,7 +129,7 @@ def with_streaming_response(self) -> AsyncInvalidationResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncInvalidationResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py index 5c745ea..94f4eb5 100644 --- a/src/imagekit/resources/custom_metadata_fields.py +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -34,7 +34,7 @@ def with_raw_response(self) -> CustomMetadataFieldsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return CustomMetadataFieldsResourceWithRawResponse(self) @@ -43,7 +43,7 @@ def with_streaming_response(self) -> CustomMetadataFieldsResourceWithStreamingRe """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return CustomMetadataFieldsResourceWithStreamingResponse(self) @@ -238,7 +238,7 @@ def with_raw_response(self) -> AsyncCustomMetadataFieldsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncCustomMetadataFieldsResourceWithRawResponse(self) @@ -247,7 +247,7 @@ def with_streaming_response(self) -> AsyncCustomMetadataFieldsResourceWithStream """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncCustomMetadataFieldsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/bulk.py b/src/imagekit/resources/files/bulk.py index 1ba19cf..a84becb 100644 --- a/src/imagekit/resources/files/bulk.py +++ b/src/imagekit/resources/files/bulk.py @@ -33,7 +33,7 @@ def with_raw_response(self) -> BulkResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return BulkResourceWithRawResponse(self) @@ -42,7 +42,7 @@ def with_streaming_response(self) -> BulkResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return BulkResourceWithStreamingResponse(self) @@ -229,7 +229,7 @@ def with_raw_response(self) -> AsyncBulkResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncBulkResourceWithRawResponse(self) @@ -238,7 +238,7 @@ def with_streaming_response(self) -> AsyncBulkResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncBulkResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 7d58b56..12ef720 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -72,7 +72,7 @@ def with_raw_response(self) -> FilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @@ -81,7 +81,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) @@ -643,7 +643,7 @@ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @@ -652,7 +652,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/metadata.py b/src/imagekit/resources/files/metadata.py index 9432b0c..e68348a 100644 --- a/src/imagekit/resources/files/metadata.py +++ b/src/imagekit/resources/files/metadata.py @@ -28,7 +28,7 @@ def with_raw_response(self) -> MetadataResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return MetadataResourceWithRawResponse(self) @@ -37,7 +37,7 @@ def with_streaming_response(self) -> MetadataResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return MetadataResourceWithStreamingResponse(self) @@ -125,7 +125,7 @@ def with_raw_response(self) -> AsyncMetadataResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncMetadataResourceWithRawResponse(self) @@ -134,7 +134,7 @@ def with_streaming_response(self) -> AsyncMetadataResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncMetadataResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py index 09b473e..77c22c3 100644 --- a/src/imagekit/resources/files/versions.py +++ b/src/imagekit/resources/files/versions.py @@ -28,7 +28,7 @@ def with_raw_response(self) -> VersionsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return VersionsResourceWithRawResponse(self) @@ -37,7 +37,7 @@ def with_streaming_response(self) -> VersionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return VersionsResourceWithStreamingResponse(self) @@ -194,7 +194,7 @@ def with_raw_response(self) -> AsyncVersionsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncVersionsResourceWithRawResponse(self) @@ -203,7 +203,7 @@ def with_streaming_response(self) -> AsyncVersionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncVersionsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekit/resources/folders/folders.py index b0e322d..7b71a40 100644 --- a/src/imagekit/resources/folders/folders.py +++ b/src/imagekit/resources/folders/folders.py @@ -50,7 +50,7 @@ def with_raw_response(self) -> FoldersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return FoldersResourceWithRawResponse(self) @@ -59,7 +59,7 @@ def with_streaming_response(self) -> FoldersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return FoldersResourceWithStreamingResponse(self) @@ -337,7 +337,7 @@ def with_raw_response(self) -> AsyncFoldersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFoldersResourceWithRawResponse(self) @@ -346,7 +346,7 @@ def with_streaming_response(self) -> AsyncFoldersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncFoldersResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/folders/job.py b/src/imagekit/resources/folders/job.py index d051b7f..c76445f 100644 --- a/src/imagekit/resources/folders/job.py +++ b/src/imagekit/resources/folders/job.py @@ -26,7 +26,7 @@ def with_raw_response(self) -> JobResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return JobResourceWithRawResponse(self) @@ -35,7 +35,7 @@ def with_streaming_response(self) -> JobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return JobResourceWithStreamingResponse(self) @@ -80,7 +80,7 @@ def with_raw_response(self) -> AsyncJobResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncJobResourceWithRawResponse(self) @@ -89,7 +89,7 @@ def with_streaming_response(self) -> AsyncJobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncJobResourceWithStreamingResponse(self) From 0c0879eb6f9f313c954b2c7e1f5e2ec2f39e8a44 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 13:50:06 +0000 Subject: [PATCH 093/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index ad85869..5d25590 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3d7da4b8ef2ed30aa32c4fb3e98e498e67402e91aaa5fd4c628fc080bfe82ea1.yml openapi_spec_hash: aaa50fcbccec6f2cf1165f34bc6ac886 -config_hash: cf9d50fe62973f4e91ef65c147aabcc1 +config_hash: 9f8a678d9d4d06daec522e8deb49e3ad From abfd0292de26f83d38b7ef92d909571742fda8ac Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 07:19:12 +0000 Subject: [PATCH 094/177] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5d25590..0818544 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3d7da4b8ef2ed30aa32c4fb3e98e498e67402e91aaa5fd4c628fc080bfe82ea1.yml -openapi_spec_hash: aaa50fcbccec6f2cf1165f34bc6ac886 -config_hash: 9f8a678d9d4d06daec522e8deb49e3ad +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-667f7f4988b44bc587d6eb9960ff5c8326e9f7e9b072f3f724f9f54166eff8b1.yml +openapi_spec_hash: f2081864a4abee0480e5ff991b4c936a +config_hash: 4e73c7e12a531edcd1366dab7eccc360 From 6003fd054e1e7126c05ba9d7b49413b930cd1120 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 07:20:38 +0000 Subject: [PATCH 095/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 1 + src/imagekit/types/__init__.py | 1 + src/imagekit/types/base_webhook_event.py | 13 +++++ .../upload_post_transform_error_event.py | 38 ++++++------- .../upload_post_transform_success_event.py | 27 +++++---- .../types/upload_pre_transform_error_event.py | 32 ++++++----- .../upload_pre_transform_success_event.py | 39 +++++++------ .../video_transformation_accepted_event.py | 38 ++++++------- .../types/video_transformation_error_event.py | 44 +++++++-------- .../types/video_transformation_ready_event.py | 56 +++++++++---------- tests/api_resources/test_webhooks.py | 4 +- 12 files changed, 158 insertions(+), 137 deletions(-) create mode 100644 src/imagekit/types/base_webhook_event.py diff --git a/.stats.yml b/.stats.yml index 0818544..52f982b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-667f7f4988b44bc587d6eb9960ff5c8326e9f7e9b072f3f724f9f54166eff8b1.yml openapi_spec_hash: f2081864a4abee0480e5ff991b4c936a -config_hash: 4e73c7e12a531edcd1366dab7eccc360 +config_hash: 08e12746cdca1c59c897cf2e50893c3c diff --git a/api.md b/api.md index 5cb14f5..9b8bf83 100644 --- a/api.md +++ b/api.md @@ -238,6 +238,7 @@ Types: ```python from imagekit.types import ( + BaseWebhookEvent, UploadPostTransformErrorEvent, UploadPostTransformSuccessEvent, UploadPreTransformErrorEvent, diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 8af42ff..ed4a09d 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -28,6 +28,7 @@ from .file_copy_params import FileCopyParams as FileCopyParams from .file_move_params import FileMoveParams as FileMoveParams from .asset_list_params import AssetListParams as AssetListParams +from .base_webhook_event import BaseWebhookEvent as BaseWebhookEvent from .file_copy_response import FileCopyResponse as FileCopyResponse from .file_move_response import FileMoveResponse as FileMoveResponse from .file_rename_params import FileRenameParams as FileRenameParams diff --git a/src/imagekit/types/base_webhook_event.py b/src/imagekit/types/base_webhook_event.py new file mode 100644 index 0000000..b37e44a --- /dev/null +++ b/src/imagekit/types/base_webhook_event.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel + +__all__ = ["BaseWebhookEvent"] + + +class BaseWebhookEvent(BaseModel): + id: str + """Unique identifier for the event.""" + + type: str + """The type of webhook event.""" diff --git a/src/imagekit/types/upload_post_transform_error_event.py b/src/imagekit/types/upload_post_transform_error_event.py index 1c85408..3b3c332 100644 --- a/src/imagekit/types/upload_post_transform_error_event.py +++ b/src/imagekit/types/upload_post_transform_error_event.py @@ -7,27 +7,28 @@ from pydantic import Field as FieldInfo from .._models import BaseModel +from .base_webhook_event import BaseWebhookEvent __all__ = [ "UploadPostTransformErrorEvent", - "Data", - "DataTransformation", - "DataTransformationError", - "Request", - "RequestTransformation", + "UploadPostTransformErrorEventData", + "UploadPostTransformErrorEventDataTransformation", + "UploadPostTransformErrorEventDataTransformationError", + "UploadPostTransformErrorEventRequest", + "UploadPostTransformErrorEventRequestTransformation", ] -class DataTransformationError(BaseModel): +class UploadPostTransformErrorEventDataTransformationError(BaseModel): reason: str """Reason for the post-transformation failure.""" -class DataTransformation(BaseModel): - error: DataTransformationError +class UploadPostTransformErrorEventDataTransformation(BaseModel): + error: UploadPostTransformErrorEventDataTransformationError -class Data(BaseModel): +class UploadPostTransformErrorEventData(BaseModel): file_id: str = FieldInfo(alias="fileId") """Unique identifier of the originally uploaded file.""" @@ -37,13 +38,13 @@ class Data(BaseModel): path: str """Path of the file.""" - transformation: DataTransformation + transformation: UploadPostTransformErrorEventDataTransformation url: str """URL of the attempted post-transformation.""" -class RequestTransformation(BaseModel): +class UploadPostTransformErrorEventRequestTransformation(BaseModel): type: Literal["transformation", "abs", "gif-to-video", "thumbnail"] """Type of the requested post-transformation.""" @@ -54,22 +55,19 @@ class RequestTransformation(BaseModel): """Value for the requested transformation type.""" -class Request(BaseModel): - transformation: RequestTransformation +class UploadPostTransformErrorEventRequest(BaseModel): + transformation: UploadPostTransformErrorEventRequestTransformation x_request_id: str """Unique identifier for the originating request.""" -class UploadPostTransformErrorEvent(BaseModel): - id: str - """Unique identifier for the event.""" - +class UploadPostTransformErrorEvent(BaseWebhookEvent): created_at: datetime """Timestamp of when the event occurred in ISO8601 format.""" - data: Data + data: UploadPostTransformErrorEventData - request: Request + request: UploadPostTransformErrorEventRequest - type: Literal["upload.post-transform.error"] + type: Literal["upload.post-transform.error"] # type: ignore diff --git a/src/imagekit/types/upload_post_transform_success_event.py b/src/imagekit/types/upload_post_transform_success_event.py index aab063a..5026cfc 100644 --- a/src/imagekit/types/upload_post_transform_success_event.py +++ b/src/imagekit/types/upload_post_transform_success_event.py @@ -7,11 +7,17 @@ from pydantic import Field as FieldInfo from .._models import BaseModel +from .base_webhook_event import BaseWebhookEvent -__all__ = ["UploadPostTransformSuccessEvent", "Data", "Request", "RequestTransformation"] +__all__ = [ + "UploadPostTransformSuccessEvent", + "UploadPostTransformSuccessEventData", + "UploadPostTransformSuccessEventRequest", + "UploadPostTransformSuccessEventRequestTransformation", +] -class Data(BaseModel): +class UploadPostTransformSuccessEventData(BaseModel): file_id: str = FieldInfo(alias="fileId") """Unique identifier of the originally uploaded file.""" @@ -22,7 +28,7 @@ class Data(BaseModel): """URL of the generated post-transformation.""" -class RequestTransformation(BaseModel): +class UploadPostTransformSuccessEventRequestTransformation(BaseModel): type: Literal["transformation", "abs", "gif-to-video", "thumbnail"] """Type of the requested post-transformation.""" @@ -33,22 +39,19 @@ class RequestTransformation(BaseModel): """Value for the requested transformation type.""" -class Request(BaseModel): - transformation: RequestTransformation +class UploadPostTransformSuccessEventRequest(BaseModel): + transformation: UploadPostTransformSuccessEventRequestTransformation x_request_id: str """Unique identifier for the originating request.""" -class UploadPostTransformSuccessEvent(BaseModel): - id: str - """Unique identifier for the event.""" - +class UploadPostTransformSuccessEvent(BaseWebhookEvent): created_at: datetime """Timestamp of when the event occurred in ISO8601 format.""" - data: Data + data: UploadPostTransformSuccessEventData - request: Request + request: UploadPostTransformSuccessEventRequest - type: Literal["upload.post-transform.success"] + type: Literal["upload.post-transform.success"] # type: ignore diff --git a/src/imagekit/types/upload_pre_transform_error_event.py b/src/imagekit/types/upload_pre_transform_error_event.py index 7691de7..6140795 100644 --- a/src/imagekit/types/upload_pre_transform_error_event.py +++ b/src/imagekit/types/upload_pre_transform_error_event.py @@ -4,30 +4,37 @@ from typing_extensions import Literal from .._models import BaseModel +from .base_webhook_event import BaseWebhookEvent -__all__ = ["UploadPreTransformErrorEvent", "Data", "DataTransformation", "DataTransformationError", "Request"] +__all__ = [ + "UploadPreTransformErrorEvent", + "UploadPreTransformErrorEventData", + "UploadPreTransformErrorEventDataTransformation", + "UploadPreTransformErrorEventDataTransformationError", + "UploadPreTransformErrorEventRequest", +] -class DataTransformationError(BaseModel): +class UploadPreTransformErrorEventDataTransformationError(BaseModel): reason: str """Reason for the pre-transformation failure.""" -class DataTransformation(BaseModel): - error: DataTransformationError +class UploadPreTransformErrorEventDataTransformation(BaseModel): + error: UploadPreTransformErrorEventDataTransformationError -class Data(BaseModel): +class UploadPreTransformErrorEventData(BaseModel): name: str """Name of the file.""" path: str """Path of the file.""" - transformation: DataTransformation + transformation: UploadPreTransformErrorEventDataTransformation -class Request(BaseModel): +class UploadPreTransformErrorEventRequest(BaseModel): transformation: str """The requested pre-transformation string.""" @@ -35,15 +42,12 @@ class Request(BaseModel): """Unique identifier for the originating request.""" -class UploadPreTransformErrorEvent(BaseModel): - id: str - """Unique identifier for the event.""" - +class UploadPreTransformErrorEvent(BaseWebhookEvent): created_at: datetime """Timestamp of when the event occurred in ISO8601 format.""" - data: Data + data: UploadPreTransformErrorEventData - request: Request + request: UploadPreTransformErrorEventRequest - type: Literal["upload.pre-transform.error"] + type: Literal["upload.pre-transform.error"] # type: ignore diff --git a/src/imagekit/types/upload_pre_transform_success_event.py b/src/imagekit/types/upload_pre_transform_success_event.py index d37813e..e29cd64 100644 --- a/src/imagekit/types/upload_pre_transform_success_event.py +++ b/src/imagekit/types/upload_pre_transform_success_event.py @@ -8,11 +8,19 @@ from .._models import BaseModel from .metadata import Metadata +from .base_webhook_event import BaseWebhookEvent -__all__ = ["UploadPreTransformSuccessEvent", "Data", "DataAITag", "DataExtensionStatus", "DataVersionInfo", "Request"] +__all__ = [ + "UploadPreTransformSuccessEvent", + "UploadPreTransformSuccessEventData", + "UploadPreTransformSuccessEventDataAITag", + "UploadPreTransformSuccessEventDataExtensionStatus", + "UploadPreTransformSuccessEventDataVersionInfo", + "UploadPreTransformSuccessEventRequest", +] -class DataAITag(BaseModel): +class UploadPreTransformSuccessEventDataAITag(BaseModel): confidence: Optional[float] = None """Confidence score of the tag.""" @@ -27,7 +35,7 @@ class DataAITag(BaseModel): """ -class DataExtensionStatus(BaseModel): +class UploadPreTransformSuccessEventDataExtensionStatus(BaseModel): ai_auto_description: Optional[Literal["success", "pending", "failed"]] = FieldInfo( alias="ai-auto-description", default=None ) @@ -43,7 +51,7 @@ class DataExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) -class DataVersionInfo(BaseModel): +class UploadPreTransformSuccessEventDataVersionInfo(BaseModel): id: Optional[str] = None """Unique identifier of the file version.""" @@ -51,8 +59,8 @@ class DataVersionInfo(BaseModel): """Name of the file version.""" -class Data(BaseModel): - ai_tags: Optional[List[DataAITag]] = FieldInfo(alias="AITags", default=None) +class UploadPreTransformSuccessEventData(BaseModel): + ai_tags: Optional[List[UploadPreTransformSuccessEventDataAITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the uploaded file by auto tagging.""" audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) @@ -95,7 +103,9 @@ class Data(BaseModel): response. """ - extension_status: Optional[DataExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) + extension_status: Optional[UploadPreTransformSuccessEventDataExtensionStatus] = FieldInfo( + alias="extensionStatus", default=None + ) """ Extension names with their processing status at the time of completion of the request. It could have one of the following status values: @@ -167,7 +177,7 @@ class Data(BaseModel): url: Optional[str] = None """A publicly accessible URL of the file.""" - version_info: Optional[DataVersionInfo] = FieldInfo(alias="versionInfo", default=None) + version_info: Optional[UploadPreTransformSuccessEventDataVersionInfo] = FieldInfo(alias="versionInfo", default=None) """An object containing the file or file version's `id` (versionId) and `name`.""" video_codec: Optional[str] = FieldInfo(alias="videoCodec", default=None) @@ -177,7 +187,7 @@ class Data(BaseModel): """Width of the image in pixels (Only for Images)""" -class Request(BaseModel): +class UploadPreTransformSuccessEventRequest(BaseModel): transformation: str """The requested pre-transformation string.""" @@ -185,16 +195,13 @@ class Request(BaseModel): """Unique identifier for the originating request.""" -class UploadPreTransformSuccessEvent(BaseModel): - id: str - """Unique identifier for the event.""" - +class UploadPreTransformSuccessEvent(BaseWebhookEvent): created_at: datetime """Timestamp of when the event occurred in ISO8601 format.""" - data: Data + data: UploadPreTransformSuccessEventData """Object containing details of a successful upload.""" - request: Request + request: UploadPreTransformSuccessEventRequest - type: Literal["upload.pre-transform.success"] + type: Literal["upload.pre-transform.success"] # type: ignore diff --git a/src/imagekit/types/video_transformation_accepted_event.py b/src/imagekit/types/video_transformation_accepted_event.py index 2176808..18ff4df 100644 --- a/src/imagekit/types/video_transformation_accepted_event.py +++ b/src/imagekit/types/video_transformation_accepted_event.py @@ -5,23 +5,24 @@ from typing_extensions import Literal from .._models import BaseModel +from .base_webhook_event import BaseWebhookEvent __all__ = [ "VideoTransformationAcceptedEvent", - "Data", - "DataAsset", - "DataTransformation", - "DataTransformationOptions", - "Request", + "VideoTransformationAcceptedEventData", + "VideoTransformationAcceptedEventDataAsset", + "VideoTransformationAcceptedEventDataTransformation", + "VideoTransformationAcceptedEventDataTransformationOptions", + "VideoTransformationAcceptedEventRequest", ] -class DataAsset(BaseModel): +class VideoTransformationAcceptedEventDataAsset(BaseModel): url: str """URL to download or access the source video file.""" -class DataTransformationOptions(BaseModel): +class VideoTransformationAcceptedEventDataTransformationOptions(BaseModel): audio_codec: Optional[Literal["aac", "opus"]] = None """Audio codec used for encoding (aac or opus).""" @@ -44,7 +45,7 @@ class DataTransformationOptions(BaseModel): """Video codec used for encoding (h264, vp9, or av1).""" -class DataTransformation(BaseModel): +class VideoTransformationAcceptedEventDataTransformation(BaseModel): type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] """Type of video transformation: @@ -54,19 +55,19 @@ class DataTransformation(BaseModel): - `video-thumbnail`: Generate thumbnail image from video """ - options: Optional[DataTransformationOptions] = None + options: Optional[VideoTransformationAcceptedEventDataTransformationOptions] = None """Configuration options for video transformations.""" -class Data(BaseModel): - asset: DataAsset +class VideoTransformationAcceptedEventData(BaseModel): + asset: VideoTransformationAcceptedEventDataAsset """Information about the source video asset being transformed.""" - transformation: DataTransformation + transformation: VideoTransformationAcceptedEventDataTransformation """Base information about a video transformation request.""" -class Request(BaseModel): +class VideoTransformationAcceptedEventRequest(BaseModel): url: str """Full URL of the transformation request that was submitted.""" @@ -77,16 +78,13 @@ class Request(BaseModel): """User-Agent header from the original request that triggered the transformation.""" -class VideoTransformationAcceptedEvent(BaseModel): - id: str - """Unique identifier for the event.""" - +class VideoTransformationAcceptedEvent(BaseWebhookEvent): created_at: datetime """Timestamp when the event was created in ISO8601 format.""" - data: Data + data: VideoTransformationAcceptedEventData - request: Request + request: VideoTransformationAcceptedEventRequest """Information about the original request that triggered the video transformation.""" - type: Literal["video.transformation.accepted"] + type: Literal["video.transformation.accepted"] # type: ignore diff --git a/src/imagekit/types/video_transformation_error_event.py b/src/imagekit/types/video_transformation_error_event.py index 244d20f..7e1970e 100644 --- a/src/imagekit/types/video_transformation_error_event.py +++ b/src/imagekit/types/video_transformation_error_event.py @@ -5,24 +5,25 @@ from typing_extensions import Literal from .._models import BaseModel +from .base_webhook_event import BaseWebhookEvent __all__ = [ "VideoTransformationErrorEvent", - "Data", - "DataAsset", - "DataTransformation", - "DataTransformationError", - "DataTransformationOptions", - "Request", + "VideoTransformationErrorEventData", + "VideoTransformationErrorEventDataAsset", + "VideoTransformationErrorEventDataTransformation", + "VideoTransformationErrorEventDataTransformationError", + "VideoTransformationErrorEventDataTransformationOptions", + "VideoTransformationErrorEventRequest", ] -class DataAsset(BaseModel): +class VideoTransformationErrorEventDataAsset(BaseModel): url: str """URL to download or access the source video file.""" -class DataTransformationError(BaseModel): +class VideoTransformationErrorEventDataTransformationError(BaseModel): reason: Literal["encoding_failed", "download_failed", "internal_server_error"] """Specific reason for the transformation failure: @@ -32,7 +33,7 @@ class DataTransformationError(BaseModel): """ -class DataTransformationOptions(BaseModel): +class VideoTransformationErrorEventDataTransformationOptions(BaseModel): audio_codec: Optional[Literal["aac", "opus"]] = None """Audio codec used for encoding (aac or opus).""" @@ -55,7 +56,7 @@ class DataTransformationOptions(BaseModel): """Video codec used for encoding (h264, vp9, or av1).""" -class DataTransformation(BaseModel): +class VideoTransformationErrorEventDataTransformation(BaseModel): type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] """Type of video transformation: @@ -65,21 +66,21 @@ class DataTransformation(BaseModel): - `video-thumbnail`: Generate thumbnail image from video """ - error: Optional[DataTransformationError] = None + error: Optional[VideoTransformationErrorEventDataTransformationError] = None """Details about the transformation error.""" - options: Optional[DataTransformationOptions] = None + options: Optional[VideoTransformationErrorEventDataTransformationOptions] = None """Configuration options for video transformations.""" -class Data(BaseModel): - asset: DataAsset +class VideoTransformationErrorEventData(BaseModel): + asset: VideoTransformationErrorEventDataAsset """Information about the source video asset being transformed.""" - transformation: DataTransformation + transformation: VideoTransformationErrorEventDataTransformation -class Request(BaseModel): +class VideoTransformationErrorEventRequest(BaseModel): url: str """Full URL of the transformation request that was submitted.""" @@ -90,16 +91,13 @@ class Request(BaseModel): """User-Agent header from the original request that triggered the transformation.""" -class VideoTransformationErrorEvent(BaseModel): - id: str - """Unique identifier for the event.""" - +class VideoTransformationErrorEvent(BaseWebhookEvent): created_at: datetime """Timestamp when the event was created in ISO8601 format.""" - data: Data + data: VideoTransformationErrorEventData - request: Request + request: VideoTransformationErrorEventRequest """Information about the original request that triggered the video transformation.""" - type: Literal["video.transformation.error"] + type: Literal["video.transformation.error"] # type: ignore diff --git a/src/imagekit/types/video_transformation_ready_event.py b/src/imagekit/types/video_transformation_ready_event.py index e962bf8..1b52dcd 100644 --- a/src/imagekit/types/video_transformation_ready_event.py +++ b/src/imagekit/types/video_transformation_ready_event.py @@ -5,26 +5,27 @@ from typing_extensions import Literal from .._models import BaseModel +from .base_webhook_event import BaseWebhookEvent __all__ = [ "VideoTransformationReadyEvent", - "Data", - "DataAsset", - "DataTransformation", - "DataTransformationOptions", - "DataTransformationOutput", - "DataTransformationOutputVideoMetadata", - "Request", - "Timings", + "VideoTransformationReadyEventData", + "VideoTransformationReadyEventDataAsset", + "VideoTransformationReadyEventDataTransformation", + "VideoTransformationReadyEventDataTransformationOptions", + "VideoTransformationReadyEventDataTransformationOutput", + "VideoTransformationReadyEventDataTransformationOutputVideoMetadata", + "VideoTransformationReadyEventRequest", + "VideoTransformationReadyEventTimings", ] -class DataAsset(BaseModel): +class VideoTransformationReadyEventDataAsset(BaseModel): url: str """URL to download or access the source video file.""" -class DataTransformationOptions(BaseModel): +class VideoTransformationReadyEventDataTransformationOptions(BaseModel): audio_codec: Optional[Literal["aac", "opus"]] = None """Audio codec used for encoding (aac or opus).""" @@ -47,7 +48,7 @@ class DataTransformationOptions(BaseModel): """Video codec used for encoding (h264, vp9, or av1).""" -class DataTransformationOutputVideoMetadata(BaseModel): +class VideoTransformationReadyEventDataTransformationOutputVideoMetadata(BaseModel): bitrate: int """Bitrate of the output video in bits per second.""" @@ -61,15 +62,15 @@ class DataTransformationOutputVideoMetadata(BaseModel): """Width of the output video in pixels.""" -class DataTransformationOutput(BaseModel): +class VideoTransformationReadyEventDataTransformationOutput(BaseModel): url: str """URL to access the transformed video.""" - video_metadata: Optional[DataTransformationOutputVideoMetadata] = None + video_metadata: Optional[VideoTransformationReadyEventDataTransformationOutputVideoMetadata] = None """Metadata of the output video file.""" -class DataTransformation(BaseModel): +class VideoTransformationReadyEventDataTransformation(BaseModel): type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] """Type of video transformation: @@ -79,21 +80,21 @@ class DataTransformation(BaseModel): - `video-thumbnail`: Generate thumbnail image from video """ - options: Optional[DataTransformationOptions] = None + options: Optional[VideoTransformationReadyEventDataTransformationOptions] = None """Configuration options for video transformations.""" - output: Optional[DataTransformationOutput] = None + output: Optional[VideoTransformationReadyEventDataTransformationOutput] = None """Information about the transformed output video.""" -class Data(BaseModel): - asset: DataAsset +class VideoTransformationReadyEventData(BaseModel): + asset: VideoTransformationReadyEventDataAsset """Information about the source video asset being transformed.""" - transformation: DataTransformation + transformation: VideoTransformationReadyEventDataTransformation -class Request(BaseModel): +class VideoTransformationReadyEventRequest(BaseModel): url: str """Full URL of the transformation request that was submitted.""" @@ -104,7 +105,7 @@ class Request(BaseModel): """User-Agent header from the original request that triggered the transformation.""" -class Timings(BaseModel): +class VideoTransformationReadyEventTimings(BaseModel): download_duration: Optional[int] = None """ Time spent downloading the source video from your origin or media library, in @@ -115,19 +116,16 @@ class Timings(BaseModel): """Time spent encoding the video, in milliseconds.""" -class VideoTransformationReadyEvent(BaseModel): - id: str - """Unique identifier for the event.""" - +class VideoTransformationReadyEvent(BaseWebhookEvent): created_at: datetime """Timestamp when the event was created in ISO8601 format.""" - data: Data + data: VideoTransformationReadyEventData - request: Request + request: VideoTransformationReadyEventRequest """Information about the original request that triggered the video transformation.""" - type: Literal["video.transformation.ready"] + type: Literal["video.transformation.ready"] # type: ignore - timings: Optional[Timings] = None + timings: Optional[VideoTransformationReadyEventTimings] = None """Performance metrics for the transformation process.""" diff --git a/tests/api_resources/test_webhooks.py b/tests/api_resources/test_webhooks.py index d12bd64..7ed992b 100644 --- a/tests/api_resources/test_webhooks.py +++ b/tests/api_resources/test_webhooks.py @@ -20,7 +20,7 @@ def test_method_unwrap(self, client: ImageKit) -> None: key = b"secret" hook = standardwebhooks.Webhook(key) - data = """{"id":"id","created_at":"2019-12-27T18:11:19.117Z","data":{"asset":{"url":"https://example.com"},"transformation":{"type":"video-transformation","options":{"audio_codec":"aac","auto_rotate":true,"format":"mp4","quality":0,"stream_protocol":"HLS","variants":["string"],"video_codec":"h264"}}},"request":{"url":"https://example.com","x_request_id":"x_request_id","user_agent":"user_agent"},"type":"video.transformation.accepted"}""" + data = """{"id":"id","type":"video.transformation.accepted","created_at":"2019-12-27T18:11:19.117Z","data":{"asset":{"url":"https://example.com"},"transformation":{"type":"video-transformation","options":{"audio_codec":"aac","auto_rotate":true,"format":"mp4","quality":0,"stream_protocol":"HLS","variants":["string"],"video_codec":"h264"}}},"request":{"url":"https://example.com","x_request_id":"x_request_id","user_agent":"user_agent"}}""" msg_id = "1" timestamp = datetime.now(tz=timezone.utc) sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data) @@ -54,7 +54,7 @@ def test_method_unwrap(self, client: ImageKit) -> None: key = b"secret" hook = standardwebhooks.Webhook(key) - data = """{"id":"id","created_at":"2019-12-27T18:11:19.117Z","data":{"asset":{"url":"https://example.com"},"transformation":{"type":"video-transformation","options":{"audio_codec":"aac","auto_rotate":true,"format":"mp4","quality":0,"stream_protocol":"HLS","variants":["string"],"video_codec":"h264"}}},"request":{"url":"https://example.com","x_request_id":"x_request_id","user_agent":"user_agent"},"type":"video.transformation.accepted"}""" + data = """{"id":"id","type":"video.transformation.accepted","created_at":"2019-12-27T18:11:19.117Z","data":{"asset":{"url":"https://example.com"},"transformation":{"type":"video-transformation","options":{"audio_codec":"aac","auto_rotate":true,"format":"mp4","quality":0,"stream_protocol":"HLS","variants":["string"],"video_codec":"h264"}}},"request":{"url":"https://example.com","x_request_id":"x_request_id","user_agent":"user_agent"}}""" msg_id = "1" timestamp = datetime.now(tz=timezone.utc) sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data) From b50d9c15a9f25ae334086e56fd4ac95edfc8b26d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 08:15:36 +0000 Subject: [PATCH 096/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 52f982b..cfcbd7f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-667f7f4988b44bc587d6eb9960ff5c8326e9f7e9b072f3f724f9f54166eff8b1.yml openapi_spec_hash: f2081864a4abee0480e5ff991b4c936a -config_hash: 08e12746cdca1c59c897cf2e50893c3c +config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c From a66a819953b9d217d6793df5f0bda61cfeac9f57 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 08:18:20 +0000 Subject: [PATCH 097/177] feat(api): manual updates --- .stats.yml | 4 +- README.md | 20 ++-- src/imagekit/resources/files/files.py | 126 +++++++++++------------ src/imagekit/types/file_upload_params.py | 3 +- tests/api_resources/test_files.py | 16 +-- tests/test_client.py | 36 +++++-- 6 files changed, 108 insertions(+), 97 deletions(-) diff --git a/.stats.yml b/.stats.yml index cfcbd7f..282d18e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-667f7f4988b44bc587d6eb9960ff5c8326e9f7e9b072f3f724f9f54166eff8b1.yml -openapi_spec_hash: f2081864a4abee0480e5ff991b4c936a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-eab9713fd85da68b41e881dfd9cd71f654e8620132da2023bab7dd01e5f7852e.yml +openapi_spec_hash: b5037b26fbe7360c6bfaf9947a65bb85 config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c diff --git a/README.md b/README.md index 19cc02b..cfa6b74 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ client = ImageKit( ) response = client.files.upload( - file=b"https://www.example.com/public-url.jpg", + file="https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) print(response.video_codec) @@ -73,7 +73,7 @@ client = AsyncImageKit( async def main() -> None: response = await client.files.upload( - file=b"https://www.example.com/public-url.jpg", + file="https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) print(response.video_codec) @@ -110,7 +110,7 @@ async def main() -> None: http_client=DefaultAioHttpClient(), ) as client: response = await client.files.upload( - file=b"https://www.example.com/public-url.jpg", + file="https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) print(response.video_codec) @@ -138,7 +138,7 @@ from imagekit import ImageKit client = ImageKit() response = client.files.upload( - file=b"raw file contents", + file="https://www.example.com/path/to-image.jpg", file_name="fileName", transformation={ "post": [ @@ -167,7 +167,7 @@ from imagekit import ImageKit client = ImageKit() -client.files.upload( +client.beta.v2.files.upload( file=Path("/path/to/file"), file_name="fileName", ) @@ -192,7 +192,7 @@ client = ImageKit() try: client.files.upload( - file=b"https://www.example.com/public-url.jpg", + file="https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) except imagekit.APIConnectionError as e: @@ -238,7 +238,7 @@ client = ImageKit( # Or, configure per-request: client.with_options(max_retries=5).files.upload( - file=b"https://www.example.com/public-url.jpg", + file="https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) ``` @@ -264,7 +264,7 @@ client = ImageKit( # Override per-request: client.with_options(timeout=5.0).files.upload( - file=b"https://www.example.com/public-url.jpg", + file="https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) ``` @@ -308,7 +308,7 @@ from imagekit import ImageKit client = ImageKit() response = client.files.with_raw_response.upload( - file=b"https://www.example.com/public-url.jpg", + file="https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) print(response.headers.get('X-My-Header')) @@ -329,7 +329,7 @@ To stream the response body, use `.with_streaming_response` instead, which requi ```python with client.files.with_streaming_response.upload( - file=b"https://www.example.com/public-url.jpg", + file="https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) as response: print(response.headers.get("X-My-Header")) diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 12ef720..1013f5f 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, List, Mapping, Iterable, cast +from typing import Dict, List, Iterable from typing_extensions import Literal import httpx @@ -16,8 +16,8 @@ AsyncBulkResourceWithStreamingResponse, ) from ...types import file_copy_params, file_move_params, file_rename_params, file_update_params, file_upload_params -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes -from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +from ..._utils import maybe_transform, async_maybe_transform from .metadata import ( MetadataResource, AsyncMetadataResource, @@ -368,7 +368,7 @@ def rename( def upload( self, *, - file: FileTypes, + file: str, file_name: str, token: str | NotGiven = NOT_GIVEN, checks: str | NotGiven = NOT_GIVEN, @@ -579,34 +579,6 @@ def upload( timeout: Override the client-level default timeout for this request, in seconds """ - body = deepcopy_minimal( - { - "file": file, - "file_name": file_name, - "token": token, - "checks": checks, - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "description": description, - "expire": expire, - "extensions": extensions, - "folder": folder, - "is_private_file": is_private_file, - "is_published": is_published, - "overwrite_ai_tags": overwrite_ai_tags, - "overwrite_custom_metadata": overwrite_custom_metadata, - "overwrite_file": overwrite_file, - "overwrite_tags": overwrite_tags, - "public_key": public_key, - "response_fields": response_fields, - "signature": signature, - "tags": tags, - "transformation": transformation, - "use_unique_file_name": use_unique_file_name, - "webhook_url": webhook_url, - } - ) - files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- @@ -615,8 +587,34 @@ def upload( "/api/v1/files/upload" if self._client._base_url_overridden else "https://upload.imagekit.io/api/v1/files/upload", - body=maybe_transform(body, file_upload_params.FileUploadParams), - files=files, + body=maybe_transform( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "expire": expire, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "public_key": public_key, + "response_fields": response_fields, + "signature": signature, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + }, + file_upload_params.FileUploadParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -939,7 +937,7 @@ async def rename( async def upload( self, *, - file: FileTypes, + file: str, file_name: str, token: str | NotGiven = NOT_GIVEN, checks: str | NotGiven = NOT_GIVEN, @@ -1150,34 +1148,6 @@ async def upload( timeout: Override the client-level default timeout for this request, in seconds """ - body = deepcopy_minimal( - { - "file": file, - "file_name": file_name, - "token": token, - "checks": checks, - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "description": description, - "expire": expire, - "extensions": extensions, - "folder": folder, - "is_private_file": is_private_file, - "is_published": is_published, - "overwrite_ai_tags": overwrite_ai_tags, - "overwrite_custom_metadata": overwrite_custom_metadata, - "overwrite_file": overwrite_file, - "overwrite_tags": overwrite_tags, - "public_key": public_key, - "response_fields": response_fields, - "signature": signature, - "tags": tags, - "transformation": transformation, - "use_unique_file_name": use_unique_file_name, - "webhook_url": webhook_url, - } - ) - files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- @@ -1186,8 +1156,34 @@ async def upload( "/api/v1/files/upload" if self._client._base_url_overridden else "https://upload.imagekit.io/api/v1/files/upload", - body=await async_maybe_transform(body, file_upload_params.FileUploadParams), - files=files, + body=await async_maybe_transform( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "expire": expire, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "public_key": public_key, + "response_fields": response_fields, + "signature": signature, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + }, + file_upload_params.FileUploadParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 228e681..51c430c 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -5,7 +5,6 @@ from typing import Dict, List, Union, Iterable from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from .._types import FileTypes from .._utils import PropertyInfo __all__ = [ @@ -25,7 +24,7 @@ class FileUploadParams(TypedDict, total=False): - file: Required[FileTypes] + file: Required[str] """The API accepts any of the following: - **Binary data** – send the raw bytes as `multipart/form-data`. diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index f639534..d7ef6b3 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -326,7 +326,7 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: @parametrize def test_method_upload(self, client: ImageKit) -> None: file = client.files.upload( - file=b"raw file contents", + file="https://www.example.com/path/to-image.jpg", file_name="fileName", ) assert_matches_type(FileUploadResponse, file, path=["response"]) @@ -335,7 +335,7 @@ def test_method_upload(self, client: ImageKit) -> None: @parametrize def test_method_upload_with_all_params(self, client: ImageKit) -> None: file = client.files.upload( - file=b"raw file contents", + file="https://www.example.com/path/to-image.jpg", file_name="fileName", token="token", checks='"request.folder" : "marketing/"\n', @@ -397,7 +397,7 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: @parametrize def test_raw_response_upload(self, client: ImageKit) -> None: response = client.files.with_raw_response.upload( - file=b"raw file contents", + file="https://www.example.com/path/to-image.jpg", file_name="fileName", ) @@ -410,7 +410,7 @@ def test_raw_response_upload(self, client: ImageKit) -> None: @parametrize def test_streaming_response_upload(self, client: ImageKit) -> None: with client.files.with_streaming_response.upload( - file=b"raw file contents", + file="https://www.example.com/path/to-image.jpg", file_name="fileName", ) as response: assert not response.is_closed @@ -729,7 +729,7 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N @parametrize async def test_method_upload(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( - file=b"raw file contents", + file="https://www.example.com/path/to-image.jpg", file_name="fileName", ) assert_matches_type(FileUploadResponse, file, path=["response"]) @@ -738,7 +738,7 @@ async def test_method_upload(self, async_client: AsyncImageKit) -> None: @parametrize async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( - file=b"raw file contents", + file="https://www.example.com/path/to-image.jpg", file_name="fileName", token="token", checks='"request.folder" : "marketing/"\n', @@ -800,7 +800,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) @parametrize async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.upload( - file=b"raw file contents", + file="https://www.example.com/path/to-image.jpg", file_name="fileName", ) @@ -813,7 +813,7 @@ async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: @parametrize async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.upload( - file=b"raw file contents", + file="https://www.example.com/path/to-image.jpg", file_name="fileName", ) as response: assert not response.is_closed diff --git a/tests/test_client.py b/tests/test_client.py index ddb5db7..7b9e889 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -806,7 +806,9 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien respx_mock.post("/api/v1/files/upload").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - client.files.with_streaming_response.upload(file=b"raw file contents", file_name="fileName").__enter__() + client.files.with_streaming_response.upload( + file="https://www.example.com/path/to-image.jpg", file_name="fileName" + ).__enter__() assert _get_open_connections(self.client) == 0 @@ -816,7 +818,9 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client respx_mock.post("/api/v1/files/upload").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - client.files.with_streaming_response.upload(file=b"raw file contents", file_name="fileName").__enter__() + client.files.with_streaming_response.upload( + file="https://www.example.com/path/to-image.jpg", file_name="fileName" + ).__enter__() assert _get_open_connections(self.client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @@ -845,7 +849,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = client.files.with_raw_response.upload(file=b"raw file contents", file_name="fileName") + response = client.files.with_raw_response.upload( + file="https://www.example.com/path/to-image.jpg", file_name="fileName" + ) assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -870,7 +876,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = client.files.with_raw_response.upload( - file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": Omit()} + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + extra_headers={"x-stainless-retry-count": Omit()}, ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -895,7 +903,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = client.files.with_raw_response.upload( - file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": "42"} + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + extra_headers={"x-stainless-retry-count": "42"}, ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1706,7 +1716,7 @@ async def test_retrying_timeout_errors_doesnt_leak( with pytest.raises(APITimeoutError): await async_client.files.with_streaming_response.upload( - file=b"raw file contents", file_name="fileName" + file="https://www.example.com/path/to-image.jpg", file_name="fileName" ).__aenter__() assert _get_open_connections(self.client) == 0 @@ -1720,7 +1730,7 @@ async def test_retrying_status_errors_doesnt_leak( with pytest.raises(APIStatusError): await async_client.files.with_streaming_response.upload( - file=b"raw file contents", file_name="fileName" + file="https://www.example.com/path/to-image.jpg", file_name="fileName" ).__aenter__() assert _get_open_connections(self.client) == 0 @@ -1751,7 +1761,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = await client.files.with_raw_response.upload(file=b"raw file contents", file_name="fileName") + response = await client.files.with_raw_response.upload( + file="https://www.example.com/path/to-image.jpg", file_name="fileName" + ) assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1777,7 +1789,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = await client.files.with_raw_response.upload( - file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": Omit()} + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + extra_headers={"x-stainless-retry-count": Omit()}, ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -1803,7 +1817,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = await client.files.with_raw_response.upload( - file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": "42"} + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + extra_headers={"x-stainless-retry-count": "42"}, ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" From 5a22deb5eae7a106a511d71f65c7c0e4fb664f3a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 08:21:15 +0000 Subject: [PATCH 098/177] feat(api): manual updates --- .stats.yml | 4 ++-- README.md | 2 +- tests/api_resources/test_files.py | 16 ++++++------- tests/test_client.py | 40 ++++++++----------------------- 4 files changed, 21 insertions(+), 41 deletions(-) diff --git a/.stats.yml b/.stats.yml index 282d18e..7698a81 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-eab9713fd85da68b41e881dfd9cd71f654e8620132da2023bab7dd01e5f7852e.yml -openapi_spec_hash: b5037b26fbe7360c6bfaf9947a65bb85 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-911102f2eaf3be4b34381f6ba089330bed099bb72eb93667ce2f6e72b5934c8c.yml +openapi_spec_hash: 637ad417a580137914441bd790b04cc2 config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c diff --git a/README.md b/README.md index cfa6b74..a4d7e93 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ from imagekit import ImageKit client = ImageKit() response = client.files.upload( - file="https://www.example.com/path/to-image.jpg", + file="file", file_name="fileName", transformation={ "post": [ diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index d7ef6b3..cd72d5c 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -326,7 +326,7 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: @parametrize def test_method_upload(self, client: ImageKit) -> None: file = client.files.upload( - file="https://www.example.com/path/to-image.jpg", + file="file", file_name="fileName", ) assert_matches_type(FileUploadResponse, file, path=["response"]) @@ -335,7 +335,7 @@ def test_method_upload(self, client: ImageKit) -> None: @parametrize def test_method_upload_with_all_params(self, client: ImageKit) -> None: file = client.files.upload( - file="https://www.example.com/path/to-image.jpg", + file="file", file_name="fileName", token="token", checks='"request.folder" : "marketing/"\n', @@ -397,7 +397,7 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: @parametrize def test_raw_response_upload(self, client: ImageKit) -> None: response = client.files.with_raw_response.upload( - file="https://www.example.com/path/to-image.jpg", + file="file", file_name="fileName", ) @@ -410,7 +410,7 @@ def test_raw_response_upload(self, client: ImageKit) -> None: @parametrize def test_streaming_response_upload(self, client: ImageKit) -> None: with client.files.with_streaming_response.upload( - file="https://www.example.com/path/to-image.jpg", + file="file", file_name="fileName", ) as response: assert not response.is_closed @@ -729,7 +729,7 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N @parametrize async def test_method_upload(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( - file="https://www.example.com/path/to-image.jpg", + file="file", file_name="fileName", ) assert_matches_type(FileUploadResponse, file, path=["response"]) @@ -738,7 +738,7 @@ async def test_method_upload(self, async_client: AsyncImageKit) -> None: @parametrize async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( - file="https://www.example.com/path/to-image.jpg", + file="file", file_name="fileName", token="token", checks='"request.folder" : "marketing/"\n', @@ -800,7 +800,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) @parametrize async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.upload( - file="https://www.example.com/path/to-image.jpg", + file="file", file_name="fileName", ) @@ -813,7 +813,7 @@ async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: @parametrize async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.upload( - file="https://www.example.com/path/to-image.jpg", + file="file", file_name="fileName", ) as response: assert not response.is_closed diff --git a/tests/test_client.py b/tests/test_client.py index 7b9e889..ff34aa1 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -806,9 +806,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien respx_mock.post("/api/v1/files/upload").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - client.files.with_streaming_response.upload( - file="https://www.example.com/path/to-image.jpg", file_name="fileName" - ).__enter__() + client.files.with_streaming_response.upload(file="file", file_name="fileName").__enter__() assert _get_open_connections(self.client) == 0 @@ -818,9 +816,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client respx_mock.post("/api/v1/files/upload").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - client.files.with_streaming_response.upload( - file="https://www.example.com/path/to-image.jpg", file_name="fileName" - ).__enter__() + client.files.with_streaming_response.upload(file="file", file_name="fileName").__enter__() assert _get_open_connections(self.client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @@ -849,9 +845,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = client.files.with_raw_response.upload( - file="https://www.example.com/path/to-image.jpg", file_name="fileName" - ) + response = client.files.with_raw_response.upload(file="file", file_name="fileName") assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -876,9 +870,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = client.files.with_raw_response.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - extra_headers={"x-stainless-retry-count": Omit()}, + file="file", file_name="fileName", extra_headers={"x-stainless-retry-count": Omit()} ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -903,9 +895,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = client.files.with_raw_response.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - extra_headers={"x-stainless-retry-count": "42"}, + file="file", file_name="fileName", extra_headers={"x-stainless-retry-count": "42"} ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1715,9 +1705,7 @@ async def test_retrying_timeout_errors_doesnt_leak( respx_mock.post("/api/v1/files/upload").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - await async_client.files.with_streaming_response.upload( - file="https://www.example.com/path/to-image.jpg", file_name="fileName" - ).__aenter__() + await async_client.files.with_streaming_response.upload(file="file", file_name="fileName").__aenter__() assert _get_open_connections(self.client) == 0 @@ -1729,9 +1717,7 @@ async def test_retrying_status_errors_doesnt_leak( respx_mock.post("/api/v1/files/upload").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - await async_client.files.with_streaming_response.upload( - file="https://www.example.com/path/to-image.jpg", file_name="fileName" - ).__aenter__() + await async_client.files.with_streaming_response.upload(file="file", file_name="fileName").__aenter__() assert _get_open_connections(self.client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @@ -1761,9 +1747,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = await client.files.with_raw_response.upload( - file="https://www.example.com/path/to-image.jpg", file_name="fileName" - ) + response = await client.files.with_raw_response.upload(file="file", file_name="fileName") assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1789,9 +1773,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = await client.files.with_raw_response.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - extra_headers={"x-stainless-retry-count": Omit()}, + file="file", file_name="fileName", extra_headers={"x-stainless-retry-count": Omit()} ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -1817,9 +1799,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = await client.files.with_raw_response.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - extra_headers={"x-stainless-retry-count": "42"}, + file="file", file_name="fileName", extra_headers={"x-stainless-retry-count": "42"} ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" From fe0a95bbaf307ccca0604e0a63e438583cabf2c9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 08:23:23 +0000 Subject: [PATCH 099/177] feat(api): manual updates --- .stats.yml | 4 +- README.md | 20 ++-- src/imagekit/resources/files/files.py | 126 ++++++++++++----------- src/imagekit/types/file_upload_params.py | 3 +- tests/api_resources/test_files.py | 16 +-- tests/test_client.py | 24 +++-- 6 files changed, 101 insertions(+), 92 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7698a81..d42605f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-911102f2eaf3be4b34381f6ba089330bed099bb72eb93667ce2f6e72b5934c8c.yml -openapi_spec_hash: 637ad417a580137914441bd790b04cc2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0726d89b19f532c7fb92990d688a9bfb5aa4a9a871d64f49d4ba45bac6998e4a.yml +openapi_spec_hash: 9525bb02ab496b3459a1f93ac50968e3 config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c diff --git a/README.md b/README.md index a4d7e93..19cc02b 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ client = ImageKit( ) response = client.files.upload( - file="https://www.example.com/public-url.jpg", + file=b"https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) print(response.video_codec) @@ -73,7 +73,7 @@ client = AsyncImageKit( async def main() -> None: response = await client.files.upload( - file="https://www.example.com/public-url.jpg", + file=b"https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) print(response.video_codec) @@ -110,7 +110,7 @@ async def main() -> None: http_client=DefaultAioHttpClient(), ) as client: response = await client.files.upload( - file="https://www.example.com/public-url.jpg", + file=b"https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) print(response.video_codec) @@ -138,7 +138,7 @@ from imagekit import ImageKit client = ImageKit() response = client.files.upload( - file="file", + file=b"raw file contents", file_name="fileName", transformation={ "post": [ @@ -167,7 +167,7 @@ from imagekit import ImageKit client = ImageKit() -client.beta.v2.files.upload( +client.files.upload( file=Path("/path/to/file"), file_name="fileName", ) @@ -192,7 +192,7 @@ client = ImageKit() try: client.files.upload( - file="https://www.example.com/public-url.jpg", + file=b"https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) except imagekit.APIConnectionError as e: @@ -238,7 +238,7 @@ client = ImageKit( # Or, configure per-request: client.with_options(max_retries=5).files.upload( - file="https://www.example.com/public-url.jpg", + file=b"https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) ``` @@ -264,7 +264,7 @@ client = ImageKit( # Override per-request: client.with_options(timeout=5.0).files.upload( - file="https://www.example.com/public-url.jpg", + file=b"https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) ``` @@ -308,7 +308,7 @@ from imagekit import ImageKit client = ImageKit() response = client.files.with_raw_response.upload( - file="https://www.example.com/public-url.jpg", + file=b"https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) print(response.headers.get('X-My-Header')) @@ -329,7 +329,7 @@ To stream the response body, use `.with_streaming_response` instead, which requi ```python with client.files.with_streaming_response.upload( - file="https://www.example.com/public-url.jpg", + file=b"https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) as response: print(response.headers.get("X-My-Header")) diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 1013f5f..12ef720 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, List, Iterable +from typing import Dict, List, Mapping, Iterable, cast from typing_extensions import Literal import httpx @@ -16,8 +16,8 @@ AsyncBulkResourceWithStreamingResponse, ) from ...types import file_copy_params, file_move_params, file_rename_params, file_update_params, file_upload_params -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from ..._utils import maybe_transform, async_maybe_transform +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes +from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from .metadata import ( MetadataResource, AsyncMetadataResource, @@ -368,7 +368,7 @@ def rename( def upload( self, *, - file: str, + file: FileTypes, file_name: str, token: str | NotGiven = NOT_GIVEN, checks: str | NotGiven = NOT_GIVEN, @@ -579,6 +579,34 @@ def upload( timeout: Override the client-level default timeout for this request, in seconds """ + body = deepcopy_minimal( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "expire": expire, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "public_key": public_key, + "response_fields": response_fields, + "signature": signature, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + } + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- @@ -587,34 +615,8 @@ def upload( "/api/v1/files/upload" if self._client._base_url_overridden else "https://upload.imagekit.io/api/v1/files/upload", - body=maybe_transform( - { - "file": file, - "file_name": file_name, - "token": token, - "checks": checks, - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "description": description, - "expire": expire, - "extensions": extensions, - "folder": folder, - "is_private_file": is_private_file, - "is_published": is_published, - "overwrite_ai_tags": overwrite_ai_tags, - "overwrite_custom_metadata": overwrite_custom_metadata, - "overwrite_file": overwrite_file, - "overwrite_tags": overwrite_tags, - "public_key": public_key, - "response_fields": response_fields, - "signature": signature, - "tags": tags, - "transformation": transformation, - "use_unique_file_name": use_unique_file_name, - "webhook_url": webhook_url, - }, - file_upload_params.FileUploadParams, - ), + body=maybe_transform(body, file_upload_params.FileUploadParams), + files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -937,7 +939,7 @@ async def rename( async def upload( self, *, - file: str, + file: FileTypes, file_name: str, token: str | NotGiven = NOT_GIVEN, checks: str | NotGiven = NOT_GIVEN, @@ -1148,6 +1150,34 @@ async def upload( timeout: Override the client-level default timeout for this request, in seconds """ + body = deepcopy_minimal( + { + "file": file, + "file_name": file_name, + "token": token, + "checks": checks, + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "expire": expire, + "extensions": extensions, + "folder": folder, + "is_private_file": is_private_file, + "is_published": is_published, + "overwrite_ai_tags": overwrite_ai_tags, + "overwrite_custom_metadata": overwrite_custom_metadata, + "overwrite_file": overwrite_file, + "overwrite_tags": overwrite_tags, + "public_key": public_key, + "response_fields": response_fields, + "signature": signature, + "tags": tags, + "transformation": transformation, + "use_unique_file_name": use_unique_file_name, + "webhook_url": webhook_url, + } + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- @@ -1156,34 +1186,8 @@ async def upload( "/api/v1/files/upload" if self._client._base_url_overridden else "https://upload.imagekit.io/api/v1/files/upload", - body=await async_maybe_transform( - { - "file": file, - "file_name": file_name, - "token": token, - "checks": checks, - "custom_coordinates": custom_coordinates, - "custom_metadata": custom_metadata, - "description": description, - "expire": expire, - "extensions": extensions, - "folder": folder, - "is_private_file": is_private_file, - "is_published": is_published, - "overwrite_ai_tags": overwrite_ai_tags, - "overwrite_custom_metadata": overwrite_custom_metadata, - "overwrite_file": overwrite_file, - "overwrite_tags": overwrite_tags, - "public_key": public_key, - "response_fields": response_fields, - "signature": signature, - "tags": tags, - "transformation": transformation, - "use_unique_file_name": use_unique_file_name, - "webhook_url": webhook_url, - }, - file_upload_params.FileUploadParams, - ), + body=await async_maybe_transform(body, file_upload_params.FileUploadParams), + files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 51c430c..228e681 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -5,6 +5,7 @@ from typing import Dict, List, Union, Iterable from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from .._types import FileTypes from .._utils import PropertyInfo __all__ = [ @@ -24,7 +25,7 @@ class FileUploadParams(TypedDict, total=False): - file: Required[str] + file: Required[FileTypes] """The API accepts any of the following: - **Binary data** – send the raw bytes as `multipart/form-data`. diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index cd72d5c..f639534 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -326,7 +326,7 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: @parametrize def test_method_upload(self, client: ImageKit) -> None: file = client.files.upload( - file="file", + file=b"raw file contents", file_name="fileName", ) assert_matches_type(FileUploadResponse, file, path=["response"]) @@ -335,7 +335,7 @@ def test_method_upload(self, client: ImageKit) -> None: @parametrize def test_method_upload_with_all_params(self, client: ImageKit) -> None: file = client.files.upload( - file="file", + file=b"raw file contents", file_name="fileName", token="token", checks='"request.folder" : "marketing/"\n', @@ -397,7 +397,7 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: @parametrize def test_raw_response_upload(self, client: ImageKit) -> None: response = client.files.with_raw_response.upload( - file="file", + file=b"raw file contents", file_name="fileName", ) @@ -410,7 +410,7 @@ def test_raw_response_upload(self, client: ImageKit) -> None: @parametrize def test_streaming_response_upload(self, client: ImageKit) -> None: with client.files.with_streaming_response.upload( - file="file", + file=b"raw file contents", file_name="fileName", ) as response: assert not response.is_closed @@ -729,7 +729,7 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N @parametrize async def test_method_upload(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( - file="file", + file=b"raw file contents", file_name="fileName", ) assert_matches_type(FileUploadResponse, file, path=["response"]) @@ -738,7 +738,7 @@ async def test_method_upload(self, async_client: AsyncImageKit) -> None: @parametrize async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( - file="file", + file=b"raw file contents", file_name="fileName", token="token", checks='"request.folder" : "marketing/"\n', @@ -800,7 +800,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) @parametrize async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.upload( - file="file", + file=b"raw file contents", file_name="fileName", ) @@ -813,7 +813,7 @@ async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: @parametrize async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.upload( - file="file", + file=b"raw file contents", file_name="fileName", ) as response: assert not response.is_closed diff --git a/tests/test_client.py b/tests/test_client.py index ff34aa1..ddb5db7 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -806,7 +806,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien respx_mock.post("/api/v1/files/upload").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - client.files.with_streaming_response.upload(file="file", file_name="fileName").__enter__() + client.files.with_streaming_response.upload(file=b"raw file contents", file_name="fileName").__enter__() assert _get_open_connections(self.client) == 0 @@ -816,7 +816,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client respx_mock.post("/api/v1/files/upload").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - client.files.with_streaming_response.upload(file="file", file_name="fileName").__enter__() + client.files.with_streaming_response.upload(file=b"raw file contents", file_name="fileName").__enter__() assert _get_open_connections(self.client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @@ -845,7 +845,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = client.files.with_raw_response.upload(file="file", file_name="fileName") + response = client.files.with_raw_response.upload(file=b"raw file contents", file_name="fileName") assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -870,7 +870,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = client.files.with_raw_response.upload( - file="file", file_name="fileName", extra_headers={"x-stainless-retry-count": Omit()} + file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": Omit()} ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -895,7 +895,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = client.files.with_raw_response.upload( - file="file", file_name="fileName", extra_headers={"x-stainless-retry-count": "42"} + file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": "42"} ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1705,7 +1705,9 @@ async def test_retrying_timeout_errors_doesnt_leak( respx_mock.post("/api/v1/files/upload").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - await async_client.files.with_streaming_response.upload(file="file", file_name="fileName").__aenter__() + await async_client.files.with_streaming_response.upload( + file=b"raw file contents", file_name="fileName" + ).__aenter__() assert _get_open_connections(self.client) == 0 @@ -1717,7 +1719,9 @@ async def test_retrying_status_errors_doesnt_leak( respx_mock.post("/api/v1/files/upload").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - await async_client.files.with_streaming_response.upload(file="file", file_name="fileName").__aenter__() + await async_client.files.with_streaming_response.upload( + file=b"raw file contents", file_name="fileName" + ).__aenter__() assert _get_open_connections(self.client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @@ -1747,7 +1751,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) - response = await client.files.with_raw_response.upload(file="file", file_name="fileName") + response = await client.files.with_raw_response.upload(file=b"raw file contents", file_name="fileName") assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1773,7 +1777,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = await client.files.with_raw_response.upload( - file="file", file_name="fileName", extra_headers={"x-stainless-retry-count": Omit()} + file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": Omit()} ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -1799,7 +1803,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/api/v1/files/upload").mock(side_effect=retry_handler) response = await client.files.with_raw_response.upload( - file="file", file_name="fileName", extra_headers={"x-stainless-retry-count": "42"} + file=b"raw file contents", file_name="fileName", extra_headers={"x-stainless-retry-count": "42"} ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" From 72a0a170a9528948bf695816945e37ed0d0ff340 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 08:32:35 +0000 Subject: [PATCH 100/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d42605f..cfcbd7f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0726d89b19f532c7fb92990d688a9bfb5aa4a9a871d64f49d4ba45bac6998e4a.yml -openapi_spec_hash: 9525bb02ab496b3459a1f93ac50968e3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-667f7f4988b44bc587d6eb9960ff5c8326e9f7e9b072f3f724f9f54166eff8b1.yml +openapi_spec_hash: f2081864a4abee0480e5ff991b4c936a config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c From 914da3aebaaa85389b8862edcbdac3baafe7a1a4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 09:03:04 +0000 Subject: [PATCH 101/177] feat(api): manual updates --- .stats.yml | 4 +- src/imagekit/resources/files/files.py | 528 ++++++++++++++++++++++- src/imagekit/types/file_upload_params.py | 407 +++++++++++++++-- tests/api_resources/test_files.py | 214 ++++++++- 4 files changed, 1109 insertions(+), 44 deletions(-) diff --git a/.stats.yml b/.stats.yml index cfcbd7f..d458a07 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-667f7f4988b44bc587d6eb9960ff5c8326e9f7e9b072f3f724f9f54166eff8b1.yml -openapi_spec_hash: f2081864a4abee0480e5ff991b4c936a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-e7bc47a9221d7da9c8c9653d3fd1d4cfdf2408588e32c4aa62bd02a50ec93c36.yml +openapi_spec_hash: 8d061396a2fff9d1add4d5baf03ab939 config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 12ef720..899d795 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Dict, List, Mapping, Iterable, cast -from typing_extensions import Literal +from typing_extensions import Literal, overload import httpx @@ -17,7 +17,7 @@ ) from ...types import file_copy_params, file_move_params, file_rename_params, file_update_params, file_upload_params from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes -from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform +from ..._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform from .metadata import ( MetadataResource, AsyncMetadataResource, @@ -365,6 +365,7 @@ def rename( cast_to=FileRenameResponse, ) + @overload def upload( self, *, @@ -376,7 +377,7 @@ def upload( custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, @@ -399,7 +400,7 @@ def upload( | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, tags: List[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -579,6 +580,263 @@ def upload( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @overload + def upload( + self, + *, + file: str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + expire: int | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadV1ByURLExtension] | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, + public_key: str | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + tags: List[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadV1ByURLTransformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadResponse: + """ + ImageKit.io allows you to upload files directly from both the server and client + sides. For server-side uploads, private API key authentication is used. For + client-side uploads, generate a one-time `token`, `signature`, and `expire` from + your secure backend using private API. + [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) + about how to implement client-side file upload. + + The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security + by verifying the entire payload using JWT. + + **File size limit** \\ + On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw + files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, + audio, and raw files and 2GB for videos. These limits can be further increased with + higher-tier plans. + + **Version limit** \\ + A file can have a maximum of 100 versions. + + **Demo applications** + + - A full-fledged + [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + supporting file selections from local storage, URL, Dropbox, Google Drive, + Instagram, and more. + - [Quick start guides](/docs/quick-start-guides) for various frameworks and + technologies. + + Args: + file: A publicly reachable URL that ImageKit’s servers can fetch. The server must + receive the response headers within 8 seconds; otherwise the request fails with + 400 Bad Request. + + file_name: + The name with which the file has to be uploaded. The file name can contain: + + - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + - Special Characters: `.`, `-` + + Any other character including space will be replaced by `_` + + token: A unique value that the ImageKit.io server will use to recognize and prevent + subsequent retries for the same request. We suggest using V4 UUIDs, or another + random string with enough entropy to avoid collisions. This field is only + required for authentication when uploading a file from the client side. + + **Note**: Sending a value that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new value for this field. + + checks: Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + + custom_coordinates: Define an important area in the image. This is only relevant for image type + files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + + custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata + fields before setting these values. + + description: Optional text to describe the contents of the file. + + expire: The time until your signature is valid. It must be a + [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into + the future. It should be in seconds. This field is only required for + authentication when uploading a file from the client side. + + extensions: Array of extensions to be applied to the image. Each extension can be configured + with specific parameters based on the extension type. + + folder: The folder path in which the image has to be uploaded. If the folder(s) didn't + exist before, a new folder(s) is created. + + The folder name can contain: + + - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + - Special Characters: `/` , `_` , `-` + + Using multiple `/` creates a nested folder. + + is_private_file: Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + + is_published: Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + + overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + + overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + + overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + + overwrite_tags: If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + + public_key: Your ImageKit.io public key. This field is only required for authentication when + uploading a file from the client side. + + response_fields: Array of response field keys to include in the API response body. + + signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a + key. Learn how to create a signature on the page below. This should be in + lowercase. + + Signature must be calculated on the server-side. This field is only required for + authentication when uploading a file from the client side. + + tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. + + transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + + use_unique_file_name: Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["file", "file_name"]) + def upload( + self, + *, + file: FileTypes | str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + expire: int | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, + public_key: str | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + tags: List[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadResponse: body = deepcopy_minimal( { "file": file, @@ -936,6 +1194,7 @@ async def rename( cast_to=FileRenameResponse, ) + @overload async def upload( self, *, @@ -947,7 +1206,7 @@ async def upload( custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, @@ -970,7 +1229,7 @@ async def upload( | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, tags: List[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -1150,6 +1409,263 @@ async def upload( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @overload + async def upload( + self, + *, + file: str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + expire: int | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadV1ByURLExtension] | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, + public_key: str | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + tags: List[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadV1ByURLTransformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadResponse: + """ + ImageKit.io allows you to upload files directly from both the server and client + sides. For server-side uploads, private API key authentication is used. For + client-side uploads, generate a one-time `token`, `signature`, and `expire` from + your secure backend using private API. + [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) + about how to implement client-side file upload. + + The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security + by verifying the entire payload using JWT. + + **File size limit** \\ + On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw + files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, + audio, and raw files and 2GB for videos. These limits can be further increased with + higher-tier plans. + + **Version limit** \\ + A file can have a maximum of 100 versions. + + **Demo applications** + + - A full-fledged + [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + supporting file selections from local storage, URL, Dropbox, Google Drive, + Instagram, and more. + - [Quick start guides](/docs/quick-start-guides) for various frameworks and + technologies. + + Args: + file: A publicly reachable URL that ImageKit’s servers can fetch. The server must + receive the response headers within 8 seconds; otherwise the request fails with + 400 Bad Request. + + file_name: + The name with which the file has to be uploaded. The file name can contain: + + - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + - Special Characters: `.`, `-` + + Any other character including space will be replaced by `_` + + token: A unique value that the ImageKit.io server will use to recognize and prevent + subsequent retries for the same request. We suggest using V4 UUIDs, or another + random string with enough entropy to avoid collisions. This field is only + required for authentication when uploading a file from the client side. + + **Note**: Sending a value that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new value for this field. + + checks: Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + + custom_coordinates: Define an important area in the image. This is only relevant for image type + files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + + custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata + fields before setting these values. + + description: Optional text to describe the contents of the file. + + expire: The time until your signature is valid. It must be a + [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into + the future. It should be in seconds. This field is only required for + authentication when uploading a file from the client side. + + extensions: Array of extensions to be applied to the image. Each extension can be configured + with specific parameters based on the extension type. + + folder: The folder path in which the image has to be uploaded. If the folder(s) didn't + exist before, a new folder(s) is created. + + The folder name can contain: + + - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + - Special Characters: `/` , `_` , `-` + + Using multiple `/` creates a nested folder. + + is_private_file: Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + + is_published: Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + + overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + + overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + + overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + + overwrite_tags: If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + + public_key: Your ImageKit.io public key. This field is only required for authentication when + uploading a file from the client side. + + response_fields: Array of response field keys to include in the API response body. + + signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a + key. Learn how to create a signature on the page below. This should be in + lowercase. + + Signature must be calculated on the server-side. This field is only required for + authentication when uploading a file from the client side. + + tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. + + transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + + use_unique_file_name: Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["file", "file_name"]) + async def upload( + self, + *, + file: FileTypes | str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + expire: int | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, + public_key: str | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + tags: List[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadResponse: body = deepcopy_minimal( { "file": file, diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 228e681..ea92822 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -10,21 +10,34 @@ __all__ = [ "FileUploadParams", - "Extension", - "ExtensionRemoveBg", - "ExtensionRemoveBgOptions", - "ExtensionAutoTaggingExtension", - "ExtensionAIAutoDescription", - "Transformation", - "TransformationPost", - "TransformationPostTransformation", - "TransformationPostGifToVideo", - "TransformationPostThumbnail", - "TransformationPostAbs", + "FileUploadV1", + "FileUploadV1Extension", + "FileUploadV1ExtensionRemoveBg", + "FileUploadV1ExtensionRemoveBgOptions", + "FileUploadV1ExtensionAutoTaggingExtension", + "FileUploadV1ExtensionAIAutoDescription", + "FileUploadV1Transformation", + "FileUploadV1TransformationPost", + "FileUploadV1TransformationPostTransformation", + "FileUploadV1TransformationPostGifToVideo", + "FileUploadV1TransformationPostThumbnail", + "FileUploadV1TransformationPostAbs", + "FileUploadV1ByURL", + "FileUploadV1ByURLExtension", + "FileUploadV1ByURLExtensionRemoveBg", + "FileUploadV1ByURLExtensionRemoveBgOptions", + "FileUploadV1ByURLExtensionAutoTaggingExtension", + "FileUploadV1ByURLExtensionAIAutoDescription", + "FileUploadV1ByURLTransformation", + "FileUploadV1ByURLTransformationPost", + "FileUploadV1ByURLTransformationPostTransformation", + "FileUploadV1ByURLTransformationPostGifToVideo", + "FileUploadV1ByURLTransformationPostThumbnail", + "FileUploadV1ByURLTransformationPostAbs", ] -class FileUploadParams(TypedDict, total=False): +class FileUploadV1(TypedDict, total=False): file: Required[FileTypes] """The API accepts any of the following: @@ -94,7 +107,7 @@ class FileUploadParams(TypedDict, total=False): authentication when uploading a file from the client side. """ - extensions: Iterable[Extension] + extensions: Iterable[FileUploadV1Extension] """Array of extensions to be applied to the image. Each extension can be configured with specific parameters based on the extension @@ -197,7 +210,7 @@ class FileUploadParams(TypedDict, total=False): and the file is overwritten, the existing tags will be removed. """ - transformation: Transformation + transformation: FileUploadV1Transformation """Configure pre-processing (`pre`) and post-processing (`post`) transformations. - `pre` — applied before the file is uploaded to the Media Library. @@ -230,7 +243,7 @@ class FileUploadParams(TypedDict, total=False): """ -class ExtensionRemoveBgOptions(TypedDict, total=False): +class FileUploadV1ExtensionRemoveBgOptions(TypedDict, total=False): add_shadow: bool """Whether to add an artificial shadow to the result. @@ -259,14 +272,14 @@ class ExtensionRemoveBgOptions(TypedDict, total=False): """ -class ExtensionRemoveBg(TypedDict, total=False): +class FileUploadV1ExtensionRemoveBg(TypedDict, total=False): name: Required[Literal["remove-bg"]] """Specifies the background removal extension.""" - options: ExtensionRemoveBgOptions + options: FileUploadV1ExtensionRemoveBgOptions -class ExtensionAutoTaggingExtension(TypedDict, total=False): +class FileUploadV1ExtensionAutoTaggingExtension(TypedDict, total=False): max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] """Maximum number of tags to attach to the asset.""" @@ -277,15 +290,347 @@ class ExtensionAutoTaggingExtension(TypedDict, total=False): """Specifies the auto-tagging extension used.""" -class ExtensionAIAutoDescription(TypedDict, total=False): +class FileUploadV1ExtensionAIAutoDescription(TypedDict, total=False): name: Required[Literal["ai-auto-description"]] """Specifies the auto description extension.""" -Extension: TypeAlias = Union[ExtensionRemoveBg, ExtensionAutoTaggingExtension, ExtensionAIAutoDescription] +FileUploadV1Extension: TypeAlias = Union[ + FileUploadV1ExtensionRemoveBg, FileUploadV1ExtensionAutoTaggingExtension, FileUploadV1ExtensionAIAutoDescription +] + + +class FileUploadV1TransformationPostTransformation(TypedDict, total=False): + type: Required[Literal["transformation"]] + """Transformation type.""" + + value: Required[str] + """Transformation string (e.g. + + `w-200,h-200`). + Same syntax as ImageKit URL-based transformations. + """ + + +class FileUploadV1TransformationPostGifToVideo(TypedDict, total=False): + type: Required[Literal["gif-to-video"]] + """Converts an animated GIF into an MP4.""" + + value: str + """Optional transformation string to apply to the output video. + + **Example**: `q-80` + """ + + +class FileUploadV1TransformationPostThumbnail(TypedDict, total=False): + type: Required[Literal["thumbnail"]] + """Generates a thumbnail image.""" + + value: str + """Optional transformation string. + + **Example**: `w-150,h-150` + """ + + +class FileUploadV1TransformationPostAbs(TypedDict, total=False): + protocol: Required[Literal["hls", "dash"]] + """Streaming protocol to use (`hls` or `dash`).""" + + type: Required[Literal["abs"]] + """Adaptive Bitrate Streaming (ABS) setup.""" + + value: Required[str] + """ + List of different representations you want to create separated by an underscore. + """ + + +FileUploadV1TransformationPost: TypeAlias = Union[ + FileUploadV1TransformationPostTransformation, + FileUploadV1TransformationPostGifToVideo, + FileUploadV1TransformationPostThumbnail, + FileUploadV1TransformationPostAbs, +] + + +class FileUploadV1Transformation(TypedDict, total=False): + post: Iterable[FileUploadV1TransformationPost] + """List of transformations to apply _after_ the file is uploaded. + + Each item must match one of the following types: `transformation`, + `gif-to-video`, `thumbnail`, `abs`. + """ + + pre: str + """Transformation string to apply before uploading the file to the Media Library. + + Useful for optimizing files at ingestion. + """ + + +class FileUploadV1ByURL(TypedDict, total=False): + file: Required[str] + """A publicly reachable URL that ImageKit’s servers can fetch. + + The server must receive the response headers within 8 seconds; otherwise the + request fails with 400 Bad Request. + """ + + file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] + """The name with which the file has to be uploaded. The file name can contain: + + - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + - Special Characters: `.`, `-` + + Any other character including space will be replaced by `_` + """ + + token: str + """ + A unique value that the ImageKit.io server will use to recognize and prevent + subsequent retries for the same request. We suggest using V4 UUIDs, or another + random string with enough entropy to avoid collisions. This field is only + required for authentication when uploading a file from the client side. + + **Note**: Sending a value that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new value for this field. + """ + + checks: str + """ + Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + """ + + custom_coordinates: Annotated[str, PropertyInfo(alias="customCoordinates")] + """Define an important area in the image. + + This is only relevant for image type files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + """ + + custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] + """JSON key-value pairs to associate with the asset. + + Create the custom metadata fields before setting these values. + """ + + description: str + """Optional text to describe the contents of the file.""" + + expire: int + """The time until your signature is valid. + + It must be a [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 + hour into the future. It should be in seconds. This field is only required for + authentication when uploading a file from the client side. + """ + + extensions: Iterable[FileUploadV1ByURLExtension] + """Array of extensions to be applied to the image. + + Each extension can be configured with specific parameters based on the extension + type. + """ + + folder: str + """The folder path in which the image has to be uploaded. + + If the folder(s) didn't exist before, a new folder(s) is created. + + The folder name can contain: + + - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + - Special Characters: `/` , `_` , `-` + + Using multiple `/` creates a nested folder. + """ + + is_private_file: Annotated[bool, PropertyInfo(alias="isPrivateFile")] + """Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + """ + + is_published: Annotated[bool, PropertyInfo(alias="isPublished")] + """Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + """ + + overwrite_ai_tags: Annotated[bool, PropertyInfo(alias="overwriteAITags")] + """ + If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + """ + overwrite_custom_metadata: Annotated[bool, PropertyInfo(alias="overwriteCustomMetadata")] + """ + If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + """ -class TransformationPostTransformation(TypedDict, total=False): + overwrite_file: Annotated[bool, PropertyInfo(alias="overwriteFile")] + """ + If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + """ + + overwrite_tags: Annotated[bool, PropertyInfo(alias="overwriteTags")] + """ + If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + """ + + public_key: Annotated[str, PropertyInfo(alias="publicKey")] + """Your ImageKit.io public key. + + This field is only required for authentication when uploading a file from the + client side. + """ + + response_fields: Annotated[ + List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ], + PropertyInfo(alias="responseFields"), + ] + """Array of response field keys to include in the API response body.""" + + signature: str + """ + HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a + key. Learn how to create a signature on the page below. This should be in + lowercase. + + Signature must be calculated on the server-side. This field is only required for + authentication when uploading a file from the client side. + """ + + tags: List[str] + """Set the tags while uploading the file. Provide an array of tag strings (e.g. + + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. + """ + + transformation: FileUploadV1ByURLTransformation + """Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + """ + + use_unique_file_name: Annotated[bool, PropertyInfo(alias="useUniqueFileName")] + """Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + """ + + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ + + +class FileUploadV1ByURLExtensionRemoveBgOptions(TypedDict, total=False): + add_shadow: bool + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: str + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: str + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: bool + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class FileUploadV1ByURLExtensionRemoveBg(TypedDict, total=False): + name: Required[Literal["remove-bg"]] + """Specifies the background removal extension.""" + + options: FileUploadV1ByURLExtensionRemoveBgOptions + + +class FileUploadV1ByURLExtensionAutoTaggingExtension(TypedDict, total=False): + max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] + """Maximum number of tags to attach to the asset.""" + + min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] + """Minimum confidence level for tags to be considered valid.""" + + name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] + """Specifies the auto-tagging extension used.""" + + +class FileUploadV1ByURLExtensionAIAutoDescription(TypedDict, total=False): + name: Required[Literal["ai-auto-description"]] + """Specifies the auto description extension.""" + + +FileUploadV1ByURLExtension: TypeAlias = Union[ + FileUploadV1ByURLExtensionRemoveBg, + FileUploadV1ByURLExtensionAutoTaggingExtension, + FileUploadV1ByURLExtensionAIAutoDescription, +] + + +class FileUploadV1ByURLTransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" @@ -297,7 +642,7 @@ class TransformationPostTransformation(TypedDict, total=False): """ -class TransformationPostGifToVideo(TypedDict, total=False): +class FileUploadV1ByURLTransformationPostGifToVideo(TypedDict, total=False): type: Required[Literal["gif-to-video"]] """Converts an animated GIF into an MP4.""" @@ -308,7 +653,7 @@ class TransformationPostGifToVideo(TypedDict, total=False): """ -class TransformationPostThumbnail(TypedDict, total=False): +class FileUploadV1ByURLTransformationPostThumbnail(TypedDict, total=False): type: Required[Literal["thumbnail"]] """Generates a thumbnail image.""" @@ -319,7 +664,7 @@ class TransformationPostThumbnail(TypedDict, total=False): """ -class TransformationPostAbs(TypedDict, total=False): +class FileUploadV1ByURLTransformationPostAbs(TypedDict, total=False): protocol: Required[Literal["hls", "dash"]] """Streaming protocol to use (`hls` or `dash`).""" @@ -332,13 +677,16 @@ class TransformationPostAbs(TypedDict, total=False): """ -TransformationPost: TypeAlias = Union[ - TransformationPostTransformation, TransformationPostGifToVideo, TransformationPostThumbnail, TransformationPostAbs +FileUploadV1ByURLTransformationPost: TypeAlias = Union[ + FileUploadV1ByURLTransformationPostTransformation, + FileUploadV1ByURLTransformationPostGifToVideo, + FileUploadV1ByURLTransformationPostThumbnail, + FileUploadV1ByURLTransformationPostAbs, ] -class Transformation(TypedDict, total=False): - post: Iterable[TransformationPost] +class FileUploadV1ByURLTransformation(TypedDict, total=False): + post: Iterable[FileUploadV1ByURLTransformationPost] """List of transformations to apply _after_ the file is uploaded. Each item must match one of the following types: `transformation`, @@ -350,3 +698,6 @@ class Transformation(TypedDict, total=False): Useful for optimizing files at ingestion. """ + + +FileUploadParams: TypeAlias = Union[FileUploadV1, FileUploadV1ByURL] diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index f639534..af158e4 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -324,7 +324,7 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload(self, client: ImageKit) -> None: + def test_method_upload_overload_1(self, client: ImageKit) -> None: file = client.files.upload( file=b"raw file contents", file_name="fileName", @@ -333,7 +333,7 @@ def test_method_upload(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload_with_all_params(self, client: ImageKit) -> None: + def test_method_upload_with_all_params_overload_1(self, client: ImageKit) -> None: file = client.files.upload( file=b"raw file contents", file_name="fileName", @@ -395,7 +395,7 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_upload(self, client: ImageKit) -> None: + def test_raw_response_upload_overload_1(self, client: ImageKit) -> None: response = client.files.with_raw_response.upload( file=b"raw file contents", file_name="fileName", @@ -408,7 +408,7 @@ def test_raw_response_upload(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_upload(self, client: ImageKit) -> None: + def test_streaming_response_upload_overload_1(self, client: ImageKit) -> None: with client.files.with_streaming_response.upload( file=b"raw file contents", file_name="fileName", @@ -421,6 +421,105 @@ def test_streaming_response_upload(self, client: ImageKit) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_upload_overload_2(self, client: ImageKit) -> None: + file = client.files.upload( + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_upload_with_all_params_overload_2(self, client: ImageKit) -> None: + file = client.files.upload( + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + token="token", + checks='"request.folder" : "marketing/"\n', + custom_coordinates="customCoordinates", + custom_metadata={ + "brand": "bar", + "color": "bar", + }, + description="Running shoes", + expire=0, + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + folder="folder", + is_private_file=True, + is_published=True, + overwrite_ai_tags=True, + overwrite_custom_metadata=True, + overwrite_file=True, + overwrite_tags=True, + public_key="publicKey", + response_fields=["tags", "customCoordinates", "isPrivateFile"], + signature="signature", + tags=["t-shirt", "round-neck", "men"], + transformation={ + "post": [ + { + "type": "thumbnail", + "value": "w-150,h-150", + }, + { + "protocol": "dash", + "type": "abs", + "value": "sr-240_360_480_720_1080", + }, + ], + "pre": "w-300,h-300,q-80", + }, + use_unique_file_name=True, + webhook_url="https://example.com", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_upload_overload_2(self, client: ImageKit) -> None: + response = client.files.with_raw_response.upload( + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_upload_overload_2(self, client: ImageKit) -> None: + with client.files.with_streaming_response.upload( + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + class TestAsyncFiles: parametrize = pytest.mark.parametrize( @@ -727,7 +826,7 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_upload(self, async_client: AsyncImageKit) -> None: + async def test_method_upload_overload_1(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( file=b"raw file contents", file_name="fileName", @@ -736,7 +835,7 @@ async def test_method_upload(self, async_client: AsyncImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) -> None: + async def test_method_upload_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( file=b"raw file contents", file_name="fileName", @@ -798,7 +897,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: + async def test_raw_response_upload_overload_1(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.upload( file=b"raw file contents", file_name="fileName", @@ -811,7 +910,7 @@ async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> None: + async def test_streaming_response_upload_overload_1(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.upload( file=b"raw file contents", file_name="fileName", @@ -823,3 +922,102 @@ async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> N assert_matches_type(FileUploadResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_upload_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.upload( + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_upload_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.upload( + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + token="token", + checks='"request.folder" : "marketing/"\n', + custom_coordinates="customCoordinates", + custom_metadata={ + "brand": "bar", + "color": "bar", + }, + description="Running shoes", + expire=0, + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + folder="folder", + is_private_file=True, + is_published=True, + overwrite_ai_tags=True, + overwrite_custom_metadata=True, + overwrite_file=True, + overwrite_tags=True, + public_key="publicKey", + response_fields=["tags", "customCoordinates", "isPrivateFile"], + signature="signature", + tags=["t-shirt", "round-neck", "men"], + transformation={ + "post": [ + { + "type": "thumbnail", + "value": "w-150,h-150", + }, + { + "protocol": "dash", + "type": "abs", + "value": "sr-240_360_480_720_1080", + }, + ], + "pre": "w-300,h-300,q-80", + }, + use_unique_file_name=True, + webhook_url="https://example.com", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_upload_overload_2(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.upload( + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_upload_overload_2(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.upload( + file="https://www.example.com/path/to-image.jpg", + file_name="fileName", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True From e0e44063845e27126a22c67b5fb1d855c3173841 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 09:10:35 +0000 Subject: [PATCH 102/177] feat(api): manual updates --- .stats.yml | 4 +- src/imagekit/resources/files/files.py | 528 +---------------------- src/imagekit/types/file_upload_params.py | 407 ++--------------- tests/api_resources/test_files.py | 214 +-------- 4 files changed, 44 insertions(+), 1109 deletions(-) diff --git a/.stats.yml b/.stats.yml index d458a07..cfcbd7f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-e7bc47a9221d7da9c8c9653d3fd1d4cfdf2408588e32c4aa62bd02a50ec93c36.yml -openapi_spec_hash: 8d061396a2fff9d1add4d5baf03ab939 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-667f7f4988b44bc587d6eb9960ff5c8326e9f7e9b072f3f724f9f54166eff8b1.yml +openapi_spec_hash: f2081864a4abee0480e5ff991b4c936a config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 899d795..12ef720 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Dict, List, Mapping, Iterable, cast -from typing_extensions import Literal, overload +from typing_extensions import Literal import httpx @@ -17,7 +17,7 @@ ) from ...types import file_copy_params, file_move_params, file_rename_params, file_update_params, file_upload_params from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes -from ..._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform +from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from .metadata import ( MetadataResource, AsyncMetadataResource, @@ -365,7 +365,6 @@ def rename( cast_to=FileRenameResponse, ) - @overload def upload( self, *, @@ -377,7 +376,7 @@ def upload( custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, @@ -400,7 +399,7 @@ def upload( | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, tags: List[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, + transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -580,263 +579,6 @@ def upload( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @overload - def upload( - self, - *, - file: str, - file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadV1ByURLExtension] | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, - public_key: str | NotGiven = NOT_GIVEN, - response_fields: List[ - Literal[ - "tags", - "customCoordinates", - "isPrivateFile", - "embeddedMetadata", - "isPublished", - "customMetadata", - "metadata", - ] - ] - | NotGiven = NOT_GIVEN, - signature: str | NotGiven = NOT_GIVEN, - tags: List[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadV1ByURLTransformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadResponse: - """ - ImageKit.io allows you to upload files directly from both the server and client - sides. For server-side uploads, private API key authentication is used. For - client-side uploads, generate a one-time `token`, `signature`, and `expire` from - your secure backend using private API. - [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) - about how to implement client-side file upload. - - The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security - by verifying the entire payload using JWT. - - **File size limit** \\ - On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw - files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, - audio, and raw files and 2GB for videos. These limits can be further increased with - higher-tier plans. - - **Version limit** \\ - A file can have a maximum of 100 versions. - - **Demo applications** - - - A full-fledged - [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), - supporting file selections from local storage, URL, Dropbox, Google Drive, - Instagram, and more. - - [Quick start guides](/docs/quick-start-guides) for various frameworks and - technologies. - - Args: - file: A publicly reachable URL that ImageKit’s servers can fetch. The server must - receive the response headers within 8 seconds; otherwise the request fails with - 400 Bad Request. - - file_name: - The name with which the file has to be uploaded. The file name can contain: - - - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. - - Special Characters: `.`, `-` - - Any other character including space will be replaced by `_` - - token: A unique value that the ImageKit.io server will use to recognize and prevent - subsequent retries for the same request. We suggest using V4 UUIDs, or another - random string with enough entropy to avoid collisions. This field is only - required for authentication when uploading a file from the client side. - - **Note**: Sending a value that has been used in the past will result in a - validation error. Even if your previous request resulted in an error, you should - always send a new value for this field. - - checks: Server-side checks to run on the asset. Read more about - [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). - - custom_coordinates: Define an important area in the image. This is only relevant for image type - files. - - - To be passed as a string with the x and y coordinates of the top-left corner, - and width and height of the area of interest in the format `x,y,width,height`. - For example - `10,10,100,100` - - Can be used with fo-customtransformation. - - If this field is not specified and the file is overwritten, then - customCoordinates will be removed. - - custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata - fields before setting these values. - - description: Optional text to describe the contents of the file. - - expire: The time until your signature is valid. It must be a - [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into - the future. It should be in seconds. This field is only required for - authentication when uploading a file from the client side. - - extensions: Array of extensions to be applied to the image. Each extension can be configured - with specific parameters based on the extension type. - - folder: The folder path in which the image has to be uploaded. If the folder(s) didn't - exist before, a new folder(s) is created. - - The folder name can contain: - - - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` - - Special Characters: `/` , `_` , `-` - - Using multiple `/` creates a nested folder. - - is_private_file: Whether to mark the file as private or not. - - If `true`, the file is marked as private and is accessible only using named - transformation or signed URL. - - is_published: Whether to upload file as published or not. - - If `false`, the file is marked as unpublished, which restricts access to the - file only via the media library. Files in draft or unpublished state can only be - publicly accessed after being published. - - The option to upload in draft state is only available in custom enterprise - pricing plans. - - overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags - will be removed. Set `overwriteAITags` to `false` to preserve AITags. - - overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the - exact location, existing customMetadata will be removed. - - overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at - the exact location, upload API will return an error immediately. - - overwrite_tags: If the request does not have `tags`, and a file already exists at the exact - location, existing tags will be removed. - - public_key: Your ImageKit.io public key. This field is only required for authentication when - uploading a file from the client side. - - response_fields: Array of response field keys to include in the API response body. - - signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a - key. Learn how to create a signature on the page below. This should be in - lowercase. - - Signature must be calculated on the server-side. This field is only required for - authentication when uploading a file from the client side. - - tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. - `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not - exceed 500, and the `%` character is not allowed. If this field is not specified - and the file is overwritten, the existing tags will be removed. - - transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. - - - `pre` — applied before the file is uploaded to the Media Library. - Useful for reducing file size or applying basic optimizations upfront (e.g., - resize, compress). - - - `post` — applied immediately after upload. - Ideal for generating transformed versions (like video encodes or thumbnails) - in advance, so they're ready for delivery without delay. - - You can mix and match any combination of post-processing types. - - use_unique_file_name: Whether to use a unique filename for this file or not. - - If `true`, ImageKit.io will add a unique suffix to the filename parameter to get - a unique filename. - - If `false`, then the image is uploaded with the provided filename parameter, and - any existing file with the same name is replaced. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @required_args(["file", "file_name"]) - def upload( - self, - *, - file: FileTypes | str, - file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, - public_key: str | NotGiven = NOT_GIVEN, - response_fields: List[ - Literal[ - "tags", - "customCoordinates", - "isPrivateFile", - "embeddedMetadata", - "isPublished", - "customMetadata", - "metadata", - ] - ] - | NotGiven = NOT_GIVEN, - signature: str | NotGiven = NOT_GIVEN, - tags: List[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadResponse: body = deepcopy_minimal( { "file": file, @@ -1194,7 +936,6 @@ async def rename( cast_to=FileRenameResponse, ) - @overload async def upload( self, *, @@ -1206,7 +947,7 @@ async def upload( custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, @@ -1229,7 +970,7 @@ async def upload( | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, tags: List[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, + transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -1409,263 +1150,6 @@ async def upload( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @overload - async def upload( - self, - *, - file: str, - file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadV1ByURLExtension] | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, - public_key: str | NotGiven = NOT_GIVEN, - response_fields: List[ - Literal[ - "tags", - "customCoordinates", - "isPrivateFile", - "embeddedMetadata", - "isPublished", - "customMetadata", - "metadata", - ] - ] - | NotGiven = NOT_GIVEN, - signature: str | NotGiven = NOT_GIVEN, - tags: List[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadV1ByURLTransformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadResponse: - """ - ImageKit.io allows you to upload files directly from both the server and client - sides. For server-side uploads, private API key authentication is used. For - client-side uploads, generate a one-time `token`, `signature`, and `expire` from - your secure backend using private API. - [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) - about how to implement client-side file upload. - - The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security - by verifying the entire payload using JWT. - - **File size limit** \\ - On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw - files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, - audio, and raw files and 2GB for videos. These limits can be further increased with - higher-tier plans. - - **Version limit** \\ - A file can have a maximum of 100 versions. - - **Demo applications** - - - A full-fledged - [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), - supporting file selections from local storage, URL, Dropbox, Google Drive, - Instagram, and more. - - [Quick start guides](/docs/quick-start-guides) for various frameworks and - technologies. - - Args: - file: A publicly reachable URL that ImageKit’s servers can fetch. The server must - receive the response headers within 8 seconds; otherwise the request fails with - 400 Bad Request. - - file_name: - The name with which the file has to be uploaded. The file name can contain: - - - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. - - Special Characters: `.`, `-` - - Any other character including space will be replaced by `_` - - token: A unique value that the ImageKit.io server will use to recognize and prevent - subsequent retries for the same request. We suggest using V4 UUIDs, or another - random string with enough entropy to avoid collisions. This field is only - required for authentication when uploading a file from the client side. - - **Note**: Sending a value that has been used in the past will result in a - validation error. Even if your previous request resulted in an error, you should - always send a new value for this field. - - checks: Server-side checks to run on the asset. Read more about - [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). - - custom_coordinates: Define an important area in the image. This is only relevant for image type - files. - - - To be passed as a string with the x and y coordinates of the top-left corner, - and width and height of the area of interest in the format `x,y,width,height`. - For example - `10,10,100,100` - - Can be used with fo-customtransformation. - - If this field is not specified and the file is overwritten, then - customCoordinates will be removed. - - custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata - fields before setting these values. - - description: Optional text to describe the contents of the file. - - expire: The time until your signature is valid. It must be a - [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into - the future. It should be in seconds. This field is only required for - authentication when uploading a file from the client side. - - extensions: Array of extensions to be applied to the image. Each extension can be configured - with specific parameters based on the extension type. - - folder: The folder path in which the image has to be uploaded. If the folder(s) didn't - exist before, a new folder(s) is created. - - The folder name can contain: - - - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` - - Special Characters: `/` , `_` , `-` - - Using multiple `/` creates a nested folder. - - is_private_file: Whether to mark the file as private or not. - - If `true`, the file is marked as private and is accessible only using named - transformation or signed URL. - - is_published: Whether to upload file as published or not. - - If `false`, the file is marked as unpublished, which restricts access to the - file only via the media library. Files in draft or unpublished state can only be - publicly accessed after being published. - - The option to upload in draft state is only available in custom enterprise - pricing plans. - - overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags - will be removed. Set `overwriteAITags` to `false` to preserve AITags. - - overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the - exact location, existing customMetadata will be removed. - - overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at - the exact location, upload API will return an error immediately. - - overwrite_tags: If the request does not have `tags`, and a file already exists at the exact - location, existing tags will be removed. - - public_key: Your ImageKit.io public key. This field is only required for authentication when - uploading a file from the client side. - - response_fields: Array of response field keys to include in the API response body. - - signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a - key. Learn how to create a signature on the page below. This should be in - lowercase. - - Signature must be calculated on the server-side. This field is only required for - authentication when uploading a file from the client side. - - tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. - `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not - exceed 500, and the `%` character is not allowed. If this field is not specified - and the file is overwritten, the existing tags will be removed. - - transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. - - - `pre` — applied before the file is uploaded to the Media Library. - Useful for reducing file size or applying basic optimizations upfront (e.g., - resize, compress). - - - `post` — applied immediately after upload. - Ideal for generating transformed versions (like video encodes or thumbnails) - in advance, so they're ready for delivery without delay. - - You can mix and match any combination of post-processing types. - - use_unique_file_name: Whether to use a unique filename for this file or not. - - If `true`, ImageKit.io will add a unique suffix to the filename parameter to get - a unique filename. - - If `false`, then the image is uploaded with the provided filename parameter, and - any existing file with the same name is replaced. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @required_args(["file", "file_name"]) - async def upload( - self, - *, - file: FileTypes | str, - file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, - public_key: str | NotGiven = NOT_GIVEN, - response_fields: List[ - Literal[ - "tags", - "customCoordinates", - "isPrivateFile", - "embeddedMetadata", - "isPublished", - "customMetadata", - "metadata", - ] - ] - | NotGiven = NOT_GIVEN, - signature: str | NotGiven = NOT_GIVEN, - tags: List[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadResponse: body = deepcopy_minimal( { "file": file, diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index ea92822..228e681 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -10,34 +10,21 @@ __all__ = [ "FileUploadParams", - "FileUploadV1", - "FileUploadV1Extension", - "FileUploadV1ExtensionRemoveBg", - "FileUploadV1ExtensionRemoveBgOptions", - "FileUploadV1ExtensionAutoTaggingExtension", - "FileUploadV1ExtensionAIAutoDescription", - "FileUploadV1Transformation", - "FileUploadV1TransformationPost", - "FileUploadV1TransformationPostTransformation", - "FileUploadV1TransformationPostGifToVideo", - "FileUploadV1TransformationPostThumbnail", - "FileUploadV1TransformationPostAbs", - "FileUploadV1ByURL", - "FileUploadV1ByURLExtension", - "FileUploadV1ByURLExtensionRemoveBg", - "FileUploadV1ByURLExtensionRemoveBgOptions", - "FileUploadV1ByURLExtensionAutoTaggingExtension", - "FileUploadV1ByURLExtensionAIAutoDescription", - "FileUploadV1ByURLTransformation", - "FileUploadV1ByURLTransformationPost", - "FileUploadV1ByURLTransformationPostTransformation", - "FileUploadV1ByURLTransformationPostGifToVideo", - "FileUploadV1ByURLTransformationPostThumbnail", - "FileUploadV1ByURLTransformationPostAbs", + "Extension", + "ExtensionRemoveBg", + "ExtensionRemoveBgOptions", + "ExtensionAutoTaggingExtension", + "ExtensionAIAutoDescription", + "Transformation", + "TransformationPost", + "TransformationPostTransformation", + "TransformationPostGifToVideo", + "TransformationPostThumbnail", + "TransformationPostAbs", ] -class FileUploadV1(TypedDict, total=False): +class FileUploadParams(TypedDict, total=False): file: Required[FileTypes] """The API accepts any of the following: @@ -107,7 +94,7 @@ class FileUploadV1(TypedDict, total=False): authentication when uploading a file from the client side. """ - extensions: Iterable[FileUploadV1Extension] + extensions: Iterable[Extension] """Array of extensions to be applied to the image. Each extension can be configured with specific parameters based on the extension @@ -210,7 +197,7 @@ class FileUploadV1(TypedDict, total=False): and the file is overwritten, the existing tags will be removed. """ - transformation: FileUploadV1Transformation + transformation: Transformation """Configure pre-processing (`pre`) and post-processing (`post`) transformations. - `pre` — applied before the file is uploaded to the Media Library. @@ -243,7 +230,7 @@ class FileUploadV1(TypedDict, total=False): """ -class FileUploadV1ExtensionRemoveBgOptions(TypedDict, total=False): +class ExtensionRemoveBgOptions(TypedDict, total=False): add_shadow: bool """Whether to add an artificial shadow to the result. @@ -272,14 +259,14 @@ class FileUploadV1ExtensionRemoveBgOptions(TypedDict, total=False): """ -class FileUploadV1ExtensionRemoveBg(TypedDict, total=False): +class ExtensionRemoveBg(TypedDict, total=False): name: Required[Literal["remove-bg"]] """Specifies the background removal extension.""" - options: FileUploadV1ExtensionRemoveBgOptions + options: ExtensionRemoveBgOptions -class FileUploadV1ExtensionAutoTaggingExtension(TypedDict, total=False): +class ExtensionAutoTaggingExtension(TypedDict, total=False): max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] """Maximum number of tags to attach to the asset.""" @@ -290,347 +277,15 @@ class FileUploadV1ExtensionAutoTaggingExtension(TypedDict, total=False): """Specifies the auto-tagging extension used.""" -class FileUploadV1ExtensionAIAutoDescription(TypedDict, total=False): +class ExtensionAIAutoDescription(TypedDict, total=False): name: Required[Literal["ai-auto-description"]] """Specifies the auto description extension.""" -FileUploadV1Extension: TypeAlias = Union[ - FileUploadV1ExtensionRemoveBg, FileUploadV1ExtensionAutoTaggingExtension, FileUploadV1ExtensionAIAutoDescription -] - - -class FileUploadV1TransformationPostTransformation(TypedDict, total=False): - type: Required[Literal["transformation"]] - """Transformation type.""" - - value: Required[str] - """Transformation string (e.g. - - `w-200,h-200`). - Same syntax as ImageKit URL-based transformations. - """ - - -class FileUploadV1TransformationPostGifToVideo(TypedDict, total=False): - type: Required[Literal["gif-to-video"]] - """Converts an animated GIF into an MP4.""" - - value: str - """Optional transformation string to apply to the output video. - - **Example**: `q-80` - """ - - -class FileUploadV1TransformationPostThumbnail(TypedDict, total=False): - type: Required[Literal["thumbnail"]] - """Generates a thumbnail image.""" - - value: str - """Optional transformation string. - - **Example**: `w-150,h-150` - """ - - -class FileUploadV1TransformationPostAbs(TypedDict, total=False): - protocol: Required[Literal["hls", "dash"]] - """Streaming protocol to use (`hls` or `dash`).""" - - type: Required[Literal["abs"]] - """Adaptive Bitrate Streaming (ABS) setup.""" - - value: Required[str] - """ - List of different representations you want to create separated by an underscore. - """ - - -FileUploadV1TransformationPost: TypeAlias = Union[ - FileUploadV1TransformationPostTransformation, - FileUploadV1TransformationPostGifToVideo, - FileUploadV1TransformationPostThumbnail, - FileUploadV1TransformationPostAbs, -] - - -class FileUploadV1Transformation(TypedDict, total=False): - post: Iterable[FileUploadV1TransformationPost] - """List of transformations to apply _after_ the file is uploaded. - - Each item must match one of the following types: `transformation`, - `gif-to-video`, `thumbnail`, `abs`. - """ - - pre: str - """Transformation string to apply before uploading the file to the Media Library. - - Useful for optimizing files at ingestion. - """ - - -class FileUploadV1ByURL(TypedDict, total=False): - file: Required[str] - """A publicly reachable URL that ImageKit’s servers can fetch. - - The server must receive the response headers within 8 seconds; otherwise the - request fails with 400 Bad Request. - """ - - file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] - """The name with which the file has to be uploaded. The file name can contain: - - - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. - - Special Characters: `.`, `-` - - Any other character including space will be replaced by `_` - """ - - token: str - """ - A unique value that the ImageKit.io server will use to recognize and prevent - subsequent retries for the same request. We suggest using V4 UUIDs, or another - random string with enough entropy to avoid collisions. This field is only - required for authentication when uploading a file from the client side. - - **Note**: Sending a value that has been used in the past will result in a - validation error. Even if your previous request resulted in an error, you should - always send a new value for this field. - """ - - checks: str - """ - Server-side checks to run on the asset. Read more about - [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). - """ - - custom_coordinates: Annotated[str, PropertyInfo(alias="customCoordinates")] - """Define an important area in the image. - - This is only relevant for image type files. - - - To be passed as a string with the x and y coordinates of the top-left corner, - and width and height of the area of interest in the format `x,y,width,height`. - For example - `10,10,100,100` - - Can be used with fo-customtransformation. - - If this field is not specified and the file is overwritten, then - customCoordinates will be removed. - """ - - custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] - """JSON key-value pairs to associate with the asset. - - Create the custom metadata fields before setting these values. - """ - - description: str - """Optional text to describe the contents of the file.""" - - expire: int - """The time until your signature is valid. - - It must be a [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 - hour into the future. It should be in seconds. This field is only required for - authentication when uploading a file from the client side. - """ - - extensions: Iterable[FileUploadV1ByURLExtension] - """Array of extensions to be applied to the image. - - Each extension can be configured with specific parameters based on the extension - type. - """ - - folder: str - """The folder path in which the image has to be uploaded. - - If the folder(s) didn't exist before, a new folder(s) is created. - - The folder name can contain: - - - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` - - Special Characters: `/` , `_` , `-` - - Using multiple `/` creates a nested folder. - """ - - is_private_file: Annotated[bool, PropertyInfo(alias="isPrivateFile")] - """Whether to mark the file as private or not. - - If `true`, the file is marked as private and is accessible only using named - transformation or signed URL. - """ - - is_published: Annotated[bool, PropertyInfo(alias="isPublished")] - """Whether to upload file as published or not. - - If `false`, the file is marked as unpublished, which restricts access to the - file only via the media library. Files in draft or unpublished state can only be - publicly accessed after being published. - - The option to upload in draft state is only available in custom enterprise - pricing plans. - """ - - overwrite_ai_tags: Annotated[bool, PropertyInfo(alias="overwriteAITags")] - """ - If set to `true` and a file already exists at the exact location, its AITags - will be removed. Set `overwriteAITags` to `false` to preserve AITags. - """ +Extension: TypeAlias = Union[ExtensionRemoveBg, ExtensionAutoTaggingExtension, ExtensionAIAutoDescription] - overwrite_custom_metadata: Annotated[bool, PropertyInfo(alias="overwriteCustomMetadata")] - """ - If the request does not have `customMetadata`, and a file already exists at the - exact location, existing customMetadata will be removed. - """ - overwrite_file: Annotated[bool, PropertyInfo(alias="overwriteFile")] - """ - If `false` and `useUniqueFileName` is also `false`, and a file already exists at - the exact location, upload API will return an error immediately. - """ - - overwrite_tags: Annotated[bool, PropertyInfo(alias="overwriteTags")] - """ - If the request does not have `tags`, and a file already exists at the exact - location, existing tags will be removed. - """ - - public_key: Annotated[str, PropertyInfo(alias="publicKey")] - """Your ImageKit.io public key. - - This field is only required for authentication when uploading a file from the - client side. - """ - - response_fields: Annotated[ - List[ - Literal[ - "tags", - "customCoordinates", - "isPrivateFile", - "embeddedMetadata", - "isPublished", - "customMetadata", - "metadata", - ] - ], - PropertyInfo(alias="responseFields"), - ] - """Array of response field keys to include in the API response body.""" - - signature: str - """ - HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a - key. Learn how to create a signature on the page below. This should be in - lowercase. - - Signature must be calculated on the server-side. This field is only required for - authentication when uploading a file from the client side. - """ - - tags: List[str] - """Set the tags while uploading the file. Provide an array of tag strings (e.g. - - `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not - exceed 500, and the `%` character is not allowed. If this field is not specified - and the file is overwritten, the existing tags will be removed. - """ - - transformation: FileUploadV1ByURLTransformation - """Configure pre-processing (`pre`) and post-processing (`post`) transformations. - - - `pre` — applied before the file is uploaded to the Media Library. - Useful for reducing file size or applying basic optimizations upfront (e.g., - resize, compress). - - - `post` — applied immediately after upload. - Ideal for generating transformed versions (like video encodes or thumbnails) - in advance, so they're ready for delivery without delay. - - You can mix and match any combination of post-processing types. - """ - - use_unique_file_name: Annotated[bool, PropertyInfo(alias="useUniqueFileName")] - """Whether to use a unique filename for this file or not. - - If `true`, ImageKit.io will add a unique suffix to the filename parameter to get - a unique filename. - - If `false`, then the image is uploaded with the provided filename parameter, and - any existing file with the same name is replaced. - """ - - webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] - """ - The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - """ - - -class FileUploadV1ByURLExtensionRemoveBgOptions(TypedDict, total=False): - add_shadow: bool - """Whether to add an artificial shadow to the result. - - Default is false. Note: Adding shadows is currently only supported for car - photos. - """ - - bg_color: str - """ - Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or - color name (e.g., "green"). If this parameter is set, `bg_image_url` must be - empty. - """ - - bg_image_url: str - """Sets a background image from a URL. - - If this parameter is set, `bg_color` must be empty. - """ - - semitransparency: bool - """Allows semi-transparent regions in the result. - - Default is true. Note: Semitransparency is currently only supported for car - windows. - """ - - -class FileUploadV1ByURLExtensionRemoveBg(TypedDict, total=False): - name: Required[Literal["remove-bg"]] - """Specifies the background removal extension.""" - - options: FileUploadV1ByURLExtensionRemoveBgOptions - - -class FileUploadV1ByURLExtensionAutoTaggingExtension(TypedDict, total=False): - max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] - """Maximum number of tags to attach to the asset.""" - - min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] - """Minimum confidence level for tags to be considered valid.""" - - name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] - """Specifies the auto-tagging extension used.""" - - -class FileUploadV1ByURLExtensionAIAutoDescription(TypedDict, total=False): - name: Required[Literal["ai-auto-description"]] - """Specifies the auto description extension.""" - - -FileUploadV1ByURLExtension: TypeAlias = Union[ - FileUploadV1ByURLExtensionRemoveBg, - FileUploadV1ByURLExtensionAutoTaggingExtension, - FileUploadV1ByURLExtensionAIAutoDescription, -] - - -class FileUploadV1ByURLTransformationPostTransformation(TypedDict, total=False): +class TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" @@ -642,7 +297,7 @@ class FileUploadV1ByURLTransformationPostTransformation(TypedDict, total=False): """ -class FileUploadV1ByURLTransformationPostGifToVideo(TypedDict, total=False): +class TransformationPostGifToVideo(TypedDict, total=False): type: Required[Literal["gif-to-video"]] """Converts an animated GIF into an MP4.""" @@ -653,7 +308,7 @@ class FileUploadV1ByURLTransformationPostGifToVideo(TypedDict, total=False): """ -class FileUploadV1ByURLTransformationPostThumbnail(TypedDict, total=False): +class TransformationPostThumbnail(TypedDict, total=False): type: Required[Literal["thumbnail"]] """Generates a thumbnail image.""" @@ -664,7 +319,7 @@ class FileUploadV1ByURLTransformationPostThumbnail(TypedDict, total=False): """ -class FileUploadV1ByURLTransformationPostAbs(TypedDict, total=False): +class TransformationPostAbs(TypedDict, total=False): protocol: Required[Literal["hls", "dash"]] """Streaming protocol to use (`hls` or `dash`).""" @@ -677,16 +332,13 @@ class FileUploadV1ByURLTransformationPostAbs(TypedDict, total=False): """ -FileUploadV1ByURLTransformationPost: TypeAlias = Union[ - FileUploadV1ByURLTransformationPostTransformation, - FileUploadV1ByURLTransformationPostGifToVideo, - FileUploadV1ByURLTransformationPostThumbnail, - FileUploadV1ByURLTransformationPostAbs, +TransformationPost: TypeAlias = Union[ + TransformationPostTransformation, TransformationPostGifToVideo, TransformationPostThumbnail, TransformationPostAbs ] -class FileUploadV1ByURLTransformation(TypedDict, total=False): - post: Iterable[FileUploadV1ByURLTransformationPost] +class Transformation(TypedDict, total=False): + post: Iterable[TransformationPost] """List of transformations to apply _after_ the file is uploaded. Each item must match one of the following types: `transformation`, @@ -698,6 +350,3 @@ class FileUploadV1ByURLTransformation(TypedDict, total=False): Useful for optimizing files at ingestion. """ - - -FileUploadParams: TypeAlias = Union[FileUploadV1, FileUploadV1ByURL] diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index af158e4..f639534 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -324,7 +324,7 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload_overload_1(self, client: ImageKit) -> None: + def test_method_upload(self, client: ImageKit) -> None: file = client.files.upload( file=b"raw file contents", file_name="fileName", @@ -333,7 +333,7 @@ def test_method_upload_overload_1(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload_with_all_params_overload_1(self, client: ImageKit) -> None: + def test_method_upload_with_all_params(self, client: ImageKit) -> None: file = client.files.upload( file=b"raw file contents", file_name="fileName", @@ -395,7 +395,7 @@ def test_method_upload_with_all_params_overload_1(self, client: ImageKit) -> Non @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_upload_overload_1(self, client: ImageKit) -> None: + def test_raw_response_upload(self, client: ImageKit) -> None: response = client.files.with_raw_response.upload( file=b"raw file contents", file_name="fileName", @@ -408,7 +408,7 @@ def test_raw_response_upload_overload_1(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_upload_overload_1(self, client: ImageKit) -> None: + def test_streaming_response_upload(self, client: ImageKit) -> None: with client.files.with_streaming_response.upload( file=b"raw file contents", file_name="fileName", @@ -421,105 +421,6 @@ def test_streaming_response_upload_overload_1(self, client: ImageKit) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_upload_overload_2(self, client: ImageKit) -> None: - file = client.files.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - ) - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_upload_with_all_params_overload_2(self, client: ImageKit) -> None: - file = client.files.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - token="token", - checks='"request.folder" : "marketing/"\n', - custom_coordinates="customCoordinates", - custom_metadata={ - "brand": "bar", - "color": "bar", - }, - description="Running shoes", - expire=0, - extensions=[ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, - }, - }, - { - "max_tags": 5, - "min_confidence": 95, - "name": "google-auto-tagging", - }, - {"name": "ai-auto-description"}, - ], - folder="folder", - is_private_file=True, - is_published=True, - overwrite_ai_tags=True, - overwrite_custom_metadata=True, - overwrite_file=True, - overwrite_tags=True, - public_key="publicKey", - response_fields=["tags", "customCoordinates", "isPrivateFile"], - signature="signature", - tags=["t-shirt", "round-neck", "men"], - transformation={ - "post": [ - { - "type": "thumbnail", - "value": "w-150,h-150", - }, - { - "protocol": "dash", - "type": "abs", - "value": "sr-240_360_480_720_1080", - }, - ], - "pre": "w-300,h-300,q-80", - }, - use_unique_file_name=True, - webhook_url="https://example.com", - ) - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_upload_overload_2(self, client: ImageKit) -> None: - response = client.files.with_raw_response.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = response.parse() - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_upload_overload_2(self, client: ImageKit) -> None: - with client.files.with_streaming_response.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = response.parse() - assert_matches_type(FileUploadResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - class TestAsyncFiles: parametrize = pytest.mark.parametrize( @@ -826,7 +727,7 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_upload_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_method_upload(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( file=b"raw file contents", file_name="fileName", @@ -835,7 +736,7 @@ async def test_method_upload_overload_1(self, async_client: AsyncImageKit) -> No @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_upload_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( file=b"raw file contents", file_name="fileName", @@ -897,7 +798,7 @@ async def test_method_upload_with_all_params_overload_1(self, async_client: Asyn @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_upload_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.upload( file=b"raw file contents", file_name="fileName", @@ -910,7 +811,7 @@ async def test_raw_response_upload_overload_1(self, async_client: AsyncImageKit) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_upload_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.upload( file=b"raw file contents", file_name="fileName", @@ -922,102 +823,3 @@ async def test_streaming_response_upload_overload_1(self, async_client: AsyncIma assert_matches_type(FileUploadResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_upload_overload_2(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - ) - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_upload_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - token="token", - checks='"request.folder" : "marketing/"\n', - custom_coordinates="customCoordinates", - custom_metadata={ - "brand": "bar", - "color": "bar", - }, - description="Running shoes", - expire=0, - extensions=[ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, - }, - }, - { - "max_tags": 5, - "min_confidence": 95, - "name": "google-auto-tagging", - }, - {"name": "ai-auto-description"}, - ], - folder="folder", - is_private_file=True, - is_published=True, - overwrite_ai_tags=True, - overwrite_custom_metadata=True, - overwrite_file=True, - overwrite_tags=True, - public_key="publicKey", - response_fields=["tags", "customCoordinates", "isPrivateFile"], - signature="signature", - tags=["t-shirt", "round-neck", "men"], - transformation={ - "post": [ - { - "type": "thumbnail", - "value": "w-150,h-150", - }, - { - "protocol": "dash", - "type": "abs", - "value": "sr-240_360_480_720_1080", - }, - ], - "pre": "w-300,h-300,q-80", - }, - use_unique_file_name=True, - webhook_url="https://example.com", - ) - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_upload_overload_2(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = await response.parse() - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_upload_overload_2(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.upload( - file="https://www.example.com/path/to-image.jpg", - file_name="fileName", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = await response.parse() - assert_matches_type(FileUploadResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True From f64fe68946120f969d2547966def7c79c987f4d9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 02:26:53 +0000 Subject: [PATCH 103/177] feat(types): replace List[str] with SequenceNotStr in params --- src/imagekit/_utils/_transform.py | 6 ++++ .../resources/accounts/url_endpoints.py | 12 +++---- src/imagekit/resources/beta/v2/files.py | 6 ++-- src/imagekit/resources/files/bulk.py | 32 +++++++++---------- src/imagekit/resources/files/files.py | 6 ++-- .../accounts/url_endpoint_create_params.py | 5 +-- .../accounts/url_endpoint_update_params.py | 5 +-- .../types/beta/v2/file_upload_params.py | 4 +-- .../custom_metadata_field_create_params.py | 9 ++++-- .../custom_metadata_field_update_params.py | 9 ++++-- src/imagekit/types/file_update_params.py | 7 ++-- src/imagekit/types/file_upload_params.py | 4 +-- .../types/files/bulk_add_tags_params.py | 6 ++-- .../types/files/bulk_delete_params.py | 4 +-- .../types/files/bulk_remove_ai_tags_params.py | 6 ++-- .../types/files/bulk_remove_tags_params.py | 6 ++-- 16 files changed, 69 insertions(+), 58 deletions(-) diff --git a/src/imagekit/_utils/_transform.py b/src/imagekit/_utils/_transform.py index b0cc20a..f0bcefd 100644 --- a/src/imagekit/_utils/_transform.py +++ b/src/imagekit/_utils/_transform.py @@ -16,6 +16,7 @@ lru_cache, is_mapping, is_iterable, + is_sequence, ) from .._files import is_base64_file_input from ._typing import ( @@ -24,6 +25,7 @@ extract_type_arg, is_iterable_type, is_required_type, + is_sequence_type, is_annotated_type, strip_annotated_type, ) @@ -184,6 +186,8 @@ def _transform_recursive( (is_list_type(stripped_type) and is_list(data)) # Iterable[T] or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str)) + # Sequence[T] + or (is_sequence_type(stripped_type) and is_sequence(data) and not isinstance(data, str)) ): # dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually # intended as an iterable, so we don't transform it. @@ -346,6 +350,8 @@ async def _async_transform_recursive( (is_list_type(stripped_type) and is_list(data)) # Iterable[T] or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str)) + # Sequence[T] + or (is_sequence_type(stripped_type) and is_sequence(data) and not isinstance(data, str)) ): # dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually # intended as an iterable, so we don't transform it. diff --git a/src/imagekit/resources/accounts/url_endpoints.py b/src/imagekit/resources/accounts/url_endpoints.py index 890a63f..cd8e6f7 100644 --- a/src/imagekit/resources/accounts/url_endpoints.py +++ b/src/imagekit/resources/accounts/url_endpoints.py @@ -2,11 +2,9 @@ from __future__ import annotations -from typing import List - import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, SequenceNotStr from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -48,7 +46,7 @@ def create( self, *, description: str, - origins: List[str] | NotGiven = NOT_GIVEN, + origins: SequenceNotStr[str] | NotGiven = NOT_GIVEN, url_prefix: str | NotGiven = NOT_GIVEN, url_rewriter: url_endpoint_create_params.URLRewriter | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -105,7 +103,7 @@ def update( id: str, *, description: str, - origins: List[str] | NotGiven = NOT_GIVEN, + origins: SequenceNotStr[str] | NotGiven = NOT_GIVEN, url_prefix: str | NotGiven = NOT_GIVEN, url_rewriter: url_endpoint_update_params.URLRewriter | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -292,7 +290,7 @@ async def create( self, *, description: str, - origins: List[str] | NotGiven = NOT_GIVEN, + origins: SequenceNotStr[str] | NotGiven = NOT_GIVEN, url_prefix: str | NotGiven = NOT_GIVEN, url_rewriter: url_endpoint_create_params.URLRewriter | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -349,7 +347,7 @@ async def update( id: str, *, description: str, - origins: List[str] | NotGiven = NOT_GIVEN, + origins: SequenceNotStr[str] | NotGiven = NOT_GIVEN, url_prefix: str | NotGiven = NOT_GIVEN, url_rewriter: url_endpoint_update_params.URLRewriter | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index 6242db3..a09604d 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -7,7 +7,7 @@ import httpx -from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes +from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr from ...._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource @@ -74,7 +74,7 @@ def upload( ] ] | NotGiven = NOT_GIVEN, - tags: List[str] | NotGiven = NOT_GIVEN, + tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, @@ -326,7 +326,7 @@ async def upload( ] ] | NotGiven = NOT_GIVEN, - tags: List[str] | NotGiven = NOT_GIVEN, + tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, diff --git a/src/imagekit/resources/files/bulk.py b/src/imagekit/resources/files/bulk.py index a84becb..8b7a216 100644 --- a/src/imagekit/resources/files/bulk.py +++ b/src/imagekit/resources/files/bulk.py @@ -2,11 +2,9 @@ from __future__ import annotations -from typing import List - import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven, SequenceNotStr from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -49,7 +47,7 @@ def with_streaming_response(self) -> BulkResourceWithStreamingResponse: def delete( self, *, - file_ids: List[str], + file_ids: SequenceNotStr[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -89,8 +87,8 @@ def delete( def add_tags( self, *, - file_ids: List[str], - tags: List[str], + file_ids: SequenceNotStr[str], + tags: SequenceNotStr[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -134,8 +132,8 @@ def add_tags( def remove_ai_tags( self, *, - ai_tags: List[str], - file_ids: List[str], + ai_tags: SequenceNotStr[str], + file_ids: SequenceNotStr[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -179,8 +177,8 @@ def remove_ai_tags( def remove_tags( self, *, - file_ids: List[str], - tags: List[str], + file_ids: SequenceNotStr[str], + tags: SequenceNotStr[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -245,7 +243,7 @@ def with_streaming_response(self) -> AsyncBulkResourceWithStreamingResponse: async def delete( self, *, - file_ids: List[str], + file_ids: SequenceNotStr[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -285,8 +283,8 @@ async def delete( async def add_tags( self, *, - file_ids: List[str], - tags: List[str], + file_ids: SequenceNotStr[str], + tags: SequenceNotStr[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -330,8 +328,8 @@ async def add_tags( async def remove_ai_tags( self, *, - ai_tags: List[str], - file_ids: List[str], + ai_tags: SequenceNotStr[str], + file_ids: SequenceNotStr[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -375,8 +373,8 @@ async def remove_ai_tags( async def remove_tags( self, *, - file_ids: List[str], - tags: List[str], + file_ids: SequenceNotStr[str], + tags: SequenceNotStr[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 12ef720..66bbefe 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -16,7 +16,7 @@ AsyncBulkResourceWithStreamingResponse, ) from ...types import file_copy_params, file_move_params, file_rename_params, file_update_params, file_upload_params -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes, SequenceNotStr from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from .metadata import ( MetadataResource, @@ -398,7 +398,7 @@ def upload( ] | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, - tags: List[str] | NotGiven = NOT_GIVEN, + tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, @@ -969,7 +969,7 @@ async def upload( ] | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, - tags: List[str] | NotGiven = NOT_GIVEN, + tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, diff --git a/src/imagekit/types/accounts/url_endpoint_create_params.py b/src/imagekit/types/accounts/url_endpoint_create_params.py index b3a81f5..1c4653f 100644 --- a/src/imagekit/types/accounts/url_endpoint_create_params.py +++ b/src/imagekit/types/accounts/url_endpoint_create_params.py @@ -2,9 +2,10 @@ from __future__ import annotations -from typing import List, Union +from typing import Union from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from ..._types import SequenceNotStr from ..._utils import PropertyInfo __all__ = ["URLEndpointCreateParams", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] @@ -14,7 +15,7 @@ class URLEndpointCreateParams(TypedDict, total=False): description: Required[str] """Description of the URL endpoint.""" - origins: List[str] + origins: SequenceNotStr[str] """ Ordered list of origin IDs to try when the file isn’t in the Media Library; ImageKit checks them in the sequence provided. Origin must be created before it diff --git a/src/imagekit/types/accounts/url_endpoint_update_params.py b/src/imagekit/types/accounts/url_endpoint_update_params.py index 16b141a..e34f27b 100644 --- a/src/imagekit/types/accounts/url_endpoint_update_params.py +++ b/src/imagekit/types/accounts/url_endpoint_update_params.py @@ -2,9 +2,10 @@ from __future__ import annotations -from typing import List, Union +from typing import Union from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from ..._types import SequenceNotStr from ..._utils import PropertyInfo __all__ = ["URLEndpointUpdateParams", "URLRewriter", "URLRewriterCloudinary", "URLRewriterImgix", "URLRewriterAkamai"] @@ -14,7 +15,7 @@ class URLEndpointUpdateParams(TypedDict, total=False): description: Required[str] """Description of the URL endpoint.""" - origins: List[str] + origins: SequenceNotStr[str] """ Ordered list of origin IDs to try when the file isn’t in the Media Library; ImageKit checks them in the sequence provided. Origin must be created before it diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekit/types/beta/v2/file_upload_params.py index 4d8470b..fa66233 100644 --- a/src/imagekit/types/beta/v2/file_upload_params.py +++ b/src/imagekit/types/beta/v2/file_upload_params.py @@ -5,7 +5,7 @@ from typing import Dict, List, Union, Iterable from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from ...._types import FileTypes +from ...._types import FileTypes, SequenceNotStr from ...._utils import PropertyInfo __all__ = [ @@ -157,7 +157,7 @@ class FileUploadParams(TypedDict, total=False): ] """Array of response field keys to include in the API response body.""" - tags: List[str] + tags: SequenceNotStr[str] """Set the tags while uploading the file. Provide an array of tag strings (e.g. `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not diff --git a/src/imagekit/types/custom_metadata_field_create_params.py b/src/imagekit/types/custom_metadata_field_create_params.py index 1d029fd..0e265b0 100644 --- a/src/imagekit/types/custom_metadata_field_create_params.py +++ b/src/imagekit/types/custom_metadata_field_create_params.py @@ -2,9 +2,10 @@ from __future__ import annotations -from typing import List, Union +from typing import Union from typing_extensions import Literal, Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["CustomMetadataFieldCreateParams", "Schema"] @@ -32,7 +33,9 @@ class Schema(TypedDict, total=False): type: Required[Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"]] """Type of the custom metadata field.""" - default_value: Annotated[Union[str, float, bool, List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue")] + default_value: Annotated[ + Union[str, float, bool, SequenceNotStr[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") + ] """The default value for this custom metadata field. This property is only required if `isValueRequired` property is set to `true`. @@ -74,7 +77,7 @@ class Schema(TypedDict, total=False): set the minimum numeric value. """ - select_options: Annotated[List[Union[str, float, bool]], PropertyInfo(alias="selectOptions")] + select_options: Annotated[SequenceNotStr[Union[str, float, bool]], PropertyInfo(alias="selectOptions")] """An array of allowed values. This property is only required if `type` property is set to `SingleSelect` or diff --git a/src/imagekit/types/custom_metadata_field_update_params.py b/src/imagekit/types/custom_metadata_field_update_params.py index ba751cc..96792a7 100644 --- a/src/imagekit/types/custom_metadata_field_update_params.py +++ b/src/imagekit/types/custom_metadata_field_update_params.py @@ -2,9 +2,10 @@ from __future__ import annotations -from typing import List, Union +from typing import Union from typing_extensions import Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["CustomMetadataFieldUpdateParams", "Schema"] @@ -30,7 +31,9 @@ class CustomMetadataFieldUpdateParams(TypedDict, total=False): class Schema(TypedDict, total=False): - default_value: Annotated[Union[str, float, bool, List[Union[str, float, bool]]], PropertyInfo(alias="defaultValue")] + default_value: Annotated[ + Union[str, float, bool, SequenceNotStr[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") + ] """The default value for this custom metadata field. This property is only required if `isValueRequired` property is set to `true`. @@ -72,7 +75,7 @@ class Schema(TypedDict, total=False): set the minimum numeric value. """ - select_options: Annotated[List[Union[str, float, bool]], PropertyInfo(alias="selectOptions")] + select_options: Annotated[SequenceNotStr[Union[str, float, bool]], PropertyInfo(alias="selectOptions")] """An array of allowed values. This property is only required if `type` property is set to `SingleSelect` or diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index ea6a9cb..fefbe40 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -2,9 +2,10 @@ from __future__ import annotations -from typing import Dict, List, Union, Iterable, Optional +from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = [ @@ -109,7 +110,7 @@ class UpdateUpdateFileDetails(TypedDict, total=False): type. """ - remove_ai_tags: Annotated[Union[List[str], Literal["all"]], PropertyInfo(alias="removeAITags")] + remove_ai_tags: Annotated[Union[SequenceNotStr[str], Literal["all"]], PropertyInfo(alias="removeAITags")] """An array of AITags associated with the file that you want to remove, e.g. `["car", "vehicle", "motorsports"]`. @@ -121,7 +122,7 @@ class UpdateUpdateFileDetails(TypedDict, total=False): are processed. """ - tags: Optional[List[str]] + tags: Optional[SequenceNotStr[str]] """An array of tags associated with the file, such as `["tag1", "tag2"]`. Send `null` to unset all tags associated with the file. diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 228e681..961db92 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -5,7 +5,7 @@ from typing import Dict, List, Union, Iterable from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from .._types import FileTypes +from .._types import FileTypes, SequenceNotStr from .._utils import PropertyInfo __all__ = [ @@ -189,7 +189,7 @@ class FileUploadParams(TypedDict, total=False): authentication when uploading a file from the client side. """ - tags: List[str] + tags: SequenceNotStr[str] """Set the tags while uploading the file. Provide an array of tag strings (e.g. `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not diff --git a/src/imagekit/types/files/bulk_add_tags_params.py b/src/imagekit/types/files/bulk_add_tags_params.py index 3103a51..f83f577 100644 --- a/src/imagekit/types/files/bulk_add_tags_params.py +++ b/src/imagekit/types/files/bulk_add_tags_params.py @@ -2,17 +2,17 @@ from __future__ import annotations -from typing import List from typing_extensions import Required, Annotated, TypedDict +from ..._types import SequenceNotStr from ..._utils import PropertyInfo __all__ = ["BulkAddTagsParams"] class BulkAddTagsParams(TypedDict, total=False): - file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] + file_ids: Required[Annotated[SequenceNotStr[str], PropertyInfo(alias="fileIds")]] """An array of fileIds to which you want to add tags.""" - tags: Required[List[str]] + tags: Required[SequenceNotStr[str]] """An array of tags that you want to add to the files.""" diff --git a/src/imagekit/types/files/bulk_delete_params.py b/src/imagekit/types/files/bulk_delete_params.py index b00f0bf..2df1ee5 100644 --- a/src/imagekit/types/files/bulk_delete_params.py +++ b/src/imagekit/types/files/bulk_delete_params.py @@ -2,14 +2,14 @@ from __future__ import annotations -from typing import List from typing_extensions import Required, Annotated, TypedDict +from ..._types import SequenceNotStr from ..._utils import PropertyInfo __all__ = ["BulkDeleteParams"] class BulkDeleteParams(TypedDict, total=False): - file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] + file_ids: Required[Annotated[SequenceNotStr[str], PropertyInfo(alias="fileIds")]] """An array of fileIds which you want to delete.""" diff --git a/src/imagekit/types/files/bulk_remove_ai_tags_params.py b/src/imagekit/types/files/bulk_remove_ai_tags_params.py index 7164c4f..7d69ed3 100644 --- a/src/imagekit/types/files/bulk_remove_ai_tags_params.py +++ b/src/imagekit/types/files/bulk_remove_ai_tags_params.py @@ -2,17 +2,17 @@ from __future__ import annotations -from typing import List from typing_extensions import Required, Annotated, TypedDict +from ..._types import SequenceNotStr from ..._utils import PropertyInfo __all__ = ["BulkRemoveAITagsParams"] class BulkRemoveAITagsParams(TypedDict, total=False): - ai_tags: Required[Annotated[List[str], PropertyInfo(alias="AITags")]] + ai_tags: Required[Annotated[SequenceNotStr[str], PropertyInfo(alias="AITags")]] """An array of AITags that you want to remove from the files.""" - file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] + file_ids: Required[Annotated[SequenceNotStr[str], PropertyInfo(alias="fileIds")]] """An array of fileIds from which you want to remove AITags.""" diff --git a/src/imagekit/types/files/bulk_remove_tags_params.py b/src/imagekit/types/files/bulk_remove_tags_params.py index e9f9ffc..02e7f24 100644 --- a/src/imagekit/types/files/bulk_remove_tags_params.py +++ b/src/imagekit/types/files/bulk_remove_tags_params.py @@ -2,17 +2,17 @@ from __future__ import annotations -from typing import List from typing_extensions import Required, Annotated, TypedDict +from ..._types import SequenceNotStr from ..._utils import PropertyInfo __all__ = ["BulkRemoveTagsParams"] class BulkRemoveTagsParams(TypedDict, total=False): - file_ids: Required[Annotated[List[str], PropertyInfo(alias="fileIds")]] + file_ids: Required[Annotated[SequenceNotStr[str], PropertyInfo(alias="fileIds")]] """An array of fileIds from which you want to remove tags.""" - tags: Required[List[str]] + tags: Required[SequenceNotStr[str]] """An array of tags that you want to remove from the files.""" From 3ecebf0bf8e62e4da13fecdd947a762533ca49ea Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 11:40:45 +0000 Subject: [PATCH 104/177] feat(api): manual updates --- .stats.yml | 4 +- src/imagekit/resources/files/files.py | 528 ++++++++++++++++++++++- src/imagekit/types/file_upload_params.py | 408 ++++++++++++++++-- tests/api_resources/test_files.py | 214 ++++++++- 4 files changed, 1110 insertions(+), 44 deletions(-) diff --git a/.stats.yml b/.stats.yml index cfcbd7f..db7d8f1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-667f7f4988b44bc587d6eb9960ff5c8326e9f7e9b072f3f724f9f54166eff8b1.yml -openapi_spec_hash: f2081864a4abee0480e5ff991b4c936a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9ae7b43dcfd6208ca37c32c887630ae186ec338bcdd36902b6fe5d1cc66459dc.yml +openapi_spec_hash: 25fb64c067e64bcff6eaaabda26de397 config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 66bbefe..7292f4d 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Dict, List, Mapping, Iterable, cast -from typing_extensions import Literal +from typing_extensions import Literal, overload import httpx @@ -17,7 +17,7 @@ ) from ...types import file_copy_params, file_move_params, file_rename_params, file_update_params, file_upload_params from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes, SequenceNotStr -from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform +from ..._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform from .metadata import ( MetadataResource, AsyncMetadataResource, @@ -365,6 +365,7 @@ def rename( cast_to=FileRenameResponse, ) + @overload def upload( self, *, @@ -376,7 +377,7 @@ def upload( custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, @@ -399,7 +400,7 @@ def upload( | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -579,6 +580,263 @@ def upload( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @overload + def upload( + self, + *, + file: str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + expire: int | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadByUrlv1Extension] | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, + public_key: str | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadByUrlv1Transformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadResponse: + """ + ImageKit.io allows you to upload files directly from both the server and client + sides. For server-side uploads, private API key authentication is used. For + client-side uploads, generate a one-time `token`, `signature`, and `expire` from + your secure backend using private API. + [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) + about how to implement client-side file upload. + + The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security + by verifying the entire payload using JWT. + + **File size limit** \\ + On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw + files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, + audio, and raw files and 2GB for videos. These limits can be further increased with + higher-tier plans. + + **Version limit** \\ + A file can have a maximum of 100 versions. + + **Demo applications** + + - A full-fledged + [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + supporting file selections from local storage, URL, Dropbox, Google Drive, + Instagram, and more. + - [Quick start guides](/docs/quick-start-guides) for various frameworks and + technologies. + + Args: + file: The URL of the file to upload. A publicly reachable URL that ImageKit servers + can fetch. The server must receive the response headers within 8 seconds; + otherwise the request fails with 400 Bad Request. + + file_name: + The name with which the file has to be uploaded. The file name can contain: + + - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + - Special Characters: `.`, `-` + + Any other character including space will be replaced by `_` + + token: A unique value that the ImageKit.io server will use to recognize and prevent + subsequent retries for the same request. We suggest using V4 UUIDs, or another + random string with enough entropy to avoid collisions. This field is only + required for authentication when uploading a file from the client side. + + **Note**: Sending a value that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new value for this field. + + checks: Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + + custom_coordinates: Define an important area in the image. This is only relevant for image type + files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + + custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata + fields before setting these values. + + description: Optional text to describe the contents of the file. + + expire: The time until your signature is valid. It must be a + [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into + the future. It should be in seconds. This field is only required for + authentication when uploading a file from the client side. + + extensions: Array of extensions to be applied to the image. Each extension can be configured + with specific parameters based on the extension type. + + folder: The folder path in which the image has to be uploaded. If the folder(s) didn't + exist before, a new folder(s) is created. + + The folder name can contain: + + - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + - Special Characters: `/` , `_` , `-` + + Using multiple `/` creates a nested folder. + + is_private_file: Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + + is_published: Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + + overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + + overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + + overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + + overwrite_tags: If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + + public_key: Your ImageKit.io public key. This field is only required for authentication when + uploading a file from the client side. + + response_fields: Array of response field keys to include in the API response body. + + signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a + key. Learn how to create a signature on the page below. This should be in + lowercase. + + Signature must be calculated on the server-side. This field is only required for + authentication when uploading a file from the client side. + + tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. + + transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + + use_unique_file_name: Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["file", "file_name"]) + def upload( + self, + *, + file: FileTypes | str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + expire: int | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, + public_key: str | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadResponse: body = deepcopy_minimal( { "file": file, @@ -936,6 +1194,7 @@ async def rename( cast_to=FileRenameResponse, ) + @overload async def upload( self, *, @@ -947,7 +1206,7 @@ async def upload( custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, @@ -970,7 +1229,7 @@ async def upload( | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -1150,6 +1409,263 @@ async def upload( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @overload + async def upload( + self, + *, + file: str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + expire: int | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadByUrlv1Extension] | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, + public_key: str | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadByUrlv1Transformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadResponse: + """ + ImageKit.io allows you to upload files directly from both the server and client + sides. For server-side uploads, private API key authentication is used. For + client-side uploads, generate a one-time `token`, `signature`, and `expire` from + your secure backend using private API. + [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) + about how to implement client-side file upload. + + The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security + by verifying the entire payload using JWT. + + **File size limit** \\ + On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw + files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, + audio, and raw files and 2GB for videos. These limits can be further increased with + higher-tier plans. + + **Version limit** \\ + A file can have a maximum of 100 versions. + + **Demo applications** + + - A full-fledged + [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + supporting file selections from local storage, URL, Dropbox, Google Drive, + Instagram, and more. + - [Quick start guides](/docs/quick-start-guides) for various frameworks and + technologies. + + Args: + file: The URL of the file to upload. A publicly reachable URL that ImageKit servers + can fetch. The server must receive the response headers within 8 seconds; + otherwise the request fails with 400 Bad Request. + + file_name: + The name with which the file has to be uploaded. The file name can contain: + + - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + - Special Characters: `.`, `-` + + Any other character including space will be replaced by `_` + + token: A unique value that the ImageKit.io server will use to recognize and prevent + subsequent retries for the same request. We suggest using V4 UUIDs, or another + random string with enough entropy to avoid collisions. This field is only + required for authentication when uploading a file from the client side. + + **Note**: Sending a value that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new value for this field. + + checks: Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + + custom_coordinates: Define an important area in the image. This is only relevant for image type + files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + + custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata + fields before setting these values. + + description: Optional text to describe the contents of the file. + + expire: The time until your signature is valid. It must be a + [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into + the future. It should be in seconds. This field is only required for + authentication when uploading a file from the client side. + + extensions: Array of extensions to be applied to the image. Each extension can be configured + with specific parameters based on the extension type. + + folder: The folder path in which the image has to be uploaded. If the folder(s) didn't + exist before, a new folder(s) is created. + + The folder name can contain: + + - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + - Special Characters: `/` , `_` , `-` + + Using multiple `/` creates a nested folder. + + is_private_file: Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + + is_published: Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + + overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + + overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + + overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + + overwrite_tags: If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + + public_key: Your ImageKit.io public key. This field is only required for authentication when + uploading a file from the client side. + + response_fields: Array of response field keys to include in the API response body. + + signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a + key. Learn how to create a signature on the page below. This should be in + lowercase. + + Signature must be calculated on the server-side. This field is only required for + authentication when uploading a file from the client side. + + tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. + + transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + + use_unique_file_name: Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["file", "file_name"]) + async def upload( + self, + *, + file: FileTypes | str, + file_name: str, + token: str | NotGiven = NOT_GIVEN, + checks: str | NotGiven = NOT_GIVEN, + custom_coordinates: str | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + expire: int | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, + folder: str | NotGiven = NOT_GIVEN, + is_private_file: bool | NotGiven = NOT_GIVEN, + is_published: bool | NotGiven = NOT_GIVEN, + overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, + overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, + overwrite_file: bool | NotGiven = NOT_GIVEN, + overwrite_tags: bool | NotGiven = NOT_GIVEN, + public_key: str | NotGiven = NOT_GIVEN, + response_fields: List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ] + | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, + transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, + use_unique_file_name: bool | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUploadResponse: body = deepcopy_minimal( { "file": file, diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 961db92..559ea2e 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -10,21 +10,34 @@ __all__ = [ "FileUploadParams", - "Extension", - "ExtensionRemoveBg", - "ExtensionRemoveBgOptions", - "ExtensionAutoTaggingExtension", - "ExtensionAIAutoDescription", - "Transformation", - "TransformationPost", - "TransformationPostTransformation", - "TransformationPostGifToVideo", - "TransformationPostThumbnail", - "TransformationPostAbs", + "FileUploadV1", + "FileUploadV1Extension", + "FileUploadV1ExtensionRemoveBg", + "FileUploadV1ExtensionRemoveBgOptions", + "FileUploadV1ExtensionAutoTaggingExtension", + "FileUploadV1ExtensionAIAutoDescription", + "FileUploadV1Transformation", + "FileUploadV1TransformationPost", + "FileUploadV1TransformationPostTransformation", + "FileUploadV1TransformationPostGifToVideo", + "FileUploadV1TransformationPostThumbnail", + "FileUploadV1TransformationPostAbs", + "FileUploadByUrlv1", + "FileUploadByUrlv1Extension", + "FileUploadByUrlv1ExtensionRemoveBg", + "FileUploadByUrlv1ExtensionRemoveBgOptions", + "FileUploadByUrlv1ExtensionAutoTaggingExtension", + "FileUploadByUrlv1ExtensionAIAutoDescription", + "FileUploadByUrlv1Transformation", + "FileUploadByUrlv1TransformationPost", + "FileUploadByUrlv1TransformationPostTransformation", + "FileUploadByUrlv1TransformationPostGifToVideo", + "FileUploadByUrlv1TransformationPostThumbnail", + "FileUploadByUrlv1TransformationPostAbs", ] -class FileUploadParams(TypedDict, total=False): +class FileUploadV1(TypedDict, total=False): file: Required[FileTypes] """The API accepts any of the following: @@ -94,7 +107,7 @@ class FileUploadParams(TypedDict, total=False): authentication when uploading a file from the client side. """ - extensions: Iterable[Extension] + extensions: Iterable[FileUploadV1Extension] """Array of extensions to be applied to the image. Each extension can be configured with specific parameters based on the extension @@ -197,7 +210,7 @@ class FileUploadParams(TypedDict, total=False): and the file is overwritten, the existing tags will be removed. """ - transformation: Transformation + transformation: FileUploadV1Transformation """Configure pre-processing (`pre`) and post-processing (`post`) transformations. - `pre` — applied before the file is uploaded to the Media Library. @@ -230,7 +243,7 @@ class FileUploadParams(TypedDict, total=False): """ -class ExtensionRemoveBgOptions(TypedDict, total=False): +class FileUploadV1ExtensionRemoveBgOptions(TypedDict, total=False): add_shadow: bool """Whether to add an artificial shadow to the result. @@ -259,14 +272,14 @@ class ExtensionRemoveBgOptions(TypedDict, total=False): """ -class ExtensionRemoveBg(TypedDict, total=False): +class FileUploadV1ExtensionRemoveBg(TypedDict, total=False): name: Required[Literal["remove-bg"]] """Specifies the background removal extension.""" - options: ExtensionRemoveBgOptions + options: FileUploadV1ExtensionRemoveBgOptions -class ExtensionAutoTaggingExtension(TypedDict, total=False): +class FileUploadV1ExtensionAutoTaggingExtension(TypedDict, total=False): max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] """Maximum number of tags to attach to the asset.""" @@ -277,15 +290,348 @@ class ExtensionAutoTaggingExtension(TypedDict, total=False): """Specifies the auto-tagging extension used.""" -class ExtensionAIAutoDescription(TypedDict, total=False): +class FileUploadV1ExtensionAIAutoDescription(TypedDict, total=False): name: Required[Literal["ai-auto-description"]] """Specifies the auto description extension.""" -Extension: TypeAlias = Union[ExtensionRemoveBg, ExtensionAutoTaggingExtension, ExtensionAIAutoDescription] +FileUploadV1Extension: TypeAlias = Union[ + FileUploadV1ExtensionRemoveBg, FileUploadV1ExtensionAutoTaggingExtension, FileUploadV1ExtensionAIAutoDescription +] + + +class FileUploadV1TransformationPostTransformation(TypedDict, total=False): + type: Required[Literal["transformation"]] + """Transformation type.""" + + value: Required[str] + """Transformation string (e.g. + + `w-200,h-200`). + Same syntax as ImageKit URL-based transformations. + """ + + +class FileUploadV1TransformationPostGifToVideo(TypedDict, total=False): + type: Required[Literal["gif-to-video"]] + """Converts an animated GIF into an MP4.""" + + value: str + """Optional transformation string to apply to the output video. + + **Example**: `q-80` + """ + + +class FileUploadV1TransformationPostThumbnail(TypedDict, total=False): + type: Required[Literal["thumbnail"]] + """Generates a thumbnail image.""" + + value: str + """Optional transformation string. + + **Example**: `w-150,h-150` + """ + + +class FileUploadV1TransformationPostAbs(TypedDict, total=False): + protocol: Required[Literal["hls", "dash"]] + """Streaming protocol to use (`hls` or `dash`).""" + + type: Required[Literal["abs"]] + """Adaptive Bitrate Streaming (ABS) setup.""" + + value: Required[str] + """ + List of different representations you want to create separated by an underscore. + """ + + +FileUploadV1TransformationPost: TypeAlias = Union[ + FileUploadV1TransformationPostTransformation, + FileUploadV1TransformationPostGifToVideo, + FileUploadV1TransformationPostThumbnail, + FileUploadV1TransformationPostAbs, +] + + +class FileUploadV1Transformation(TypedDict, total=False): + post: Iterable[FileUploadV1TransformationPost] + """List of transformations to apply _after_ the file is uploaded. + + Each item must match one of the following types: `transformation`, + `gif-to-video`, `thumbnail`, `abs`. + """ + + pre: str + """Transformation string to apply before uploading the file to the Media Library. + + Useful for optimizing files at ingestion. + """ + + +class FileUploadByUrlv1(TypedDict, total=False): + file: Required[str] + """The URL of the file to upload. + + A publicly reachable URL that ImageKit servers can fetch. The server must + receive the response headers within 8 seconds; otherwise the request fails with + 400 Bad Request. + """ + + file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] + """The name with which the file has to be uploaded. The file name can contain: + + - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + - Special Characters: `.`, `-` + + Any other character including space will be replaced by `_` + """ + + token: str + """ + A unique value that the ImageKit.io server will use to recognize and prevent + subsequent retries for the same request. We suggest using V4 UUIDs, or another + random string with enough entropy to avoid collisions. This field is only + required for authentication when uploading a file from the client side. + + **Note**: Sending a value that has been used in the past will result in a + validation error. Even if your previous request resulted in an error, you should + always send a new value for this field. + """ + + checks: str + """ + Server-side checks to run on the asset. Read more about + [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + """ + + custom_coordinates: Annotated[str, PropertyInfo(alias="customCoordinates")] + """Define an important area in the image. + + This is only relevant for image type files. + + - To be passed as a string with the x and y coordinates of the top-left corner, + and width and height of the area of interest in the format `x,y,width,height`. + For example - `10,10,100,100` + - Can be used with fo-customtransformation. + - If this field is not specified and the file is overwritten, then + customCoordinates will be removed. + """ + + custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] + """JSON key-value pairs to associate with the asset. + + Create the custom metadata fields before setting these values. + """ + + description: str + """Optional text to describe the contents of the file.""" + + expire: int + """The time until your signature is valid. + + It must be a [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 + hour into the future. It should be in seconds. This field is only required for + authentication when uploading a file from the client side. + """ + + extensions: Iterable[FileUploadByUrlv1Extension] + """Array of extensions to be applied to the image. + + Each extension can be configured with specific parameters based on the extension + type. + """ + + folder: str + """The folder path in which the image has to be uploaded. + + If the folder(s) didn't exist before, a new folder(s) is created. + + The folder name can contain: + + - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + - Special Characters: `/` , `_` , `-` + + Using multiple `/` creates a nested folder. + """ + + is_private_file: Annotated[bool, PropertyInfo(alias="isPrivateFile")] + """Whether to mark the file as private or not. + + If `true`, the file is marked as private and is accessible only using named + transformation or signed URL. + """ + + is_published: Annotated[bool, PropertyInfo(alias="isPublished")] + """Whether to upload file as published or not. + + If `false`, the file is marked as unpublished, which restricts access to the + file only via the media library. Files in draft or unpublished state can only be + publicly accessed after being published. + + The option to upload in draft state is only available in custom enterprise + pricing plans. + """ + + overwrite_ai_tags: Annotated[bool, PropertyInfo(alias="overwriteAITags")] + """ + If set to `true` and a file already exists at the exact location, its AITags + will be removed. Set `overwriteAITags` to `false` to preserve AITags. + """ + overwrite_custom_metadata: Annotated[bool, PropertyInfo(alias="overwriteCustomMetadata")] + """ + If the request does not have `customMetadata`, and a file already exists at the + exact location, existing customMetadata will be removed. + """ -class TransformationPostTransformation(TypedDict, total=False): + overwrite_file: Annotated[bool, PropertyInfo(alias="overwriteFile")] + """ + If `false` and `useUniqueFileName` is also `false`, and a file already exists at + the exact location, upload API will return an error immediately. + """ + + overwrite_tags: Annotated[bool, PropertyInfo(alias="overwriteTags")] + """ + If the request does not have `tags`, and a file already exists at the exact + location, existing tags will be removed. + """ + + public_key: Annotated[str, PropertyInfo(alias="publicKey")] + """Your ImageKit.io public key. + + This field is only required for authentication when uploading a file from the + client side. + """ + + response_fields: Annotated[ + List[ + Literal[ + "tags", + "customCoordinates", + "isPrivateFile", + "embeddedMetadata", + "isPublished", + "customMetadata", + "metadata", + ] + ], + PropertyInfo(alias="responseFields"), + ] + """Array of response field keys to include in the API response body.""" + + signature: str + """ + HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a + key. Learn how to create a signature on the page below. This should be in + lowercase. + + Signature must be calculated on the server-side. This field is only required for + authentication when uploading a file from the client side. + """ + + tags: SequenceNotStr[str] + """Set the tags while uploading the file. Provide an array of tag strings (e.g. + + `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + exceed 500, and the `%` character is not allowed. If this field is not specified + and the file is overwritten, the existing tags will be removed. + """ + + transformation: FileUploadByUrlv1Transformation + """Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., + resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) + in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + """ + + use_unique_file_name: Annotated[bool, PropertyInfo(alias="useUniqueFileName")] + """Whether to use a unique filename for this file or not. + + If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + a unique filename. + + If `false`, then the image is uploaded with the provided filename parameter, and + any existing file with the same name is replaced. + """ + + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ + + +class FileUploadByUrlv1ExtensionRemoveBgOptions(TypedDict, total=False): + add_shadow: bool + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: str + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: str + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: bool + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class FileUploadByUrlv1ExtensionRemoveBg(TypedDict, total=False): + name: Required[Literal["remove-bg"]] + """Specifies the background removal extension.""" + + options: FileUploadByUrlv1ExtensionRemoveBgOptions + + +class FileUploadByUrlv1ExtensionAutoTaggingExtension(TypedDict, total=False): + max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] + """Maximum number of tags to attach to the asset.""" + + min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] + """Minimum confidence level for tags to be considered valid.""" + + name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] + """Specifies the auto-tagging extension used.""" + + +class FileUploadByUrlv1ExtensionAIAutoDescription(TypedDict, total=False): + name: Required[Literal["ai-auto-description"]] + """Specifies the auto description extension.""" + + +FileUploadByUrlv1Extension: TypeAlias = Union[ + FileUploadByUrlv1ExtensionRemoveBg, + FileUploadByUrlv1ExtensionAutoTaggingExtension, + FileUploadByUrlv1ExtensionAIAutoDescription, +] + + +class FileUploadByUrlv1TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" @@ -297,7 +643,7 @@ class TransformationPostTransformation(TypedDict, total=False): """ -class TransformationPostGifToVideo(TypedDict, total=False): +class FileUploadByUrlv1TransformationPostGifToVideo(TypedDict, total=False): type: Required[Literal["gif-to-video"]] """Converts an animated GIF into an MP4.""" @@ -308,7 +654,7 @@ class TransformationPostGifToVideo(TypedDict, total=False): """ -class TransformationPostThumbnail(TypedDict, total=False): +class FileUploadByUrlv1TransformationPostThumbnail(TypedDict, total=False): type: Required[Literal["thumbnail"]] """Generates a thumbnail image.""" @@ -319,7 +665,7 @@ class TransformationPostThumbnail(TypedDict, total=False): """ -class TransformationPostAbs(TypedDict, total=False): +class FileUploadByUrlv1TransformationPostAbs(TypedDict, total=False): protocol: Required[Literal["hls", "dash"]] """Streaming protocol to use (`hls` or `dash`).""" @@ -332,13 +678,16 @@ class TransformationPostAbs(TypedDict, total=False): """ -TransformationPost: TypeAlias = Union[ - TransformationPostTransformation, TransformationPostGifToVideo, TransformationPostThumbnail, TransformationPostAbs +FileUploadByUrlv1TransformationPost: TypeAlias = Union[ + FileUploadByUrlv1TransformationPostTransformation, + FileUploadByUrlv1TransformationPostGifToVideo, + FileUploadByUrlv1TransformationPostThumbnail, + FileUploadByUrlv1TransformationPostAbs, ] -class Transformation(TypedDict, total=False): - post: Iterable[TransformationPost] +class FileUploadByUrlv1Transformation(TypedDict, total=False): + post: Iterable[FileUploadByUrlv1TransformationPost] """List of transformations to apply _after_ the file is uploaded. Each item must match one of the following types: `transformation`, @@ -350,3 +699,6 @@ class Transformation(TypedDict, total=False): Useful for optimizing files at ingestion. """ + + +FileUploadParams: TypeAlias = Union[FileUploadV1, FileUploadByUrlv1] diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index f639534..9b8cb7d 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -324,7 +324,7 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload(self, client: ImageKit) -> None: + def test_method_upload_overload_1(self, client: ImageKit) -> None: file = client.files.upload( file=b"raw file contents", file_name="fileName", @@ -333,7 +333,7 @@ def test_method_upload(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload_with_all_params(self, client: ImageKit) -> None: + def test_method_upload_with_all_params_overload_1(self, client: ImageKit) -> None: file = client.files.upload( file=b"raw file contents", file_name="fileName", @@ -395,7 +395,7 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_upload(self, client: ImageKit) -> None: + def test_raw_response_upload_overload_1(self, client: ImageKit) -> None: response = client.files.with_raw_response.upload( file=b"raw file contents", file_name="fileName", @@ -408,7 +408,7 @@ def test_raw_response_upload(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_upload(self, client: ImageKit) -> None: + def test_streaming_response_upload_overload_1(self, client: ImageKit) -> None: with client.files.with_streaming_response.upload( file=b"raw file contents", file_name="fileName", @@ -421,6 +421,105 @@ def test_streaming_response_upload(self, client: ImageKit) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_upload_overload_2(self, client: ImageKit) -> None: + file = client.files.upload( + file="https://example.com", + file_name="fileName", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_upload_with_all_params_overload_2(self, client: ImageKit) -> None: + file = client.files.upload( + file="https://example.com", + file_name="fileName", + token="token", + checks='"request.folder" : "marketing/"\n', + custom_coordinates="customCoordinates", + custom_metadata={ + "brand": "bar", + "color": "bar", + }, + description="Running shoes", + expire=0, + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + folder="folder", + is_private_file=True, + is_published=True, + overwrite_ai_tags=True, + overwrite_custom_metadata=True, + overwrite_file=True, + overwrite_tags=True, + public_key="publicKey", + response_fields=["tags", "customCoordinates", "isPrivateFile"], + signature="signature", + tags=["t-shirt", "round-neck", "men"], + transformation={ + "post": [ + { + "type": "thumbnail", + "value": "w-150,h-150", + }, + { + "protocol": "dash", + "type": "abs", + "value": "sr-240_360_480_720_1080", + }, + ], + "pre": "w-300,h-300,q-80", + }, + use_unique_file_name=True, + webhook_url="https://example.com", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_upload_overload_2(self, client: ImageKit) -> None: + response = client.files.with_raw_response.upload( + file="https://example.com", + file_name="fileName", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_upload_overload_2(self, client: ImageKit) -> None: + with client.files.with_streaming_response.upload( + file="https://example.com", + file_name="fileName", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + class TestAsyncFiles: parametrize = pytest.mark.parametrize( @@ -727,7 +826,7 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_upload(self, async_client: AsyncImageKit) -> None: + async def test_method_upload_overload_1(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( file=b"raw file contents", file_name="fileName", @@ -736,7 +835,7 @@ async def test_method_upload(self, async_client: AsyncImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) -> None: + async def test_method_upload_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( file=b"raw file contents", file_name="fileName", @@ -798,7 +897,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: + async def test_raw_response_upload_overload_1(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.upload( file=b"raw file contents", file_name="fileName", @@ -811,7 +910,7 @@ async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> None: + async def test_streaming_response_upload_overload_1(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.upload( file=b"raw file contents", file_name="fileName", @@ -823,3 +922,102 @@ async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> N assert_matches_type(FileUploadResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_upload_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.upload( + file="https://example.com", + file_name="fileName", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_upload_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.upload( + file="https://example.com", + file_name="fileName", + token="token", + checks='"request.folder" : "marketing/"\n', + custom_coordinates="customCoordinates", + custom_metadata={ + "brand": "bar", + "color": "bar", + }, + description="Running shoes", + expire=0, + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + folder="folder", + is_private_file=True, + is_published=True, + overwrite_ai_tags=True, + overwrite_custom_metadata=True, + overwrite_file=True, + overwrite_tags=True, + public_key="publicKey", + response_fields=["tags", "customCoordinates", "isPrivateFile"], + signature="signature", + tags=["t-shirt", "round-neck", "men"], + transformation={ + "post": [ + { + "type": "thumbnail", + "value": "w-150,h-150", + }, + { + "protocol": "dash", + "type": "abs", + "value": "sr-240_360_480_720_1080", + }, + ], + "pre": "w-300,h-300,q-80", + }, + use_unique_file_name=True, + webhook_url="https://example.com", + ) + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_upload_overload_2(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.upload( + file="https://example.com", + file_name="fileName", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_upload_overload_2(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.upload( + file="https://example.com", + file_name="fileName", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileUploadResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True From 9c8eaa237c933a7b0ff67f93439a20a447e612b1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 11:45:01 +0000 Subject: [PATCH 105/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index db7d8f1..f8166f4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9ae7b43dcfd6208ca37c32c887630ae186ec338bcdd36902b6fe5d1cc66459dc.yml -openapi_spec_hash: 25fb64c067e64bcff6eaaabda26de397 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-5ce78cb448cc4520f5fbcc753452e0237b50a4bf64902e0548a8ad24bbdc82cf.yml +openapi_spec_hash: fd8ac4c2cdddc3d3a0b0c81be6a9edfe config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c From fbe46f845754c49a9e28237f605a3b35a29d39a3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 02:30:37 +0000 Subject: [PATCH 106/177] feat: improve future compat with pydantic v3 --- src/imagekit/_base_client.py | 6 +- src/imagekit/_compat.py | 96 ++++++++--------- src/imagekit/_models.py | 80 +++++++------- src/imagekit/_utils/__init__.py | 10 +- src/imagekit/_utils/_compat.py | 45 ++++++++ src/imagekit/_utils/_datetime_parse.py | 136 ++++++++++++++++++++++++ src/imagekit/_utils/_transform.py | 6 +- src/imagekit/_utils/_typing.py | 2 +- src/imagekit/_utils/_utils.py | 1 - src/imagekit/types/__init__.py | 8 +- src/imagekit/types/shared/overlay.py | 4 +- tests/test_models.py | 48 ++++----- tests/test_transform.py | 16 +-- tests/test_utils/test_datetime_parse.py | 110 +++++++++++++++++++ tests/utils.py | 8 +- 15 files changed, 438 insertions(+), 138 deletions(-) create mode 100644 src/imagekit/_utils/_compat.py create mode 100644 src/imagekit/_utils/_datetime_parse.py create mode 100644 tests/test_utils/test_datetime_parse.py diff --git a/src/imagekit/_base_client.py b/src/imagekit/_base_client.py index 9dcf022..fca8ec9 100644 --- a/src/imagekit/_base_client.py +++ b/src/imagekit/_base_client.py @@ -59,7 +59,7 @@ ModelBuilderProtocol, ) from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping -from ._compat import PYDANTIC_V2, model_copy, model_dump +from ._compat import PYDANTIC_V1, model_copy, model_dump from ._models import GenericModel, FinalRequestOptions, validate_type, construct_type from ._response import ( APIResponse, @@ -232,7 +232,7 @@ def _set_private_attributes( model: Type[_T], options: FinalRequestOptions, ) -> None: - if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None: + if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None: self.__pydantic_private__ = {} self._model = model @@ -320,7 +320,7 @@ def _set_private_attributes( client: AsyncAPIClient, options: FinalRequestOptions, ) -> None: - if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None: + if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None: self.__pydantic_private__ = {} self._model = model diff --git a/src/imagekit/_compat.py b/src/imagekit/_compat.py index 92d9ee6..bdef67f 100644 --- a/src/imagekit/_compat.py +++ b/src/imagekit/_compat.py @@ -12,14 +12,13 @@ _T = TypeVar("_T") _ModelT = TypeVar("_ModelT", bound=pydantic.BaseModel) -# --------------- Pydantic v2 compatibility --------------- +# --------------- Pydantic v2, v3 compatibility --------------- # Pyright incorrectly reports some of our functions as overriding a method when they don't # pyright: reportIncompatibleMethodOverride=false -PYDANTIC_V2 = pydantic.VERSION.startswith("2.") +PYDANTIC_V1 = pydantic.VERSION.startswith("1.") -# v1 re-exports if TYPE_CHECKING: def parse_date(value: date | StrBytesIntFloat) -> date: # noqa: ARG001 @@ -44,90 +43,92 @@ def is_typeddict(type_: type[Any]) -> bool: # noqa: ARG001 ... else: - if PYDANTIC_V2: - from pydantic.v1.typing import ( + # v1 re-exports + if PYDANTIC_V1: + from pydantic.typing import ( get_args as get_args, is_union as is_union, get_origin as get_origin, is_typeddict as is_typeddict, is_literal_type as is_literal_type, ) - from pydantic.v1.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime + from pydantic.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime else: - from pydantic.typing import ( + from ._utils import ( get_args as get_args, is_union as is_union, get_origin as get_origin, + parse_date as parse_date, is_typeddict as is_typeddict, + parse_datetime as parse_datetime, is_literal_type as is_literal_type, ) - from pydantic.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime # refactored config if TYPE_CHECKING: from pydantic import ConfigDict as ConfigDict else: - if PYDANTIC_V2: - from pydantic import ConfigDict - else: + if PYDANTIC_V1: # TODO: provide an error message here? ConfigDict = None + else: + from pydantic import ConfigDict as ConfigDict # renamed methods / properties def parse_obj(model: type[_ModelT], value: object) -> _ModelT: - if PYDANTIC_V2: - return model.model_validate(value) - else: + if PYDANTIC_V1: return cast(_ModelT, model.parse_obj(value)) # pyright: ignore[reportDeprecated, reportUnnecessaryCast] + else: + return model.model_validate(value) def field_is_required(field: FieldInfo) -> bool: - if PYDANTIC_V2: - return field.is_required() - return field.required # type: ignore + if PYDANTIC_V1: + return field.required # type: ignore + return field.is_required() def field_get_default(field: FieldInfo) -> Any: value = field.get_default() - if PYDANTIC_V2: - from pydantic_core import PydanticUndefined - - if value == PydanticUndefined: - return None + if PYDANTIC_V1: return value + from pydantic_core import PydanticUndefined + + if value == PydanticUndefined: + return None return value def field_outer_type(field: FieldInfo) -> Any: - if PYDANTIC_V2: - return field.annotation - return field.outer_type_ # type: ignore + if PYDANTIC_V1: + return field.outer_type_ # type: ignore + return field.annotation def get_model_config(model: type[pydantic.BaseModel]) -> Any: - if PYDANTIC_V2: - return model.model_config - return model.__config__ # type: ignore + if PYDANTIC_V1: + return model.__config__ # type: ignore + return model.model_config def get_model_fields(model: type[pydantic.BaseModel]) -> dict[str, FieldInfo]: - if PYDANTIC_V2: - return model.model_fields - return model.__fields__ # type: ignore + if PYDANTIC_V1: + return model.__fields__ # type: ignore + return model.model_fields def model_copy(model: _ModelT, *, deep: bool = False) -> _ModelT: - if PYDANTIC_V2: - return model.model_copy(deep=deep) - return model.copy(deep=deep) # type: ignore + if PYDANTIC_V1: + return model.copy(deep=deep) # type: ignore + return model.model_copy(deep=deep) def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str: - if PYDANTIC_V2: - return model.model_dump_json(indent=indent) - return model.json(indent=indent) # type: ignore + if PYDANTIC_V1: + return model.json(indent=indent) # type: ignore + return model.model_dump_json(indent=indent) def model_dump( @@ -139,14 +140,14 @@ def model_dump( warnings: bool = True, mode: Literal["json", "python"] = "python", ) -> dict[str, Any]: - if PYDANTIC_V2 or hasattr(model, "model_dump"): + if (not PYDANTIC_V1) or hasattr(model, "model_dump"): return model.model_dump( mode=mode, exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, # warnings are not supported in Pydantic v1 - warnings=warnings if PYDANTIC_V2 else True, + warnings=True if PYDANTIC_V1 else warnings, ) return cast( "dict[str, Any]", @@ -159,9 +160,9 @@ def model_dump( def model_parse(model: type[_ModelT], data: Any) -> _ModelT: - if PYDANTIC_V2: - return model.model_validate(data) - return model.parse_obj(data) # pyright: ignore[reportDeprecated] + if PYDANTIC_V1: + return model.parse_obj(data) # pyright: ignore[reportDeprecated] + return model.model_validate(data) # generic models @@ -170,17 +171,16 @@ def model_parse(model: type[_ModelT], data: Any) -> _ModelT: class GenericModel(pydantic.BaseModel): ... else: - if PYDANTIC_V2: + if PYDANTIC_V1: + import pydantic.generics + + class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): ... + else: # there no longer needs to be a distinction in v2 but # we still have to create our own subclass to avoid # inconsistent MRO ordering errors class GenericModel(pydantic.BaseModel): ... - else: - import pydantic.generics - - class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): ... - # cached properties if TYPE_CHECKING: diff --git a/src/imagekit/_models.py b/src/imagekit/_models.py index 92f7c10..3a6017e 100644 --- a/src/imagekit/_models.py +++ b/src/imagekit/_models.py @@ -50,7 +50,7 @@ strip_annotated_type, ) from ._compat import ( - PYDANTIC_V2, + PYDANTIC_V1, ConfigDict, GenericModel as BaseGenericModel, get_args, @@ -81,11 +81,7 @@ class _ConfigProtocol(Protocol): class BaseModel(pydantic.BaseModel): - if PYDANTIC_V2: - model_config: ClassVar[ConfigDict] = ConfigDict( - extra="allow", defer_build=coerce_boolean(os.environ.get("DEFER_PYDANTIC_BUILD", "true")) - ) - else: + if PYDANTIC_V1: @property @override @@ -95,6 +91,10 @@ def model_fields_set(self) -> set[str]: class Config(pydantic.BaseConfig): # pyright: ignore[reportDeprecated] extra: Any = pydantic.Extra.allow # type: ignore + else: + model_config: ClassVar[ConfigDict] = ConfigDict( + extra="allow", defer_build=coerce_boolean(os.environ.get("DEFER_PYDANTIC_BUILD", "true")) + ) def to_dict( self, @@ -215,25 +215,25 @@ def construct( # pyright: ignore[reportIncompatibleMethodOverride] if key not in model_fields: parsed = construct_type(value=value, type_=extra_field_type) if extra_field_type is not None else value - if PYDANTIC_V2: - _extra[key] = parsed - else: + if PYDANTIC_V1: _fields_set.add(key) fields_values[key] = parsed + else: + _extra[key] = parsed object.__setattr__(m, "__dict__", fields_values) - if PYDANTIC_V2: - # these properties are copied from Pydantic's `model_construct()` method - object.__setattr__(m, "__pydantic_private__", None) - object.__setattr__(m, "__pydantic_extra__", _extra) - object.__setattr__(m, "__pydantic_fields_set__", _fields_set) - else: + if PYDANTIC_V1: # init_private_attributes() does not exist in v2 m._init_private_attributes() # type: ignore # copied from Pydantic v1's `construct()` method object.__setattr__(m, "__fields_set__", _fields_set) + else: + # these properties are copied from Pydantic's `model_construct()` method + object.__setattr__(m, "__pydantic_private__", None) + object.__setattr__(m, "__pydantic_extra__", _extra) + object.__setattr__(m, "__pydantic_fields_set__", _fields_set) return m @@ -243,7 +243,7 @@ def construct( # pyright: ignore[reportIncompatibleMethodOverride] # although not in practice model_construct = construct - if not PYDANTIC_V2: + if PYDANTIC_V1: # we define aliases for some of the new pydantic v2 methods so # that we can just document these methods without having to specify # a specific pydantic version as some users may not know which @@ -363,10 +363,10 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object: if value is None: return field_get_default(field) - if PYDANTIC_V2: - type_ = field.annotation - else: + if PYDANTIC_V1: type_ = cast(type, field.outer_type_) # type: ignore + else: + type_ = field.annotation # type: ignore if type_ is None: raise RuntimeError(f"Unexpected field type is None for {key}") @@ -375,7 +375,7 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object: def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None: - if not PYDANTIC_V2: + if PYDANTIC_V1: # TODO return None @@ -628,30 +628,30 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, for variant in get_args(union): variant = strip_annotated_type(variant) if is_basemodel_type(variant): - if PYDANTIC_V2: - field = _extract_field_schema_pv2(variant, discriminator_field_name) - if not field: + if PYDANTIC_V1: + field_info = cast("dict[str, FieldInfo]", variant.__fields__).get(discriminator_field_name) # pyright: ignore[reportDeprecated, reportUnnecessaryCast] + if not field_info: continue # Note: if one variant defines an alias then they all should - discriminator_alias = field.get("serialization_alias") - - field_schema = field["schema"] + discriminator_alias = field_info.alias - if field_schema["type"] == "literal": - for entry in cast("LiteralSchema", field_schema)["expected"]: + if (annotation := getattr(field_info, "annotation", None)) and is_literal_type(annotation): + for entry in get_args(annotation): if isinstance(entry, str): mapping[entry] = variant else: - field_info = cast("dict[str, FieldInfo]", variant.__fields__).get(discriminator_field_name) # pyright: ignore[reportDeprecated, reportUnnecessaryCast] - if not field_info: + field = _extract_field_schema_pv2(variant, discriminator_field_name) + if not field: continue # Note: if one variant defines an alias then they all should - discriminator_alias = field_info.alias + discriminator_alias = field.get("serialization_alias") - if (annotation := getattr(field_info, "annotation", None)) and is_literal_type(annotation): - for entry in get_args(annotation): + field_schema = field["schema"] + + if field_schema["type"] == "literal": + for entry in cast("LiteralSchema", field_schema)["expected"]: if isinstance(entry, str): mapping[entry] = variant @@ -714,7 +714,7 @@ class GenericModel(BaseGenericModel, BaseModel): pass -if PYDANTIC_V2: +if not PYDANTIC_V1: from pydantic import TypeAdapter as _TypeAdapter _CachedTypeAdapter = cast("TypeAdapter[object]", lru_cache(maxsize=None)(_TypeAdapter)) @@ -782,12 +782,12 @@ class FinalRequestOptions(pydantic.BaseModel): json_data: Union[Body, None] = None extra_json: Union[AnyMapping, None] = None - if PYDANTIC_V2: - model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True) - else: + if PYDANTIC_V1: class Config(pydantic.BaseConfig): # pyright: ignore[reportDeprecated] arbitrary_types_allowed: bool = True + else: + model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True) def get_max_retries(self, max_retries: int) -> int: if isinstance(self.max_retries, NotGiven): @@ -820,9 +820,9 @@ def construct( # type: ignore key: strip_not_given(value) for key, value in values.items() } - if PYDANTIC_V2: - return super().model_construct(_fields_set, **kwargs) - return cast(FinalRequestOptions, super().construct(_fields_set, **kwargs)) # pyright: ignore[reportDeprecated] + if PYDANTIC_V1: + return cast(FinalRequestOptions, super().construct(_fields_set, **kwargs)) # pyright: ignore[reportDeprecated] + return super().model_construct(_fields_set, **kwargs) if not TYPE_CHECKING: # type checkers incorrectly complain about this assignment diff --git a/src/imagekit/_utils/__init__.py b/src/imagekit/_utils/__init__.py index ca547ce..dc64e29 100644 --- a/src/imagekit/_utils/__init__.py +++ b/src/imagekit/_utils/__init__.py @@ -10,7 +10,6 @@ lru_cache as lru_cache, is_mapping as is_mapping, is_tuple_t as is_tuple_t, - parse_date as parse_date, is_iterable as is_iterable, is_sequence as is_sequence, coerce_float as coerce_float, @@ -23,7 +22,6 @@ coerce_boolean as coerce_boolean, coerce_integer as coerce_integer, file_from_path as file_from_path, - parse_datetime as parse_datetime, strip_not_given as strip_not_given, deepcopy_minimal as deepcopy_minimal, get_async_library as get_async_library, @@ -32,6 +30,13 @@ maybe_coerce_boolean as maybe_coerce_boolean, maybe_coerce_integer as maybe_coerce_integer, ) +from ._compat import ( + get_args as get_args, + is_union as is_union, + get_origin as get_origin, + is_typeddict as is_typeddict, + is_literal_type as is_literal_type, +) from ._typing import ( is_list_type as is_list_type, is_union_type as is_union_type, @@ -56,3 +61,4 @@ function_has_argument as function_has_argument, assert_signatures_in_sync as assert_signatures_in_sync, ) +from ._datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime diff --git a/src/imagekit/_utils/_compat.py b/src/imagekit/_utils/_compat.py new file mode 100644 index 0000000..dd70323 --- /dev/null +++ b/src/imagekit/_utils/_compat.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +import sys +import typing_extensions +from typing import Any, Type, Union, Literal, Optional +from datetime import date, datetime +from typing_extensions import get_args as _get_args, get_origin as _get_origin + +from .._types import StrBytesIntFloat +from ._datetime_parse import parse_date as _parse_date, parse_datetime as _parse_datetime + +_LITERAL_TYPES = {Literal, typing_extensions.Literal} + + +def get_args(tp: type[Any]) -> tuple[Any, ...]: + return _get_args(tp) + + +def get_origin(tp: type[Any]) -> type[Any] | None: + return _get_origin(tp) + + +def is_union(tp: Optional[Type[Any]]) -> bool: + if sys.version_info < (3, 10): + return tp is Union # type: ignore[comparison-overlap] + else: + import types + + return tp is Union or tp is types.UnionType + + +def is_typeddict(tp: Type[Any]) -> bool: + return typing_extensions.is_typeddict(tp) + + +def is_literal_type(tp: Type[Any]) -> bool: + return get_origin(tp) in _LITERAL_TYPES + + +def parse_date(value: Union[date, StrBytesIntFloat]) -> date: + return _parse_date(value) + + +def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime: + return _parse_datetime(value) diff --git a/src/imagekit/_utils/_datetime_parse.py b/src/imagekit/_utils/_datetime_parse.py new file mode 100644 index 0000000..7cb9d9e --- /dev/null +++ b/src/imagekit/_utils/_datetime_parse.py @@ -0,0 +1,136 @@ +""" +This file contains code from https://github.com/pydantic/pydantic/blob/main/pydantic/v1/datetime_parse.py +without the Pydantic v1 specific errors. +""" + +from __future__ import annotations + +import re +from typing import Dict, Union, Optional +from datetime import date, datetime, timezone, timedelta + +from .._types import StrBytesIntFloat + +date_expr = r"(?P\d{4})-(?P\d{1,2})-(?P\d{1,2})" +time_expr = ( + r"(?P\d{1,2}):(?P\d{1,2})" + r"(?::(?P\d{1,2})(?:\.(?P\d{1,6})\d{0,6})?)?" + r"(?PZ|[+-]\d{2}(?::?\d{2})?)?$" +) + +date_re = re.compile(f"{date_expr}$") +datetime_re = re.compile(f"{date_expr}[T ]{time_expr}") + + +EPOCH = datetime(1970, 1, 1) +# if greater than this, the number is in ms, if less than or equal it's in seconds +# (in seconds this is 11th October 2603, in ms it's 20th August 1970) +MS_WATERSHED = int(2e10) +# slightly more than datetime.max in ns - (datetime.max - EPOCH).total_seconds() * 1e9 +MAX_NUMBER = int(3e20) + + +def _get_numeric(value: StrBytesIntFloat, native_expected_type: str) -> Union[None, int, float]: + if isinstance(value, (int, float)): + return value + try: + return float(value) + except ValueError: + return None + except TypeError: + raise TypeError(f"invalid type; expected {native_expected_type}, string, bytes, int or float") from None + + +def _from_unix_seconds(seconds: Union[int, float]) -> datetime: + if seconds > MAX_NUMBER: + return datetime.max + elif seconds < -MAX_NUMBER: + return datetime.min + + while abs(seconds) > MS_WATERSHED: + seconds /= 1000 + dt = EPOCH + timedelta(seconds=seconds) + return dt.replace(tzinfo=timezone.utc) + + +def _parse_timezone(value: Optional[str]) -> Union[None, int, timezone]: + if value == "Z": + return timezone.utc + elif value is not None: + offset_mins = int(value[-2:]) if len(value) > 3 else 0 + offset = 60 * int(value[1:3]) + offset_mins + if value[0] == "-": + offset = -offset + return timezone(timedelta(minutes=offset)) + else: + return None + + +def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime: + """ + Parse a datetime/int/float/string and return a datetime.datetime. + + This function supports time zone offsets. When the input contains one, + the output uses a timezone with a fixed offset from UTC. + + Raise ValueError if the input is well formatted but not a valid datetime. + Raise ValueError if the input isn't well formatted. + """ + if isinstance(value, datetime): + return value + + number = _get_numeric(value, "datetime") + if number is not None: + return _from_unix_seconds(number) + + if isinstance(value, bytes): + value = value.decode() + + assert not isinstance(value, (float, int)) + + match = datetime_re.match(value) + if match is None: + raise ValueError("invalid datetime format") + + kw = match.groupdict() + if kw["microsecond"]: + kw["microsecond"] = kw["microsecond"].ljust(6, "0") + + tzinfo = _parse_timezone(kw.pop("tzinfo")) + kw_: Dict[str, Union[None, int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None} + kw_["tzinfo"] = tzinfo + + return datetime(**kw_) # type: ignore + + +def parse_date(value: Union[date, StrBytesIntFloat]) -> date: + """ + Parse a date/int/float/string and return a datetime.date. + + Raise ValueError if the input is well formatted but not a valid date. + Raise ValueError if the input isn't well formatted. + """ + if isinstance(value, date): + if isinstance(value, datetime): + return value.date() + else: + return value + + number = _get_numeric(value, "date") + if number is not None: + return _from_unix_seconds(number).date() + + if isinstance(value, bytes): + value = value.decode() + + assert not isinstance(value, (float, int)) + match = date_re.match(value) + if match is None: + raise ValueError("invalid date format") + + kw = {k: int(v) for k, v in match.groupdict().items()} + + try: + return date(**kw) + except ValueError: + raise ValueError("invalid date format") from None diff --git a/src/imagekit/_utils/_transform.py b/src/imagekit/_utils/_transform.py index f0bcefd..c19124f 100644 --- a/src/imagekit/_utils/_transform.py +++ b/src/imagekit/_utils/_transform.py @@ -19,6 +19,7 @@ is_sequence, ) from .._files import is_base64_file_input +from ._compat import get_origin, is_typeddict from ._typing import ( is_list_type, is_union_type, @@ -29,7 +30,6 @@ is_annotated_type, strip_annotated_type, ) -from .._compat import get_origin, model_dump, is_typeddict _T = TypeVar("_T") @@ -169,6 +169,8 @@ def _transform_recursive( Defaults to the same value as the `annotation` argument. """ + from .._compat import model_dump + if inner_type is None: inner_type = annotation @@ -333,6 +335,8 @@ async def _async_transform_recursive( Defaults to the same value as the `annotation` argument. """ + from .._compat import model_dump + if inner_type is None: inner_type = annotation diff --git a/src/imagekit/_utils/_typing.py b/src/imagekit/_utils/_typing.py index 845cd6b..193109f 100644 --- a/src/imagekit/_utils/_typing.py +++ b/src/imagekit/_utils/_typing.py @@ -15,7 +15,7 @@ from ._utils import lru_cache from .._types import InheritsGeneric -from .._compat import is_union as _is_union +from ._compat import is_union as _is_union def is_annotated_type(typ: type) -> bool: diff --git a/src/imagekit/_utils/_utils.py b/src/imagekit/_utils/_utils.py index ea3cf3f..f081859 100644 --- a/src/imagekit/_utils/_utils.py +++ b/src/imagekit/_utils/_utils.py @@ -22,7 +22,6 @@ import sniffio from .._types import NotGiven, FileTypes, NotGivenOr, HeadersLike -from .._compat import parse_date as parse_date, parse_datetime as parse_datetime _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index ed4a09d..b3794c6 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -70,9 +70,9 @@ # This ensures that, when building the deferred (due to cyclical references) model schema, # Pydantic can resolve the necessary references. # See: https://github.com/pydantic/pydantic/issues/11250 for more context. -if _compat.PYDANTIC_V2: - shared.src_options.SrcOptions.model_rebuild(_parent_namespace_depth=0) - shared.transformation.Transformation.model_rebuild(_parent_namespace_depth=0) -else: +if _compat.PYDANTIC_V1: shared.src_options.SrcOptions.update_forward_refs() # type: ignore shared.transformation.Transformation.update_forward_refs() # type: ignore +else: + shared.src_options.SrcOptions.model_rebuild(_parent_namespace_depth=0) + shared.transformation.Transformation.model_rebuild(_parent_namespace_depth=0) diff --git a/src/imagekit/types/shared/overlay.py b/src/imagekit/types/shared/overlay.py index 00e685a..f7c120d 100644 --- a/src/imagekit/types/shared/overlay.py +++ b/src/imagekit/types/shared/overlay.py @@ -6,14 +6,14 @@ from typing_extensions import Annotated, TypeAlias, TypeAliasType from ..._utils import PropertyInfo -from ..._compat import PYDANTIC_V2 +from ..._compat import PYDANTIC_V1 from .text_overlay import TextOverlay from .subtitle_overlay import SubtitleOverlay from .solid_color_overlay import SolidColorOverlay __all__ = ["Overlay"] -if TYPE_CHECKING or PYDANTIC_V2: +if TYPE_CHECKING or not PYDANTIC_V1: Overlay = TypeAliasType( "Overlay", Annotated[ diff --git a/tests/test_models.py b/tests/test_models.py index 5203983..3f73b94 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -8,7 +8,7 @@ from pydantic import Field from imagekit._utils import PropertyInfo -from imagekit._compat import PYDANTIC_V2, parse_obj, model_dump, model_json +from imagekit._compat import PYDANTIC_V1, parse_obj, model_dump, model_json from imagekit._models import BaseModel, construct_type @@ -294,12 +294,12 @@ class Model(BaseModel): assert cast(bool, m.foo) is True m = Model.construct(foo={"name": 3}) - if PYDANTIC_V2: - assert isinstance(m.foo, Submodel1) - assert m.foo.name == 3 # type: ignore - else: + if PYDANTIC_V1: assert isinstance(m.foo, Submodel2) assert m.foo.name == "3" + else: + assert isinstance(m.foo, Submodel1) + assert m.foo.name == 3 # type: ignore def test_list_of_unions() -> None: @@ -426,10 +426,10 @@ class Model(BaseModel): expected = datetime(2019, 12, 27, 18, 11, 19, 117000, tzinfo=timezone.utc) - if PYDANTIC_V2: - expected_json = '{"created_at":"2019-12-27T18:11:19.117000Z"}' - else: + if PYDANTIC_V1: expected_json = '{"created_at": "2019-12-27T18:11:19.117000+00:00"}' + else: + expected_json = '{"created_at":"2019-12-27T18:11:19.117000Z"}' model = Model.construct(created_at="2019-12-27T18:11:19.117Z") assert model.created_at == expected @@ -531,7 +531,7 @@ class Model2(BaseModel): assert m4.to_dict(mode="python") == {"created_at": datetime.fromisoformat(time_str)} assert m4.to_dict(mode="json") == {"created_at": time_str} - if not PYDANTIC_V2: + if PYDANTIC_V1: with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): m.to_dict(warnings=False) @@ -556,7 +556,7 @@ class Model(BaseModel): assert m3.model_dump() == {"foo": None} assert m3.model_dump(exclude_none=True) == {} - if not PYDANTIC_V2: + if PYDANTIC_V1: with pytest.raises(ValueError, match="round_trip is only supported in Pydantic v2"): m.model_dump(round_trip=True) @@ -580,10 +580,10 @@ class Model(BaseModel): assert json.loads(m.to_json()) == {"FOO": "hello"} assert json.loads(m.to_json(use_api_names=False)) == {"foo": "hello"} - if PYDANTIC_V2: - assert m.to_json(indent=None) == '{"FOO":"hello"}' - else: + if PYDANTIC_V1: assert m.to_json(indent=None) == '{"FOO": "hello"}' + else: + assert m.to_json(indent=None) == '{"FOO":"hello"}' m2 = Model() assert json.loads(m2.to_json()) == {} @@ -595,7 +595,7 @@ class Model(BaseModel): assert json.loads(m3.to_json()) == {"FOO": None} assert json.loads(m3.to_json(exclude_none=True)) == {} - if not PYDANTIC_V2: + if PYDANTIC_V1: with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): m.to_json(warnings=False) @@ -622,7 +622,7 @@ class Model(BaseModel): assert json.loads(m3.model_dump_json()) == {"foo": None} assert json.loads(m3.model_dump_json(exclude_none=True)) == {} - if not PYDANTIC_V2: + if PYDANTIC_V1: with pytest.raises(ValueError, match="round_trip is only supported in Pydantic v2"): m.model_dump_json(round_trip=True) @@ -679,12 +679,12 @@ class B(BaseModel): ) assert isinstance(m, A) assert m.type == "a" - if PYDANTIC_V2: - assert m.data == 100 # type: ignore[comparison-overlap] - else: + if PYDANTIC_V1: # pydantic v1 automatically converts inputs to strings # if the expected type is a str assert m.data == "100" + else: + assert m.data == 100 # type: ignore[comparison-overlap] def test_discriminated_unions_unknown_variant() -> None: @@ -768,12 +768,12 @@ class B(BaseModel): ) assert isinstance(m, A) assert m.foo_type == "a" - if PYDANTIC_V2: - assert m.data == 100 # type: ignore[comparison-overlap] - else: + if PYDANTIC_V1: # pydantic v1 automatically converts inputs to strings # if the expected type is a str assert m.data == "100" + else: + assert m.data == 100 # type: ignore[comparison-overlap] def test_discriminated_unions_overlapping_discriminators_invalid_data() -> None: @@ -833,7 +833,7 @@ class B(BaseModel): assert UnionType.__discriminator__ is discriminator -@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1") +@pytest.mark.skipif(PYDANTIC_V1, reason="TypeAliasType is not supported in Pydantic v1") def test_type_alias_type() -> None: Alias = TypeAliasType("Alias", str) # pyright: ignore @@ -849,7 +849,7 @@ class Model(BaseModel): assert m.union == "bar" -@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1") +@pytest.mark.skipif(PYDANTIC_V1, reason="TypeAliasType is not supported in Pydantic v1") def test_field_named_cls() -> None: class Model(BaseModel): cls: str @@ -936,7 +936,7 @@ class Type2(BaseModel): assert isinstance(model.value, InnerType2) -@pytest.mark.skipif(not PYDANTIC_V2, reason="this is only supported in pydantic v2 for now") +@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2 for now") def test_extra_properties() -> None: class Item(BaseModel): prop: int diff --git a/tests/test_transform.py b/tests/test_transform.py index 0d9defb..479e32f 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -15,7 +15,7 @@ parse_datetime, async_transform as _async_transform, ) -from imagekit._compat import PYDANTIC_V2 +from imagekit._compat import PYDANTIC_V1 from imagekit._models import BaseModel _T = TypeVar("_T") @@ -189,7 +189,7 @@ class DateModel(BaseModel): @pytest.mark.asyncio async def test_iso8601_format(use_async: bool) -> None: dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") - tz = "Z" if PYDANTIC_V2 else "+00:00" + tz = "+00:00" if PYDANTIC_V1 else "Z" assert await transform({"foo": dt}, DatetimeDict, use_async) == {"foo": "2023-02-23T14:16:36.337692+00:00"} # type: ignore[comparison-overlap] assert await transform(DatetimeModel(foo=dt), Any, use_async) == {"foo": "2023-02-23T14:16:36.337692" + tz} # type: ignore[comparison-overlap] @@ -297,11 +297,11 @@ async def test_pydantic_unknown_field(use_async: bool) -> None: @pytest.mark.asyncio async def test_pydantic_mismatched_types(use_async: bool) -> None: model = MyModel.construct(foo=True) - if PYDANTIC_V2: + if PYDANTIC_V1: + params = await transform(model, Any, use_async) + else: with pytest.warns(UserWarning): params = await transform(model, Any, use_async) - else: - params = await transform(model, Any, use_async) assert cast(Any, params) == {"foo": True} @@ -309,11 +309,11 @@ async def test_pydantic_mismatched_types(use_async: bool) -> None: @pytest.mark.asyncio async def test_pydantic_mismatched_object_type(use_async: bool) -> None: model = MyModel.construct(foo=MyModel.construct(hello="world")) - if PYDANTIC_V2: + if PYDANTIC_V1: + params = await transform(model, Any, use_async) + else: with pytest.warns(UserWarning): params = await transform(model, Any, use_async) - else: - params = await transform(model, Any, use_async) assert cast(Any, params) == {"foo": {"hello": "world"}} diff --git a/tests/test_utils/test_datetime_parse.py b/tests/test_utils/test_datetime_parse.py new file mode 100644 index 0000000..959bb47 --- /dev/null +++ b/tests/test_utils/test_datetime_parse.py @@ -0,0 +1,110 @@ +""" +Copied from https://github.com/pydantic/pydantic/blob/v1.10.22/tests/test_datetime_parse.py +with modifications so it works without pydantic v1 imports. +""" + +from typing import Type, Union +from datetime import date, datetime, timezone, timedelta + +import pytest + +from imagekit._utils import parse_date, parse_datetime + + +def create_tz(minutes: int) -> timezone: + return timezone(timedelta(minutes=minutes)) + + +@pytest.mark.parametrize( + "value,result", + [ + # Valid inputs + ("1494012444.883309", date(2017, 5, 5)), + (b"1494012444.883309", date(2017, 5, 5)), + (1_494_012_444.883_309, date(2017, 5, 5)), + ("1494012444", date(2017, 5, 5)), + (1_494_012_444, date(2017, 5, 5)), + (0, date(1970, 1, 1)), + ("2012-04-23", date(2012, 4, 23)), + (b"2012-04-23", date(2012, 4, 23)), + ("2012-4-9", date(2012, 4, 9)), + (date(2012, 4, 9), date(2012, 4, 9)), + (datetime(2012, 4, 9, 12, 15), date(2012, 4, 9)), + # Invalid inputs + ("x20120423", ValueError), + ("2012-04-56", ValueError), + (19_999_999_999, date(2603, 10, 11)), # just before watershed + (20_000_000_001, date(1970, 8, 20)), # just after watershed + (1_549_316_052, date(2019, 2, 4)), # nowish in s + (1_549_316_052_104, date(2019, 2, 4)), # nowish in ms + (1_549_316_052_104_324, date(2019, 2, 4)), # nowish in μs + (1_549_316_052_104_324_096, date(2019, 2, 4)), # nowish in ns + ("infinity", date(9999, 12, 31)), + ("inf", date(9999, 12, 31)), + (float("inf"), date(9999, 12, 31)), + ("infinity ", date(9999, 12, 31)), + (int("1" + "0" * 100), date(9999, 12, 31)), + (1e1000, date(9999, 12, 31)), + ("-infinity", date(1, 1, 1)), + ("-inf", date(1, 1, 1)), + ("nan", ValueError), + ], +) +def test_date_parsing(value: Union[str, bytes, int, float], result: Union[date, Type[Exception]]) -> None: + if type(result) == type and issubclass(result, Exception): # pyright: ignore[reportUnnecessaryIsInstance] + with pytest.raises(result): + parse_date(value) + else: + assert parse_date(value) == result + + +@pytest.mark.parametrize( + "value,result", + [ + # Valid inputs + # values in seconds + ("1494012444.883309", datetime(2017, 5, 5, 19, 27, 24, 883_309, tzinfo=timezone.utc)), + (1_494_012_444.883_309, datetime(2017, 5, 5, 19, 27, 24, 883_309, tzinfo=timezone.utc)), + ("1494012444", datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), + (b"1494012444", datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), + (1_494_012_444, datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), + # values in ms + ("1494012444000.883309", datetime(2017, 5, 5, 19, 27, 24, 883, tzinfo=timezone.utc)), + ("-1494012444000.883309", datetime(1922, 8, 29, 4, 32, 35, 999117, tzinfo=timezone.utc)), + (1_494_012_444_000, datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), + ("2012-04-23T09:15:00", datetime(2012, 4, 23, 9, 15)), + ("2012-4-9 4:8:16", datetime(2012, 4, 9, 4, 8, 16)), + ("2012-04-23T09:15:00Z", datetime(2012, 4, 23, 9, 15, 0, 0, timezone.utc)), + ("2012-4-9 4:8:16-0320", datetime(2012, 4, 9, 4, 8, 16, 0, create_tz(-200))), + ("2012-04-23T10:20:30.400+02:30", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(150))), + ("2012-04-23T10:20:30.400+02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(120))), + ("2012-04-23T10:20:30.400-02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(-120))), + (b"2012-04-23T10:20:30.400-02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(-120))), + (datetime(2017, 5, 5), datetime(2017, 5, 5)), + (0, datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc)), + # Invalid inputs + ("x20120423091500", ValueError), + ("2012-04-56T09:15:90", ValueError), + ("2012-04-23T11:05:00-25:00", ValueError), + (19_999_999_999, datetime(2603, 10, 11, 11, 33, 19, tzinfo=timezone.utc)), # just before watershed + (20_000_000_001, datetime(1970, 8, 20, 11, 33, 20, 1000, tzinfo=timezone.utc)), # just after watershed + (1_549_316_052, datetime(2019, 2, 4, 21, 34, 12, 0, tzinfo=timezone.utc)), # nowish in s + (1_549_316_052_104, datetime(2019, 2, 4, 21, 34, 12, 104_000, tzinfo=timezone.utc)), # nowish in ms + (1_549_316_052_104_324, datetime(2019, 2, 4, 21, 34, 12, 104_324, tzinfo=timezone.utc)), # nowish in μs + (1_549_316_052_104_324_096, datetime(2019, 2, 4, 21, 34, 12, 104_324, tzinfo=timezone.utc)), # nowish in ns + ("infinity", datetime(9999, 12, 31, 23, 59, 59, 999999)), + ("inf", datetime(9999, 12, 31, 23, 59, 59, 999999)), + ("inf ", datetime(9999, 12, 31, 23, 59, 59, 999999)), + (1e50, datetime(9999, 12, 31, 23, 59, 59, 999999)), + (float("inf"), datetime(9999, 12, 31, 23, 59, 59, 999999)), + ("-infinity", datetime(1, 1, 1, 0, 0)), + ("-inf", datetime(1, 1, 1, 0, 0)), + ("nan", ValueError), + ], +) +def test_datetime_parsing(value: Union[str, bytes, int, float], result: Union[datetime, Type[Exception]]) -> None: + if type(result) == type and issubclass(result, Exception): # pyright: ignore[reportUnnecessaryIsInstance] + with pytest.raises(result): + parse_datetime(value) + else: + assert parse_datetime(value) == result diff --git a/tests/utils.py b/tests/utils.py index eed9080..3701958 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -19,7 +19,7 @@ is_annotated_type, is_type_alias_type, ) -from imagekit._compat import PYDANTIC_V2, field_outer_type, get_model_fields +from imagekit._compat import PYDANTIC_V1, field_outer_type, get_model_fields from imagekit._models import BaseModel BaseModelT = TypeVar("BaseModelT", bound=BaseModel) @@ -28,12 +28,12 @@ def assert_matches_model(model: type[BaseModelT], value: BaseModelT, *, path: list[str]) -> bool: for name, field in get_model_fields(model).items(): field_value = getattr(value, name) - if PYDANTIC_V2: - allow_none = False - else: + if PYDANTIC_V1: # in v1 nullability was structured differently # https://docs.pydantic.dev/2.0/migration/#required-optional-and-nullable-fields allow_none = getattr(field, "allow_none", False) + else: + allow_none = False assert_matches_type( field_outer_type(field), From 42b397773c82a236ea4e57501bb792aa47638dc0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 05:43:27 +0000 Subject: [PATCH 107/177] feat(api): manual updates --- .stats.yml | 4 +- src/imagekit/resources/files/files.py | 528 +---------------------- src/imagekit/types/file_upload_params.py | 408 ++---------------- tests/api_resources/test_files.py | 214 +-------- 4 files changed, 44 insertions(+), 1110 deletions(-) diff --git a/.stats.yml b/.stats.yml index f8166f4..cfcbd7f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-5ce78cb448cc4520f5fbcc753452e0237b50a4bf64902e0548a8ad24bbdc82cf.yml -openapi_spec_hash: fd8ac4c2cdddc3d3a0b0c81be6a9edfe +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-667f7f4988b44bc587d6eb9960ff5c8326e9f7e9b072f3f724f9f54166eff8b1.yml +openapi_spec_hash: f2081864a4abee0480e5ff991b4c936a config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 7292f4d..66bbefe 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Dict, List, Mapping, Iterable, cast -from typing_extensions import Literal, overload +from typing_extensions import Literal import httpx @@ -17,7 +17,7 @@ ) from ...types import file_copy_params, file_move_params, file_rename_params, file_update_params, file_upload_params from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes, SequenceNotStr -from ..._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform +from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from .metadata import ( MetadataResource, AsyncMetadataResource, @@ -365,7 +365,6 @@ def rename( cast_to=FileRenameResponse, ) - @overload def upload( self, *, @@ -377,7 +376,7 @@ def upload( custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, @@ -400,7 +399,7 @@ def upload( | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, + transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -580,263 +579,6 @@ def upload( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @overload - def upload( - self, - *, - file: str, - file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadByUrlv1Extension] | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, - public_key: str | NotGiven = NOT_GIVEN, - response_fields: List[ - Literal[ - "tags", - "customCoordinates", - "isPrivateFile", - "embeddedMetadata", - "isPublished", - "customMetadata", - "metadata", - ] - ] - | NotGiven = NOT_GIVEN, - signature: str | NotGiven = NOT_GIVEN, - tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadByUrlv1Transformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadResponse: - """ - ImageKit.io allows you to upload files directly from both the server and client - sides. For server-side uploads, private API key authentication is used. For - client-side uploads, generate a one-time `token`, `signature`, and `expire` from - your secure backend using private API. - [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) - about how to implement client-side file upload. - - The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security - by verifying the entire payload using JWT. - - **File size limit** \\ - On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw - files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, - audio, and raw files and 2GB for videos. These limits can be further increased with - higher-tier plans. - - **Version limit** \\ - A file can have a maximum of 100 versions. - - **Demo applications** - - - A full-fledged - [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), - supporting file selections from local storage, URL, Dropbox, Google Drive, - Instagram, and more. - - [Quick start guides](/docs/quick-start-guides) for various frameworks and - technologies. - - Args: - file: The URL of the file to upload. A publicly reachable URL that ImageKit servers - can fetch. The server must receive the response headers within 8 seconds; - otherwise the request fails with 400 Bad Request. - - file_name: - The name with which the file has to be uploaded. The file name can contain: - - - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. - - Special Characters: `.`, `-` - - Any other character including space will be replaced by `_` - - token: A unique value that the ImageKit.io server will use to recognize and prevent - subsequent retries for the same request. We suggest using V4 UUIDs, or another - random string with enough entropy to avoid collisions. This field is only - required for authentication when uploading a file from the client side. - - **Note**: Sending a value that has been used in the past will result in a - validation error. Even if your previous request resulted in an error, you should - always send a new value for this field. - - checks: Server-side checks to run on the asset. Read more about - [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). - - custom_coordinates: Define an important area in the image. This is only relevant for image type - files. - - - To be passed as a string with the x and y coordinates of the top-left corner, - and width and height of the area of interest in the format `x,y,width,height`. - For example - `10,10,100,100` - - Can be used with fo-customtransformation. - - If this field is not specified and the file is overwritten, then - customCoordinates will be removed. - - custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata - fields before setting these values. - - description: Optional text to describe the contents of the file. - - expire: The time until your signature is valid. It must be a - [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into - the future. It should be in seconds. This field is only required for - authentication when uploading a file from the client side. - - extensions: Array of extensions to be applied to the image. Each extension can be configured - with specific parameters based on the extension type. - - folder: The folder path in which the image has to be uploaded. If the folder(s) didn't - exist before, a new folder(s) is created. - - The folder name can contain: - - - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` - - Special Characters: `/` , `_` , `-` - - Using multiple `/` creates a nested folder. - - is_private_file: Whether to mark the file as private or not. - - If `true`, the file is marked as private and is accessible only using named - transformation or signed URL. - - is_published: Whether to upload file as published or not. - - If `false`, the file is marked as unpublished, which restricts access to the - file only via the media library. Files in draft or unpublished state can only be - publicly accessed after being published. - - The option to upload in draft state is only available in custom enterprise - pricing plans. - - overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags - will be removed. Set `overwriteAITags` to `false` to preserve AITags. - - overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the - exact location, existing customMetadata will be removed. - - overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at - the exact location, upload API will return an error immediately. - - overwrite_tags: If the request does not have `tags`, and a file already exists at the exact - location, existing tags will be removed. - - public_key: Your ImageKit.io public key. This field is only required for authentication when - uploading a file from the client side. - - response_fields: Array of response field keys to include in the API response body. - - signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a - key. Learn how to create a signature on the page below. This should be in - lowercase. - - Signature must be calculated on the server-side. This field is only required for - authentication when uploading a file from the client side. - - tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. - `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not - exceed 500, and the `%` character is not allowed. If this field is not specified - and the file is overwritten, the existing tags will be removed. - - transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. - - - `pre` — applied before the file is uploaded to the Media Library. - Useful for reducing file size or applying basic optimizations upfront (e.g., - resize, compress). - - - `post` — applied immediately after upload. - Ideal for generating transformed versions (like video encodes or thumbnails) - in advance, so they're ready for delivery without delay. - - You can mix and match any combination of post-processing types. - - use_unique_file_name: Whether to use a unique filename for this file or not. - - If `true`, ImageKit.io will add a unique suffix to the filename parameter to get - a unique filename. - - If `false`, then the image is uploaded with the provided filename parameter, and - any existing file with the same name is replaced. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @required_args(["file", "file_name"]) - def upload( - self, - *, - file: FileTypes | str, - file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, - public_key: str | NotGiven = NOT_GIVEN, - response_fields: List[ - Literal[ - "tags", - "customCoordinates", - "isPrivateFile", - "embeddedMetadata", - "isPublished", - "customMetadata", - "metadata", - ] - ] - | NotGiven = NOT_GIVEN, - signature: str | NotGiven = NOT_GIVEN, - tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadResponse: body = deepcopy_minimal( { "file": file, @@ -1194,7 +936,6 @@ async def rename( cast_to=FileRenameResponse, ) - @overload async def upload( self, *, @@ -1206,7 +947,7 @@ async def upload( custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, + extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, @@ -1229,7 +970,7 @@ async def upload( | NotGiven = NOT_GIVEN, signature: str | NotGiven = NOT_GIVEN, tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, + transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, use_unique_file_name: bool | NotGiven = NOT_GIVEN, webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -1409,263 +1150,6 @@ async def upload( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @overload - async def upload( - self, - *, - file: str, - file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadByUrlv1Extension] | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, - public_key: str | NotGiven = NOT_GIVEN, - response_fields: List[ - Literal[ - "tags", - "customCoordinates", - "isPrivateFile", - "embeddedMetadata", - "isPublished", - "customMetadata", - "metadata", - ] - ] - | NotGiven = NOT_GIVEN, - signature: str | NotGiven = NOT_GIVEN, - tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadByUrlv1Transformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadResponse: - """ - ImageKit.io allows you to upload files directly from both the server and client - sides. For server-side uploads, private API key authentication is used. For - client-side uploads, generate a one-time `token`, `signature`, and `expire` from - your secure backend using private API. - [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) - about how to implement client-side file upload. - - The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security - by verifying the entire payload using JWT. - - **File size limit** \\ - On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw - files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, - audio, and raw files and 2GB for videos. These limits can be further increased with - higher-tier plans. - - **Version limit** \\ - A file can have a maximum of 100 versions. - - **Demo applications** - - - A full-fledged - [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), - supporting file selections from local storage, URL, Dropbox, Google Drive, - Instagram, and more. - - [Quick start guides](/docs/quick-start-guides) for various frameworks and - technologies. - - Args: - file: The URL of the file to upload. A publicly reachable URL that ImageKit servers - can fetch. The server must receive the response headers within 8 seconds; - otherwise the request fails with 400 Bad Request. - - file_name: - The name with which the file has to be uploaded. The file name can contain: - - - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. - - Special Characters: `.`, `-` - - Any other character including space will be replaced by `_` - - token: A unique value that the ImageKit.io server will use to recognize and prevent - subsequent retries for the same request. We suggest using V4 UUIDs, or another - random string with enough entropy to avoid collisions. This field is only - required for authentication when uploading a file from the client side. - - **Note**: Sending a value that has been used in the past will result in a - validation error. Even if your previous request resulted in an error, you should - always send a new value for this field. - - checks: Server-side checks to run on the asset. Read more about - [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). - - custom_coordinates: Define an important area in the image. This is only relevant for image type - files. - - - To be passed as a string with the x and y coordinates of the top-left corner, - and width and height of the area of interest in the format `x,y,width,height`. - For example - `10,10,100,100` - - Can be used with fo-customtransformation. - - If this field is not specified and the file is overwritten, then - customCoordinates will be removed. - - custom_metadata: JSON key-value pairs to associate with the asset. Create the custom metadata - fields before setting these values. - - description: Optional text to describe the contents of the file. - - expire: The time until your signature is valid. It must be a - [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into - the future. It should be in seconds. This field is only required for - authentication when uploading a file from the client side. - - extensions: Array of extensions to be applied to the image. Each extension can be configured - with specific parameters based on the extension type. - - folder: The folder path in which the image has to be uploaded. If the folder(s) didn't - exist before, a new folder(s) is created. - - The folder name can contain: - - - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` - - Special Characters: `/` , `_` , `-` - - Using multiple `/` creates a nested folder. - - is_private_file: Whether to mark the file as private or not. - - If `true`, the file is marked as private and is accessible only using named - transformation or signed URL. - - is_published: Whether to upload file as published or not. - - If `false`, the file is marked as unpublished, which restricts access to the - file only via the media library. Files in draft or unpublished state can only be - publicly accessed after being published. - - The option to upload in draft state is only available in custom enterprise - pricing plans. - - overwrite_ai_tags: If set to `true` and a file already exists at the exact location, its AITags - will be removed. Set `overwriteAITags` to `false` to preserve AITags. - - overwrite_custom_metadata: If the request does not have `customMetadata`, and a file already exists at the - exact location, existing customMetadata will be removed. - - overwrite_file: If `false` and `useUniqueFileName` is also `false`, and a file already exists at - the exact location, upload API will return an error immediately. - - overwrite_tags: If the request does not have `tags`, and a file already exists at the exact - location, existing tags will be removed. - - public_key: Your ImageKit.io public key. This field is only required for authentication when - uploading a file from the client side. - - response_fields: Array of response field keys to include in the API response body. - - signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a - key. Learn how to create a signature on the page below. This should be in - lowercase. - - Signature must be calculated on the server-side. This field is only required for - authentication when uploading a file from the client side. - - tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. - `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not - exceed 500, and the `%` character is not allowed. If this field is not specified - and the file is overwritten, the existing tags will be removed. - - transformation: Configure pre-processing (`pre`) and post-processing (`post`) transformations. - - - `pre` — applied before the file is uploaded to the Media Library. - Useful for reducing file size or applying basic optimizations upfront (e.g., - resize, compress). - - - `post` — applied immediately after upload. - Ideal for generating transformed versions (like video encodes or thumbnails) - in advance, so they're ready for delivery without delay. - - You can mix and match any combination of post-processing types. - - use_unique_file_name: Whether to use a unique filename for this file or not. - - If `true`, ImageKit.io will add a unique suffix to the filename parameter to get - a unique filename. - - If `false`, then the image is uploaded with the provided filename parameter, and - any existing file with the same name is replaced. - - webhook_url: The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @required_args(["file", "file_name"]) - async def upload( - self, - *, - file: FileTypes | str, - file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.FileUploadV1Extension] | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, - public_key: str | NotGiven = NOT_GIVEN, - response_fields: List[ - Literal[ - "tags", - "customCoordinates", - "isPrivateFile", - "embeddedMetadata", - "isPublished", - "customMetadata", - "metadata", - ] - ] - | NotGiven = NOT_GIVEN, - signature: str | NotGiven = NOT_GIVEN, - tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.FileUploadV1Transformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> FileUploadResponse: body = deepcopy_minimal( { "file": file, diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 559ea2e..961db92 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -10,34 +10,21 @@ __all__ = [ "FileUploadParams", - "FileUploadV1", - "FileUploadV1Extension", - "FileUploadV1ExtensionRemoveBg", - "FileUploadV1ExtensionRemoveBgOptions", - "FileUploadV1ExtensionAutoTaggingExtension", - "FileUploadV1ExtensionAIAutoDescription", - "FileUploadV1Transformation", - "FileUploadV1TransformationPost", - "FileUploadV1TransformationPostTransformation", - "FileUploadV1TransformationPostGifToVideo", - "FileUploadV1TransformationPostThumbnail", - "FileUploadV1TransformationPostAbs", - "FileUploadByUrlv1", - "FileUploadByUrlv1Extension", - "FileUploadByUrlv1ExtensionRemoveBg", - "FileUploadByUrlv1ExtensionRemoveBgOptions", - "FileUploadByUrlv1ExtensionAutoTaggingExtension", - "FileUploadByUrlv1ExtensionAIAutoDescription", - "FileUploadByUrlv1Transformation", - "FileUploadByUrlv1TransformationPost", - "FileUploadByUrlv1TransformationPostTransformation", - "FileUploadByUrlv1TransformationPostGifToVideo", - "FileUploadByUrlv1TransformationPostThumbnail", - "FileUploadByUrlv1TransformationPostAbs", + "Extension", + "ExtensionRemoveBg", + "ExtensionRemoveBgOptions", + "ExtensionAutoTaggingExtension", + "ExtensionAIAutoDescription", + "Transformation", + "TransformationPost", + "TransformationPostTransformation", + "TransformationPostGifToVideo", + "TransformationPostThumbnail", + "TransformationPostAbs", ] -class FileUploadV1(TypedDict, total=False): +class FileUploadParams(TypedDict, total=False): file: Required[FileTypes] """The API accepts any of the following: @@ -107,7 +94,7 @@ class FileUploadV1(TypedDict, total=False): authentication when uploading a file from the client side. """ - extensions: Iterable[FileUploadV1Extension] + extensions: Iterable[Extension] """Array of extensions to be applied to the image. Each extension can be configured with specific parameters based on the extension @@ -210,7 +197,7 @@ class FileUploadV1(TypedDict, total=False): and the file is overwritten, the existing tags will be removed. """ - transformation: FileUploadV1Transformation + transformation: Transformation """Configure pre-processing (`pre`) and post-processing (`post`) transformations. - `pre` — applied before the file is uploaded to the Media Library. @@ -243,7 +230,7 @@ class FileUploadV1(TypedDict, total=False): """ -class FileUploadV1ExtensionRemoveBgOptions(TypedDict, total=False): +class ExtensionRemoveBgOptions(TypedDict, total=False): add_shadow: bool """Whether to add an artificial shadow to the result. @@ -272,14 +259,14 @@ class FileUploadV1ExtensionRemoveBgOptions(TypedDict, total=False): """ -class FileUploadV1ExtensionRemoveBg(TypedDict, total=False): +class ExtensionRemoveBg(TypedDict, total=False): name: Required[Literal["remove-bg"]] """Specifies the background removal extension.""" - options: FileUploadV1ExtensionRemoveBgOptions + options: ExtensionRemoveBgOptions -class FileUploadV1ExtensionAutoTaggingExtension(TypedDict, total=False): +class ExtensionAutoTaggingExtension(TypedDict, total=False): max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] """Maximum number of tags to attach to the asset.""" @@ -290,348 +277,15 @@ class FileUploadV1ExtensionAutoTaggingExtension(TypedDict, total=False): """Specifies the auto-tagging extension used.""" -class FileUploadV1ExtensionAIAutoDescription(TypedDict, total=False): +class ExtensionAIAutoDescription(TypedDict, total=False): name: Required[Literal["ai-auto-description"]] """Specifies the auto description extension.""" -FileUploadV1Extension: TypeAlias = Union[ - FileUploadV1ExtensionRemoveBg, FileUploadV1ExtensionAutoTaggingExtension, FileUploadV1ExtensionAIAutoDescription -] - - -class FileUploadV1TransformationPostTransformation(TypedDict, total=False): - type: Required[Literal["transformation"]] - """Transformation type.""" - - value: Required[str] - """Transformation string (e.g. - - `w-200,h-200`). - Same syntax as ImageKit URL-based transformations. - """ - - -class FileUploadV1TransformationPostGifToVideo(TypedDict, total=False): - type: Required[Literal["gif-to-video"]] - """Converts an animated GIF into an MP4.""" - - value: str - """Optional transformation string to apply to the output video. - - **Example**: `q-80` - """ - - -class FileUploadV1TransformationPostThumbnail(TypedDict, total=False): - type: Required[Literal["thumbnail"]] - """Generates a thumbnail image.""" - - value: str - """Optional transformation string. - - **Example**: `w-150,h-150` - """ - - -class FileUploadV1TransformationPostAbs(TypedDict, total=False): - protocol: Required[Literal["hls", "dash"]] - """Streaming protocol to use (`hls` or `dash`).""" - - type: Required[Literal["abs"]] - """Adaptive Bitrate Streaming (ABS) setup.""" - - value: Required[str] - """ - List of different representations you want to create separated by an underscore. - """ - - -FileUploadV1TransformationPost: TypeAlias = Union[ - FileUploadV1TransformationPostTransformation, - FileUploadV1TransformationPostGifToVideo, - FileUploadV1TransformationPostThumbnail, - FileUploadV1TransformationPostAbs, -] - - -class FileUploadV1Transformation(TypedDict, total=False): - post: Iterable[FileUploadV1TransformationPost] - """List of transformations to apply _after_ the file is uploaded. - - Each item must match one of the following types: `transformation`, - `gif-to-video`, `thumbnail`, `abs`. - """ - - pre: str - """Transformation string to apply before uploading the file to the Media Library. - - Useful for optimizing files at ingestion. - """ - - -class FileUploadByUrlv1(TypedDict, total=False): - file: Required[str] - """The URL of the file to upload. - - A publicly reachable URL that ImageKit servers can fetch. The server must - receive the response headers within 8 seconds; otherwise the request fails with - 400 Bad Request. - """ - - file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] - """The name with which the file has to be uploaded. The file name can contain: - - - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. - - Special Characters: `.`, `-` - - Any other character including space will be replaced by `_` - """ - - token: str - """ - A unique value that the ImageKit.io server will use to recognize and prevent - subsequent retries for the same request. We suggest using V4 UUIDs, or another - random string with enough entropy to avoid collisions. This field is only - required for authentication when uploading a file from the client side. - - **Note**: Sending a value that has been used in the past will result in a - validation error. Even if your previous request resulted in an error, you should - always send a new value for this field. - """ - - checks: str - """ - Server-side checks to run on the asset. Read more about - [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). - """ - - custom_coordinates: Annotated[str, PropertyInfo(alias="customCoordinates")] - """Define an important area in the image. - - This is only relevant for image type files. - - - To be passed as a string with the x and y coordinates of the top-left corner, - and width and height of the area of interest in the format `x,y,width,height`. - For example - `10,10,100,100` - - Can be used with fo-customtransformation. - - If this field is not specified and the file is overwritten, then - customCoordinates will be removed. - """ - - custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] - """JSON key-value pairs to associate with the asset. - - Create the custom metadata fields before setting these values. - """ - - description: str - """Optional text to describe the contents of the file.""" - - expire: int - """The time until your signature is valid. - - It must be a [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 - hour into the future. It should be in seconds. This field is only required for - authentication when uploading a file from the client side. - """ - - extensions: Iterable[FileUploadByUrlv1Extension] - """Array of extensions to be applied to the image. - - Each extension can be configured with specific parameters based on the extension - type. - """ - - folder: str - """The folder path in which the image has to be uploaded. - - If the folder(s) didn't exist before, a new folder(s) is created. - - The folder name can contain: - - - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` - - Special Characters: `/` , `_` , `-` - - Using multiple `/` creates a nested folder. - """ - - is_private_file: Annotated[bool, PropertyInfo(alias="isPrivateFile")] - """Whether to mark the file as private or not. - - If `true`, the file is marked as private and is accessible only using named - transformation or signed URL. - """ - - is_published: Annotated[bool, PropertyInfo(alias="isPublished")] - """Whether to upload file as published or not. - - If `false`, the file is marked as unpublished, which restricts access to the - file only via the media library. Files in draft or unpublished state can only be - publicly accessed after being published. - - The option to upload in draft state is only available in custom enterprise - pricing plans. - """ - - overwrite_ai_tags: Annotated[bool, PropertyInfo(alias="overwriteAITags")] - """ - If set to `true` and a file already exists at the exact location, its AITags - will be removed. Set `overwriteAITags` to `false` to preserve AITags. - """ +Extension: TypeAlias = Union[ExtensionRemoveBg, ExtensionAutoTaggingExtension, ExtensionAIAutoDescription] - overwrite_custom_metadata: Annotated[bool, PropertyInfo(alias="overwriteCustomMetadata")] - """ - If the request does not have `customMetadata`, and a file already exists at the - exact location, existing customMetadata will be removed. - """ - overwrite_file: Annotated[bool, PropertyInfo(alias="overwriteFile")] - """ - If `false` and `useUniqueFileName` is also `false`, and a file already exists at - the exact location, upload API will return an error immediately. - """ - - overwrite_tags: Annotated[bool, PropertyInfo(alias="overwriteTags")] - """ - If the request does not have `tags`, and a file already exists at the exact - location, existing tags will be removed. - """ - - public_key: Annotated[str, PropertyInfo(alias="publicKey")] - """Your ImageKit.io public key. - - This field is only required for authentication when uploading a file from the - client side. - """ - - response_fields: Annotated[ - List[ - Literal[ - "tags", - "customCoordinates", - "isPrivateFile", - "embeddedMetadata", - "isPublished", - "customMetadata", - "metadata", - ] - ], - PropertyInfo(alias="responseFields"), - ] - """Array of response field keys to include in the API response body.""" - - signature: str - """ - HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a - key. Learn how to create a signature on the page below. This should be in - lowercase. - - Signature must be calculated on the server-side. This field is only required for - authentication when uploading a file from the client side. - """ - - tags: SequenceNotStr[str] - """Set the tags while uploading the file. Provide an array of tag strings (e.g. - - `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not - exceed 500, and the `%` character is not allowed. If this field is not specified - and the file is overwritten, the existing tags will be removed. - """ - - transformation: FileUploadByUrlv1Transformation - """Configure pre-processing (`pre`) and post-processing (`post`) transformations. - - - `pre` — applied before the file is uploaded to the Media Library. - Useful for reducing file size or applying basic optimizations upfront (e.g., - resize, compress). - - - `post` — applied immediately after upload. - Ideal for generating transformed versions (like video encodes or thumbnails) - in advance, so they're ready for delivery without delay. - - You can mix and match any combination of post-processing types. - """ - - use_unique_file_name: Annotated[bool, PropertyInfo(alias="useUniqueFileName")] - """Whether to use a unique filename for this file or not. - - If `true`, ImageKit.io will add a unique suffix to the filename parameter to get - a unique filename. - - If `false`, then the image is uploaded with the provided filename parameter, and - any existing file with the same name is replaced. - """ - - webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] - """ - The final status of extensions after they have completed execution will be - delivered to this endpoint as a POST request. - [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) - about the webhook payload structure. - """ - - -class FileUploadByUrlv1ExtensionRemoveBgOptions(TypedDict, total=False): - add_shadow: bool - """Whether to add an artificial shadow to the result. - - Default is false. Note: Adding shadows is currently only supported for car - photos. - """ - - bg_color: str - """ - Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or - color name (e.g., "green"). If this parameter is set, `bg_image_url` must be - empty. - """ - - bg_image_url: str - """Sets a background image from a URL. - - If this parameter is set, `bg_color` must be empty. - """ - - semitransparency: bool - """Allows semi-transparent regions in the result. - - Default is true. Note: Semitransparency is currently only supported for car - windows. - """ - - -class FileUploadByUrlv1ExtensionRemoveBg(TypedDict, total=False): - name: Required[Literal["remove-bg"]] - """Specifies the background removal extension.""" - - options: FileUploadByUrlv1ExtensionRemoveBgOptions - - -class FileUploadByUrlv1ExtensionAutoTaggingExtension(TypedDict, total=False): - max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] - """Maximum number of tags to attach to the asset.""" - - min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] - """Minimum confidence level for tags to be considered valid.""" - - name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] - """Specifies the auto-tagging extension used.""" - - -class FileUploadByUrlv1ExtensionAIAutoDescription(TypedDict, total=False): - name: Required[Literal["ai-auto-description"]] - """Specifies the auto description extension.""" - - -FileUploadByUrlv1Extension: TypeAlias = Union[ - FileUploadByUrlv1ExtensionRemoveBg, - FileUploadByUrlv1ExtensionAutoTaggingExtension, - FileUploadByUrlv1ExtensionAIAutoDescription, -] - - -class FileUploadByUrlv1TransformationPostTransformation(TypedDict, total=False): +class TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" @@ -643,7 +297,7 @@ class FileUploadByUrlv1TransformationPostTransformation(TypedDict, total=False): """ -class FileUploadByUrlv1TransformationPostGifToVideo(TypedDict, total=False): +class TransformationPostGifToVideo(TypedDict, total=False): type: Required[Literal["gif-to-video"]] """Converts an animated GIF into an MP4.""" @@ -654,7 +308,7 @@ class FileUploadByUrlv1TransformationPostGifToVideo(TypedDict, total=False): """ -class FileUploadByUrlv1TransformationPostThumbnail(TypedDict, total=False): +class TransformationPostThumbnail(TypedDict, total=False): type: Required[Literal["thumbnail"]] """Generates a thumbnail image.""" @@ -665,7 +319,7 @@ class FileUploadByUrlv1TransformationPostThumbnail(TypedDict, total=False): """ -class FileUploadByUrlv1TransformationPostAbs(TypedDict, total=False): +class TransformationPostAbs(TypedDict, total=False): protocol: Required[Literal["hls", "dash"]] """Streaming protocol to use (`hls` or `dash`).""" @@ -678,16 +332,13 @@ class FileUploadByUrlv1TransformationPostAbs(TypedDict, total=False): """ -FileUploadByUrlv1TransformationPost: TypeAlias = Union[ - FileUploadByUrlv1TransformationPostTransformation, - FileUploadByUrlv1TransformationPostGifToVideo, - FileUploadByUrlv1TransformationPostThumbnail, - FileUploadByUrlv1TransformationPostAbs, +TransformationPost: TypeAlias = Union[ + TransformationPostTransformation, TransformationPostGifToVideo, TransformationPostThumbnail, TransformationPostAbs ] -class FileUploadByUrlv1Transformation(TypedDict, total=False): - post: Iterable[FileUploadByUrlv1TransformationPost] +class Transformation(TypedDict, total=False): + post: Iterable[TransformationPost] """List of transformations to apply _after_ the file is uploaded. Each item must match one of the following types: `transformation`, @@ -699,6 +350,3 @@ class FileUploadByUrlv1Transformation(TypedDict, total=False): Useful for optimizing files at ingestion. """ - - -FileUploadParams: TypeAlias = Union[FileUploadV1, FileUploadByUrlv1] diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 9b8cb7d..f639534 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -324,7 +324,7 @@ def test_streaming_response_rename(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload_overload_1(self, client: ImageKit) -> None: + def test_method_upload(self, client: ImageKit) -> None: file = client.files.upload( file=b"raw file contents", file_name="fileName", @@ -333,7 +333,7 @@ def test_method_upload_overload_1(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_upload_with_all_params_overload_1(self, client: ImageKit) -> None: + def test_method_upload_with_all_params(self, client: ImageKit) -> None: file = client.files.upload( file=b"raw file contents", file_name="fileName", @@ -395,7 +395,7 @@ def test_method_upload_with_all_params_overload_1(self, client: ImageKit) -> Non @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_upload_overload_1(self, client: ImageKit) -> None: + def test_raw_response_upload(self, client: ImageKit) -> None: response = client.files.with_raw_response.upload( file=b"raw file contents", file_name="fileName", @@ -408,7 +408,7 @@ def test_raw_response_upload_overload_1(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_upload_overload_1(self, client: ImageKit) -> None: + def test_streaming_response_upload(self, client: ImageKit) -> None: with client.files.with_streaming_response.upload( file=b"raw file contents", file_name="fileName", @@ -421,105 +421,6 @@ def test_streaming_response_upload_overload_1(self, client: ImageKit) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_upload_overload_2(self, client: ImageKit) -> None: - file = client.files.upload( - file="https://example.com", - file_name="fileName", - ) - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_upload_with_all_params_overload_2(self, client: ImageKit) -> None: - file = client.files.upload( - file="https://example.com", - file_name="fileName", - token="token", - checks='"request.folder" : "marketing/"\n', - custom_coordinates="customCoordinates", - custom_metadata={ - "brand": "bar", - "color": "bar", - }, - description="Running shoes", - expire=0, - extensions=[ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, - }, - }, - { - "max_tags": 5, - "min_confidence": 95, - "name": "google-auto-tagging", - }, - {"name": "ai-auto-description"}, - ], - folder="folder", - is_private_file=True, - is_published=True, - overwrite_ai_tags=True, - overwrite_custom_metadata=True, - overwrite_file=True, - overwrite_tags=True, - public_key="publicKey", - response_fields=["tags", "customCoordinates", "isPrivateFile"], - signature="signature", - tags=["t-shirt", "round-neck", "men"], - transformation={ - "post": [ - { - "type": "thumbnail", - "value": "w-150,h-150", - }, - { - "protocol": "dash", - "type": "abs", - "value": "sr-240_360_480_720_1080", - }, - ], - "pre": "w-300,h-300,q-80", - }, - use_unique_file_name=True, - webhook_url="https://example.com", - ) - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_upload_overload_2(self, client: ImageKit) -> None: - response = client.files.with_raw_response.upload( - file="https://example.com", - file_name="fileName", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = response.parse() - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_upload_overload_2(self, client: ImageKit) -> None: - with client.files.with_streaming_response.upload( - file="https://example.com", - file_name="fileName", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = response.parse() - assert_matches_type(FileUploadResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - class TestAsyncFiles: parametrize = pytest.mark.parametrize( @@ -826,7 +727,7 @@ async def test_streaming_response_rename(self, async_client: AsyncImageKit) -> N @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_upload_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_method_upload(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( file=b"raw file contents", file_name="fileName", @@ -835,7 +736,7 @@ async def test_method_upload_overload_1(self, async_client: AsyncImageKit) -> No @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_upload_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) -> None: file = await async_client.files.upload( file=b"raw file contents", file_name="fileName", @@ -897,7 +798,7 @@ async def test_method_upload_with_all_params_overload_1(self, async_client: Asyn @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_upload_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_raw_response_upload(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.upload( file=b"raw file contents", file_name="fileName", @@ -910,7 +811,7 @@ async def test_raw_response_upload_overload_1(self, async_client: AsyncImageKit) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_upload_overload_1(self, async_client: AsyncImageKit) -> None: + async def test_streaming_response_upload(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.upload( file=b"raw file contents", file_name="fileName", @@ -922,102 +823,3 @@ async def test_streaming_response_upload_overload_1(self, async_client: AsyncIma assert_matches_type(FileUploadResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_upload_overload_2(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.upload( - file="https://example.com", - file_name="fileName", - ) - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_upload_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.upload( - file="https://example.com", - file_name="fileName", - token="token", - checks='"request.folder" : "marketing/"\n', - custom_coordinates="customCoordinates", - custom_metadata={ - "brand": "bar", - "color": "bar", - }, - description="Running shoes", - expire=0, - extensions=[ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, - }, - }, - { - "max_tags": 5, - "min_confidence": 95, - "name": "google-auto-tagging", - }, - {"name": "ai-auto-description"}, - ], - folder="folder", - is_private_file=True, - is_published=True, - overwrite_ai_tags=True, - overwrite_custom_metadata=True, - overwrite_file=True, - overwrite_tags=True, - public_key="publicKey", - response_fields=["tags", "customCoordinates", "isPrivateFile"], - signature="signature", - tags=["t-shirt", "round-neck", "men"], - transformation={ - "post": [ - { - "type": "thumbnail", - "value": "w-150,h-150", - }, - { - "protocol": "dash", - "type": "abs", - "value": "sr-240_360_480_720_1080", - }, - ], - "pre": "w-300,h-300,q-80", - }, - use_unique_file_name=True, - webhook_url="https://example.com", - ) - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_upload_overload_2(self, async_client: AsyncImageKit) -> None: - response = await async_client.files.with_raw_response.upload( - file="https://example.com", - file_name="fileName", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = await response.parse() - assert_matches_type(FileUploadResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_upload_overload_2(self, async_client: AsyncImageKit) -> None: - async with async_client.files.with_streaming_response.upload( - file="https://example.com", - file_name="fileName", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = await response.parse() - assert_matches_type(FileUploadResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True From d2ae4c10f7063b27637222a7cd1a41d0dc87ca83 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 05:59:38 +0000 Subject: [PATCH 108/177] feat(api): manual updates --- .stats.yml | 4 ++-- src/imagekit/resources/beta/v2/files.py | 4 ++-- src/imagekit/resources/files/files.py | 4 ++-- src/imagekit/types/beta/v2/file_upload_params.py | 2 +- src/imagekit/types/file_upload_params.py | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index cfcbd7f..5908457 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-667f7f4988b44bc587d6eb9960ff5c8326e9f7e9b072f3f724f9f54166eff8b1.yml -openapi_spec_hash: f2081864a4abee0480e5ff991b4c936a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0470196862abd722b09f1af798d6f2bcbdeba0f82d1162f57c287b1a43233531.yml +openapi_spec_hash: 043dd7c67d741d0034b86f2fc0bce072 config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index a09604d..29bfdda 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -161,7 +161,7 @@ def upload( description: Optional text to describe the contents of the file. - extensions: Array of extensions to be applied to the image. Each extension can be configured + extensions: Array of extensions to be applied to the asset. Each extension can be configured with specific parameters based on the extension type. folder: The folder path in which the image has to be uploaded. If the folder(s) didn't @@ -413,7 +413,7 @@ async def upload( description: Optional text to describe the contents of the file. - extensions: Array of extensions to be applied to the image. Each extension can be configured + extensions: Array of extensions to be applied to the asset. Each extension can be configured with specific parameters based on the extension type. folder: The folder path in which the image has to be uploaded. If the folder(s) didn't diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 66bbefe..3b9fdd6 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -490,7 +490,7 @@ def upload( the future. It should be in seconds. This field is only required for authentication when uploading a file from the client side. - extensions: Array of extensions to be applied to the image. Each extension can be configured + extensions: Array of extensions to be applied to the asset. Each extension can be configured with specific parameters based on the extension type. folder: The folder path in which the image has to be uploaded. If the folder(s) didn't @@ -1061,7 +1061,7 @@ async def upload( the future. It should be in seconds. This field is only required for authentication when uploading a file from the client side. - extensions: Array of extensions to be applied to the image. Each extension can be configured + extensions: Array of extensions to be applied to the asset. Each extension can be configured with specific parameters based on the extension type. folder: The folder path in which the image has to be uploaded. If the folder(s) didn't diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekit/types/beta/v2/file_upload_params.py index fa66233..c7783ca 100644 --- a/src/imagekit/types/beta/v2/file_upload_params.py +++ b/src/imagekit/types/beta/v2/file_upload_params.py @@ -86,7 +86,7 @@ class FileUploadParams(TypedDict, total=False): """Optional text to describe the contents of the file.""" extensions: Iterable[Extension] - """Array of extensions to be applied to the image. + """Array of extensions to be applied to the asset. Each extension can be configured with specific parameters based on the extension type. diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 961db92..8e48ab7 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -95,7 +95,7 @@ class FileUploadParams(TypedDict, total=False): """ extensions: Iterable[Extension] - """Array of extensions to be applied to the image. + """Array of extensions to be applied to the asset. Each extension can be configured with specific parameters based on the extension type. From dc34e1db2c0f5d2d3e998f40d5512eb201ba0d0b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 06:02:49 +0000 Subject: [PATCH 109/177] feat(api): manual updates --- .stats.yml | 2 +- api.md | 1 + src/imagekit/resources/beta/v2/files.py | 7 +- src/imagekit/resources/files/files.py | 15 +++- src/imagekit/types/__init__.py | 1 + .../types/beta/v2/file_upload_params.py | 63 +-------------- src/imagekit/types/file_update_params.py | 69 +--------------- src/imagekit/types/file_upload_params.py | 63 +-------------- src/imagekit/types/shared/__init__.py | 1 + src/imagekit/types/shared/extensions.py | 78 +++++++++++++++++++ src/imagekit/types/shared_params/__init__.py | 3 + .../types/shared_params/extensions.py | 76 ++++++++++++++++++ 12 files changed, 183 insertions(+), 196 deletions(-) create mode 100644 src/imagekit/types/shared/extensions.py create mode 100644 src/imagekit/types/shared_params/__init__.py create mode 100644 src/imagekit/types/shared_params/extensions.py diff --git a/.stats.yml b/.stats.yml index 5908457..2dc65d2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0470196862abd722b09f1af798d6f2bcbdeba0f82d1162f57c287b1a43233531.yml openapi_spec_hash: 043dd7c67d741d0034b86f2fc0bce072 -config_hash: 70f9408b8d1dfbcf262a20d6eed50e1c +config_hash: da949a1217f48ac01676eab81ca9d1b1 diff --git a/api.md b/api.md index 9b8bf83..0c5149c 100644 --- a/api.md +++ b/api.md @@ -3,6 +3,7 @@ ```python from imagekit.types import ( BaseOverlay, + Extensions, ImageOverlay, Overlay, OverlayPosition, diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index 29bfdda..c2422d1 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, List, Mapping, Iterable, cast +from typing import Dict, List, Mapping, cast from typing_extensions import Literal import httpx @@ -19,6 +19,7 @@ ) from ...._base_client import make_request_options from ....types.beta.v2 import file_upload_params +from ....types.shared_params.extensions import Extensions from ....types.beta.v2.file_upload_response import FileUploadResponse __all__ = ["FilesResource", "AsyncFilesResource"] @@ -54,7 +55,7 @@ def upload( custom_coordinates: str | NotGiven = NOT_GIVEN, custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, + extensions: Extensions | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, @@ -306,7 +307,7 @@ async def upload( custom_coordinates: str | NotGiven = NOT_GIVEN, custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, + extensions: Extensions | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 3b9fdd6..d135055 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, List, Mapping, Iterable, cast +from typing import Dict, List, Mapping, cast from typing_extensions import Literal import httpx @@ -15,7 +15,13 @@ BulkResourceWithStreamingResponse, AsyncBulkResourceWithStreamingResponse, ) -from ...types import file_copy_params, file_move_params, file_rename_params, file_update_params, file_upload_params +from ...types import ( + file_copy_params, + file_move_params, + file_rename_params, + file_update_params, + file_upload_params, +) from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes, SequenceNotStr from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from .metadata import ( @@ -49,6 +55,7 @@ from ...types.file_rename_response import FileRenameResponse from ...types.file_update_response import FileUpdateResponse from ...types.file_upload_response import FileUploadResponse +from ...types.shared_params.extensions import Extensions __all__ = ["FilesResource", "AsyncFilesResource"] @@ -376,7 +383,7 @@ def upload( custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, + extensions: Extensions | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, @@ -947,7 +954,7 @@ async def upload( custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, expire: int | NotGiven = NOT_GIVEN, - extensions: Iterable[file_upload_params.Extension] | NotGiven = NOT_GIVEN, + extensions: Extensions | NotGiven = NOT_GIVEN, folder: str | NotGiven = NOT_GIVEN, is_private_file: bool | NotGiven = NOT_GIVEN, is_published: bool | NotGiven = NOT_GIVEN, diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index b3794c6..6bc39cf 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -8,6 +8,7 @@ from .folder import Folder as Folder from .shared import ( Overlay as Overlay, + Extensions as Extensions, SrcOptions as SrcOptions, BaseOverlay as BaseOverlay, TextOverlay as TextOverlay, diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekit/types/beta/v2/file_upload_params.py index c7783ca..53679b8 100644 --- a/src/imagekit/types/beta/v2/file_upload_params.py +++ b/src/imagekit/types/beta/v2/file_upload_params.py @@ -7,14 +7,10 @@ from ...._types import FileTypes, SequenceNotStr from ...._utils import PropertyInfo +from ...shared_params.extensions import Extensions __all__ = [ "FileUploadParams", - "Extension", - "ExtensionRemoveBg", - "ExtensionRemoveBgOptions", - "ExtensionAutoTaggingExtension", - "ExtensionAIAutoDescription", "Transformation", "TransformationPost", "TransformationPostTransformation", @@ -85,7 +81,7 @@ class FileUploadParams(TypedDict, total=False): description: str """Optional text to describe the contents of the file.""" - extensions: Iterable[Extension] + extensions: Extensions """Array of extensions to be applied to the asset. Each extension can be configured with specific parameters based on the extension @@ -198,61 +194,6 @@ class FileUploadParams(TypedDict, total=False): """ -class ExtensionRemoveBgOptions(TypedDict, total=False): - add_shadow: bool - """Whether to add an artificial shadow to the result. - - Default is false. Note: Adding shadows is currently only supported for car - photos. - """ - - bg_color: str - """ - Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or - color name (e.g., "green"). If this parameter is set, `bg_image_url` must be - empty. - """ - - bg_image_url: str - """Sets a background image from a URL. - - If this parameter is set, `bg_color` must be empty. - """ - - semitransparency: bool - """Allows semi-transparent regions in the result. - - Default is true. Note: Semitransparency is currently only supported for car - windows. - """ - - -class ExtensionRemoveBg(TypedDict, total=False): - name: Required[Literal["remove-bg"]] - """Specifies the background removal extension.""" - - options: ExtensionRemoveBgOptions - - -class ExtensionAutoTaggingExtension(TypedDict, total=False): - max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] - """Maximum number of tags to attach to the asset.""" - - min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] - """Minimum confidence level for tags to be considered valid.""" - - name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] - """Specifies the auto-tagging extension used.""" - - -class ExtensionAIAutoDescription(TypedDict, total=False): - name: Required[Literal["ai-auto-description"]] - """Specifies the auto description extension.""" - - -Extension: TypeAlias = Union[ExtensionRemoveBg, ExtensionAutoTaggingExtension, ExtensionAIAutoDescription] - - class TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index fefbe40..90dee08 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -2,21 +2,17 @@ from __future__ import annotations -from typing import Dict, Union, Iterable, Optional +from typing import Dict, Union, Optional from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict from .._types import SequenceNotStr from .._utils import PropertyInfo +from .shared_params.extensions import Extensions __all__ = [ "FileUpdateParams", "Update", "UpdateUpdateFileDetails", - "UpdateUpdateFileDetailsExtension", - "UpdateUpdateFileDetailsExtensionRemoveBg", - "UpdateUpdateFileDetailsExtensionRemoveBgOptions", - "UpdateUpdateFileDetailsExtensionAutoTaggingExtension", - "UpdateUpdateFileDetailsExtensionAIAutoDescription", "UpdateChangePublicationStatus", "UpdateChangePublicationStatusPublish", ] @@ -26,65 +22,6 @@ class FileUpdateParams(TypedDict, total=False): update: Update -class UpdateUpdateFileDetailsExtensionRemoveBgOptions(TypedDict, total=False): - add_shadow: bool - """Whether to add an artificial shadow to the result. - - Default is false. Note: Adding shadows is currently only supported for car - photos. - """ - - bg_color: str - """ - Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or - color name (e.g., "green"). If this parameter is set, `bg_image_url` must be - empty. - """ - - bg_image_url: str - """Sets a background image from a URL. - - If this parameter is set, `bg_color` must be empty. - """ - - semitransparency: bool - """Allows semi-transparent regions in the result. - - Default is true. Note: Semitransparency is currently only supported for car - windows. - """ - - -class UpdateUpdateFileDetailsExtensionRemoveBg(TypedDict, total=False): - name: Required[Literal["remove-bg"]] - """Specifies the background removal extension.""" - - options: UpdateUpdateFileDetailsExtensionRemoveBgOptions - - -class UpdateUpdateFileDetailsExtensionAutoTaggingExtension(TypedDict, total=False): - max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] - """Maximum number of tags to attach to the asset.""" - - min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] - """Minimum confidence level for tags to be considered valid.""" - - name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] - """Specifies the auto-tagging extension used.""" - - -class UpdateUpdateFileDetailsExtensionAIAutoDescription(TypedDict, total=False): - name: Required[Literal["ai-auto-description"]] - """Specifies the auto description extension.""" - - -UpdateUpdateFileDetailsExtension: TypeAlias = Union[ - UpdateUpdateFileDetailsExtensionRemoveBg, - UpdateUpdateFileDetailsExtensionAutoTaggingExtension, - UpdateUpdateFileDetailsExtensionAIAutoDescription, -] - - class UpdateUpdateFileDetails(TypedDict, total=False): custom_coordinates: Annotated[Optional[str], PropertyInfo(alias="customCoordinates")] """Define an important area in the image in the format `x,y,width,height` e.g. @@ -103,7 +40,7 @@ class UpdateUpdateFileDetails(TypedDict, total=False): description: str """Optional text to describe the contents of the file.""" - extensions: Iterable[UpdateUpdateFileDetailsExtension] + extensions: Extensions """Array of extensions to be applied to the asset. Each extension can be configured with specific parameters based on the extension diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 8e48ab7..13faef4 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -7,14 +7,10 @@ from .._types import FileTypes, SequenceNotStr from .._utils import PropertyInfo +from .shared_params.extensions import Extensions __all__ = [ "FileUploadParams", - "Extension", - "ExtensionRemoveBg", - "ExtensionRemoveBgOptions", - "ExtensionAutoTaggingExtension", - "ExtensionAIAutoDescription", "Transformation", "TransformationPost", "TransformationPostTransformation", @@ -94,7 +90,7 @@ class FileUploadParams(TypedDict, total=False): authentication when uploading a file from the client side. """ - extensions: Iterable[Extension] + extensions: Extensions """Array of extensions to be applied to the asset. Each extension can be configured with specific parameters based on the extension @@ -230,61 +226,6 @@ class FileUploadParams(TypedDict, total=False): """ -class ExtensionRemoveBgOptions(TypedDict, total=False): - add_shadow: bool - """Whether to add an artificial shadow to the result. - - Default is false. Note: Adding shadows is currently only supported for car - photos. - """ - - bg_color: str - """ - Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or - color name (e.g., "green"). If this parameter is set, `bg_image_url` must be - empty. - """ - - bg_image_url: str - """Sets a background image from a URL. - - If this parameter is set, `bg_color` must be empty. - """ - - semitransparency: bool - """Allows semi-transparent regions in the result. - - Default is true. Note: Semitransparency is currently only supported for car - windows. - """ - - -class ExtensionRemoveBg(TypedDict, total=False): - name: Required[Literal["remove-bg"]] - """Specifies the background removal extension.""" - - options: ExtensionRemoveBgOptions - - -class ExtensionAutoTaggingExtension(TypedDict, total=False): - max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] - """Maximum number of tags to attach to the asset.""" - - min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] - """Minimum confidence level for tags to be considered valid.""" - - name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] - """Specifies the auto-tagging extension used.""" - - -class ExtensionAIAutoDescription(TypedDict, total=False): - name: Required[Literal["ai-auto-description"]] - """Specifies the auto description extension.""" - - -Extension: TypeAlias = Union[ExtensionRemoveBg, ExtensionAutoTaggingExtension, ExtensionAIAutoDescription] - - class TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" diff --git a/src/imagekit/types/shared/__init__.py b/src/imagekit/types/shared/__init__.py index 794a18b..a91ccbd 100644 --- a/src/imagekit/types/shared/__init__.py +++ b/src/imagekit/types/shared/__init__.py @@ -1,6 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .overlay import Overlay as Overlay +from .extensions import Extensions as Extensions from .src_options import SrcOptions as SrcOptions from .base_overlay import BaseOverlay as BaseOverlay from .text_overlay import TextOverlay as TextOverlay diff --git a/src/imagekit/types/shared/extensions.py b/src/imagekit/types/shared/extensions.py new file mode 100644 index 0000000..36d0a05 --- /dev/null +++ b/src/imagekit/types/shared/extensions.py @@ -0,0 +1,78 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, Annotated, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._utils import PropertyInfo +from ..._models import BaseModel + +__all__ = [ + "Extensions", + "ExtensionItem", + "ExtensionItemRemoveBg", + "ExtensionItemRemoveBgOptions", + "ExtensionItemAutoTaggingExtension", + "ExtensionItemAIAutoDescription", +] + + +class ExtensionItemRemoveBgOptions(BaseModel): + add_shadow: Optional[bool] = None + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: Optional[str] = None + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: Optional[str] = None + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: Optional[bool] = None + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class ExtensionItemRemoveBg(BaseModel): + name: Literal["remove-bg"] + """Specifies the background removal extension.""" + + options: Optional[ExtensionItemRemoveBgOptions] = None + + +class ExtensionItemAutoTaggingExtension(BaseModel): + max_tags: int = FieldInfo(alias="maxTags") + """Maximum number of tags to attach to the asset.""" + + min_confidence: int = FieldInfo(alias="minConfidence") + """Minimum confidence level for tags to be considered valid.""" + + name: Literal["google-auto-tagging", "aws-auto-tagging"] + """Specifies the auto-tagging extension used.""" + + +class ExtensionItemAIAutoDescription(BaseModel): + name: Literal["ai-auto-description"] + """Specifies the auto description extension.""" + + +ExtensionItem: TypeAlias = Annotated[ + Union[ExtensionItemRemoveBg, ExtensionItemAutoTaggingExtension, ExtensionItemAIAutoDescription], + PropertyInfo(discriminator="name"), +] + +Extensions: TypeAlias = List[ExtensionItem] diff --git a/src/imagekit/types/shared_params/__init__.py b/src/imagekit/types/shared_params/__init__.py new file mode 100644 index 0000000..165dee4 --- /dev/null +++ b/src/imagekit/types/shared_params/__init__.py @@ -0,0 +1,3 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .extensions import Extensions as Extensions diff --git a/src/imagekit/types/shared_params/extensions.py b/src/imagekit/types/shared_params/extensions.py new file mode 100644 index 0000000..f2ab9d1 --- /dev/null +++ b/src/imagekit/types/shared_params/extensions.py @@ -0,0 +1,76 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from ..._utils import PropertyInfo + +__all__ = [ + "Extensions", + "ExtensionItem", + "ExtensionItemRemoveBg", + "ExtensionItemRemoveBgOptions", + "ExtensionItemAutoTaggingExtension", + "ExtensionItemAIAutoDescription", +] + + +class ExtensionItemRemoveBgOptions(TypedDict, total=False): + add_shadow: bool + """Whether to add an artificial shadow to the result. + + Default is false. Note: Adding shadows is currently only supported for car + photos. + """ + + bg_color: str + """ + Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + empty. + """ + + bg_image_url: str + """Sets a background image from a URL. + + If this parameter is set, `bg_color` must be empty. + """ + + semitransparency: bool + """Allows semi-transparent regions in the result. + + Default is true. Note: Semitransparency is currently only supported for car + windows. + """ + + +class ExtensionItemRemoveBg(TypedDict, total=False): + name: Required[Literal["remove-bg"]] + """Specifies the background removal extension.""" + + options: ExtensionItemRemoveBgOptions + + +class ExtensionItemAutoTaggingExtension(TypedDict, total=False): + max_tags: Required[Annotated[int, PropertyInfo(alias="maxTags")]] + """Maximum number of tags to attach to the asset.""" + + min_confidence: Required[Annotated[int, PropertyInfo(alias="minConfidence")]] + """Minimum confidence level for tags to be considered valid.""" + + name: Required[Literal["google-auto-tagging", "aws-auto-tagging"]] + """Specifies the auto-tagging extension used.""" + + +class ExtensionItemAIAutoDescription(TypedDict, total=False): + name: Required[Literal["ai-auto-description"]] + """Specifies the auto description extension.""" + + +ExtensionItem: TypeAlias = Union[ + ExtensionItemRemoveBg, ExtensionItemAutoTaggingExtension, ExtensionItemAIAutoDescription +] + +Extensions: TypeAlias = List[ExtensionItem] From 5170ba9c727e96aebf31a87444c7e81f389b8df3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 06:46:49 +0000 Subject: [PATCH 110/177] feat(api): manual updates --- .stats.yml | 2 +- src/imagekit/resources/accounts/origins.py | 1890 +++++++++++++- src/imagekit/resources/files/files.py | 212 +- .../types/accounts/origin_create_params.py | 206 +- .../types/accounts/origin_update_params.py | 206 +- src/imagekit/types/file_update_params.py | 28 +- tests/api_resources/accounts/test_origins.py | 2299 +++++++++++++++-- tests/api_resources/test_files.py | 232 +- 8 files changed, 4657 insertions(+), 418 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2dc65d2..335e38e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0470196862abd722b09f1af798d6f2bcbdeba0f82d1162f57c287b1a43233531.yml openapi_spec_hash: 043dd7c67d741d0034b86f2fc0bce072 -config_hash: da949a1217f48ac01676eab81ca9d1b1 +config_hash: a652d68098d82eaf611a49507fb4b831 diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index c036f03..533af6c 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -3,11 +3,12 @@ from __future__ import annotations from typing import Any, cast +from typing_extensions import Literal, overload import httpx from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from ..._utils import maybe_transform, async_maybe_transform +from ..._utils import required_args, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -20,7 +21,6 @@ from ...types.accounts import origin_create_params, origin_update_params from ...types.accounts.origin_response import OriginResponse from ...types.accounts.origin_list_response import OriginListResponse -from ...types.accounts.origin_request_param import OriginRequestParam __all__ = ["OriginsResource", "AsyncOriginsResource"] @@ -45,10 +45,18 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: """ return OriginsResourceWithStreamingResponse(self) + @overload def create( self, *, - origin: OriginRequestParam, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["S3"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -62,7 +70,1347 @@ def create( Creates a new origin and returns the origin object. Args: - origin: Schema for origin request resources. + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + access_key: str, + bucket: str, + endpoint: str, + name: str, + secret_key: str, + type: Literal["S3_COMPATIBLE"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + endpoint: Custom S3-compatible endpoint. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + s3_force_path_style: Use path-style S3 URLs? + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["CLOUDINARY_BACKUP"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + base_url: str, + name: str, + type: Literal["WEB_FOLDER"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + base_url: Root URL for the web folder origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + forward_host_header_to_origin: Forward the Host header to origin? + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + name: str, + type: Literal["WEB_PROXY"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + bucket: str, + client_email: str, + name: str, + private_key: str, + type: Literal["GCS"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + account_name: str, + container: str, + name: str, + sas_token: str, + type: Literal["AZURE_BLOB"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + base_url: str, + client_id: str, + client_secret: str, + name: str, + password: str, + type: Literal["AKENEO_PIM"], + username: str, + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + base_url: Akeneo instance base URL. + + client_id: Akeneo API client ID. + + client_secret: Akeneo API client secret. + + name: Display name of the origin. + + password: Akeneo API password. + + username: Akeneo API username. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args( + ["access_key", "bucket", "name", "secret_key", "type"], + ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], + ["base_url", "name", "type"], + ["name", "type"], + ["bucket", "client_email", "name", "private_key", "type"], + ["account_name", "container", "name", "sas_token", "type"], + ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], + ) + def create( + self, + *, + access_key: str | NotGiven = NOT_GIVEN, + bucket: str | NotGiven = NOT_GIVEN, + name: str, + secret_key: str | NotGiven = NOT_GIVEN, + type: Literal["S3"] + | Literal["S3_COMPATIBLE"] + | Literal["CLOUDINARY_BACKUP"] + | Literal["WEB_FOLDER"] + | Literal["WEB_PROXY"] + | Literal["GCS"] + | Literal["AZURE_BLOB"] + | Literal["AKENEO_PIM"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + endpoint: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + client_email: str | NotGiven = NOT_GIVEN, + private_key: str | NotGiven = NOT_GIVEN, + account_name: str | NotGiven = NOT_GIVEN, + container: str | NotGiven = NOT_GIVEN, + sas_token: str | NotGiven = NOT_GIVEN, + client_id: str | NotGiven = NOT_GIVEN, + client_secret: str | NotGiven = NOT_GIVEN, + password: str | NotGiven = NOT_GIVEN, + username: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + return cast( + OriginResponse, + self._post( + "/v1/accounts/origins", + body=maybe_transform( + { + "access_key": access_key, + "bucket": bucket, + "name": name, + "secret_key": secret_key, + "type": type, + "base_url_for_canonical_header": base_url_for_canonical_header, + "include_canonical_header": include_canonical_header, + "prefix": prefix, + "endpoint": endpoint, + "s3_force_path_style": s3_force_path_style, + "base_url": base_url, + "forward_host_header_to_origin": forward_host_header_to_origin, + "client_email": client_email, + "private_key": private_key, + "account_name": account_name, + "container": container, + "sas_token": sas_token, + "client_id": client_id, + "client_secret": client_secret, + "password": password, + "username": username, + }, + origin_create_params.OriginCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system + ), + ) + + @overload + def update( + self, + id: str, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["S3"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + access_key: str, + bucket: str, + endpoint: str, + name: str, + secret_key: str, + type: Literal["S3_COMPATIBLE"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + endpoint: Custom S3-compatible endpoint. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + s3_force_path_style: Use path-style S3 URLs? + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["CLOUDINARY_BACKUP"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + base_url: str, + name: str, + type: Literal["WEB_FOLDER"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + base_url: Root URL for the web folder origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + forward_host_header_to_origin: Forward the Host header to origin? + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + name: str, + type: Literal["WEB_PROXY"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + bucket: str, + client_email: str, + name: str, + private_key: str, + type: Literal["GCS"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + account_name: str, + container: str, + name: str, + sas_token: str, + type: Literal["AZURE_BLOB"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + id: str, + *, + base_url: str, + client_id: str, + client_secret: str, + name: str, + password: str, + type: Literal["AKENEO_PIM"], + username: str, + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + base_url: Akeneo instance base URL. + + client_id: Akeneo API client ID. + + client_secret: Akeneo API client secret. + + name: Display name of the origin. + + password: Akeneo API password. + + username: Akeneo API username. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args( + ["access_key", "bucket", "name", "secret_key", "type"], + ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], + ["base_url", "name", "type"], + ["name", "type"], + ["bucket", "client_email", "name", "private_key", "type"], + ["account_name", "container", "name", "sas_token", "type"], + ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], + ) + def update( + self, + id: str, + *, + access_key: str | NotGiven = NOT_GIVEN, + bucket: str | NotGiven = NOT_GIVEN, + name: str, + secret_key: str | NotGiven = NOT_GIVEN, + type: Literal["S3"] + | Literal["S3_COMPATIBLE"] + | Literal["CLOUDINARY_BACKUP"] + | Literal["WEB_FOLDER"] + | Literal["WEB_PROXY"] + | Literal["GCS"] + | Literal["AZURE_BLOB"] + | Literal["AKENEO_PIM"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + endpoint: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + client_email: str | NotGiven = NOT_GIVEN, + private_key: str | NotGiven = NOT_GIVEN, + account_name: str | NotGiven = NOT_GIVEN, + container: str | NotGiven = NOT_GIVEN, + sas_token: str | NotGiven = NOT_GIVEN, + client_id: str | NotGiven = NOT_GIVEN, + client_secret: str | NotGiven = NOT_GIVEN, + password: str | NotGiven = NOT_GIVEN, + username: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginResponse, + self._put( + f"/v1/accounts/origins/{id}", + body=maybe_transform( + { + "access_key": access_key, + "bucket": bucket, + "name": name, + "secret_key": secret_key, + "type": type, + "base_url_for_canonical_header": base_url_for_canonical_header, + "include_canonical_header": include_canonical_header, + "prefix": prefix, + "endpoint": endpoint, + "s3_force_path_style": s3_force_path_style, + "base_url": base_url, + "forward_host_header_to_origin": forward_host_header_to_origin, + "client_email": client_email, + "private_key": private_key, + "account_name": account_name, + "container": container, + "sas_token": sas_token, + "client_id": client_id, + "client_secret": client_secret, + "password": password, + "username": username, + }, + origin_update_params.OriginUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system + ), + ) + + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginListResponse: + """**Note:** This API is currently in beta. + + + Returns an array of all configured origins for the current account. + """ + return self._get( + "/v1/accounts/origins", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=OriginListResponse, + ) + + def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """**Note:** This API is currently in beta. + + + Permanently removes the origin identified by `id`. If the origin is in use by + any URL‑endpoints, the API will return an error. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def get( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Retrieves the origin identified by `id`. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return cast( + OriginResponse, + self._get( + f"/v1/accounts/origins/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system + ), + ) + + +class AsyncOriginsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncOriginsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + """ + return AsyncOriginsResourceWithStreamingResponse(self) + + @overload + async def create( + self, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["S3"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + access_key: str, + bucket: str, + endpoint: str, + name: str, + secret_key: str, + type: Literal["S3_COMPATIBLE"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + endpoint: Custom S3-compatible endpoint. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + s3_force_path_style: Use path-style S3 URLs? + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["CLOUDINARY_BACKUP"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + base_url: str, + name: str, + type: Literal["WEB_FOLDER"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + base_url: Root URL for the web folder origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + forward_host_header_to_origin: Forward the Host header to origin? + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + name: str, + type: Literal["WEB_PROXY"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + bucket: str, + client_email: str, + name: str, + private_key: str, + type: Literal["GCS"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + account_name: str, + container: str, + name: str, + sas_token: str, + type: Literal["AZURE_BLOB"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. extra_headers: Send extra headers @@ -72,11 +1420,137 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @overload + async def create( + self, + *, + base_url: str, + client_id: str, + client_secret: str, + name: str, + password: str, + type: Literal["AKENEO_PIM"], + username: str, + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Creates a new origin and returns the origin object. + + Args: + base_url: Akeneo instance base URL. + + client_id: Akeneo API client ID. + + client_secret: Akeneo API client secret. + + name: Display name of the origin. + + password: Akeneo API password. + + username: Akeneo API username. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args( + ["access_key", "bucket", "name", "secret_key", "type"], + ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], + ["base_url", "name", "type"], + ["name", "type"], + ["bucket", "client_email", "name", "private_key", "type"], + ["account_name", "container", "name", "sas_token", "type"], + ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], + ) + async def create( + self, + *, + access_key: str | NotGiven = NOT_GIVEN, + bucket: str | NotGiven = NOT_GIVEN, + name: str, + secret_key: str | NotGiven = NOT_GIVEN, + type: Literal["S3"] + | Literal["S3_COMPATIBLE"] + | Literal["CLOUDINARY_BACKUP"] + | Literal["WEB_FOLDER"] + | Literal["WEB_PROXY"] + | Literal["GCS"] + | Literal["AZURE_BLOB"] + | Literal["AKENEO_PIM"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + endpoint: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + client_email: str | NotGiven = NOT_GIVEN, + private_key: str | NotGiven = NOT_GIVEN, + account_name: str | NotGiven = NOT_GIVEN, + container: str | NotGiven = NOT_GIVEN, + sas_token: str | NotGiven = NOT_GIVEN, + client_id: str | NotGiven = NOT_GIVEN, + client_secret: str | NotGiven = NOT_GIVEN, + password: str | NotGiven = NOT_GIVEN, + username: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: return cast( OriginResponse, - self._post( + await self._post( "/v1/accounts/origins", - body=maybe_transform(origin, origin_create_params.OriginCreateParams), + body=await async_maybe_transform( + { + "access_key": access_key, + "bucket": bucket, + "name": name, + "secret_key": secret_key, + "type": type, + "base_url_for_canonical_header": base_url_for_canonical_header, + "include_canonical_header": include_canonical_header, + "prefix": prefix, + "endpoint": endpoint, + "s3_force_path_style": s3_force_path_style, + "base_url": base_url, + "forward_host_header_to_origin": forward_host_header_to_origin, + "client_email": client_email, + "private_key": private_key, + "account_name": account_name, + "container": container, + "sas_token": sas_token, + "client_id": client_id, + "client_secret": client_secret, + "password": password, + "username": username, + }, + origin_create_params.OriginCreateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -84,11 +1558,19 @@ def create( ), ) - def update( + @overload + async def update( self, id: str, *, - origin: OriginRequestParam, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["S3"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -105,7 +1587,19 @@ def update( id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - origin: Schema for origin request resources. + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. extra_headers: Send extra headers @@ -115,64 +1609,110 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return cast( - OriginResponse, - self._put( - f"/v1/accounts/origins/{id}", - body=maybe_transform(origin, origin_update_params.OriginUpdateParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system - ), - ) + ... - def list( + @overload + async def update( self, + id: str, *, + access_key: str, + bucket: str, + endpoint: str, + name: str, + secret_key: str, + type: Literal["S3_COMPATIBLE"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> OriginListResponse: + ) -> OriginResponse: """**Note:** This API is currently in beta. - Returns an array of all configured origins for the current account. + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + endpoint: Custom S3-compatible endpoint. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + + s3_force_path_style: Use path-style S3 URLs? + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds """ - return self._get( - "/v1/accounts/origins", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=OriginListResponse, - ) + ... - def delete( + @overload + async def update( self, id: str, *, + access_key: str, + bucket: str, + name: str, + secret_key: str, + type: Literal["CLOUDINARY_BACKUP"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> None: + ) -> OriginResponse: """**Note:** This API is currently in beta. - Permanently removes the origin identified by `id`. If the origin is in use by - any URL‑endpoints, the API will return an error. + Updates the origin identified by `id` and returns the updated origin object. Args: id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. + access_key: Access key for the bucket. + + bucket: S3 bucket name. + + name: Display name of the origin. + + secret_key: Secret key for the bucket. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + prefix: Path prefix inside the bucket. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -181,21 +1721,19 @@ def delete( timeout: Override the client-level default timeout for this request, in seconds """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - f"/v1/accounts/origins/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) + ... - def get( + @overload + async def update( self, id: str, *, + base_url: str, + name: str, + type: Literal["WEB_FOLDER"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -206,12 +1744,22 @@ def get( """**Note:** This API is currently in beta. - Retrieves the origin identified by `id`. + Updates the origin identified by `id` and returns the updated origin object. Args: id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. + base_url: Root URL for the web folder origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + forward_host_header_to_origin: Forward the Host header to origin? + + include_canonical_header: Whether to send a Canonical header. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -220,44 +1768,107 @@ def get( timeout: Override the client-level default timeout for this request, in seconds """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return cast( - OriginResponse, - self._get( - f"/v1/accounts/origins/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system - ), - ) + ... + @overload + async def update( + self, + id: str, + *, + name: str, + type: Literal["WEB_PROXY"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. -class AsyncOriginsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers - """ - return AsyncOriginsResourceWithRawResponse(self) + Updates the origin identified by `id` and returns the updated origin object. - @cached_property - def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. + ... - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + @overload + async def update( + self, + id: str, + *, + bucket: str, + client_email: str, + name: str, + private_key: str, + type: Literal["GCS"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: + """**Note:** This API is currently in beta. + + + Updates the origin identified by `id` and returns the updated origin object. + + Args: + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds """ - return AsyncOriginsResourceWithStreamingResponse(self) + ... - async def create( + @overload + async def update( self, + id: str, *, - origin: OriginRequestParam, + account_name: str, + container: str, + name: str, + sas_token: str, + type: Literal["AZURE_BLOB"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -268,10 +1879,17 @@ async def create( """**Note:** This API is currently in beta. - Creates a new origin and returns the origin object. + Updates the origin identified by `id` and returns the updated origin object. Args: - origin: Schema for origin request resources. + id: Unique identifier for the origin. This is generated by ImageKit when you create + a new origin. + + name: Display name of the origin. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. extra_headers: Send extra headers @@ -281,23 +1899,22 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ - return cast( - OriginResponse, - await self._post( - "/v1/accounts/origins", - body=await async_maybe_transform(origin, origin_create_params.OriginCreateParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast(Any, OriginResponse), # Union types cannot be passed in as arguments in the type system - ), - ) + ... + @overload async def update( self, id: str, *, - origin: OriginRequestParam, + base_url: str, + client_id: str, + client_secret: str, + name: str, + password: str, + type: Literal["AKENEO_PIM"], + username: str, + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -314,7 +1931,21 @@ async def update( id: Unique identifier for the origin. This is generated by ImageKit when you create a new origin. - origin: Schema for origin request resources. + base_url: Akeneo instance base URL. + + client_id: Akeneo API client ID. + + client_secret: Akeneo API client secret. + + name: Display name of the origin. + + password: Akeneo API password. + + username: Akeneo API username. + + base_url_for_canonical_header: URL used in the Canonical header (if enabled). + + include_canonical_header: Whether to send a Canonical header. extra_headers: Send extra headers @@ -324,13 +1955,88 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @required_args( + ["access_key", "bucket", "name", "secret_key", "type"], + ["access_key", "bucket", "endpoint", "name", "secret_key", "type"], + ["base_url", "name", "type"], + ["name", "type"], + ["bucket", "client_email", "name", "private_key", "type"], + ["account_name", "container", "name", "sas_token", "type"], + ["base_url", "client_id", "client_secret", "name", "password", "type", "username"], + ) + async def update( + self, + id: str, + *, + access_key: str | NotGiven = NOT_GIVEN, + bucket: str | NotGiven = NOT_GIVEN, + name: str, + secret_key: str | NotGiven = NOT_GIVEN, + type: Literal["S3"] + | Literal["S3_COMPATIBLE"] + | Literal["CLOUDINARY_BACKUP"] + | Literal["WEB_FOLDER"] + | Literal["WEB_PROXY"] + | Literal["GCS"] + | Literal["AZURE_BLOB"] + | Literal["AKENEO_PIM"], + base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, + include_canonical_header: bool | NotGiven = NOT_GIVEN, + prefix: str | NotGiven = NOT_GIVEN, + endpoint: str | NotGiven = NOT_GIVEN, + s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url: str | NotGiven = NOT_GIVEN, + forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, + client_email: str | NotGiven = NOT_GIVEN, + private_key: str | NotGiven = NOT_GIVEN, + account_name: str | NotGiven = NOT_GIVEN, + container: str | NotGiven = NOT_GIVEN, + sas_token: str | NotGiven = NOT_GIVEN, + client_id: str | NotGiven = NOT_GIVEN, + client_secret: str | NotGiven = NOT_GIVEN, + password: str | NotGiven = NOT_GIVEN, + username: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> OriginResponse: if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return cast( OriginResponse, await self._put( f"/v1/accounts/origins/{id}", - body=await async_maybe_transform(origin, origin_update_params.OriginUpdateParams), + body=await async_maybe_transform( + { + "access_key": access_key, + "bucket": bucket, + "name": name, + "secret_key": secret_key, + "type": type, + "base_url_for_canonical_header": base_url_for_canonical_header, + "include_canonical_header": include_canonical_header, + "prefix": prefix, + "endpoint": endpoint, + "s3_force_path_style": s3_force_path_style, + "base_url": base_url, + "forward_host_header_to_origin": forward_host_header_to_origin, + "client_email": client_email, + "private_key": private_key, + "account_name": account_name, + "container": container, + "sas_token": sas_token, + "client_id": client_id, + "client_secret": client_secret, + "password": password, + "username": username, + }, + origin_update_params.OriginUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index d135055..0798330 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -2,8 +2,8 @@ from __future__ import annotations -from typing import Dict, List, Mapping, cast -from typing_extensions import Literal +from typing import Dict, List, Union, Mapping, Optional, cast +from typing_extensions import Literal, overload import httpx @@ -92,11 +92,18 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ return FilesResourceWithStreamingResponse(self) + @overload def update( self, file_id: str, *, - update: file_update_params.Update | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Extensions | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[SequenceNotStr[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -110,6 +117,35 @@ def update( status, remove existing `AITags` and apply extensions using this API. Args: + custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. + `10,10,100,100`. Send `null` to unset this value. + + custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` + value for that key. Before setting any custom metadata on an asset you have to + create the field using custom metadata fields API. + + description: Optional text to describe the contents of the file. + + extensions: Array of extensions to be applied to the asset. Each extension can be configured + with specific parameters based on the extension type. + + remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". + + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + + tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send + `null` to unset all tags associated with the file. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -118,11 +154,75 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @overload + def update( + self, + file_id: str, + *, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUpdateResponse: + """ + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. + + Args: + publish: Configure the publication status of a file and its versions. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + def update( + self, + file_id: str, + *, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Extensions | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[SequenceNotStr[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._patch( f"/v1/files/{file_id}/details", - body=maybe_transform(update, file_update_params.FileUpdateParams), + body=maybe_transform( + { + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "extensions": extensions, + "remove_ai_tags": remove_ai_tags, + "tags": tags, + "webhook_url": webhook_url, + "publish": publish, + }, + file_update_params.FileUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -663,11 +763,18 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ return AsyncFilesResourceWithStreamingResponse(self) + @overload async def update( self, file_id: str, *, - update: file_update_params.Update | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Extensions | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[SequenceNotStr[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -681,6 +788,35 @@ async def update( status, remove existing `AITags` and apply extensions using this API. Args: + custom_coordinates: Define an important area in the image in the format `x,y,width,height` e.g. + `10,10,100,100`. Send `null` to unset this value. + + custom_metadata: A key-value data to be associated with the asset. To unset a key, send `null` + value for that key. Before setting any custom metadata on an asset you have to + create the field using custom metadata fields API. + + description: Optional text to describe the contents of the file. + + extensions: Array of extensions to be applied to the asset. Each extension can be configured + with specific parameters based on the extension type. + + remove_ai_tags: An array of AITags associated with the file that you want to remove, e.g. + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". + + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + + tags: An array of tags associated with the file, such as `["tag1", "tag2"]`. Send + `null` to unset all tags associated with the file. + + webhook_url: The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -689,11 +825,75 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @overload + async def update( + self, + file_id: str, + *, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUpdateResponse: + """ + This API updates the details or attributes of the current version of the file. + You can update `tags`, `customCoordinates`, `customMetadata`, publication + status, remove existing `AITags` and apply extensions using this API. + + Args: + publish: Configure the publication status of a file and its versions. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + async def update( + self, + file_id: str, + *, + custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, + custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, + description: str | NotGiven = NOT_GIVEN, + extensions: Extensions | NotGiven = NOT_GIVEN, + remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | NotGiven = NOT_GIVEN, + tags: Optional[SequenceNotStr[str]] | NotGiven = NOT_GIVEN, + webhook_url: str | NotGiven = NOT_GIVEN, + publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._patch( f"/v1/files/{file_id}/details", - body=await async_maybe_transform(update, file_update_params.FileUpdateParams), + body=await async_maybe_transform( + { + "custom_coordinates": custom_coordinates, + "custom_metadata": custom_metadata, + "description": description, + "extensions": extensions, + "remove_ai_tags": remove_ai_tags, + "tags": tags, + "webhook_url": webhook_url, + "publish": publish, + }, + file_update_params.FileUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/imagekit/types/accounts/origin_create_params.py b/src/imagekit/types/accounts/origin_create_params.py index adb74db..7489a1d 100644 --- a/src/imagekit/types/accounts/origin_create_params.py +++ b/src/imagekit/types/accounts/origin_create_params.py @@ -2,13 +2,207 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing import Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from .origin_request_param import OriginRequestParam +from ..._utils import PropertyInfo -__all__ = ["OriginCreateParams"] +__all__ = [ + "OriginCreateParams", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "GoogleCloudStorageGcs", + "AzureBlobStorage", + "AkeneoPim", +] -class OriginCreateParams(TypedDict, total=False): - origin: Required[OriginRequestParam] - """Schema for origin request resources.""" +class S3(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class S3Compatible(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + endpoint: Required[str] + """Custom S3-compatible endpoint.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3_COMPATIBLE"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] + """Use path-style S3 URLs?""" + + +class CloudinaryBackup(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["CLOUDINARY_BACKUP"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class WebFolder(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Root URL for the web folder origin.""" + + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_FOLDER"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] + """Forward the Host header to origin?""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class WebProxy(TypedDict, total=False): + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_PROXY"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class GoogleCloudStorageGcs(TypedDict, total=False): + bucket: Required[str] + + client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] + + name: Required[str] + """Display name of the origin.""" + + private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] + + type: Required[Literal["GCS"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AzureBlobStorage(TypedDict, total=False): + account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] + + container: Required[str] + + name: Required[str] + """Display name of the origin.""" + + sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] + + type: Required[Literal["AZURE_BLOB"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AkeneoPim(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Akeneo instance base URL.""" + + client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] + """Akeneo API client ID.""" + + client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] + """Akeneo API client secret.""" + + name: Required[str] + """Display name of the origin.""" + + password: Required[str] + """Akeneo API password.""" + + type: Required[Literal["AKENEO_PIM"]] + + username: Required[str] + """Akeneo API username.""" + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +OriginCreateParams: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +] diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekit/types/accounts/origin_update_params.py index 138bf3c..a7b39fb 100644 --- a/src/imagekit/types/accounts/origin_update_params.py +++ b/src/imagekit/types/accounts/origin_update_params.py @@ -2,13 +2,207 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing import Union +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from .origin_request_param import OriginRequestParam +from ..._utils import PropertyInfo -__all__ = ["OriginUpdateParams"] +__all__ = [ + "OriginUpdateParams", + "S3", + "S3Compatible", + "CloudinaryBackup", + "WebFolder", + "WebProxy", + "GoogleCloudStorageGcs", + "AzureBlobStorage", + "AkeneoPim", +] -class OriginUpdateParams(TypedDict, total=False): - origin: Required[OriginRequestParam] - """Schema for origin request resources.""" +class S3(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class S3Compatible(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + endpoint: Required[str] + """Custom S3-compatible endpoint.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["S3_COMPATIBLE"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + s3_force_path_style: Annotated[bool, PropertyInfo(alias="s3ForcePathStyle")] + """Use path-style S3 URLs?""" + + +class CloudinaryBackup(TypedDict, total=False): + access_key: Required[Annotated[str, PropertyInfo(alias="accessKey")]] + """Access key for the bucket.""" + + bucket: Required[str] + """S3 bucket name.""" + + name: Required[str] + """Display name of the origin.""" + + secret_key: Required[Annotated[str, PropertyInfo(alias="secretKey")]] + """Secret key for the bucket.""" + + type: Required[Literal["CLOUDINARY_BACKUP"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + """Path prefix inside the bucket.""" + + +class WebFolder(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Root URL for the web folder origin.""" + + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_FOLDER"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + forward_host_header_to_origin: Annotated[bool, PropertyInfo(alias="forwardHostHeaderToOrigin")] + """Forward the Host header to origin?""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class WebProxy(TypedDict, total=False): + name: Required[str] + """Display name of the origin.""" + + type: Required[Literal["WEB_PROXY"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +class GoogleCloudStorageGcs(TypedDict, total=False): + bucket: Required[str] + + client_email: Required[Annotated[str, PropertyInfo(alias="clientEmail")]] + + name: Required[str] + """Display name of the origin.""" + + private_key: Required[Annotated[str, PropertyInfo(alias="privateKey")]] + + type: Required[Literal["GCS"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AzureBlobStorage(TypedDict, total=False): + account_name: Required[Annotated[str, PropertyInfo(alias="accountName")]] + + container: Required[str] + + name: Required[str] + """Display name of the origin.""" + + sas_token: Required[Annotated[str, PropertyInfo(alias="sasToken")]] + + type: Required[Literal["AZURE_BLOB"]] + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + prefix: str + + +class AkeneoPim(TypedDict, total=False): + base_url: Required[Annotated[str, PropertyInfo(alias="baseUrl")]] + """Akeneo instance base URL.""" + + client_id: Required[Annotated[str, PropertyInfo(alias="clientId")]] + """Akeneo API client ID.""" + + client_secret: Required[Annotated[str, PropertyInfo(alias="clientSecret")]] + """Akeneo API client secret.""" + + name: Required[str] + """Display name of the origin.""" + + password: Required[str] + """Akeneo API password.""" + + type: Required[Literal["AKENEO_PIM"]] + + username: Required[str] + """Akeneo API username.""" + + base_url_for_canonical_header: Annotated[str, PropertyInfo(alias="baseUrlForCanonicalHeader")] + """URL used in the Canonical header (if enabled).""" + + include_canonical_header: Annotated[bool, PropertyInfo(alias="includeCanonicalHeader")] + """Whether to send a Canonical header.""" + + +OriginUpdateParams: TypeAlias = Union[ + S3, S3Compatible, CloudinaryBackup, WebFolder, WebProxy, GoogleCloudStorageGcs, AzureBlobStorage, AkeneoPim +] diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index 90dee08..233492c 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -9,20 +9,10 @@ from .._utils import PropertyInfo from .shared_params.extensions import Extensions -__all__ = [ - "FileUpdateParams", - "Update", - "UpdateUpdateFileDetails", - "UpdateChangePublicationStatus", - "UpdateChangePublicationStatusPublish", -] +__all__ = ["FileUpdateParams", "UpdateFileDetails", "ChangePublicationStatus", "ChangePublicationStatusPublish"] -class FileUpdateParams(TypedDict, total=False): - update: Update - - -class UpdateUpdateFileDetails(TypedDict, total=False): +class UpdateFileDetails(TypedDict, total=False): custom_coordinates: Annotated[Optional[str], PropertyInfo(alias="customCoordinates")] """Define an important area in the image in the format `x,y,width,height` e.g. @@ -74,7 +64,12 @@ class UpdateUpdateFileDetails(TypedDict, total=False): """ -class UpdateChangePublicationStatusPublish(TypedDict, total=False): +class ChangePublicationStatus(TypedDict, total=False): + publish: ChangePublicationStatusPublish + """Configure the publication status of a file and its versions.""" + + +class ChangePublicationStatusPublish(TypedDict, total=False): is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] """Set to `true` to publish the file. Set to `false` to unpublish the file.""" @@ -85,9 +80,4 @@ class UpdateChangePublicationStatusPublish(TypedDict, total=False): """ -class UpdateChangePublicationStatus(TypedDict, total=False): - publish: UpdateChangePublicationStatusPublish - """Configure the publication status of a file and its versions.""" - - -Update: TypeAlias = Union[UpdateUpdateFileDetails, UpdateChangePublicationStatus] +FileUpdateParams: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] diff --git a/tests/api_resources/accounts/test_origins.py b/tests/api_resources/accounts/test_origins.py index ba060f6..8afdef4 100644 --- a/tests/api_resources/accounts/test_origins.py +++ b/tests/api_resources/accounts/test_origins.py @@ -9,10 +9,7 @@ from imagekit import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.accounts import ( - OriginResponse, - OriginListResponse, -) +from imagekit.types.accounts import OriginResponse, OriginListResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -22,46 +19,40 @@ class TestOrigins: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_create(self, client: ImageKit) -> None: + def test_method_create_overload_1(self, client: ImageKit) -> None: origin = client.accounts.origins.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_create_with_all_params(self, client: ImageKit) -> None: + def test_method_create_with_all_params_overload_1(self, client: ImageKit) -> None: origin = client.accounts.origins.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - "base_url_for_canonical_header": "https://cdn.example.com", - "include_canonical_header": False, - "prefix": "images", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", ) assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_create(self, client: ImageKit) -> None: + def test_raw_response_create_overload_1(self, client: ImageKit) -> None: response = client.accounts.origins.with_raw_response.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) assert response.is_closed is True @@ -71,15 +62,13 @@ def test_raw_response_create(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_create(self, client: ImageKit) -> None: + def test_streaming_response_create_overload_1(self, client: ImageKit) -> None: with client.accounts.origins.with_streaming_response.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -91,252 +80,2041 @@ def test_streaming_response_create(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update(self, client: ImageKit) -> None: + def test_method_create_overload_2(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_2(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + s3_force_path_style=True, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_2(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_2(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_3(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_3(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_3(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_3(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_4(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_4(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + base_url_for_canonical_header="https://cdn.example.com", + forward_host_header_to_origin=False, + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_4(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_4(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_5(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + name="US S3 Storage", + type="WEB_PROXY", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_5(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + name="US S3 Storage", + type="WEB_PROXY", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_5(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + name="US S3 Storage", + type="WEB_PROXY", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_5(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + name="US S3 Storage", + type="WEB_PROXY", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_6(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_6(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="products", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_6(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_6(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_7(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_7(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="uploads", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_7(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_7(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_overload_8(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_8(self, client: ImageKit) -> None: + origin = client.accounts.origins.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_overload_8(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_overload_8(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_1(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: origin = client.accounts.origins.update( id="id", - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_1(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_1(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_2(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + s3_force_path_style=True, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_2(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_2(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_3(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_3(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_3(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_3(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_3(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_4(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_4(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + base_url_for_canonical_header="https://cdn.example.com", + forward_host_header_to_origin=False, + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_4(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_4(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_4(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_5(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_5(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_5(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_5(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_5(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + name="US S3 Storage", + type="WEB_PROXY", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_6(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_6(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="products", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_6(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_6(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_6(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_7(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_7(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="uploads", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_7(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_7(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_7(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_8(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_8(self, client: ImageKit) -> None: + origin = client.accounts.origins.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_8(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_8(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_8(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.update( + id="", + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: ImageKit) -> None: + origin = client.accounts.origins.list() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginListResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: ImageKit) -> None: + origin = client.accounts.origins.delete( + "id", + ) + assert origin is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert origin is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert origin is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_get(self, client: ImageKit) -> None: + origin = client.accounts.origins.get( + "id", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_get(self, client: ImageKit) -> None: + response = client.accounts.origins.with_raw_response.get( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_get(self, client: ImageKit) -> None: + with client.accounts.origins.with_streaming_response.get( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_get(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.accounts.origins.with_raw_response.get( + "", + ) + + +class TestAsyncOrigins: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_1(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_1(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_1(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_2(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + s3_force_path_style=True, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_2(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_2(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_3(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_3(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_3(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_3(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_4(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_4(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + base_url_for_canonical_header="https://cdn.example.com", + forward_host_header_to_origin=False, + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_4(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_4(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_5(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + name="US S3 Storage", + type="WEB_PROXY", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_5(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + name="US S3 Storage", + type="WEB_PROXY", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_5(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + name="US S3 Storage", + type="WEB_PROXY", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_5(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + name="US S3 Storage", + type="WEB_PROXY", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_6(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_6(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="products", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_6(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_6(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_7(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_7(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="uploads", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_7(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_7(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_overload_8(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_8(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_overload_8(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_overload_8(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.create( + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_with_all_params(self, client: ImageKit) -> None: - origin = client.accounts.origins.update( + async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( id="id", - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - "base_url_for_canonical_header": "https://cdn.example.com", - "include_canonical_header": False, - "prefix": "images", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", ) assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.update( + async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( id="id", - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() + origin = await response.parse() assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.update( + async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( id="id", - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() + origin = await response.parse() assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update(self, client: ImageKit) -> None: + async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.update( + await async_client.accounts.origins.with_raw_response.update( id="", - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3", ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_list(self, client: ImageKit) -> None: - origin = client.accounts.origins.list() - assert_matches_type(OriginListResponse, origin, path=["response"]) + async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_list(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.list() + async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + s3_force_path_style=True, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginListResponse, origin, path=["response"]) + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_list(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.list() as response: + async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert_matches_type(OriginListResponse, origin, path=["response"]) + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_delete(self, client: ImageKit) -> None: - origin = client.accounts.origins.delete( - "id", + async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + endpoint="https://s3.eu-central-1.wasabisys.com", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="S3_COMPATIBLE", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_3(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", ) - assert origin is None + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_delete(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.delete( - "id", + async def test_method_update_with_all_params_overload_3(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="raw-assets", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_3(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert origin is None + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_delete(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.delete( - "id", + async def test_streaming_response_update_overload_3(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() - assert origin is None + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_delete(self, client: ImageKit) -> None: + async def test_path_params_update_overload_3(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.delete( - "", + await async_client.accounts.origins.with_raw_response.update( + id="", + access_key="AKIAIOSFODNN7EXAMPLE", + bucket="product-images", + name="US S3 Storage", + secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + type="CLOUDINARY_BACKUP", ) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_get(self, client: ImageKit) -> None: - origin = client.accounts.origins.get( - "id", + async def test_method_update_overload_4(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", ) assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_get(self, client: ImageKit) -> None: - response = client.accounts.origins.with_raw_response.get( - "id", + async def test_method_update_with_all_params_overload_4(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", + base_url_for_canonical_header="https://cdn.example.com", + forward_host_header_to_origin=False, + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_4(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() + origin = await response.parse() assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_get(self, client: ImageKit) -> None: - with client.accounts.origins.with_streaming_response.get( - "id", + async def test_streaming_response_update_overload_4(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - origin = response.parse() + origin = await response.parse() assert_matches_type(OriginResponse, origin, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_get(self, client: ImageKit) -> None: + async def test_path_params_update_overload_4(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.accounts.origins.with_raw_response.get( - "", + await async_client.accounts.origins.with_raw_response.update( + id="", + base_url="https://images.example.com/assets", + name="US S3 Storage", + type="WEB_FOLDER", ) + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_5(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) -class TestAsyncOrigins: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_5(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + ) + assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_create(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + async def test_raw_response_update_overload_5(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncImageKit) -> None: - origin = await async_client.accounts.origins.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - "base_url_for_canonical_header": "https://cdn.example.com", - "include_canonical_header": False, - "prefix": "images", - }, + async def test_streaming_response_update_overload_5(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + name="US S3 Storage", + type="WEB_PROXY", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_5(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + name="US S3 Storage", + type="WEB_PROXY", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_6(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", ) assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: - response = await async_client.accounts.origins.with_raw_response.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + async def test_method_update_with_all_params_overload_6(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="products", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_6(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", ) assert response.is_closed is True @@ -346,15 +2124,92 @@ async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: - async with async_client.accounts.origins.with_streaming_response.create( - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + async def test_streaming_response_update_overload_6(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_6(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + bucket="gcs-media", + client_email="service-account@project.iam.gserviceaccount.com", + name="US S3 Storage", + private_key="-----BEGIN PRIVATE KEY-----\\nMIIEv...", + type="GCS", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_7(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_7(self, async_client: AsyncImageKit) -> None: + origin = await async_client.accounts.origins.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, + prefix="uploads", + ) + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_7(self, async_client: AsyncImageKit) -> None: + response = await async_client.accounts.origins.with_raw_response.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + origin = await response.parse() + assert_matches_type(OriginResponse, origin, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_7(self, async_client: AsyncImageKit) -> None: + async with async_client.accounts.origins.with_streaming_response.update( + id="id", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -366,49 +2221,61 @@ async def test_streaming_response_create(self, async_client: AsyncImageKit) -> N @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update(self, async_client: AsyncImageKit) -> None: + async def test_path_params_update_overload_7(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.accounts.origins.with_raw_response.update( + id="", + account_name="account123", + container="images", + name="US S3 Storage", + sas_token="?sv=2023-01-03&sr=c&sig=abc123", + type="AZURE_BLOB", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_8(self, async_client: AsyncImageKit) -> None: origin = await async_client.accounts.origins.update( id="id", - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", ) assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncImageKit) -> None: + async def test_method_update_with_all_params_overload_8(self, async_client: AsyncImageKit) -> None: origin = await async_client.accounts.origins.update( id="id", - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - "base_url_for_canonical_header": "https://cdn.example.com", - "include_canonical_header": False, - "prefix": "images", - }, + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", + base_url_for_canonical_header="https://cdn.example.com", + include_canonical_header=False, ) assert_matches_type(OriginResponse, origin, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: + async def test_raw_response_update_overload_8(self, async_client: AsyncImageKit) -> None: response = await async_client.accounts.origins.with_raw_response.update( id="id", - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", ) assert response.is_closed is True @@ -418,16 +2285,16 @@ async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update(self, async_client: AsyncImageKit) -> None: + async def test_streaming_response_update_overload_8(self, async_client: AsyncImageKit) -> None: async with async_client.accounts.origins.with_streaming_response.update( id="id", - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -439,17 +2306,17 @@ async def test_streaming_response_update(self, async_client: AsyncImageKit) -> N @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update(self, async_client: AsyncImageKit) -> None: + async def test_path_params_update_overload_8(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): await async_client.accounts.origins.with_raw_response.update( id="", - origin={ - "access_key": "AKIATEST123", - "bucket": "test-bucket", - "name": "My S3 Origin", - "secret_key": "secrettest123", - "type": "S3", - }, + base_url="https://akeneo.company.com", + client_id="akeneo-client-id", + client_secret="akeneo-client-secret", + name="US S3 Storage", + password="strongpassword123", + type="AKENEO_PIM", + username="integration-user", ) @pytest.mark.skip(reason="Prism tests are disabled") diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index f639534..5a9594f 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -26,7 +26,7 @@ class TestFiles: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update(self, client: ImageKit) -> None: + def test_method_update_overload_1(self, client: ImageKit) -> None: file = client.files.update( file_id="fileId", ) @@ -34,48 +34,92 @@ def test_method_update(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_update_with_all_params(self, client: ImageKit) -> None: + def test_method_update_with_all_params_overload_1(self, client: ImageKit) -> None: file = client.files.update( file_id="fileId", - update={ - "custom_coordinates": "10,10,100,100", - "custom_metadata": { - "brand": "bar", - "color": "bar", - }, - "description": "description", - "extensions": [ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, - }, - }, - { - "max_tags": 10, - "min_confidence": 80, - "name": "google-auto-tagging", - }, - { - "max_tags": 10, - "min_confidence": 80, - "name": "aws-auto-tagging", + custom_coordinates="customCoordinates", + custom_metadata={"foo": "bar"}, + description="description", + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, }, - {"name": "ai-auto-description"}, - ], - "remove_ai_tags": ["car", "vehicle", "motorsports"], - "tags": ["tag1", "tag2"], - "webhook_url": "https://webhook.site/0d6b6c7a-8e5a-4b3a-8b7c-0d6b6c7a8e5a", + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + remove_ai_tags=["string"], + tags=["tag1", "tag2"], + webhook_url="https://example.com", + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update_overload_1(self, client: ImageKit) -> None: + response = client.files.with_raw_response.update( + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update_overload_1(self, client: ImageKit) -> None: + with client.files.with_streaming_response.update( + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update_overload_1(self, client: ImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.with_raw_response.update( + file_id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_overload_2(self, client: ImageKit) -> None: + file = client.files.update( + file_id="fileId", + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: + file = client.files.update( + file_id="fileId", + publish={ + "is_published": True, + "include_file_versions": True, }, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_update(self, client: ImageKit) -> None: + def test_raw_response_update_overload_2(self, client: ImageKit) -> None: response = client.files.with_raw_response.update( file_id="fileId", ) @@ -87,7 +131,7 @@ def test_raw_response_update(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_update(self, client: ImageKit) -> None: + def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: with client.files.with_streaming_response.update( file_id="fileId", ) as response: @@ -101,7 +145,7 @@ def test_streaming_response_update(self, client: ImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_update(self, client: ImageKit) -> None: + def test_path_params_update_overload_2(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.files.with_raw_response.update( file_id="", @@ -429,7 +473,7 @@ class TestAsyncFiles: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update(self, async_client: AsyncImageKit) -> None: + async def test_method_update_overload_1(self, async_client: AsyncImageKit) -> None: file = await async_client.files.update( file_id="fileId", ) @@ -437,48 +481,92 @@ async def test_method_update(self, async_client: AsyncImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncImageKit) -> None: + async def test_method_update_with_all_params_overload_1(self, async_client: AsyncImageKit) -> None: file = await async_client.files.update( file_id="fileId", - update={ - "custom_coordinates": "10,10,100,100", - "custom_metadata": { - "brand": "bar", - "color": "bar", - }, - "description": "description", - "extensions": [ - { - "name": "remove-bg", - "options": { - "add_shadow": True, - "bg_color": "bg_color", - "bg_image_url": "bg_image_url", - "semitransparency": True, - }, - }, - { - "max_tags": 10, - "min_confidence": 80, - "name": "google-auto-tagging", - }, - { - "max_tags": 10, - "min_confidence": 80, - "name": "aws-auto-tagging", + custom_coordinates="customCoordinates", + custom_metadata={"foo": "bar"}, + description="description", + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, }, - {"name": "ai-auto-description"}, - ], - "remove_ai_tags": ["car", "vehicle", "motorsports"], - "tags": ["tag1", "tag2"], - "webhook_url": "https://webhook.site/0d6b6c7a-8e5a-4b3a-8b7c-0d6b6c7a8e5a", + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + remove_ai_tags=["string"], + tags=["tag1", "tag2"], + webhook_url="https://example.com", + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + response = await async_client.files.with_raw_response.update( + file_id="fileId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update_overload_1(self, async_client: AsyncImageKit) -> None: + async with async_client.files.with_streaming_response.update( + file_id="fileId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.with_raw_response.update( + file_id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.update( + file_id="fileId", + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.update( + file_id="fileId", + publish={ + "is_published": True, + "include_file_versions": True, }, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: + async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.update( file_id="fileId", ) @@ -490,7 +578,7 @@ async def test_raw_response_update(self, async_client: AsyncImageKit) -> None: @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_update(self, async_client: AsyncImageKit) -> None: + async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.update( file_id="fileId", ) as response: @@ -504,7 +592,7 @@ async def test_streaming_response_update(self, async_client: AsyncImageKit) -> N @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_update(self, async_client: AsyncImageKit) -> None: + async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.files.with_raw_response.update( file_id="", From df34df3107e3b10b7a6835d97cb3e0bfa1d3e61c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 07:05:06 +0000 Subject: [PATCH 111/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 335e38e..e13d327 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0470196862abd722b09f1af798d6f2bcbdeba0f82d1162f57c287b1a43233531.yml -openapi_spec_hash: 043dd7c67d741d0034b86f2fc0bce072 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-afb67c3a2098b1a2dca37d0995d183fa6cf59dd144ed47bcdb924f14e3cc90a3.yml +openapi_spec_hash: 55a2f38df85126a87d1be0b27b9b8470 config_hash: a652d68098d82eaf611a49507fb4b831 From abe3f674614ea591281c2a75f848451753c8136e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 07:10:51 +0000 Subject: [PATCH 112/177] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e13d327..bbfdcb4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-afb67c3a2098b1a2dca37d0995d183fa6cf59dd144ed47bcdb924f14e3cc90a3.yml -openapi_spec_hash: 55a2f38df85126a87d1be0b27b9b8470 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-bc7c0d27962b30c19c778656988e154b54696819389289f34420a5e5fdfbd3b8.yml +openapi_spec_hash: 1bfde02a63416c036e9545927f727459 config_hash: a652d68098d82eaf611a49507fb4b831 From 44ebb07f2c9133d2a680c6ad8370860d80458b66 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 14:55:56 +0000 Subject: [PATCH 113/177] chore(internal): codegen related update --- mypy.ini | 50 ------------------------------------------------ pyproject.toml | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 50 deletions(-) delete mode 100644 mypy.ini diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index b2e3de8..0000000 --- a/mypy.ini +++ /dev/null @@ -1,50 +0,0 @@ -[mypy] -pretty = True -show_error_codes = True - -# Exclude _files.py because mypy isn't smart enough to apply -# the correct type narrowing and as this is an internal module -# it's fine to just use Pyright. -# -# We also exclude our `tests` as mypy doesn't always infer -# types correctly and Pyright will still catch any type errors. -exclude = ^(src/imagekit/_files\.py|_dev/.*\.py|tests/.*)$ - -strict_equality = True -implicit_reexport = True -check_untyped_defs = True -no_implicit_optional = True - -warn_return_any = True -warn_unreachable = True -warn_unused_configs = True - -# Turn these options off as it could cause conflicts -# with the Pyright options. -warn_unused_ignores = False -warn_redundant_casts = False - -disallow_any_generics = True -disallow_untyped_defs = True -disallow_untyped_calls = True -disallow_subclassing_any = True -disallow_incomplete_defs = True -disallow_untyped_decorators = True -cache_fine_grained = True - -# By default, mypy reports an error if you assign a value to the result -# of a function call that doesn't return anything. We do this in our test -# cases: -# ``` -# result = ... -# assert result is None -# ``` -# Changing this codegen to make mypy happy would increase complexity -# and would not be worth it. -disable_error_code = func-returns-value,overload-cannot-match - -# https://github.com/python/mypy/issues/12162 -[mypy.overrides] -module = "black.files.*" -ignore_errors = true -ignore_missing_imports = true diff --git a/pyproject.toml b/pyproject.toml index f3403c4..1edc811 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -158,6 +158,58 @@ reportOverlappingOverload = false reportImportCycles = false reportPrivateUsage = false +[tool.mypy] +pretty = true +show_error_codes = true + +# Exclude _files.py because mypy isn't smart enough to apply +# the correct type narrowing and as this is an internal module +# it's fine to just use Pyright. +# +# We also exclude our `tests` as mypy doesn't always infer +# types correctly and Pyright will still catch any type errors. +exclude = ['src/imagekit/_files.py', '_dev/.*.py', 'tests/.*'] + +strict_equality = true +implicit_reexport = true +check_untyped_defs = true +no_implicit_optional = true + +warn_return_any = true +warn_unreachable = true +warn_unused_configs = true + +# Turn these options off as it could cause conflicts +# with the Pyright options. +warn_unused_ignores = false +warn_redundant_casts = false + +disallow_any_generics = true +disallow_untyped_defs = true +disallow_untyped_calls = true +disallow_subclassing_any = true +disallow_incomplete_defs = true +disallow_untyped_decorators = true +cache_fine_grained = true + +# By default, mypy reports an error if you assign a value to the result +# of a function call that doesn't return anything. We do this in our test +# cases: +# ``` +# result = ... +# assert result is None +# ``` +# Changing this codegen to make mypy happy would increase complexity +# and would not be worth it. +disable_error_code = "func-returns-value,overload-cannot-match" + +# https://github.com/python/mypy/issues/12162 +[[tool.mypy.overrides]] +module = "black.files.*" +ignore_errors = true +ignore_missing_imports = true + + [tool.ruff] line-length = 120 output-format = "grouped" From 5c61b5ec8b3ba9a478b83c3c93aaec7b9786f2e2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 20:07:22 +0000 Subject: [PATCH 114/177] feat(api): extract UpdateFileDetailsRequest to model --- .stats.yml | 2 +- api.md | 1 + src/imagekit/types/__init__.py | 1 + .../update_file_details_request_param.py | 88 +++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/imagekit/types/update_file_details_request_param.py diff --git a/.stats.yml b/.stats.yml index bbfdcb4..b0086e9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-bc7c0d27962b30c19c778656988e154b54696819389289f34420a5e5fdfbd3b8.yml openapi_spec_hash: 1bfde02a63416c036e9545927f727459 -config_hash: a652d68098d82eaf611a49507fb4b831 +config_hash: b415c06a3b29485af4601beb94ae1aeb diff --git a/api.md b/api.md index 0c5149c..697c667 100644 --- a/api.md +++ b/api.md @@ -50,6 +50,7 @@ from imagekit.types import ( File, Folder, Metadata, + UpdateFileDetailsRequest, FileUpdateResponse, FileCopyResponse, FileMoveResponse, diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 6bc39cf..9a8b535 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -56,6 +56,7 @@ from .video_transformation_error_event import VideoTransformationErrorEvent as VideoTransformationErrorEvent from .video_transformation_ready_event import VideoTransformationReadyEvent as VideoTransformationReadyEvent from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams +from .update_file_details_request_param import UpdateFileDetailsRequestParam as UpdateFileDetailsRequestParam from .upload_post_transform_error_event import UploadPostTransformErrorEvent as UploadPostTransformErrorEvent from .upload_pre_transform_success_event import UploadPreTransformSuccessEvent as UploadPreTransformSuccessEvent from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams diff --git a/src/imagekit/types/update_file_details_request_param.py b/src/imagekit/types/update_file_details_request_param.py new file mode 100644 index 0000000..75a1f40 --- /dev/null +++ b/src/imagekit/types/update_file_details_request_param.py @@ -0,0 +1,88 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Union, Optional +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict + +from .._types import SequenceNotStr +from .._utils import PropertyInfo +from .shared_params.extensions import Extensions + +__all__ = [ + "UpdateFileDetailsRequestParam", + "UpdateFileDetails", + "ChangePublicationStatus", + "ChangePublicationStatusPublish", +] + + +class UpdateFileDetails(TypedDict, total=False): + custom_coordinates: Annotated[Optional[str], PropertyInfo(alias="customCoordinates")] + """Define an important area in the image in the format `x,y,width,height` e.g. + + `10,10,100,100`. Send `null` to unset this value. + """ + + custom_metadata: Annotated[Dict[str, object], PropertyInfo(alias="customMetadata")] + """A key-value data to be associated with the asset. + + To unset a key, send `null` value for that key. Before setting any custom + metadata on an asset you have to create the field using custom metadata fields + API. + """ + + description: str + """Optional text to describe the contents of the file.""" + + extensions: Extensions + """Array of extensions to be applied to the asset. + + Each extension can be configured with specific parameters based on the extension + type. + """ + + remove_ai_tags: Annotated[Union[SequenceNotStr[str], Literal["all"]], PropertyInfo(alias="removeAITags")] + """An array of AITags associated with the file that you want to remove, e.g. + + `["car", "vehicle", "motorsports"]`. + + If you want to remove all AITags associated with the file, send a string - + "all". + + Note: The remove operation for `AITags` executes before any of the `extensions` + are processed. + """ + + tags: Optional[SequenceNotStr[str]] + """An array of tags associated with the file, such as `["tag1", "tag2"]`. + + Send `null` to unset all tags associated with the file. + """ + + webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] + """ + The final status of extensions after they have completed execution will be + delivered to this endpoint as a POST request. + [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + about the webhook payload structure. + """ + + +class ChangePublicationStatusPublish(TypedDict, total=False): + is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] + """Set to `true` to publish the file. Set to `false` to unpublish the file.""" + + include_file_versions: Annotated[bool, PropertyInfo(alias="includeFileVersions")] + """Set to `true` to publish/unpublish all versions of the file. + + Set to `false` to publish/unpublish only the current version of the file. + """ + + +class ChangePublicationStatus(TypedDict, total=False): + publish: ChangePublicationStatusPublish + """Configure the publication status of a file and its versions.""" + + +UpdateFileDetailsRequestParam: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] From aa026a9bc3f359351ae1c9c570b79a4a17fd5a8e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Sep 2025 02:59:17 +0000 Subject: [PATCH 115/177] chore(tests): simplify `get_platform` test `nest_asyncio` is archived and broken on some platforms so it's not worth keeping in our test suite. --- pyproject.toml | 1 - requirements-dev.lock | 1 - tests/test_client.py | 53 +++++-------------------------------------- 3 files changed, 6 insertions(+), 49 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1edc811..ebdb5e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,6 @@ dev-dependencies = [ "dirty-equals>=0.6.0", "importlib-metadata>=6.7.0", "rich>=13.7.1", - "nest_asyncio==1.6.0", "pytest-xdist>=3.6.1", ] diff --git a/requirements-dev.lock b/requirements-dev.lock index 396ac99..7cf01b7 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -79,7 +79,6 @@ multidict==6.4.4 mypy==1.14.1 mypy-extensions==1.0.0 # via mypy -nest-asyncio==1.6.0 nodeenv==1.8.0 # via pyright nox==2023.4.22 diff --git a/tests/test_client.py b/tests/test_client.py index ddb5db7..265d599 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -6,13 +6,10 @@ import os import sys import json -import time import asyncio import inspect -import subprocess import tracemalloc from typing import Any, Union, cast -from textwrap import dedent from unittest import mock from typing_extensions import Literal @@ -23,14 +20,17 @@ from imagekit import ImageKit, AsyncImageKit, APIResponseValidationError from imagekit._types import Omit +from imagekit._utils import asyncify from imagekit._models import BaseModel, FinalRequestOptions from imagekit._exceptions import ImageKitError, APIStatusError, APITimeoutError, APIResponseValidationError from imagekit._base_client import ( DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, BaseClient, + OtherPlatform, DefaultHttpxClient, DefaultAsyncHttpxClient, + get_platform, make_request_options, ) @@ -1808,50 +1808,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert response.http_request.headers.get("x-stainless-retry-count") == "42" - def test_get_platform(self) -> None: - # A previous implementation of asyncify could leave threads unterminated when - # used with nest_asyncio. - # - # Since nest_asyncio.apply() is global and cannot be un-applied, this - # test is run in a separate process to avoid affecting other tests. - test_code = dedent(""" - import asyncio - import nest_asyncio - import threading - - from imagekit._utils import asyncify - from imagekit._base_client import get_platform - - async def test_main() -> None: - result = await asyncify(get_platform)() - print(result) - for thread in threading.enumerate(): - print(thread.name) - - nest_asyncio.apply() - asyncio.run(test_main()) - """) - with subprocess.Popen( - [sys.executable, "-c", test_code], - text=True, - ) as process: - timeout = 10 # seconds - - start_time = time.monotonic() - while True: - return_code = process.poll() - if return_code is not None: - if return_code != 0: - raise AssertionError("calling get_platform using asyncify resulted in a non-zero exit code") - - # success - break - - if time.monotonic() - start_time > timeout: - process.kill() - raise AssertionError("calling get_platform using asyncify resulted in a hung process") - - time.sleep(0.1) + async def test_get_platform(self) -> None: + platform = await asyncify(get_platform)() + assert isinstance(platform, (str, OtherPlatform)) async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly From 22ccb93b1110104b664f5a5a5c54594304b76b4b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Sep 2025 02:18:53 +0000 Subject: [PATCH 116/177] chore(internal): update pydantic dependency --- requirements-dev.lock | 7 +++++-- requirements.lock | 7 +++++-- src/imagekit/_models.py | 14 ++++++++++---- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 7cf01b7..ec7b01b 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -92,9 +92,9 @@ pluggy==1.5.0 propcache==0.3.1 # via aiohttp # via yarl -pydantic==2.10.3 +pydantic==2.11.9 # via imagekit -pydantic-core==2.27.1 +pydantic-core==2.33.2 # via pydantic pygments==2.18.0 # via rich @@ -137,6 +137,9 @@ typing-extensions==4.12.2 # via pydantic # via pydantic-core # via pyright + # via typing-inspection +typing-inspection==0.4.1 + # via pydantic virtualenv==20.24.5 # via nox wrapt==1.17.3 diff --git a/requirements.lock b/requirements.lock index a922302..52c73ee 100644 --- a/requirements.lock +++ b/requirements.lock @@ -59,9 +59,9 @@ multidict==6.4.4 propcache==0.3.1 # via aiohttp # via yarl -pydantic==2.10.3 +pydantic==2.11.9 # via imagekit -pydantic-core==2.27.1 +pydantic-core==2.33.2 # via pydantic python-dateutil==2.9.0.post0 # via standardwebhooks @@ -82,6 +82,9 @@ typing-extensions==4.12.2 # via multidict # via pydantic # via pydantic-core + # via typing-inspection +typing-inspection==0.4.1 + # via pydantic wrapt==1.17.3 # via deprecated yarl==1.20.0 diff --git a/src/imagekit/_models.py b/src/imagekit/_models.py index 3a6017e..6a3cd1d 100644 --- a/src/imagekit/_models.py +++ b/src/imagekit/_models.py @@ -256,7 +256,7 @@ def model_dump( mode: Literal["json", "python"] | str = "python", include: IncEx | None = None, exclude: IncEx | None = None, - by_alias: bool = False, + by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, @@ -264,6 +264,7 @@ def model_dump( warnings: bool | Literal["none", "warn", "error"] = True, context: dict[str, Any] | None = None, serialize_as_any: bool = False, + fallback: Callable[[Any], Any] | None = None, ) -> dict[str, Any]: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump @@ -295,10 +296,12 @@ def model_dump( raise ValueError("context is only supported in Pydantic v2") if serialize_as_any != False: raise ValueError("serialize_as_any is only supported in Pydantic v2") + if fallback is not None: + raise ValueError("fallback is only supported in Pydantic v2") dumped = super().dict( # pyright: ignore[reportDeprecated] include=include, exclude=exclude, - by_alias=by_alias, + by_alias=by_alias if by_alias is not None else False, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, @@ -313,13 +316,14 @@ def model_dump_json( indent: int | None = None, include: IncEx | None = None, exclude: IncEx | None = None, - by_alias: bool = False, + by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, context: dict[str, Any] | None = None, + fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, ) -> str: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump_json @@ -348,11 +352,13 @@ def model_dump_json( raise ValueError("context is only supported in Pydantic v2") if serialize_as_any != False: raise ValueError("serialize_as_any is only supported in Pydantic v2") + if fallback is not None: + raise ValueError("fallback is only supported in Pydantic v2") return super().json( # type: ignore[reportDeprecated] indent=indent, include=include, exclude=exclude, - by_alias=by_alias, + by_alias=by_alias if by_alias is not None else False, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, From 4ca5030528a609e771e02bbdb7c347e504d761d1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 02:21:31 +0000 Subject: [PATCH 117/177] chore(types): change optional parameter type from NotGiven to Omit --- src/imagekit/__init__.py | 4 +- src/imagekit/_base_client.py | 18 +- src/imagekit/_client.py | 16 +- src/imagekit/_qs.py | 14 +- src/imagekit/_types.py | 29 +- src/imagekit/_utils/_transform.py | 4 +- src/imagekit/_utils/_utils.py | 8 +- src/imagekit/resources/accounts/origins.py | 422 +++++++++--------- .../resources/accounts/url_endpoints.py | 46 +- src/imagekit/resources/accounts/usage.py | 6 +- src/imagekit/resources/assets.py | 34 +- src/imagekit/resources/beta/v2/files.py | 88 ++-- src/imagekit/resources/cache/invalidation.py | 10 +- .../resources/custom_metadata_fields.py | 30 +- src/imagekit/resources/files/bulk.py | 18 +- src/imagekit/resources/files/files.py | 205 +++++---- src/imagekit/resources/files/metadata.py | 10 +- src/imagekit/resources/files/versions.py | 18 +- src/imagekit/resources/folders/folders.py | 30 +- src/imagekit/resources/folders/job.py | 6 +- tests/test_transform.py | 11 +- 21 files changed, 532 insertions(+), 495 deletions(-) diff --git a/src/imagekit/__init__.py b/src/imagekit/__init__.py index 43d69f6..335e8f0 100644 --- a/src/imagekit/__init__.py +++ b/src/imagekit/__init__.py @@ -3,7 +3,7 @@ import typing as _t from . import types -from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes +from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given from ._utils import file_from_path from ._client import ( Client, @@ -49,7 +49,9 @@ "ProxiesTypes", "NotGiven", "NOT_GIVEN", + "not_given", "Omit", + "omit", "ImageKitError", "APIError", "APIStatusError", diff --git a/src/imagekit/_base_client.py b/src/imagekit/_base_client.py index fca8ec9..cde8075 100644 --- a/src/imagekit/_base_client.py +++ b/src/imagekit/_base_client.py @@ -42,7 +42,6 @@ from ._qs import Querystring from ._files import to_httpx_files, async_to_httpx_files from ._types import ( - NOT_GIVEN, Body, Omit, Query, @@ -57,6 +56,7 @@ RequestOptions, HttpxRequestFiles, ModelBuilderProtocol, + not_given, ) from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping from ._compat import PYDANTIC_V1, model_copy, model_dump @@ -145,9 +145,9 @@ def __init__( def __init__( self, *, - url: URL | NotGiven = NOT_GIVEN, - json: Body | NotGiven = NOT_GIVEN, - params: Query | NotGiven = NOT_GIVEN, + url: URL | NotGiven = not_given, + json: Body | NotGiven = not_given, + params: Query | NotGiven = not_given, ) -> None: self.url = url self.json = json @@ -595,7 +595,7 @@ def _maybe_override_cast_to(self, cast_to: type[ResponseT], options: FinalReques # we internally support defining a temporary header to override the # default `cast_to` type for use with `.with_raw_response` and `.with_streaming_response` # see _response.py for implementation details - override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, NOT_GIVEN) + override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, not_given) if is_given(override_cast_to): options.headers = headers return cast(Type[ResponseT], override_cast_to) @@ -825,7 +825,7 @@ def __init__( version: str, base_url: str | URL, max_retries: int = DEFAULT_MAX_RETRIES, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, @@ -1356,7 +1356,7 @@ def __init__( base_url: str | URL, _strict_response_validation: bool, max_retries: int = DEFAULT_MAX_RETRIES, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, @@ -1818,8 +1818,8 @@ def make_request_options( extra_query: Query | None = None, extra_body: Body | None = None, idempotency_key: str | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - post_parser: PostParser | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + post_parser: PostParser | NotGiven = not_given, ) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" options: RequestOptions = {} diff --git a/src/imagekit/_client.py b/src/imagekit/_client.py index 6166974..b2a104b 100644 --- a/src/imagekit/_client.py +++ b/src/imagekit/_client.py @@ -4,7 +4,7 @@ import os import base64 -from typing import Any, Union, Mapping +from typing import Any, Mapping from typing_extensions import Self, override import httpx @@ -12,7 +12,6 @@ from . import _exceptions from ._qs import Querystring from ._types import ( - NOT_GIVEN, Omit, Headers, Timeout, @@ -20,6 +19,7 @@ Transport, ProxiesTypes, RequestOptions, + not_given, ) from ._utils import is_given, get_async_library from ._version import __version__ @@ -73,7 +73,7 @@ def __init__( password: str | None = None, webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, - timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -183,9 +183,9 @@ def copy( password: str | None = None, webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, - max_retries: int | NotGiven = NOT_GIVEN, + max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -291,7 +291,7 @@ def __init__( password: str | None = None, webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, - timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -401,9 +401,9 @@ def copy( password: str | None = None, webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, - max_retries: int | NotGiven = NOT_GIVEN, + max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, diff --git a/src/imagekit/_qs.py b/src/imagekit/_qs.py index 274320c..ada6fd3 100644 --- a/src/imagekit/_qs.py +++ b/src/imagekit/_qs.py @@ -4,7 +4,7 @@ from urllib.parse import parse_qs, urlencode from typing_extensions import Literal, get_args -from ._types import NOT_GIVEN, NotGiven, NotGivenOr +from ._types import NotGiven, not_given from ._utils import flatten _T = TypeVar("_T") @@ -41,8 +41,8 @@ def stringify( self, params: Params, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> str: return urlencode( self.stringify_items( @@ -56,8 +56,8 @@ def stringify_items( self, params: Params, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> list[tuple[str, str]]: opts = Options( qs=self, @@ -143,8 +143,8 @@ def __init__( self, qs: Querystring = _qs, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> None: self.array_format = qs.array_format if isinstance(array_format, NotGiven) else array_format self.nested_format = qs.nested_format if isinstance(nested_format, NotGiven) else nested_format diff --git a/src/imagekit/_types.py b/src/imagekit/_types.py index 62059ad..ba04a4b 100644 --- a/src/imagekit/_types.py +++ b/src/imagekit/_types.py @@ -117,18 +117,21 @@ class RequestOptions(TypedDict, total=False): # Sentinel class used until PEP 0661 is accepted class NotGiven: """ - A sentinel singleton class used to distinguish omitted keyword arguments - from those passed in with the value None (which may have different behavior). + For parameters with a meaningful None value, we need to distinguish between + the user explicitly passing None, and the user not passing the parameter at + all. + + User code shouldn't need to use not_given directly. For example: ```py - def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response: ... + def create(timeout: Timeout | None | NotGiven = not_given): ... - get(timeout=1) # 1s timeout - get(timeout=None) # No timeout - get() # Default timeout behavior, which may not be statically known at the method definition. + create(timeout=1) # 1s timeout + create(timeout=None) # No timeout + create() # Default timeout behavior ``` """ @@ -140,13 +143,14 @@ def __repr__(self) -> str: return "NOT_GIVEN" -NotGivenOr = Union[_T, NotGiven] +not_given = NotGiven() +# for backwards compatibility: NOT_GIVEN = NotGiven() class Omit: - """In certain situations you need to be able to represent a case where a default value has - to be explicitly removed and `None` is not an appropriate substitute, for example: + """ + To explicitly omit something from being sent in a request, use `omit`. ```py # as the default `Content-Type` header is `application/json` that will be sent @@ -156,8 +160,8 @@ class Omit: # to look something like: 'multipart/form-data; boundary=0d8382fcf5f8c3be01ca2e11002d2983' client.post(..., headers={"Content-Type": "multipart/form-data"}) - # instead you can remove the default `application/json` header by passing Omit - client.post(..., headers={"Content-Type": Omit()}) + # instead you can remove the default `application/json` header by passing omit + client.post(..., headers={"Content-Type": omit}) ``` """ @@ -165,6 +169,9 @@ def __bool__(self) -> Literal[False]: return False +omit = Omit() + + @runtime_checkable class ModelBuilderProtocol(Protocol): @classmethod diff --git a/src/imagekit/_utils/_transform.py b/src/imagekit/_utils/_transform.py index c19124f..5207549 100644 --- a/src/imagekit/_utils/_transform.py +++ b/src/imagekit/_utils/_transform.py @@ -268,7 +268,7 @@ def _transform_typeddict( annotations = get_type_hints(expected_type, include_extras=True) for key, value in data.items(): if not is_given(value): - # we don't need to include `NotGiven` values here as they'll + # we don't need to include omitted values here as they'll # be stripped out before the request is sent anyway continue @@ -434,7 +434,7 @@ async def _async_transform_typeddict( annotations = get_type_hints(expected_type, include_extras=True) for key, value in data.items(): if not is_given(value): - # we don't need to include `NotGiven` values here as they'll + # we don't need to include omitted values here as they'll # be stripped out before the request is sent anyway continue diff --git a/src/imagekit/_utils/_utils.py b/src/imagekit/_utils/_utils.py index f081859..50d5926 100644 --- a/src/imagekit/_utils/_utils.py +++ b/src/imagekit/_utils/_utils.py @@ -21,7 +21,7 @@ import sniffio -from .._types import NotGiven, FileTypes, NotGivenOr, HeadersLike +from .._types import Omit, NotGiven, FileTypes, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -63,7 +63,7 @@ def _extract_items( try: key = path[index] except IndexError: - if isinstance(obj, NotGiven): + if not is_given(obj): # no value was provided - we can safely ignore return [] @@ -126,8 +126,8 @@ def _extract_items( return [] -def is_given(obj: NotGivenOr[_T]) -> TypeGuard[_T]: - return not isinstance(obj, NotGiven) +def is_given(obj: _T | NotGiven | Omit) -> TypeGuard[_T]: + return not isinstance(obj, NotGiven) and not isinstance(obj, Omit) # Type safe methods for narrowing types with TypeVars. diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index 533af6c..27dc7af 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -7,7 +7,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from ..._utils import required_args, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -54,15 +54,15 @@ def create( name: str, secret_key: str, type: Literal["S3"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -104,16 +104,16 @@ def create( name: str, secret_key: str, type: Literal["S3_COMPATIBLE"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, + s3_force_path_style: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -158,15 +158,15 @@ def create( name: str, secret_key: str, type: Literal["CLOUDINARY_BACKUP"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -205,15 +205,15 @@ def create( base_url: str, name: str, type: Literal["WEB_FOLDER"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + forward_host_header_to_origin: bool | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -247,14 +247,14 @@ def create( *, name: str, type: Literal["WEB_PROXY"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -287,15 +287,15 @@ def create( name: str, private_key: str, type: Literal["GCS"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -328,15 +328,15 @@ def create( name: str, sas_token: str, type: Literal["AZURE_BLOB"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -371,14 +371,14 @@ def create( password: str, type: Literal["AKENEO_PIM"], username: str, - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -424,10 +424,10 @@ def create( def create( self, *, - access_key: str | NotGiven = NOT_GIVEN, - bucket: str | NotGiven = NOT_GIVEN, + access_key: str | Omit = omit, + bucket: str | Omit = omit, name: str, - secret_key: str | NotGiven = NOT_GIVEN, + secret_key: str | Omit = omit, type: Literal["S3"] | Literal["S3_COMPATIBLE"] | Literal["CLOUDINARY_BACKUP"] @@ -436,28 +436,28 @@ def create( | Literal["GCS"] | Literal["AZURE_BLOB"] | Literal["AKENEO_PIM"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - endpoint: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - base_url: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - client_email: str | NotGiven = NOT_GIVEN, - private_key: str | NotGiven = NOT_GIVEN, - account_name: str | NotGiven = NOT_GIVEN, - container: str | NotGiven = NOT_GIVEN, - sas_token: str | NotGiven = NOT_GIVEN, - client_id: str | NotGiven = NOT_GIVEN, - client_secret: str | NotGiven = NOT_GIVEN, - password: str | NotGiven = NOT_GIVEN, - username: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, + endpoint: str | Omit = omit, + s3_force_path_style: bool | Omit = omit, + base_url: str | Omit = omit, + forward_host_header_to_origin: bool | Omit = omit, + client_email: str | Omit = omit, + private_key: str | Omit = omit, + account_name: str | Omit = omit, + container: str | Omit = omit, + sas_token: str | Omit = omit, + client_id: str | Omit = omit, + client_secret: str | Omit = omit, + password: str | Omit = omit, + username: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: return cast( OriginResponse, @@ -506,15 +506,15 @@ def update( name: str, secret_key: str, type: Literal["S3"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -560,16 +560,16 @@ def update( name: str, secret_key: str, type: Literal["S3_COMPATIBLE"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, + s3_force_path_style: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -618,15 +618,15 @@ def update( name: str, secret_key: str, type: Literal["CLOUDINARY_BACKUP"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -669,15 +669,15 @@ def update( base_url: str, name: str, type: Literal["WEB_FOLDER"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + forward_host_header_to_origin: bool | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -715,14 +715,14 @@ def update( *, name: str, type: Literal["WEB_PROXY"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -759,15 +759,15 @@ def update( name: str, private_key: str, type: Literal["GCS"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -804,15 +804,15 @@ def update( name: str, sas_token: str, type: Literal["AZURE_BLOB"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -851,14 +851,14 @@ def update( password: str, type: Literal["AKENEO_PIM"], username: str, - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -908,10 +908,10 @@ def update( self, id: str, *, - access_key: str | NotGiven = NOT_GIVEN, - bucket: str | NotGiven = NOT_GIVEN, + access_key: str | Omit = omit, + bucket: str | Omit = omit, name: str, - secret_key: str | NotGiven = NOT_GIVEN, + secret_key: str | Omit = omit, type: Literal["S3"] | Literal["S3_COMPATIBLE"] | Literal["CLOUDINARY_BACKUP"] @@ -920,28 +920,28 @@ def update( | Literal["GCS"] | Literal["AZURE_BLOB"] | Literal["AKENEO_PIM"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - endpoint: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - base_url: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - client_email: str | NotGiven = NOT_GIVEN, - private_key: str | NotGiven = NOT_GIVEN, - account_name: str | NotGiven = NOT_GIVEN, - container: str | NotGiven = NOT_GIVEN, - sas_token: str | NotGiven = NOT_GIVEN, - client_id: str | NotGiven = NOT_GIVEN, - client_secret: str | NotGiven = NOT_GIVEN, - password: str | NotGiven = NOT_GIVEN, - username: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, + endpoint: str | Omit = omit, + s3_force_path_style: bool | Omit = omit, + base_url: str | Omit = omit, + forward_host_header_to_origin: bool | Omit = omit, + client_email: str | Omit = omit, + private_key: str | Omit = omit, + account_name: str | Omit = omit, + container: str | Omit = omit, + sas_token: str | Omit = omit, + client_id: str | Omit = omit, + client_secret: str | Omit = omit, + password: str | Omit = omit, + username: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") @@ -990,7 +990,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginListResponse: """**Note:** This API is currently in beta. @@ -1014,7 +1014,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """**Note:** This API is currently in beta. @@ -1054,7 +1054,7 @@ def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1116,15 +1116,15 @@ async def create( name: str, secret_key: str, type: Literal["S3"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1166,16 +1166,16 @@ async def create( name: str, secret_key: str, type: Literal["S3_COMPATIBLE"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, + s3_force_path_style: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1220,15 +1220,15 @@ async def create( name: str, secret_key: str, type: Literal["CLOUDINARY_BACKUP"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1267,15 +1267,15 @@ async def create( base_url: str, name: str, type: Literal["WEB_FOLDER"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + forward_host_header_to_origin: bool | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1309,14 +1309,14 @@ async def create( *, name: str, type: Literal["WEB_PROXY"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1349,15 +1349,15 @@ async def create( name: str, private_key: str, type: Literal["GCS"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1390,15 +1390,15 @@ async def create( name: str, sas_token: str, type: Literal["AZURE_BLOB"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1433,14 +1433,14 @@ async def create( password: str, type: Literal["AKENEO_PIM"], username: str, - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1486,10 +1486,10 @@ async def create( async def create( self, *, - access_key: str | NotGiven = NOT_GIVEN, - bucket: str | NotGiven = NOT_GIVEN, + access_key: str | Omit = omit, + bucket: str | Omit = omit, name: str, - secret_key: str | NotGiven = NOT_GIVEN, + secret_key: str | Omit = omit, type: Literal["S3"] | Literal["S3_COMPATIBLE"] | Literal["CLOUDINARY_BACKUP"] @@ -1498,28 +1498,28 @@ async def create( | Literal["GCS"] | Literal["AZURE_BLOB"] | Literal["AKENEO_PIM"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - endpoint: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - base_url: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - client_email: str | NotGiven = NOT_GIVEN, - private_key: str | NotGiven = NOT_GIVEN, - account_name: str | NotGiven = NOT_GIVEN, - container: str | NotGiven = NOT_GIVEN, - sas_token: str | NotGiven = NOT_GIVEN, - client_id: str | NotGiven = NOT_GIVEN, - client_secret: str | NotGiven = NOT_GIVEN, - password: str | NotGiven = NOT_GIVEN, - username: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, + endpoint: str | Omit = omit, + s3_force_path_style: bool | Omit = omit, + base_url: str | Omit = omit, + forward_host_header_to_origin: bool | Omit = omit, + client_email: str | Omit = omit, + private_key: str | Omit = omit, + account_name: str | Omit = omit, + container: str | Omit = omit, + sas_token: str | Omit = omit, + client_id: str | Omit = omit, + client_secret: str | Omit = omit, + password: str | Omit = omit, + username: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: return cast( OriginResponse, @@ -1568,15 +1568,15 @@ async def update( name: str, secret_key: str, type: Literal["S3"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1622,16 +1622,16 @@ async def update( name: str, secret_key: str, type: Literal["S3_COMPATIBLE"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, + s3_force_path_style: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1680,15 +1680,15 @@ async def update( name: str, secret_key: str, type: Literal["CLOUDINARY_BACKUP"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1731,15 +1731,15 @@ async def update( base_url: str, name: str, type: Literal["WEB_FOLDER"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + forward_host_header_to_origin: bool | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1777,14 +1777,14 @@ async def update( *, name: str, type: Literal["WEB_PROXY"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1821,15 +1821,15 @@ async def update( name: str, private_key: str, type: Literal["GCS"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1866,15 +1866,15 @@ async def update( name: str, sas_token: str, type: Literal["AZURE_BLOB"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1913,14 +1913,14 @@ async def update( password: str, type: Literal["AKENEO_PIM"], username: str, - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. @@ -1970,10 +1970,10 @@ async def update( self, id: str, *, - access_key: str | NotGiven = NOT_GIVEN, - bucket: str | NotGiven = NOT_GIVEN, + access_key: str | Omit = omit, + bucket: str | Omit = omit, name: str, - secret_key: str | NotGiven = NOT_GIVEN, + secret_key: str | Omit = omit, type: Literal["S3"] | Literal["S3_COMPATIBLE"] | Literal["CLOUDINARY_BACKUP"] @@ -1982,28 +1982,28 @@ async def update( | Literal["GCS"] | Literal["AZURE_BLOB"] | Literal["AKENEO_PIM"], - base_url_for_canonical_header: str | NotGiven = NOT_GIVEN, - include_canonical_header: bool | NotGiven = NOT_GIVEN, - prefix: str | NotGiven = NOT_GIVEN, - endpoint: str | NotGiven = NOT_GIVEN, - s3_force_path_style: bool | NotGiven = NOT_GIVEN, - base_url: str | NotGiven = NOT_GIVEN, - forward_host_header_to_origin: bool | NotGiven = NOT_GIVEN, - client_email: str | NotGiven = NOT_GIVEN, - private_key: str | NotGiven = NOT_GIVEN, - account_name: str | NotGiven = NOT_GIVEN, - container: str | NotGiven = NOT_GIVEN, - sas_token: str | NotGiven = NOT_GIVEN, - client_id: str | NotGiven = NOT_GIVEN, - client_secret: str | NotGiven = NOT_GIVEN, - password: str | NotGiven = NOT_GIVEN, - username: str | NotGiven = NOT_GIVEN, + base_url_for_canonical_header: str | Omit = omit, + include_canonical_header: bool | Omit = omit, + prefix: str | Omit = omit, + endpoint: str | Omit = omit, + s3_force_path_style: bool | Omit = omit, + base_url: str | Omit = omit, + forward_host_header_to_origin: bool | Omit = omit, + client_email: str | Omit = omit, + private_key: str | Omit = omit, + account_name: str | Omit = omit, + container: str | Omit = omit, + sas_token: str | Omit = omit, + client_id: str | Omit = omit, + client_secret: str | Omit = omit, + password: str | Omit = omit, + username: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") @@ -2052,7 +2052,7 @@ async def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginListResponse: """**Note:** This API is currently in beta. @@ -2076,7 +2076,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """**Note:** This API is currently in beta. @@ -2116,7 +2116,7 @@ async def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OriginResponse: """**Note:** This API is currently in beta. diff --git a/src/imagekit/resources/accounts/url_endpoints.py b/src/imagekit/resources/accounts/url_endpoints.py index cd8e6f7..ab8d422 100644 --- a/src/imagekit/resources/accounts/url_endpoints.py +++ b/src/imagekit/resources/accounts/url_endpoints.py @@ -4,7 +4,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, SequenceNotStr +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -46,15 +46,15 @@ def create( self, *, description: str, - origins: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - url_prefix: str | NotGiven = NOT_GIVEN, - url_rewriter: url_endpoint_create_params.URLRewriter | NotGiven = NOT_GIVEN, + origins: SequenceNotStr[str] | Omit = omit, + url_prefix: str | Omit = omit, + url_rewriter: url_endpoint_create_params.URLRewriter | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -103,15 +103,15 @@ def update( id: str, *, description: str, - origins: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - url_prefix: str | NotGiven = NOT_GIVEN, - url_rewriter: url_endpoint_update_params.URLRewriter | NotGiven = NOT_GIVEN, + origins: SequenceNotStr[str] | Omit = omit, + url_prefix: str | Omit = omit, + url_rewriter: url_endpoint_update_params.URLRewriter | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -169,7 +169,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> URLEndpointListResponse: """**Note:** This API is currently in beta. @@ -194,7 +194,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """**Note:** This API is currently in beta. @@ -235,7 +235,7 @@ def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -290,15 +290,15 @@ async def create( self, *, description: str, - origins: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - url_prefix: str | NotGiven = NOT_GIVEN, - url_rewriter: url_endpoint_create_params.URLRewriter | NotGiven = NOT_GIVEN, + origins: SequenceNotStr[str] | Omit = omit, + url_prefix: str | Omit = omit, + url_rewriter: url_endpoint_create_params.URLRewriter | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -347,15 +347,15 @@ async def update( id: str, *, description: str, - origins: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - url_prefix: str | NotGiven = NOT_GIVEN, - url_rewriter: url_endpoint_update_params.URLRewriter | NotGiven = NOT_GIVEN, + origins: SequenceNotStr[str] | Omit = omit, + url_prefix: str | Omit = omit, + url_rewriter: url_endpoint_update_params.URLRewriter | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> URLEndpointResponse: """**Note:** This API is currently in beta. @@ -413,7 +413,7 @@ async def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> URLEndpointListResponse: """**Note:** This API is currently in beta. @@ -438,7 +438,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """**Note:** This API is currently in beta. @@ -479,7 +479,7 @@ async def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> URLEndpointResponse: """**Note:** This API is currently in beta. diff --git a/src/imagekit/resources/accounts/usage.py b/src/imagekit/resources/accounts/usage.py index 3e0fd41..b35d3c9 100644 --- a/src/imagekit/resources/accounts/usage.py +++ b/src/imagekit/resources/accounts/usage.py @@ -7,7 +7,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Query, Headers, NotGiven, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -54,7 +54,7 @@ def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> UsageGetResponse: """Get the account usage information between two dates. @@ -127,7 +127,7 @@ async def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> UsageGetResponse: """Get the account usage information between two dates. diff --git a/src/imagekit/resources/assets.py b/src/imagekit/resources/assets.py index 51173fa..1d239da 100644 --- a/src/imagekit/resources/assets.py +++ b/src/imagekit/resources/assets.py @@ -7,7 +7,7 @@ import httpx from ..types import asset_list_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -46,11 +46,11 @@ def with_streaming_response(self) -> AssetsResourceWithStreamingResponse: def list( self, *, - file_type: Literal["all", "image", "non-image"] | NotGiven = NOT_GIVEN, - limit: int | NotGiven = NOT_GIVEN, - path: str | NotGiven = NOT_GIVEN, - search_query: str | NotGiven = NOT_GIVEN, - skip: int | NotGiven = NOT_GIVEN, + file_type: Literal["all", "image", "non-image"] | Omit = omit, + limit: int | Omit = omit, + path: str | Omit = omit, + search_query: str | Omit = omit, + skip: int | Omit = omit, sort: Literal[ "ASC_NAME", "DESC_NAME", @@ -67,14 +67,14 @@ def list( "ASC_RELEVANCE", "DESC_RELEVANCE", ] - | NotGiven = NOT_GIVEN, - type: Literal["file", "file-version", "folder", "all"] | NotGiven = NOT_GIVEN, + | Omit = omit, + type: Literal["file", "file-version", "folder", "all"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AssetListResponse: """ This API can list all the uploaded files and folders in your ImageKit.io media @@ -179,11 +179,11 @@ def with_streaming_response(self) -> AsyncAssetsResourceWithStreamingResponse: async def list( self, *, - file_type: Literal["all", "image", "non-image"] | NotGiven = NOT_GIVEN, - limit: int | NotGiven = NOT_GIVEN, - path: str | NotGiven = NOT_GIVEN, - search_query: str | NotGiven = NOT_GIVEN, - skip: int | NotGiven = NOT_GIVEN, + file_type: Literal["all", "image", "non-image"] | Omit = omit, + limit: int | Omit = omit, + path: str | Omit = omit, + search_query: str | Omit = omit, + skip: int | Omit = omit, sort: Literal[ "ASC_NAME", "DESC_NAME", @@ -200,14 +200,14 @@ async def list( "ASC_RELEVANCE", "DESC_RELEVANCE", ] - | NotGiven = NOT_GIVEN, - type: Literal["file", "file-version", "folder", "all"] | NotGiven = NOT_GIVEN, + | Omit = omit, + type: Literal["file", "file-version", "folder", "all"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AssetListResponse: """ This API can list all the uploaded files and folders in your ImageKit.io media diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index c2422d1..4d64161 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -7,7 +7,17 @@ import httpx -from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr +from ...._types import ( + Body, + Omit, + Query, + Headers, + NotGiven, + FileTypes, + SequenceNotStr, + omit, + not_given, +) from ...._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource @@ -50,19 +60,19 @@ def upload( *, file: FileTypes, file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Extensions | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, + token: str | Omit = omit, + checks: str | Omit = omit, + custom_coordinates: str | Omit = omit, + custom_metadata: Dict[str, object] | Omit = omit, + description: str | Omit = omit, + extensions: Extensions | Omit = omit, + folder: str | Omit = omit, + is_private_file: bool | Omit = omit, + is_published: bool | Omit = omit, + overwrite_ai_tags: bool | Omit = omit, + overwrite_custom_metadata: bool | Omit = omit, + overwrite_file: bool | Omit = omit, + overwrite_tags: bool | Omit = omit, response_fields: List[ Literal[ "tags", @@ -74,17 +84,17 @@ def upload( "metadata", ] ] - | NotGiven = NOT_GIVEN, - tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, + | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + transformation: file_upload_params.Transformation | Omit = omit, + use_unique_file_name: bool | Omit = omit, + webhook_url: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUploadResponse: """The V2 API enhances security by verifying the entire payload using JWT. @@ -302,19 +312,19 @@ async def upload( *, file: FileTypes, file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Extensions | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, + token: str | Omit = omit, + checks: str | Omit = omit, + custom_coordinates: str | Omit = omit, + custom_metadata: Dict[str, object] | Omit = omit, + description: str | Omit = omit, + extensions: Extensions | Omit = omit, + folder: str | Omit = omit, + is_private_file: bool | Omit = omit, + is_published: bool | Omit = omit, + overwrite_ai_tags: bool | Omit = omit, + overwrite_custom_metadata: bool | Omit = omit, + overwrite_file: bool | Omit = omit, + overwrite_tags: bool | Omit = omit, response_fields: List[ Literal[ "tags", @@ -326,17 +336,17 @@ async def upload( "metadata", ] ] - | NotGiven = NOT_GIVEN, - tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, + | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + transformation: file_upload_params.Transformation | Omit = omit, + use_unique_file_name: bool | Omit = omit, + webhook_url: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUploadResponse: """The V2 API enhances security by verifying the entire payload using JWT. diff --git a/src/imagekit/resources/cache/invalidation.py b/src/imagekit/resources/cache/invalidation.py index a1c83d7..9c95dc8 100644 --- a/src/imagekit/resources/cache/invalidation.py +++ b/src/imagekit/resources/cache/invalidation.py @@ -4,7 +4,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Query, Headers, NotGiven, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -51,7 +51,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvalidationCreateResponse: """This API will purge CDN cache and ImageKit.io's internal cache for a file. @@ -88,7 +88,7 @@ def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvalidationGetResponse: """ This API returns the status of a purge cache request. @@ -142,7 +142,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvalidationCreateResponse: """This API will purge CDN cache and ImageKit.io's internal cache for a file. @@ -179,7 +179,7 @@ async def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvalidationGetResponse: """ This API returns the status of a purge cache request. diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py index 94f4eb5..1668c53 100644 --- a/src/imagekit/resources/custom_metadata_fields.py +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -9,7 +9,7 @@ custom_metadata_field_create_params, custom_metadata_field_update_params, ) -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -58,7 +58,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CustomMetadataField: """This API creates a new custom metadata field. @@ -104,14 +104,14 @@ def update( self, id: str, *, - label: str | NotGiven = NOT_GIVEN, - schema: custom_metadata_field_update_params.Schema | NotGiven = NOT_GIVEN, + label: str | Omit = omit, + schema: custom_metadata_field_update_params.Schema | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CustomMetadataField: """ This API updates the label or schema of an existing custom metadata field. @@ -155,13 +155,13 @@ def update( def list( self, *, - include_deleted: bool | NotGiven = NOT_GIVEN, + include_deleted: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CustomMetadataFieldListResponse: """This API returns the array of created custom metadata field objects. @@ -204,7 +204,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CustomMetadataFieldDeleteResponse: """This API deletes a custom metadata field. @@ -262,7 +262,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CustomMetadataField: """This API creates a new custom metadata field. @@ -308,14 +308,14 @@ async def update( self, id: str, *, - label: str | NotGiven = NOT_GIVEN, - schema: custom_metadata_field_update_params.Schema | NotGiven = NOT_GIVEN, + label: str | Omit = omit, + schema: custom_metadata_field_update_params.Schema | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CustomMetadataField: """ This API updates the label or schema of an existing custom metadata field. @@ -359,13 +359,13 @@ async def update( async def list( self, *, - include_deleted: bool | NotGiven = NOT_GIVEN, + include_deleted: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CustomMetadataFieldListResponse: """This API returns the array of created custom metadata field objects. @@ -408,7 +408,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CustomMetadataFieldDeleteResponse: """This API deletes a custom metadata field. diff --git a/src/imagekit/resources/files/bulk.py b/src/imagekit/resources/files/bulk.py index 8b7a216..43c02cb 100644 --- a/src/imagekit/resources/files/bulk.py +++ b/src/imagekit/resources/files/bulk.py @@ -4,7 +4,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven, SequenceNotStr +from ..._types import Body, Query, Headers, NotGiven, SequenceNotStr, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -53,7 +53,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BulkDeleteResponse: """ This API deletes multiple files and all their file versions permanently. @@ -94,7 +94,7 @@ def add_tags( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BulkAddTagsResponse: """This API adds tags to multiple files in bulk. @@ -139,7 +139,7 @@ def remove_ai_tags( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BulkRemoveAITagsResponse: """This API removes AITags from multiple files in bulk. @@ -184,7 +184,7 @@ def remove_tags( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BulkRemoveTagsResponse: """This API removes tags from multiple files in bulk. @@ -249,7 +249,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BulkDeleteResponse: """ This API deletes multiple files and all their file versions permanently. @@ -290,7 +290,7 @@ async def add_tags( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BulkAddTagsResponse: """This API adds tags to multiple files in bulk. @@ -335,7 +335,7 @@ async def remove_ai_tags( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BulkRemoveAITagsResponse: """This API removes AITags from multiple files in bulk. @@ -380,7 +380,7 @@ async def remove_tags( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BulkRemoveTagsResponse: """This API removes tags from multiple files in bulk. diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 0798330..d8c224c 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -22,7 +22,18 @@ file_update_params, file_upload_params, ) -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven, FileTypes, SequenceNotStr +from ..._types import ( + Body, + Omit, + Query, + Headers, + NoneType, + NotGiven, + FileTypes, + SequenceNotStr, + omit, + not_given, +) from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from .metadata import ( MetadataResource, @@ -97,19 +108,19 @@ def update( self, file_id: str, *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Extensions | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[SequenceNotStr[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | Omit = omit, + custom_metadata: Dict[str, object] | Omit = omit, + description: str | Omit = omit, + extensions: Extensions | Omit = omit, + remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | Omit = omit, + tags: Optional[SequenceNotStr[str]] | Omit = omit, + webhook_url: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUpdateResponse: """ This API updates the details or attributes of the current version of the file. @@ -161,13 +172,13 @@ def update( self, file_id: str, *, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUpdateResponse: """ This API updates the details or attributes of the current version of the file. @@ -191,20 +202,20 @@ def update( self, file_id: str, *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Extensions | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[SequenceNotStr[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | Omit = omit, + custom_metadata: Dict[str, object] | Omit = omit, + description: str | Omit = omit, + extensions: Extensions | Omit = omit, + remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | Omit = omit, + tags: Optional[SequenceNotStr[str]] | Omit = omit, + webhook_url: str | Omit = omit, + publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") @@ -238,7 +249,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ This API deletes the file and all its file versions permanently. @@ -272,13 +283,13 @@ def copy( *, destination_path: str, source_file_path: str, - include_file_versions: bool | NotGiven = NOT_GIVEN, + include_file_versions: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileCopyResponse: """ This will copy a file from one folder to another. @@ -329,7 +340,7 @@ def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> File: """ This API returns an object with details or attributes about the current version @@ -364,7 +375,7 @@ def move( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileMoveResponse: """ This will move a file and all its versions from one folder to another. @@ -405,13 +416,13 @@ def rename( *, file_path: str, new_file_name: str, - purge_cache: bool | NotGiven = NOT_GIVEN, + purge_cache: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileRenameResponse: """ You can rename an already existing file in the media library using rename file @@ -477,21 +488,21 @@ def upload( *, file: FileTypes, file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - expire: int | NotGiven = NOT_GIVEN, - extensions: Extensions | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, - public_key: str | NotGiven = NOT_GIVEN, + token: str | Omit = omit, + checks: str | Omit = omit, + custom_coordinates: str | Omit = omit, + custom_metadata: Dict[str, object] | Omit = omit, + description: str | Omit = omit, + expire: int | Omit = omit, + extensions: Extensions | Omit = omit, + folder: str | Omit = omit, + is_private_file: bool | Omit = omit, + is_published: bool | Omit = omit, + overwrite_ai_tags: bool | Omit = omit, + overwrite_custom_metadata: bool | Omit = omit, + overwrite_file: bool | Omit = omit, + overwrite_tags: bool | Omit = omit, + public_key: str | Omit = omit, response_fields: List[ Literal[ "tags", @@ -503,18 +514,18 @@ def upload( "metadata", ] ] - | NotGiven = NOT_GIVEN, - signature: str | NotGiven = NOT_GIVEN, - tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, + | Omit = omit, + signature: str | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + transformation: file_upload_params.Transformation | Omit = omit, + use_unique_file_name: bool | Omit = omit, + webhook_url: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUploadResponse: """ ImageKit.io allows you to upload files directly from both the server and client @@ -768,19 +779,19 @@ async def update( self, file_id: str, *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Extensions | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[SequenceNotStr[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | Omit = omit, + custom_metadata: Dict[str, object] | Omit = omit, + description: str | Omit = omit, + extensions: Extensions | Omit = omit, + remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | Omit = omit, + tags: Optional[SequenceNotStr[str]] | Omit = omit, + webhook_url: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUpdateResponse: """ This API updates the details or attributes of the current version of the file. @@ -832,13 +843,13 @@ async def update( self, file_id: str, *, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUpdateResponse: """ This API updates the details or attributes of the current version of the file. @@ -862,20 +873,20 @@ async def update( self, file_id: str, *, - custom_coordinates: Optional[str] | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - extensions: Extensions | NotGiven = NOT_GIVEN, - remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | NotGiven = NOT_GIVEN, - tags: Optional[SequenceNotStr[str]] | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, - publish: file_update_params.ChangePublicationStatusPublish | NotGiven = NOT_GIVEN, + custom_coordinates: Optional[str] | Omit = omit, + custom_metadata: Dict[str, object] | Omit = omit, + description: str | Omit = omit, + extensions: Extensions | Omit = omit, + remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | Omit = omit, + tags: Optional[SequenceNotStr[str]] | Omit = omit, + webhook_url: str | Omit = omit, + publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUpdateResponse: if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") @@ -909,7 +920,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ This API deletes the file and all its file versions permanently. @@ -943,13 +954,13 @@ async def copy( *, destination_path: str, source_file_path: str, - include_file_versions: bool | NotGiven = NOT_GIVEN, + include_file_versions: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileCopyResponse: """ This will copy a file from one folder to another. @@ -1000,7 +1011,7 @@ async def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> File: """ This API returns an object with details or attributes about the current version @@ -1035,7 +1046,7 @@ async def move( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileMoveResponse: """ This will move a file and all its versions from one folder to another. @@ -1076,13 +1087,13 @@ async def rename( *, file_path: str, new_file_name: str, - purge_cache: bool | NotGiven = NOT_GIVEN, + purge_cache: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileRenameResponse: """ You can rename an already existing file in the media library using rename file @@ -1148,21 +1159,21 @@ async def upload( *, file: FileTypes, file_name: str, - token: str | NotGiven = NOT_GIVEN, - checks: str | NotGiven = NOT_GIVEN, - custom_coordinates: str | NotGiven = NOT_GIVEN, - custom_metadata: Dict[str, object] | NotGiven = NOT_GIVEN, - description: str | NotGiven = NOT_GIVEN, - expire: int | NotGiven = NOT_GIVEN, - extensions: Extensions | NotGiven = NOT_GIVEN, - folder: str | NotGiven = NOT_GIVEN, - is_private_file: bool | NotGiven = NOT_GIVEN, - is_published: bool | NotGiven = NOT_GIVEN, - overwrite_ai_tags: bool | NotGiven = NOT_GIVEN, - overwrite_custom_metadata: bool | NotGiven = NOT_GIVEN, - overwrite_file: bool | NotGiven = NOT_GIVEN, - overwrite_tags: bool | NotGiven = NOT_GIVEN, - public_key: str | NotGiven = NOT_GIVEN, + token: str | Omit = omit, + checks: str | Omit = omit, + custom_coordinates: str | Omit = omit, + custom_metadata: Dict[str, object] | Omit = omit, + description: str | Omit = omit, + expire: int | Omit = omit, + extensions: Extensions | Omit = omit, + folder: str | Omit = omit, + is_private_file: bool | Omit = omit, + is_published: bool | Omit = omit, + overwrite_ai_tags: bool | Omit = omit, + overwrite_custom_metadata: bool | Omit = omit, + overwrite_file: bool | Omit = omit, + overwrite_tags: bool | Omit = omit, + public_key: str | Omit = omit, response_fields: List[ Literal[ "tags", @@ -1174,18 +1185,18 @@ async def upload( "metadata", ] ] - | NotGiven = NOT_GIVEN, - signature: str | NotGiven = NOT_GIVEN, - tags: SequenceNotStr[str] | NotGiven = NOT_GIVEN, - transformation: file_upload_params.Transformation | NotGiven = NOT_GIVEN, - use_unique_file_name: bool | NotGiven = NOT_GIVEN, - webhook_url: str | NotGiven = NOT_GIVEN, + | Omit = omit, + signature: str | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + transformation: file_upload_params.Transformation | Omit = omit, + use_unique_file_name: bool | Omit = omit, + webhook_url: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUploadResponse: """ ImageKit.io allows you to upload files directly from both the server and client diff --git a/src/imagekit/resources/files/metadata.py b/src/imagekit/resources/files/metadata.py index e68348a..d9e0541 100644 --- a/src/imagekit/resources/files/metadata.py +++ b/src/imagekit/resources/files/metadata.py @@ -4,7 +4,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Query, Headers, NotGiven, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -50,7 +50,7 @@ def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Metadata: """ You can programmatically get image EXIF, pHash, and other metadata for uploaded @@ -87,7 +87,7 @@ def get_from_url( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Metadata: """ Get image EXIF, pHash, and other metadata from ImageKit.io powered remote URL @@ -147,7 +147,7 @@ async def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Metadata: """ You can programmatically get image EXIF, pHash, and other metadata for uploaded @@ -184,7 +184,7 @@ async def get_from_url( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Metadata: """ Get image EXIF, pHash, and other metadata from ImageKit.io powered remote URL diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py index 77c22c3..e6479e1 100644 --- a/src/imagekit/resources/files/versions.py +++ b/src/imagekit/resources/files/versions.py @@ -4,7 +4,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Query, Headers, NotGiven, not_given from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -50,7 +50,7 @@ def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VersionListResponse: """ This API returns details of all versions of a file. @@ -84,7 +84,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VersionDeleteResponse: """This API deletes a non-current file version permanently. @@ -124,7 +124,7 @@ def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> File: """ This API returns an object with details or attributes of a file version. @@ -160,7 +160,7 @@ def restore( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> File: """ This API restores a file version as the current file version. @@ -216,7 +216,7 @@ async def list( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VersionListResponse: """ This API returns details of all versions of a file. @@ -250,7 +250,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VersionDeleteResponse: """This API deletes a non-current file version permanently. @@ -290,7 +290,7 @@ async def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> File: """ This API returns an object with details or attributes of a file version. @@ -326,7 +326,7 @@ async def restore( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> File: """ This API restores a file version as the current file version. diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekit/resources/folders/folders.py index 7b71a40..d986fd7 100644 --- a/src/imagekit/resources/folders/folders.py +++ b/src/imagekit/resources/folders/folders.py @@ -19,7 +19,7 @@ folder_delete_params, folder_rename_params, ) -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -73,7 +73,7 @@ def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FolderCreateResponse: """This will create a new folder. @@ -127,7 +127,7 @@ def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FolderDeleteResponse: """This will delete a folder and all its contents permanently. @@ -159,13 +159,13 @@ def copy( *, destination_path: str, source_folder_path: str, - include_versions: bool | NotGiven = NOT_GIVEN, + include_versions: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FolderCopyResponse: """This will copy one folder into another. @@ -219,7 +219,7 @@ def move( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FolderMoveResponse: """This will move one folder into another. @@ -262,13 +262,13 @@ def rename( *, folder_path: str, new_folder_name: str, - purge_cache: bool | NotGiven = NOT_GIVEN, + purge_cache: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FolderRenameResponse: """This API allows you to rename an existing folder. @@ -360,7 +360,7 @@ async def create( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FolderCreateResponse: """This will create a new folder. @@ -414,7 +414,7 @@ async def delete( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FolderDeleteResponse: """This will delete a folder and all its contents permanently. @@ -446,13 +446,13 @@ async def copy( *, destination_path: str, source_folder_path: str, - include_versions: bool | NotGiven = NOT_GIVEN, + include_versions: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FolderCopyResponse: """This will copy one folder into another. @@ -506,7 +506,7 @@ async def move( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FolderMoveResponse: """This will move one folder into another. @@ -549,13 +549,13 @@ async def rename( *, folder_path: str, new_folder_name: str, - purge_cache: bool | NotGiven = NOT_GIVEN, + purge_cache: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FolderRenameResponse: """This API allows you to rename an existing folder. diff --git a/src/imagekit/resources/folders/job.py b/src/imagekit/resources/folders/job.py index c76445f..5ccbd3b 100644 --- a/src/imagekit/resources/folders/job.py +++ b/src/imagekit/resources/folders/job.py @@ -4,7 +4,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Query, Headers, NotGiven, not_given from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -48,7 +48,7 @@ def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> JobGetResponse: """ This API returns the status of a bulk job like copy and move folder operations. @@ -102,7 +102,7 @@ async def get( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> JobGetResponse: """ This API returns the status of a bulk job like copy and move folder operations. diff --git a/tests/test_transform.py b/tests/test_transform.py index 479e32f..2d745f5 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -8,7 +8,7 @@ import pytest -from imagekit._types import NOT_GIVEN, Base64FileInput +from imagekit._types import Base64FileInput, omit, not_given from imagekit._utils import ( PropertyInfo, transform as _transform, @@ -450,4 +450,11 @@ async def test_transform_skipping(use_async: bool) -> None: @pytest.mark.asyncio async def test_strips_notgiven(use_async: bool) -> None: assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} - assert await transform({"foo_bar": NOT_GIVEN}, Foo1, use_async) == {} + assert await transform({"foo_bar": not_given}, Foo1, use_async) == {} + + +@parametrize +@pytest.mark.asyncio +async def test_strips_omit(use_async: bool) -> None: + assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} + assert await transform({"foo_bar": omit}, Foo1, use_async) == {} From d2019fa91a3b1297193c233e0964a4567f0be05a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 12:57:32 +0000 Subject: [PATCH 118/177] feat(api): manual updates --- .stats.yml | 6 ++-- api.md | 2 +- src/imagekit/resources/files/files.py | 16 ++++------ src/imagekit/types/__init__.py | 2 +- src/imagekit/types/file_update_params.py | 16 ++-------- ..._param.py => update_file_request_param.py} | 27 ++-------------- tests/api_resources/test_files.py | 32 +++++-------------- 7 files changed, 24 insertions(+), 77 deletions(-) rename src/imagekit/types/{update_file_details_request_param.py => update_file_request_param.py} (69%) diff --git a/.stats.yml b/.stats.yml index b0086e9..bb4a090 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-bc7c0d27962b30c19c778656988e154b54696819389289f34420a5e5fdfbd3b8.yml -openapi_spec_hash: 1bfde02a63416c036e9545927f727459 -config_hash: b415c06a3b29485af4601beb94ae1aeb +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-dd864816d7f4316ae89f57394da2fd1926166d4704db5a0bb5d23461d2d75e49.yml +openapi_spec_hash: 7f7c416563a15bbaea98804ecdc1a8f9 +config_hash: 54c05a157f2cc730fac9e1df5dc3ca29 diff --git a/api.md b/api.md index 697c667..f815131 100644 --- a/api.md +++ b/api.md @@ -50,7 +50,7 @@ from imagekit.types import ( File, Folder, Metadata, - UpdateFileDetailsRequest, + UpdateFileRequest, FileUpdateResponse, FileCopyResponse, FileMoveResponse, diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index d8c224c..da16beb 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -172,7 +172,7 @@ def update( self, file_id: str, *, - publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, + body: object, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -186,8 +186,6 @@ def update( status, remove existing `AITags` and apply extensions using this API. Args: - publish: Configure the publication status of a file and its versions. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -209,7 +207,7 @@ def update( remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | Omit = omit, tags: Optional[SequenceNotStr[str]] | Omit = omit, webhook_url: str | Omit = omit, - publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, + body: object | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -230,7 +228,7 @@ def update( "remove_ai_tags": remove_ai_tags, "tags": tags, "webhook_url": webhook_url, - "publish": publish, + "body": body, }, file_update_params.FileUpdateParams, ), @@ -843,7 +841,7 @@ async def update( self, file_id: str, *, - publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, + body: object, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -857,8 +855,6 @@ async def update( status, remove existing `AITags` and apply extensions using this API. Args: - publish: Configure the publication status of a file and its versions. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -880,7 +876,7 @@ async def update( remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | Omit = omit, tags: Optional[SequenceNotStr[str]] | Omit = omit, webhook_url: str | Omit = omit, - publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, + body: object | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -901,7 +897,7 @@ async def update( "remove_ai_tags": remove_ai_tags, "tags": tags, "webhook_url": webhook_url, - "publish": publish, + "body": body, }, file_update_params.FileUpdateParams, ), diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index 9a8b535..c686db1 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -51,12 +51,12 @@ from .folder_create_response import FolderCreateResponse as FolderCreateResponse from .folder_delete_response import FolderDeleteResponse as FolderDeleteResponse from .folder_rename_response import FolderRenameResponse as FolderRenameResponse +from .update_file_request_param import UpdateFileRequestParam as UpdateFileRequestParam from .unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent as UnsafeUnwrapWebhookEvent from .upload_pre_transform_error_event import UploadPreTransformErrorEvent as UploadPreTransformErrorEvent from .video_transformation_error_event import VideoTransformationErrorEvent as VideoTransformationErrorEvent from .video_transformation_ready_event import VideoTransformationReadyEvent as VideoTransformationReadyEvent from .custom_metadata_field_list_params import CustomMetadataFieldListParams as CustomMetadataFieldListParams -from .update_file_details_request_param import UpdateFileDetailsRequestParam as UpdateFileDetailsRequestParam from .upload_post_transform_error_event import UploadPostTransformErrorEvent as UploadPostTransformErrorEvent from .upload_pre_transform_success_event import UploadPreTransformSuccessEvent as UploadPreTransformSuccessEvent from .custom_metadata_field_create_params import CustomMetadataFieldCreateParams as CustomMetadataFieldCreateParams diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index 233492c..c9dba81 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -9,7 +9,7 @@ from .._utils import PropertyInfo from .shared_params.extensions import Extensions -__all__ = ["FileUpdateParams", "UpdateFileDetails", "ChangePublicationStatus", "ChangePublicationStatusPublish"] +__all__ = ["FileUpdateParams", "UpdateFileDetails", "ChangePublicationStatus"] class UpdateFileDetails(TypedDict, total=False): @@ -65,19 +65,7 @@ class UpdateFileDetails(TypedDict, total=False): class ChangePublicationStatus(TypedDict, total=False): - publish: ChangePublicationStatusPublish - """Configure the publication status of a file and its versions.""" - - -class ChangePublicationStatusPublish(TypedDict, total=False): - is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] - """Set to `true` to publish the file. Set to `false` to unpublish the file.""" - - include_file_versions: Annotated[bool, PropertyInfo(alias="includeFileVersions")] - """Set to `true` to publish/unpublish all versions of the file. - - Set to `false` to publish/unpublish only the current version of the file. - """ + body: Required[object] FileUpdateParams: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] diff --git a/src/imagekit/types/update_file_details_request_param.py b/src/imagekit/types/update_file_request_param.py similarity index 69% rename from src/imagekit/types/update_file_details_request_param.py rename to src/imagekit/types/update_file_request_param.py index 75a1f40..c0be94a 100644 --- a/src/imagekit/types/update_file_details_request_param.py +++ b/src/imagekit/types/update_file_request_param.py @@ -3,18 +3,13 @@ from __future__ import annotations from typing import Dict, Union, Optional -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Literal, Annotated, TypeAlias, TypedDict from .._types import SequenceNotStr from .._utils import PropertyInfo from .shared_params.extensions import Extensions -__all__ = [ - "UpdateFileDetailsRequestParam", - "UpdateFileDetails", - "ChangePublicationStatus", - "ChangePublicationStatusPublish", -] +__all__ = ["UpdateFileRequestParam", "UpdateFileDetails"] class UpdateFileDetails(TypedDict, total=False): @@ -69,20 +64,4 @@ class UpdateFileDetails(TypedDict, total=False): """ -class ChangePublicationStatusPublish(TypedDict, total=False): - is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] - """Set to `true` to publish the file. Set to `false` to unpublish the file.""" - - include_file_versions: Annotated[bool, PropertyInfo(alias="includeFileVersions")] - """Set to `true` to publish/unpublish all versions of the file. - - Set to `false` to publish/unpublish only the current version of the file. - """ - - -class ChangePublicationStatus(TypedDict, total=False): - publish: ChangePublicationStatusPublish - """Configure the publication status of a file and its versions.""" - - -UpdateFileDetailsRequestParam: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] +UpdateFileRequestParam: TypeAlias = Union[UpdateFileDetails, object] diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 5a9594f..897629f 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -102,18 +102,7 @@ def test_path_params_update_overload_1(self, client: ImageKit) -> None: def test_method_update_overload_2(self, client: ImageKit) -> None: file = client.files.update( file_id="fileId", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: - file = client.files.update( - file_id="fileId", - publish={ - "is_published": True, - "include_file_versions": True, - }, + body={}, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @@ -122,6 +111,7 @@ def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> Non def test_raw_response_update_overload_2(self, client: ImageKit) -> None: response = client.files.with_raw_response.update( file_id="fileId", + body={}, ) assert response.is_closed is True @@ -134,6 +124,7 @@ def test_raw_response_update_overload_2(self, client: ImageKit) -> None: def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: with client.files.with_streaming_response.update( file_id="fileId", + body={}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -149,6 +140,7 @@ def test_path_params_update_overload_2(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.files.with_raw_response.update( file_id="", + body={}, ) @pytest.mark.skip(reason="Prism tests are disabled") @@ -549,18 +541,7 @@ async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: file = await async_client.files.update( file_id="fileId", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: - file = await async_client.files.update( - file_id="fileId", - publish={ - "is_published": True, - "include_file_versions": True, - }, + body={}, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @@ -569,6 +550,7 @@ async def test_method_update_with_all_params_overload_2(self, async_client: Asyn async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.update( file_id="fileId", + body={}, ) assert response.is_closed is True @@ -581,6 +563,7 @@ async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.update( file_id="fileId", + body={}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -596,6 +579,7 @@ async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.files.with_raw_response.update( file_id="", + body={}, ) @pytest.mark.skip(reason="Prism tests are disabled") From 91878d4dc9e26e68b8b22aa3ac4fe482aed73ae2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:02:09 +0000 Subject: [PATCH 119/177] feat(api): manual updates --- .stats.yml | 4 +-- src/imagekit/resources/files/files.py | 16 ++++++---- src/imagekit/types/file_update_params.py | 16 ++++++++-- .../types/update_file_request_param.py | 22 +++++++++++-- tests/api_resources/test_files.py | 32 ++++++++++++++----- 5 files changed, 69 insertions(+), 21 deletions(-) diff --git a/.stats.yml b/.stats.yml index bb4a090..c9c84db 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-dd864816d7f4316ae89f57394da2fd1926166d4704db5a0bb5d23461d2d75e49.yml -openapi_spec_hash: 7f7c416563a15bbaea98804ecdc1a8f9 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d1a3e6dfc45ae832b6b14a0aef25878985c679fa9f48c1470df188b1578ba648.yml +openapi_spec_hash: 1d382866fce3284f26d341f112988d9d config_hash: 54c05a157f2cc730fac9e1df5dc3ca29 diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index da16beb..d8c224c 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -172,7 +172,7 @@ def update( self, file_id: str, *, - body: object, + publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -186,6 +186,8 @@ def update( status, remove existing `AITags` and apply extensions using this API. Args: + publish: Configure the publication status of a file and its versions. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -207,7 +209,7 @@ def update( remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | Omit = omit, tags: Optional[SequenceNotStr[str]] | Omit = omit, webhook_url: str | Omit = omit, - body: object | Omit = omit, + publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -228,7 +230,7 @@ def update( "remove_ai_tags": remove_ai_tags, "tags": tags, "webhook_url": webhook_url, - "body": body, + "publish": publish, }, file_update_params.FileUpdateParams, ), @@ -841,7 +843,7 @@ async def update( self, file_id: str, *, - body: object, + publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -855,6 +857,8 @@ async def update( status, remove existing `AITags` and apply extensions using this API. Args: + publish: Configure the publication status of a file and its versions. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -876,7 +880,7 @@ async def update( remove_ai_tags: Union[SequenceNotStr[str], Literal["all"]] | Omit = omit, tags: Optional[SequenceNotStr[str]] | Omit = omit, webhook_url: str | Omit = omit, - body: object | Omit = omit, + publish: file_update_params.ChangePublicationStatusPublish | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -897,7 +901,7 @@ async def update( "remove_ai_tags": remove_ai_tags, "tags": tags, "webhook_url": webhook_url, - "body": body, + "publish": publish, }, file_update_params.FileUpdateParams, ), diff --git a/src/imagekit/types/file_update_params.py b/src/imagekit/types/file_update_params.py index c9dba81..233492c 100644 --- a/src/imagekit/types/file_update_params.py +++ b/src/imagekit/types/file_update_params.py @@ -9,7 +9,7 @@ from .._utils import PropertyInfo from .shared_params.extensions import Extensions -__all__ = ["FileUpdateParams", "UpdateFileDetails", "ChangePublicationStatus"] +__all__ = ["FileUpdateParams", "UpdateFileDetails", "ChangePublicationStatus", "ChangePublicationStatusPublish"] class UpdateFileDetails(TypedDict, total=False): @@ -65,7 +65,19 @@ class UpdateFileDetails(TypedDict, total=False): class ChangePublicationStatus(TypedDict, total=False): - body: Required[object] + publish: ChangePublicationStatusPublish + """Configure the publication status of a file and its versions.""" + + +class ChangePublicationStatusPublish(TypedDict, total=False): + is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] + """Set to `true` to publish the file. Set to `false` to unpublish the file.""" + + include_file_versions: Annotated[bool, PropertyInfo(alias="includeFileVersions")] + """Set to `true` to publish/unpublish all versions of the file. + + Set to `false` to publish/unpublish only the current version of the file. + """ FileUpdateParams: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] diff --git a/src/imagekit/types/update_file_request_param.py b/src/imagekit/types/update_file_request_param.py index c0be94a..e72b585 100644 --- a/src/imagekit/types/update_file_request_param.py +++ b/src/imagekit/types/update_file_request_param.py @@ -3,13 +3,13 @@ from __future__ import annotations from typing import Dict, Union, Optional -from typing_extensions import Literal, Annotated, TypeAlias, TypedDict +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict from .._types import SequenceNotStr from .._utils import PropertyInfo from .shared_params.extensions import Extensions -__all__ = ["UpdateFileRequestParam", "UpdateFileDetails"] +__all__ = ["UpdateFileRequestParam", "UpdateFileDetails", "ChangePublicationStatus", "ChangePublicationStatusPublish"] class UpdateFileDetails(TypedDict, total=False): @@ -64,4 +64,20 @@ class UpdateFileDetails(TypedDict, total=False): """ -UpdateFileRequestParam: TypeAlias = Union[UpdateFileDetails, object] +class ChangePublicationStatusPublish(TypedDict, total=False): + is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] + """Set to `true` to publish the file. Set to `false` to unpublish the file.""" + + include_file_versions: Annotated[bool, PropertyInfo(alias="includeFileVersions")] + """Set to `true` to publish/unpublish all versions of the file. + + Set to `false` to publish/unpublish only the current version of the file. + """ + + +class ChangePublicationStatus(TypedDict, total=False): + publish: ChangePublicationStatusPublish + """Configure the publication status of a file and its versions.""" + + +UpdateFileRequestParam: TypeAlias = Union[UpdateFileDetails, ChangePublicationStatus] diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 897629f..5a9594f 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -102,7 +102,18 @@ def test_path_params_update_overload_1(self, client: ImageKit) -> None: def test_method_update_overload_2(self, client: ImageKit) -> None: file = client.files.update( file_id="fileId", - body={}, + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_2(self, client: ImageKit) -> None: + file = client.files.update( + file_id="fileId", + publish={ + "is_published": True, + "include_file_versions": True, + }, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @@ -111,7 +122,6 @@ def test_method_update_overload_2(self, client: ImageKit) -> None: def test_raw_response_update_overload_2(self, client: ImageKit) -> None: response = client.files.with_raw_response.update( file_id="fileId", - body={}, ) assert response.is_closed is True @@ -124,7 +134,6 @@ def test_raw_response_update_overload_2(self, client: ImageKit) -> None: def test_streaming_response_update_overload_2(self, client: ImageKit) -> None: with client.files.with_streaming_response.update( file_id="fileId", - body={}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -140,7 +149,6 @@ def test_path_params_update_overload_2(self, client: ImageKit) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.files.with_raw_response.update( file_id="", - body={}, ) @pytest.mark.skip(reason="Prism tests are disabled") @@ -541,7 +549,18 @@ async def test_path_params_update_overload_1(self, async_client: AsyncImageKit) async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> None: file = await async_client.files.update( file_id="fileId", - body={}, + ) + assert_matches_type(FileUpdateResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_2(self, async_client: AsyncImageKit) -> None: + file = await async_client.files.update( + file_id="fileId", + publish={ + "is_published": True, + "include_file_versions": True, + }, ) assert_matches_type(FileUpdateResponse, file, path=["response"]) @@ -550,7 +569,6 @@ async def test_method_update_overload_2(self, async_client: AsyncImageKit) -> No async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) -> None: response = await async_client.files.with_raw_response.update( file_id="fileId", - body={}, ) assert response.is_closed is True @@ -563,7 +581,6 @@ async def test_raw_response_update_overload_2(self, async_client: AsyncImageKit) async def test_streaming_response_update_overload_2(self, async_client: AsyncImageKit) -> None: async with async_client.files.with_streaming_response.update( file_id="fileId", - body={}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -579,7 +596,6 @@ async def test_path_params_update_overload_2(self, async_client: AsyncImageKit) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.files.with_raw_response.update( file_id="", - body={}, ) @pytest.mark.skip(reason="Prism tests are disabled") From 860bfbdf3f72c93488abaedcc86e55d3595c22bb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:38:06 +0000 Subject: [PATCH 120/177] feat(api): manual updates --- .stats.yml | 2 +- README.md | 12 ++-- src/imagekit/_client.py | 52 ++++++++--------- tests/conftest.py | 6 +- tests/test_client.py | 126 +++++++++++++++++++--------------------- 5 files changed, 97 insertions(+), 101 deletions(-) diff --git a/.stats.yml b/.stats.yml index c9c84db..00fd95d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d1a3e6dfc45ae832b6b14a0aef25878985c679fa9f48c1470df188b1578ba648.yml openapi_spec_hash: 1d382866fce3284f26d341f112988d9d -config_hash: 54c05a157f2cc730fac9e1df5dc3ca29 +config_hash: 29a2351fe2be89392b15719be8bc964f diff --git a/README.md b/README.md index 19cc02b..5a17eae 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ import os from imagekit import ImageKit client = ImageKit( - private_api_key=os.environ.get( + private_key=os.environ.get( "IMAGEKIT_PRIVATE_API_KEY" ), # This is the default and can be omitted password=os.environ.get( @@ -47,10 +47,10 @@ response = client.files.upload( print(response.video_codec) ``` -While you can provide a `private_api_key` keyword argument, +While you can provide a `private_key` keyword argument, we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/) -to add `IMAGEKIT_PRIVATE_API_KEY="My Private API Key"` to your `.env` file -so that your Private API Key is not stored in source control. +to add `IMAGEKIT_PRIVATE_API_KEY="My Private Key"` to your `.env` file +so that your Private Key is not stored in source control. ## Async usage @@ -62,7 +62,7 @@ import asyncio from imagekit import AsyncImageKit client = AsyncImageKit( - private_api_key=os.environ.get( + private_key=os.environ.get( "IMAGEKIT_PRIVATE_API_KEY" ), # This is the default and can be omitted password=os.environ.get( @@ -105,7 +105,7 @@ from imagekit import AsyncImageKit async def main() -> None: async with AsyncImageKit( - private_api_key="My Private API Key", + private_key="My Private Key", password="My Password", http_client=DefaultAioHttpClient(), ) as client: diff --git a/src/imagekit/_client.py b/src/imagekit/_client.py index b2a104b..38357d7 100644 --- a/src/imagekit/_client.py +++ b/src/imagekit/_client.py @@ -62,14 +62,14 @@ class ImageKit(SyncAPIClient): with_streaming_response: ImageKitWithStreamedResponse # client options - private_api_key: str + private_key: str password: str | None webhook_secret: str | None def __init__( self, *, - private_api_key: str | None = None, + private_key: str | None = None, password: str | None = None, webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, @@ -94,17 +94,17 @@ def __init__( """Construct a new synchronous ImageKit client instance. This automatically infers the following arguments from their corresponding environment variables if they are not provided: - - `private_api_key` from `IMAGEKIT_PRIVATE_API_KEY` + - `private_key` from `IMAGEKIT_PRIVATE_API_KEY` - `password` from `OPTIONAL_IMAGEKIT_IGNORES_THIS` - `webhook_secret` from `IMAGEKIT_WEBHOOK_SECRET` """ - if private_api_key is None: - private_api_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") - if private_api_key is None: + if private_key is None: + private_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") + if private_key is None: raise ImageKitError( - "The private_api_key client option must be set either by passing private_api_key to the client or by setting the IMAGEKIT_PRIVATE_API_KEY environment variable" + "The private_key client option must be set either by passing private_key to the client or by setting the IMAGEKIT_PRIVATE_API_KEY environment variable" ) - self.private_api_key = private_api_key + self.private_key = private_key if password is None: password = os.environ.get("OPTIONAL_IMAGEKIT_IGNORES_THIS") or "do_not_set" @@ -152,7 +152,7 @@ def qs(self) -> Querystring: def auth_headers(self) -> dict[str, str]: if self.password is None: return {} - credentials = f"{self.private_api_key}:{self.password}".encode("ascii") + credentials = f"{self.private_key}:{self.password}".encode("ascii") header = f"Basic {base64.b64encode(credentials).decode('ascii')}" return {"Authorization": header} @@ -167,19 +167,19 @@ def default_headers(self) -> dict[str, str | Omit]: @override def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None: - if self.private_api_key and self.password and headers.get("Authorization"): + if self.private_key and self.password and headers.get("Authorization"): return if isinstance(custom_headers.get("Authorization"), Omit): return raise TypeError( - '"Could not resolve authentication method. Expected the private_api_key or password to be set. Or for the `Authorization` headers to be explicitly omitted"' + '"Could not resolve authentication method. Expected the private_key or password to be set. Or for the `Authorization` headers to be explicitly omitted"' ) def copy( self, *, - private_api_key: str | None = None, + private_key: str | None = None, password: str | None = None, webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, @@ -215,7 +215,7 @@ def copy( http_client = http_client or self._client client = self.__class__( - private_api_key=private_api_key or self.private_api_key, + private_key=private_key or self.private_key, password=password or self.password, webhook_secret=webhook_secret or self.webhook_secret, base_url=base_url or self.base_url, @@ -280,14 +280,14 @@ class AsyncImageKit(AsyncAPIClient): with_streaming_response: AsyncImageKitWithStreamedResponse # client options - private_api_key: str + private_key: str password: str | None webhook_secret: str | None def __init__( self, *, - private_api_key: str | None = None, + private_key: str | None = None, password: str | None = None, webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, @@ -312,17 +312,17 @@ def __init__( """Construct a new async AsyncImageKit client instance. This automatically infers the following arguments from their corresponding environment variables if they are not provided: - - `private_api_key` from `IMAGEKIT_PRIVATE_API_KEY` + - `private_key` from `IMAGEKIT_PRIVATE_API_KEY` - `password` from `OPTIONAL_IMAGEKIT_IGNORES_THIS` - `webhook_secret` from `IMAGEKIT_WEBHOOK_SECRET` """ - if private_api_key is None: - private_api_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") - if private_api_key is None: + if private_key is None: + private_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") + if private_key is None: raise ImageKitError( - "The private_api_key client option must be set either by passing private_api_key to the client or by setting the IMAGEKIT_PRIVATE_API_KEY environment variable" + "The private_key client option must be set either by passing private_key to the client or by setting the IMAGEKIT_PRIVATE_API_KEY environment variable" ) - self.private_api_key = private_api_key + self.private_key = private_key if password is None: password = os.environ.get("OPTIONAL_IMAGEKIT_IGNORES_THIS") or "do_not_set" @@ -370,7 +370,7 @@ def qs(self) -> Querystring: def auth_headers(self) -> dict[str, str]: if self.password is None: return {} - credentials = f"{self.private_api_key}:{self.password}".encode("ascii") + credentials = f"{self.private_key}:{self.password}".encode("ascii") header = f"Basic {base64.b64encode(credentials).decode('ascii')}" return {"Authorization": header} @@ -385,19 +385,19 @@ def default_headers(self) -> dict[str, str | Omit]: @override def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None: - if self.private_api_key and self.password and headers.get("Authorization"): + if self.private_key and self.password and headers.get("Authorization"): return if isinstance(custom_headers.get("Authorization"), Omit): return raise TypeError( - '"Could not resolve authentication method. Expected the private_api_key or password to be set. Or for the `Authorization` headers to be explicitly omitted"' + '"Could not resolve authentication method. Expected the private_key or password to be set. Or for the `Authorization` headers to be explicitly omitted"' ) def copy( self, *, - private_api_key: str | None = None, + private_key: str | None = None, password: str | None = None, webhook_secret: str | None = None, base_url: str | httpx.URL | None = None, @@ -433,7 +433,7 @@ def copy( http_client = http_client or self._client client = self.__class__( - private_api_key=private_api_key or self.private_api_key, + private_key=private_key or self.private_key, password=password or self.password, webhook_secret=webhook_secret or self.webhook_secret, base_url=base_url or self.base_url, diff --git a/tests/conftest.py b/tests/conftest.py index 347776e..4471f83 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -45,7 +45,7 @@ def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -private_api_key = "My Private API Key" +private_key = "My Private Key" password = "My Password" @@ -56,7 +56,7 @@ def client(request: FixtureRequest) -> Iterator[ImageKit]: raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") with ImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=strict + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=strict ) as client: yield client @@ -83,7 +83,7 @@ async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncImageKit]: async with AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=strict, http_client=http_client, diff --git a/tests/test_client.py b/tests/test_client.py index 265d599..62a5ea2 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -37,7 +37,7 @@ from .utils import update_env base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -private_api_key = "My Private API Key" +private_key = "My Private Key" password = "My Password" @@ -60,9 +60,7 @@ def _get_open_connections(client: ImageKit | AsyncImageKit) -> int: class TestImageKit: - client = ImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True - ) + client = ImageKit(base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True) @pytest.mark.respx(base_url=base_url) def test_raw_response(self, respx_mock: MockRouter) -> None: @@ -88,9 +86,9 @@ def test_copy(self) -> None: copied = self.client.copy() assert id(copied) != id(self.client) - copied = self.client.copy(private_api_key="another My Private API Key") - assert copied.private_api_key == "another My Private API Key" - assert self.client.private_api_key == "My Private API Key" + copied = self.client.copy(private_key="another My Private Key") + assert copied.private_key == "another My Private Key" + assert self.client.private_key == "My Private Key" copied = self.client.copy(password="another My Password") assert copied.password == "another My Password" @@ -115,7 +113,7 @@ def test_copy_default_options(self) -> None: def test_copy_default_headers(self) -> None: client = ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, default_headers={"X-Foo": "bar"}, @@ -153,7 +151,7 @@ def test_copy_default_headers(self) -> None: def test_copy_default_query(self) -> None: client = ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, default_query={"foo": "bar"}, @@ -283,7 +281,7 @@ def test_request_timeout(self) -> None: def test_client_timeout_option(self) -> None: client = ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, timeout=httpx.Timeout(0), @@ -298,7 +296,7 @@ def test_http_client_timeout_option(self) -> None: with httpx.Client(timeout=None) as http_client: client = ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=http_client, @@ -312,7 +310,7 @@ def test_http_client_timeout_option(self) -> None: with httpx.Client() as http_client: client = ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=http_client, @@ -326,7 +324,7 @@ def test_http_client_timeout_option(self) -> None: with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=http_client, @@ -341,7 +339,7 @@ async def test_invalid_http_client(self) -> None: async with httpx.AsyncClient() as http_client: ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=cast(Any, http_client), @@ -350,7 +348,7 @@ async def test_invalid_http_client(self) -> None: def test_default_headers_option(self) -> None: client = ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, default_headers={"X-Foo": "bar"}, @@ -361,7 +359,7 @@ def test_default_headers_option(self) -> None: client2 = ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, default_headers={ @@ -375,7 +373,7 @@ def test_default_headers_option(self) -> None: def test_validate_headers(self) -> None: client = ImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) assert "Basic" in request.headers.get("Authorization") @@ -387,15 +385,13 @@ def test_validate_headers(self) -> None: "OPTIONAL_IMAGEKIT_IGNORES_THIS": Omit(), } ): - client2 = ImageKit( - base_url=base_url, private_api_key=None, password=None, _strict_response_validation=True - ) + client2 = ImageKit(base_url=base_url, private_key=None, password=None, _strict_response_validation=True) _ = client2 def test_default_query_option(self) -> None: client = ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, default_query={"query_param": "bar"}, @@ -600,7 +596,7 @@ class Model(BaseModel): def test_base_url_setter(self) -> None: client = ImageKit( base_url="https://example.com/from_init", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, ) @@ -612,7 +608,7 @@ def test_base_url_setter(self) -> None: def test_base_url_env(self) -> None: with update_env(IMAGE_KIT_BASE_URL="http://localhost:5000/from/env"): - client = ImageKit(private_api_key=private_api_key, password=password, _strict_response_validation=True) + client = ImageKit(private_key=private_key, password=password, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" @pytest.mark.parametrize( @@ -620,13 +616,13 @@ def test_base_url_env(self) -> None: [ ImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, ), ImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=httpx.Client(), @@ -649,13 +645,13 @@ def test_base_url_trailing_slash(self, client: ImageKit) -> None: [ ImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, ), ImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=httpx.Client(), @@ -678,13 +674,13 @@ def test_base_url_no_trailing_slash(self, client: ImageKit) -> None: [ ImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, ), ImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=httpx.Client(), @@ -704,7 +700,7 @@ def test_absolute_request_url(self, client: ImageKit) -> None: def test_copied_client_does_not_close_http(self) -> None: client = ImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) assert not client.is_closed() @@ -717,7 +713,7 @@ def test_copied_client_does_not_close_http(self) -> None: def test_client_context_manager(self) -> None: client = ImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) with client as c2: assert c2 is client @@ -741,7 +737,7 @@ def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): ImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, max_retries=cast(Any, None), @@ -755,14 +751,14 @@ class Model(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) strict_client = ImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) with pytest.raises(APIResponseValidationError): strict_client.get("/foo", cast_to=Model) client = ImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=False + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=False ) response = client.get("/foo", cast_to=Model) @@ -792,7 +788,7 @@ class Model(BaseModel): @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: client = ImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) headers = httpx.Headers({"retry-after": retry_after}) @@ -952,7 +948,7 @@ def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: class TestAsyncImageKit: client = AsyncImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) @pytest.mark.respx(base_url=base_url) @@ -981,9 +977,9 @@ def test_copy(self) -> None: copied = self.client.copy() assert id(copied) != id(self.client) - copied = self.client.copy(private_api_key="another My Private API Key") - assert copied.private_api_key == "another My Private API Key" - assert self.client.private_api_key == "My Private API Key" + copied = self.client.copy(private_key="another My Private Key") + assert copied.private_key == "another My Private Key" + assert self.client.private_key == "My Private Key" copied = self.client.copy(password="another My Password") assert copied.password == "another My Password" @@ -1008,7 +1004,7 @@ def test_copy_default_options(self) -> None: def test_copy_default_headers(self) -> None: client = AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, default_headers={"X-Foo": "bar"}, @@ -1046,7 +1042,7 @@ def test_copy_default_headers(self) -> None: def test_copy_default_query(self) -> None: client = AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, default_query={"foo": "bar"}, @@ -1176,7 +1172,7 @@ async def test_request_timeout(self) -> None: async def test_client_timeout_option(self) -> None: client = AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, timeout=httpx.Timeout(0), @@ -1191,7 +1187,7 @@ async def test_http_client_timeout_option(self) -> None: async with httpx.AsyncClient(timeout=None) as http_client: client = AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=http_client, @@ -1205,7 +1201,7 @@ async def test_http_client_timeout_option(self) -> None: async with httpx.AsyncClient() as http_client: client = AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=http_client, @@ -1219,7 +1215,7 @@ async def test_http_client_timeout_option(self) -> None: async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=http_client, @@ -1234,7 +1230,7 @@ def test_invalid_http_client(self) -> None: with httpx.Client() as http_client: AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=cast(Any, http_client), @@ -1243,7 +1239,7 @@ def test_invalid_http_client(self) -> None: def test_default_headers_option(self) -> None: client = AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, default_headers={"X-Foo": "bar"}, @@ -1254,7 +1250,7 @@ def test_default_headers_option(self) -> None: client2 = AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, default_headers={ @@ -1268,7 +1264,7 @@ def test_default_headers_option(self) -> None: def test_validate_headers(self) -> None: client = AsyncImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) assert "Basic" in request.headers.get("Authorization") @@ -1281,14 +1277,14 @@ def test_validate_headers(self) -> None: } ): client2 = AsyncImageKit( - base_url=base_url, private_api_key=None, password=None, _strict_response_validation=True + base_url=base_url, private_key=None, password=None, _strict_response_validation=True ) _ = client2 def test_default_query_option(self) -> None: client = AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, default_query={"query_param": "bar"}, @@ -1493,7 +1489,7 @@ class Model(BaseModel): def test_base_url_setter(self) -> None: client = AsyncImageKit( base_url="https://example.com/from_init", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, ) @@ -1505,7 +1501,7 @@ def test_base_url_setter(self) -> None: def test_base_url_env(self) -> None: with update_env(IMAGE_KIT_BASE_URL="http://localhost:5000/from/env"): - client = AsyncImageKit(private_api_key=private_api_key, password=password, _strict_response_validation=True) + client = AsyncImageKit(private_key=private_key, password=password, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" @pytest.mark.parametrize( @@ -1513,13 +1509,13 @@ def test_base_url_env(self) -> None: [ AsyncImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, ), AsyncImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=httpx.AsyncClient(), @@ -1542,13 +1538,13 @@ def test_base_url_trailing_slash(self, client: AsyncImageKit) -> None: [ AsyncImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, ), AsyncImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=httpx.AsyncClient(), @@ -1571,13 +1567,13 @@ def test_base_url_no_trailing_slash(self, client: AsyncImageKit) -> None: [ AsyncImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, ), AsyncImageKit( base_url="http://localhost:5000/custom/path/", - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, http_client=httpx.AsyncClient(), @@ -1597,7 +1593,7 @@ def test_absolute_request_url(self, client: AsyncImageKit) -> None: async def test_copied_client_does_not_close_http(self) -> None: client = AsyncImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) assert not client.is_closed() @@ -1611,7 +1607,7 @@ async def test_copied_client_does_not_close_http(self) -> None: async def test_client_context_manager(self) -> None: client = AsyncImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) async with client as c2: assert c2 is client @@ -1636,7 +1632,7 @@ async def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): AsyncImageKit( base_url=base_url, - private_api_key=private_api_key, + private_key=private_key, password=password, _strict_response_validation=True, max_retries=cast(Any, None), @@ -1651,14 +1647,14 @@ class Model(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) strict_client = AsyncImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) with pytest.raises(APIResponseValidationError): await strict_client.get("/foo", cast_to=Model) client = AsyncImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=False + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=False ) response = await client.get("/foo", cast_to=Model) @@ -1689,7 +1685,7 @@ class Model(BaseModel): @pytest.mark.asyncio async def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: client = AsyncImageKit( - base_url=base_url, private_api_key=private_api_key, password=password, _strict_response_validation=True + base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) headers = httpx.Headers({"retry-after": retry_after}) From 15ed7b7186d21b33a1523302bf819bd14cf5baea Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:45:28 +0000 Subject: [PATCH 121/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 00fd95d..d3fcabb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d1a3e6dfc45ae832b6b14a0aef25878985c679fa9f48c1470df188b1578ba648.yml openapi_spec_hash: 1d382866fce3284f26d341f112988d9d -config_hash: 29a2351fe2be89392b15719be8bc964f +config_hash: c9c7bed2a4341f915a2dc85958ce7f0e From 5083c8a7c7367dda867738d56ec218a682e2ae87 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:51:57 +0000 Subject: [PATCH 122/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index d3fcabb..ee45f3d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d1a3e6dfc45ae832b6b14a0aef25878985c679fa9f48c1470df188b1578ba648.yml openapi_spec_hash: 1d382866fce3284f26d341f112988d9d -config_hash: c9c7bed2a4341f915a2dc85958ce7f0e +config_hash: 51a9632be24fc533ad69a5bd56934651 From a7246e3bd73296247db8d868a376aeb1e6f82da6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 02:24:59 +0000 Subject: [PATCH 123/177] chore: do not install brew dependencies in ./scripts/bootstrap by default --- scripts/bootstrap | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index e84fe62..b430fee 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,10 +4,18 @@ set -e cd "$(dirname "$0")/.." -if ! command -v rye >/dev/null 2>&1 && [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { - echo "==> Installing Homebrew dependencies…" - brew bundle + echo -n "==> Install Homebrew dependencies? (y/N): " + read -r response + case "$response" in + [yY][eE][sS]|[yY]) + brew bundle + ;; + *) + ;; + esac + echo } fi From 30f0bb0d8541c93b72325decc418ccee52090442 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 08:05:10 +0000 Subject: [PATCH 124/177] feat(api): Update env var name --- .stats.yml | 2 +- README.md | 10 +++------- src/imagekit/_client.py | 12 ++++++------ tests/test_client.py | 4 ++-- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/.stats.yml b/.stats.yml index ee45f3d..0f9a4aa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d1a3e6dfc45ae832b6b14a0aef25878985c679fa9f48c1470df188b1578ba648.yml openapi_spec_hash: 1d382866fce3284f26d341f112988d9d -config_hash: 51a9632be24fc533ad69a5bd56934651 +config_hash: f1fafe5e607e996b58b67fd1dd3e74fa diff --git a/README.md b/README.md index 5a17eae..8644359 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,7 @@ import os from imagekit import ImageKit client = ImageKit( - private_key=os.environ.get( - "IMAGEKIT_PRIVATE_API_KEY" - ), # This is the default and can be omitted + private_key=os.environ.get("IMAGEKIT_PRIVATE_KEY"), # This is the default and can be omitted password=os.environ.get( "OPTIONAL_IMAGEKIT_IGNORES_THIS" ), # This is the default and can be omitted @@ -49,7 +47,7 @@ print(response.video_codec) While you can provide a `private_key` keyword argument, we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/) -to add `IMAGEKIT_PRIVATE_API_KEY="My Private Key"` to your `.env` file +to add `IMAGEKIT_PRIVATE_KEY="My Private Key"` to your `.env` file so that your Private Key is not stored in source control. ## Async usage @@ -62,9 +60,7 @@ import asyncio from imagekit import AsyncImageKit client = AsyncImageKit( - private_key=os.environ.get( - "IMAGEKIT_PRIVATE_API_KEY" - ), # This is the default and can be omitted + private_key=os.environ.get("IMAGEKIT_PRIVATE_KEY"), # This is the default and can be omitted password=os.environ.get( "OPTIONAL_IMAGEKIT_IGNORES_THIS" ), # This is the default and can be omitted diff --git a/src/imagekit/_client.py b/src/imagekit/_client.py index 38357d7..85e1ff5 100644 --- a/src/imagekit/_client.py +++ b/src/imagekit/_client.py @@ -94,15 +94,15 @@ def __init__( """Construct a new synchronous ImageKit client instance. This automatically infers the following arguments from their corresponding environment variables if they are not provided: - - `private_key` from `IMAGEKIT_PRIVATE_API_KEY` + - `private_key` from `IMAGEKIT_PRIVATE_KEY` - `password` from `OPTIONAL_IMAGEKIT_IGNORES_THIS` - `webhook_secret` from `IMAGEKIT_WEBHOOK_SECRET` """ if private_key is None: - private_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") + private_key = os.environ.get("IMAGEKIT_PRIVATE_KEY") if private_key is None: raise ImageKitError( - "The private_key client option must be set either by passing private_key to the client or by setting the IMAGEKIT_PRIVATE_API_KEY environment variable" + "The private_key client option must be set either by passing private_key to the client or by setting the IMAGEKIT_PRIVATE_KEY environment variable" ) self.private_key = private_key @@ -312,15 +312,15 @@ def __init__( """Construct a new async AsyncImageKit client instance. This automatically infers the following arguments from their corresponding environment variables if they are not provided: - - `private_key` from `IMAGEKIT_PRIVATE_API_KEY` + - `private_key` from `IMAGEKIT_PRIVATE_KEY` - `password` from `OPTIONAL_IMAGEKIT_IGNORES_THIS` - `webhook_secret` from `IMAGEKIT_WEBHOOK_SECRET` """ if private_key is None: - private_key = os.environ.get("IMAGEKIT_PRIVATE_API_KEY") + private_key = os.environ.get("IMAGEKIT_PRIVATE_KEY") if private_key is None: raise ImageKitError( - "The private_key client option must be set either by passing private_key to the client or by setting the IMAGEKIT_PRIVATE_API_KEY environment variable" + "The private_key client option must be set either by passing private_key to the client or by setting the IMAGEKIT_PRIVATE_KEY environment variable" ) self.private_key = private_key diff --git a/tests/test_client.py b/tests/test_client.py index 62a5ea2..ab2dfce 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -381,7 +381,7 @@ def test_validate_headers(self) -> None: with pytest.raises(ImageKitError): with update_env( **{ - "IMAGEKIT_PRIVATE_API_KEY": Omit(), + "IMAGEKIT_PRIVATE_KEY": Omit(), "OPTIONAL_IMAGEKIT_IGNORES_THIS": Omit(), } ): @@ -1272,7 +1272,7 @@ def test_validate_headers(self) -> None: with pytest.raises(ImageKitError): with update_env( **{ - "IMAGEKIT_PRIVATE_API_KEY": Omit(), + "IMAGEKIT_PRIVATE_KEY": Omit(), "OPTIONAL_IMAGEKIT_IGNORES_THIS": Omit(), } ): From 02d042d3adf421c32a9a4250290e881c2230db34 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 09:23:47 +0000 Subject: [PATCH 125/177] feat(api): update api docs link --- .stats.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0f9a4aa..7dfc3c2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d1a3e6dfc45ae832b6b14a0aef25878985c679fa9f48c1470df188b1578ba648.yml openapi_spec_hash: 1d382866fce3284f26d341f112988d9d -config_hash: f1fafe5e607e996b58b67fd1dd3e74fa +config_hash: 5f7498f5ea66e8a544c6c37b10f77467 diff --git a/README.md b/README.md index 8644359..20c6fe2 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It is generated with [Stainless](https://www.stainless.com/). ## Documentation -The REST API documentation can be found on [imagekit.io](https://imagekit.io/docs). The full API of this library can be found in [api.md](api.md). +The REST API documentation can be found on [imagekit.io](https://imagekit.io/docs/api-reference). The full API of this library can be found in [api.md](api.md). ## Installation From 423804a47a2f7ece36cd0de6b704608363bf3684 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 09:25:08 +0000 Subject: [PATCH 126/177] feat(api): remove Stainless attribution from readme --- .stats.yml | 2 +- README.md | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7dfc3c2..e1604c7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d1a3e6dfc45ae832b6b14a0aef25878985c679fa9f48c1470df188b1578ba648.yml openapi_spec_hash: 1d382866fce3284f26d341f112988d9d -config_hash: 5f7498f5ea66e8a544c6c37b10f77467 +config_hash: ff23f46fe08ef3f43c57c8cf13eff3a1 diff --git a/README.md b/README.md index 20c6fe2..ea4a60a 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,6 @@ The Image Kit Python library provides convenient access to the Image Kit REST AP application. The library includes type definitions for all request params and response fields, and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx). -It is generated with [Stainless](https://www.stainless.com/). - ## Documentation The REST API documentation can be found on [imagekit.io](https://imagekit.io/docs/api-reference). The full API of this library can be found in [api.md](api.md). From 236b580fc85a8d0cb8da5f4bb045a14a5239838b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 21 Sep 2025 03:10:05 +0000 Subject: [PATCH 127/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index e1604c7..031fed9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d1a3e6dfc45ae832b6b14a0aef25878985c679fa9f48c1470df188b1578ba648.yml openapi_spec_hash: 1d382866fce3284f26d341f112988d9d -config_hash: ff23f46fe08ef3f43c57c8cf13eff3a1 +config_hash: d57f3c7c581048428b41398f30da8b9b From dbd7b7816ea51081d0c966f647491d24adb1dbf9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 12:33:56 +0000 Subject: [PATCH 128/177] feat(api): manual updates --- .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 | 14 ++-- bin/check-release-environment | 21 ------ pyproject.toml | 6 +- release-please-config.json | 66 ------------------- src/imagekit/_files.py | 2 +- src/imagekit/_version.py | 2 +- src/imagekit/resources/accounts/accounts.py | 8 +-- src/imagekit/resources/accounts/origins.py | 8 +-- .../resources/accounts/url_endpoints.py | 8 +-- src/imagekit/resources/accounts/usage.py | 8 +-- src/imagekit/resources/assets.py | 8 +-- src/imagekit/resources/beta/beta.py | 8 +-- src/imagekit/resources/beta/v2/files.py | 8 +-- src/imagekit/resources/beta/v2/v2.py | 8 +-- src/imagekit/resources/cache/cache.py | 8 +-- src/imagekit/resources/cache/invalidation.py | 8 +-- .../resources/custom_metadata_fields.py | 8 +-- src/imagekit/resources/files/bulk.py | 8 +-- src/imagekit/resources/files/files.py | 8 +-- src/imagekit/resources/files/metadata.py | 8 +-- src/imagekit/resources/files/versions.py | 8 +-- src/imagekit/resources/folders/folders.py | 8 +-- src/imagekit/resources/folders/job.py | 8 +-- 28 files changed, 83 insertions(+), 225 deletions(-) delete mode 100644 .github/workflows/publish-pypi.yml delete mode 100644 .github/workflows/release-doctor.yml delete mode 100644 .release-please-manifest.json delete mode 100644 bin/check-release-environment delete mode 100644 release-please-config.json diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml deleted file mode 100644 index 08adafc..0000000 --- a/.github/workflows/publish-pypi.yml +++ /dev/null @@ -1,31 +0,0 @@ -# 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/imagekit-developer/imagekit-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.44.0' - RYE_INSTALL_OPTION: '--yes' - - - name: Publish to PyPI - run: | - bash ./bin/publish-pypi - env: - PYPI_TOKEN: ${{ secrets.IMAGE_KIT_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml deleted file mode 100644 index c36a89d..0000000 --- a/.github/workflows/release-doctor.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Release Doctor -on: - pull_request: - branches: - - master - workflow_dispatch: - -jobs: - release_doctor: - name: release doctor - runs-on: ubuntu-latest - if: github.repository == 'imagekit-developer/imagekit-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.IMAGE_KIT_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json deleted file mode 100644 index 1332969..0000000 --- a/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "0.0.1" -} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 031fed9..7c3aae1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d1a3e6dfc45ae832b6b14a0aef25878985c679fa9f48c1470df188b1578ba648.yml openapi_spec_hash: 1d382866fce3284f26d341f112988d9d -config_hash: d57f3c7c581048428b41398f30da8b9b +config_hash: e42d7fc3a8c92c35099cc283f9a4467a diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf4695d..a133f19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,7 +62,7 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git +$ pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git ``` Alternatively, you can build from source and install the wheel file: @@ -120,7 +120,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/imagekit-developer/imagekit-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/stainless-sdks/imagekit-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 ea4a60a..32ac1bd 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ The REST API documentation can be found on [imagekit.io](https://imagekit.io/doc ## Installation ```sh -# install from the production repo -pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git +# install from this staging repo +pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git ``` > [!NOTE] @@ -85,8 +85,8 @@ By default, the async client uses `httpx` for HTTP requests. However, for improv You can enable this by installing `aiohttp`: ```sh -# install from the production repo -pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git' +# install from this staging repo +pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/stainless-sdks/imagekit-python.git' ``` Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: @@ -311,9 +311,9 @@ file = response.parse() # get the object that `files.upload()` would have retur print(file.video_codec) ``` -These methods return an [`APIResponse`](https://github.com/imagekit-developer/imagekit-python/tree/master/src/imagekit/_response.py) object. +These methods return an [`APIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekit/_response.py) object. -The async client returns an [`AsyncAPIResponse`](https://github.com/imagekit-developer/imagekit-python/tree/master/src/imagekit/_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/stainless-sdks/imagekit-python/tree/main/src/imagekit/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. #### `.with_streaming_response` @@ -420,7 +420,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/imagekit-developer/imagekit-python/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/imagekit-python/issues) with questions, bugs, or suggestions. ### Determining the installed version diff --git a/bin/check-release-environment b/bin/check-release-environment deleted file mode 100644 index b845b0f..0000000 --- a/bin/check-release-environment +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -errors=() - -if [ -z "${PYPI_TOKEN}" ]; then - errors+=("The 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 ebdb5e8..3e0e194 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,8 +35,8 @@ classifiers = [ ] [project.urls] -Homepage = "https://github.com/imagekit-developer/imagekit-python" -Repository = "https://github.com/imagekit-developer/imagekit-python" +Homepage = "https://github.com/stainless-sdks/imagekit-python" +Repository = "https://github.com/stainless-sdks/imagekit-python" [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] @@ -125,7 +125,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/imagekit-developer/imagekit-python/tree/master/\g<2>)' +replacement = '[\1](https://github.com/stainless-sdks/imagekit-python/tree/main/\g<2>)' [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/release-please-config.json b/release-please-config.json deleted file mode 100644 index 48e2b41..0000000 --- a/release-please-config.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "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/imagekit/_version.py" - ] -} \ No newline at end of file diff --git a/src/imagekit/_files.py b/src/imagekit/_files.py index 331bc44..3cf7941 100644 --- a/src/imagekit/_files.py +++ b/src/imagekit/_files.py @@ -34,7 +34,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None: if not is_file_content(obj): prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" raise RuntimeError( - f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/imagekit-developer/imagekit-python/tree/master#file-uploads" + f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/stainless-sdks/imagekit-python/tree/main#file-uploads" ) from None diff --git a/src/imagekit/_version.py b/src/imagekit/_version.py index e521ae3..3eb6f6a 100644 --- a/src/imagekit/_version.py +++ b/src/imagekit/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "imagekit" -__version__ = "0.0.1" # x-release-please-version +__version__ = "0.0.1" diff --git a/src/imagekit/resources/accounts/accounts.py b/src/imagekit/resources/accounts/accounts.py index 461e8cf..dba376c 100644 --- a/src/imagekit/resources/accounts/accounts.py +++ b/src/imagekit/resources/accounts/accounts.py @@ -51,7 +51,7 @@ def with_raw_response(self) -> AccountsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AccountsResourceWithRawResponse(self) @@ -60,7 +60,7 @@ def with_streaming_response(self) -> AccountsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AccountsResourceWithStreamingResponse(self) @@ -84,7 +84,7 @@ def with_raw_response(self) -> AsyncAccountsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncAccountsResourceWithRawResponse(self) @@ -93,7 +93,7 @@ def with_streaming_response(self) -> AsyncAccountsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncAccountsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekit/resources/accounts/origins.py index 27dc7af..15354aa 100644 --- a/src/imagekit/resources/accounts/origins.py +++ b/src/imagekit/resources/accounts/origins.py @@ -32,7 +32,7 @@ def with_raw_response(self) -> OriginsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return OriginsResourceWithRawResponse(self) @@ -41,7 +41,7 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return OriginsResourceWithStreamingResponse(self) @@ -1094,7 +1094,7 @@ def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncOriginsResourceWithRawResponse(self) @@ -1103,7 +1103,7 @@ def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncOriginsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/url_endpoints.py b/src/imagekit/resources/accounts/url_endpoints.py index ab8d422..b5d9f36 100644 --- a/src/imagekit/resources/accounts/url_endpoints.py +++ b/src/imagekit/resources/accounts/url_endpoints.py @@ -29,7 +29,7 @@ def with_raw_response(self) -> URLEndpointsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return URLEndpointsResourceWithRawResponse(self) @@ -38,7 +38,7 @@ def with_streaming_response(self) -> URLEndpointsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return URLEndpointsResourceWithStreamingResponse(self) @@ -273,7 +273,7 @@ def with_raw_response(self) -> AsyncURLEndpointsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncURLEndpointsResourceWithRawResponse(self) @@ -282,7 +282,7 @@ def with_streaming_response(self) -> AsyncURLEndpointsResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncURLEndpointsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/accounts/usage.py b/src/imagekit/resources/accounts/usage.py index b35d3c9..c044c9b 100644 --- a/src/imagekit/resources/accounts/usage.py +++ b/src/imagekit/resources/accounts/usage.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> UsageResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return UsageResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> UsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return UsageResourceWithStreamingResponse(self) @@ -104,7 +104,7 @@ def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncUsageResourceWithRawResponse(self) @@ -113,7 +113,7 @@ def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncUsageResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/assets.py b/src/imagekit/resources/assets.py index 1d239da..18828fb 100644 --- a/src/imagekit/resources/assets.py +++ b/src/imagekit/resources/assets.py @@ -30,7 +30,7 @@ def with_raw_response(self) -> AssetsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AssetsResourceWithRawResponse(self) @@ -39,7 +39,7 @@ def with_streaming_response(self) -> AssetsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AssetsResourceWithStreamingResponse(self) @@ -163,7 +163,7 @@ def with_raw_response(self) -> AsyncAssetsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncAssetsResourceWithRawResponse(self) @@ -172,7 +172,7 @@ def with_streaming_response(self) -> AsyncAssetsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncAssetsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/beta.py b/src/imagekit/resources/beta/beta.py index 01e43aa..e37c117 100644 --- a/src/imagekit/resources/beta/beta.py +++ b/src/imagekit/resources/beta/beta.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> BetaResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return BetaResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> BetaResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return BetaResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncBetaResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncBetaResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncBetaResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncBetaResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index 4d64161..5318cea 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -42,7 +42,7 @@ def with_raw_response(self) -> FilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @@ -51,7 +51,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) @@ -294,7 +294,7 @@ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @@ -303,7 +303,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/beta/v2/v2.py b/src/imagekit/resources/beta/v2/v2.py index 2fb9830..f552e26 100644 --- a/src/imagekit/resources/beta/v2/v2.py +++ b/src/imagekit/resources/beta/v2/v2.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> V2ResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return V2ResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> V2ResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return V2ResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncV2ResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncV2ResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncV2ResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncV2ResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/cache/cache.py b/src/imagekit/resources/cache/cache.py index 936b39f..47016b0 100644 --- a/src/imagekit/resources/cache/cache.py +++ b/src/imagekit/resources/cache/cache.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> CacheResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return CacheResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> CacheResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return CacheResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncCacheResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncCacheResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncCacheResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncCacheResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/cache/invalidation.py b/src/imagekit/resources/cache/invalidation.py index 9c95dc8..f1f6c72 100644 --- a/src/imagekit/resources/cache/invalidation.py +++ b/src/imagekit/resources/cache/invalidation.py @@ -29,7 +29,7 @@ def with_raw_response(self) -> InvalidationResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return InvalidationResourceWithRawResponse(self) @@ -38,7 +38,7 @@ def with_streaming_response(self) -> InvalidationResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return InvalidationResourceWithStreamingResponse(self) @@ -120,7 +120,7 @@ def with_raw_response(self) -> AsyncInvalidationResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncInvalidationResourceWithRawResponse(self) @@ -129,7 +129,7 @@ def with_streaming_response(self) -> AsyncInvalidationResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncInvalidationResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py index 1668c53..55551e4 100644 --- a/src/imagekit/resources/custom_metadata_fields.py +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -34,7 +34,7 @@ def with_raw_response(self) -> CustomMetadataFieldsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return CustomMetadataFieldsResourceWithRawResponse(self) @@ -43,7 +43,7 @@ def with_streaming_response(self) -> CustomMetadataFieldsResourceWithStreamingRe """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return CustomMetadataFieldsResourceWithStreamingResponse(self) @@ -238,7 +238,7 @@ def with_raw_response(self) -> AsyncCustomMetadataFieldsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncCustomMetadataFieldsResourceWithRawResponse(self) @@ -247,7 +247,7 @@ def with_streaming_response(self) -> AsyncCustomMetadataFieldsResourceWithStream """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncCustomMetadataFieldsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/bulk.py b/src/imagekit/resources/files/bulk.py index 43c02cb..cd525b8 100644 --- a/src/imagekit/resources/files/bulk.py +++ b/src/imagekit/resources/files/bulk.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> BulkResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return BulkResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> BulkResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return BulkResourceWithStreamingResponse(self) @@ -227,7 +227,7 @@ def with_raw_response(self) -> AsyncBulkResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncBulkResourceWithRawResponse(self) @@ -236,7 +236,7 @@ def with_streaming_response(self) -> AsyncBulkResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncBulkResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index d8c224c..f6491f5 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -90,7 +90,7 @@ def with_raw_response(self) -> FilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @@ -99,7 +99,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) @@ -761,7 +761,7 @@ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @@ -770,7 +770,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/metadata.py b/src/imagekit/resources/files/metadata.py index d9e0541..1648e6e 100644 --- a/src/imagekit/resources/files/metadata.py +++ b/src/imagekit/resources/files/metadata.py @@ -28,7 +28,7 @@ def with_raw_response(self) -> MetadataResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return MetadataResourceWithRawResponse(self) @@ -37,7 +37,7 @@ def with_streaming_response(self) -> MetadataResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return MetadataResourceWithStreamingResponse(self) @@ -125,7 +125,7 @@ def with_raw_response(self) -> AsyncMetadataResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncMetadataResourceWithRawResponse(self) @@ -134,7 +134,7 @@ def with_streaming_response(self) -> AsyncMetadataResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncMetadataResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/files/versions.py b/src/imagekit/resources/files/versions.py index e6479e1..b2df5cb 100644 --- a/src/imagekit/resources/files/versions.py +++ b/src/imagekit/resources/files/versions.py @@ -28,7 +28,7 @@ def with_raw_response(self) -> VersionsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return VersionsResourceWithRawResponse(self) @@ -37,7 +37,7 @@ def with_streaming_response(self) -> VersionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return VersionsResourceWithStreamingResponse(self) @@ -194,7 +194,7 @@ def with_raw_response(self) -> AsyncVersionsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncVersionsResourceWithRawResponse(self) @@ -203,7 +203,7 @@ def with_streaming_response(self) -> AsyncVersionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncVersionsResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekit/resources/folders/folders.py index d986fd7..a5fdf81 100644 --- a/src/imagekit/resources/folders/folders.py +++ b/src/imagekit/resources/folders/folders.py @@ -50,7 +50,7 @@ def with_raw_response(self) -> FoldersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return FoldersResourceWithRawResponse(self) @@ -59,7 +59,7 @@ def with_streaming_response(self) -> FoldersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return FoldersResourceWithStreamingResponse(self) @@ -337,7 +337,7 @@ def with_raw_response(self) -> AsyncFoldersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFoldersResourceWithRawResponse(self) @@ -346,7 +346,7 @@ def with_streaming_response(self) -> AsyncFoldersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncFoldersResourceWithStreamingResponse(self) diff --git a/src/imagekit/resources/folders/job.py b/src/imagekit/resources/folders/job.py index 5ccbd3b..f731d08 100644 --- a/src/imagekit/resources/folders/job.py +++ b/src/imagekit/resources/folders/job.py @@ -26,7 +26,7 @@ def with_raw_response(self) -> JobResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return JobResourceWithRawResponse(self) @@ -35,7 +35,7 @@ def with_streaming_response(self) -> JobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return JobResourceWithStreamingResponse(self) @@ -80,7 +80,7 @@ def with_raw_response(self) -> AsyncJobResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncJobResourceWithRawResponse(self) @@ -89,7 +89,7 @@ def with_streaming_response(self) -> AsyncJobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response """ return AsyncJobResourceWithStreamingResponse(self) From c8bb60bcad3674a58bb939c0f48f26e0e2976fc8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 07:21:40 +0000 Subject: [PATCH 129/177] feat(api): add path policy related non-breaking changes --- .stats.yml | 4 +-- src/imagekit/resources/beta/v2/files.py | 2 ++ .../resources/custom_metadata_fields.py | 32 +++++++++++++++++-- src/imagekit/resources/files/files.py | 2 ++ .../types/beta/v2/file_upload_params.py | 1 + .../custom_metadata_field_list_params.py | 8 +++++ src/imagekit/types/file_upload_params.py | 1 + .../test_custom_metadata_fields.py | 2 ++ 8 files changed, 48 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7c3aae1..da19a2b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-d1a3e6dfc45ae832b6b14a0aef25878985c679fa9f48c1470df188b1578ba648.yml -openapi_spec_hash: 1d382866fce3284f26d341f112988d9d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-1499148ce5fc81b4d8c8b3eaadf7adfaf54df5fa0b3a0452c3f5ef0dfe884a95.yml +openapi_spec_hash: e91526b143d3e696bef2b4d0ea3aa2b4 config_hash: e42d7fc3a8c92c35099cc283f9a4467a diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index 5318cea..7ed6a96 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -82,6 +82,7 @@ def upload( "isPublished", "customMetadata", "metadata", + "selectedFieldsSchema", ] ] | Omit = omit, @@ -334,6 +335,7 @@ async def upload( "isPublished", "customMetadata", "metadata", + "selectedFieldsSchema", ] ] | Omit = omit, diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py index 55551e4..4c33ec4 100644 --- a/src/imagekit/resources/custom_metadata_fields.py +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -155,6 +155,7 @@ def update( def list( self, *, + folder_path: str | Omit = omit, include_deleted: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -169,7 +170,17 @@ def list( the API returns only non deleted field objects, but you can include deleted fields in the API response. + You can also filter results by a specific folder path to retrieve custom + metadata fields applicable at that location. This path-specific filtering is + useful when using the **Path policy** feature to determine which custom metadata + fields are selected for a given path. + Args: + folder_path: The folder path (e.g., `/path/to/folder`) for which to retrieve applicable + custom metadata fields. + Useful for determining path-specific field selections when the + [Path policy](https://imagekit.io/docs/dam/path-policy) feature is in use. + include_deleted: Set it to `true` to include deleted field objects in the API response. extra_headers: Send extra headers @@ -188,7 +199,10 @@ def list( extra_body=extra_body, timeout=timeout, query=maybe_transform( - {"include_deleted": include_deleted}, + { + "folder_path": folder_path, + "include_deleted": include_deleted, + }, custom_metadata_field_list_params.CustomMetadataFieldListParams, ), ), @@ -359,6 +373,7 @@ async def update( async def list( self, *, + folder_path: str | Omit = omit, include_deleted: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -373,7 +388,17 @@ async def list( the API returns only non deleted field objects, but you can include deleted fields in the API response. + You can also filter results by a specific folder path to retrieve custom + metadata fields applicable at that location. This path-specific filtering is + useful when using the **Path policy** feature to determine which custom metadata + fields are selected for a given path. + Args: + folder_path: The folder path (e.g., `/path/to/folder`) for which to retrieve applicable + custom metadata fields. + Useful for determining path-specific field selections when the + [Path policy](https://imagekit.io/docs/dam/path-policy) feature is in use. + include_deleted: Set it to `true` to include deleted field objects in the API response. extra_headers: Send extra headers @@ -392,7 +417,10 @@ async def list( extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( - {"include_deleted": include_deleted}, + { + "folder_path": folder_path, + "include_deleted": include_deleted, + }, custom_metadata_field_list_params.CustomMetadataFieldListParams, ), ), diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index f6491f5..a7168fa 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -512,6 +512,7 @@ def upload( "isPublished", "customMetadata", "metadata", + "selectedFieldsSchema", ] ] | Omit = omit, @@ -1183,6 +1184,7 @@ async def upload( "isPublished", "customMetadata", "metadata", + "selectedFieldsSchema", ] ] | Omit = omit, diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekit/types/beta/v2/file_upload_params.py index 53679b8..b4efce6 100644 --- a/src/imagekit/types/beta/v2/file_upload_params.py +++ b/src/imagekit/types/beta/v2/file_upload_params.py @@ -147,6 +147,7 @@ class FileUploadParams(TypedDict, total=False): "isPublished", "customMetadata", "metadata", + "selectedFieldsSchema", ] ], PropertyInfo(alias="responseFields"), diff --git a/src/imagekit/types/custom_metadata_field_list_params.py b/src/imagekit/types/custom_metadata_field_list_params.py index 41eb2bd..af950be 100644 --- a/src/imagekit/types/custom_metadata_field_list_params.py +++ b/src/imagekit/types/custom_metadata_field_list_params.py @@ -10,5 +10,13 @@ class CustomMetadataFieldListParams(TypedDict, total=False): + folder_path: Annotated[str, PropertyInfo(alias="folderPath")] + """ + The folder path (e.g., `/path/to/folder`) for which to retrieve applicable + custom metadata fields. + Useful for determining path-specific field selections when the + [Path policy](https://imagekit.io/docs/dam/path-policy) feature is in use. + """ + include_deleted: Annotated[bool, PropertyInfo(alias="includeDeleted")] """Set it to `true` to include deleted field objects in the API response.""" diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 13faef4..1c14594 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -169,6 +169,7 @@ class FileUploadParams(TypedDict, total=False): "isPublished", "customMetadata", "metadata", + "selectedFieldsSchema", ] ], PropertyInfo(alias="responseFields"), diff --git a/tests/api_resources/test_custom_metadata_fields.py b/tests/api_resources/test_custom_metadata_fields.py index a2e3318..53941eb 100644 --- a/tests/api_resources/test_custom_metadata_fields.py +++ b/tests/api_resources/test_custom_metadata_fields.py @@ -150,6 +150,7 @@ def test_method_list(self, client: ImageKit) -> None: @parametrize def test_method_list_with_all_params(self, client: ImageKit) -> None: custom_metadata_field = client.custom_metadata_fields.list( + folder_path="folderPath", include_deleted=True, ) assert_matches_type(CustomMetadataFieldListResponse, custom_metadata_field, path=["response"]) @@ -353,6 +354,7 @@ async def test_method_list(self, async_client: AsyncImageKit) -> None: @parametrize async def test_method_list_with_all_params(self, async_client: AsyncImageKit) -> None: custom_metadata_field = await async_client.custom_metadata_fields.list( + folder_path="folderPath", include_deleted=True, ) assert_matches_type(CustomMetadataFieldListResponse, custom_metadata_field, path=["response"]) From 0334e7d6e4ea8490ee3e7af44c75ebeaef59d3fd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 07:24:46 +0000 Subject: [PATCH 130/177] feat(api): updated docs --- .stats.yml | 4 ++-- src/imagekit/resources/custom_metadata_fields.py | 12 ++++++------ .../types/custom_metadata_field_list_params.py | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.stats.yml b/.stats.yml index da19a2b..6b1c558 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-1499148ce5fc81b4d8c8b3eaadf7adfaf54df5fa0b3a0452c3f5ef0dfe884a95.yml -openapi_spec_hash: e91526b143d3e696bef2b4d0ea3aa2b4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-8d944c932f09191791cc09e90ebf8142e523c0a6dd82ae9d1dbd7ff884acfc4b.yml +openapi_spec_hash: 179e38a7a472a5f98d17aed41099cbfd config_hash: e42d7fc3a8c92c35099cc283f9a4467a diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekit/resources/custom_metadata_fields.py index 4c33ec4..0c56e03 100644 --- a/src/imagekit/resources/custom_metadata_fields.py +++ b/src/imagekit/resources/custom_metadata_fields.py @@ -177,9 +177,9 @@ def list( Args: folder_path: The folder path (e.g., `/path/to/folder`) for which to retrieve applicable - custom metadata fields. - Useful for determining path-specific field selections when the - [Path policy](https://imagekit.io/docs/dam/path-policy) feature is in use. + custom metadata fields. Useful for determining path-specific field selections + when the [Path policy](https://imagekit.io/docs/dam/path-policy) feature is in + use. include_deleted: Set it to `true` to include deleted field objects in the API response. @@ -395,9 +395,9 @@ async def list( Args: folder_path: The folder path (e.g., `/path/to/folder`) for which to retrieve applicable - custom metadata fields. - Useful for determining path-specific field selections when the - [Path policy](https://imagekit.io/docs/dam/path-policy) feature is in use. + custom metadata fields. Useful for determining path-specific field selections + when the [Path policy](https://imagekit.io/docs/dam/path-policy) feature is in + use. include_deleted: Set it to `true` to include deleted field objects in the API response. diff --git a/src/imagekit/types/custom_metadata_field_list_params.py b/src/imagekit/types/custom_metadata_field_list_params.py index af950be..a84f93e 100644 --- a/src/imagekit/types/custom_metadata_field_list_params.py +++ b/src/imagekit/types/custom_metadata_field_list_params.py @@ -13,9 +13,9 @@ class CustomMetadataFieldListParams(TypedDict, total=False): folder_path: Annotated[str, PropertyInfo(alias="folderPath")] """ The folder path (e.g., `/path/to/folder`) for which to retrieve applicable - custom metadata fields. - Useful for determining path-specific field selections when the - [Path policy](https://imagekit.io/docs/dam/path-policy) feature is in use. + custom metadata fields. Useful for determining path-specific field selections + when the [Path policy](https://imagekit.io/docs/dam/path-policy) feature is in + use. """ include_deleted: Annotated[bool, PropertyInfo(alias="includeDeleted")] From fb7da9f21ed7f4de30279878b73d1740efb75758 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 07:29:10 +0000 Subject: [PATCH 131/177] feat(api): add selectedFieldsSchema in upload and list API response --- .stats.yml | 4 +- src/imagekit/resources/beta/v2/files.py | 20 ++++++ src/imagekit/resources/files/files.py | 20 ++++++ .../types/beta/v2/file_upload_params.py | 66 +++++++++++++++++ src/imagekit/types/file.py | 71 ++++++++++++++++++- src/imagekit/types/file_upload_params.py | 66 +++++++++++++++++ tests/api_resources/beta/v2/test_files.py | 28 ++++++++ tests/api_resources/test_files.py | 28 ++++++++ 8 files changed, 299 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6b1c558..bceb847 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-8d944c932f09191791cc09e90ebf8142e523c0a6dd82ae9d1dbd7ff884acfc4b.yml -openapi_spec_hash: 179e38a7a472a5f98d17aed41099cbfd +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-7a42233daaf82345cc6d92cc49d4885126176b014c05ea0618c035869319fe53.yml +openapi_spec_hash: c41b1b6062b7c2ea548b16e0462aa358 config_hash: e42d7fc3a8c92c35099cc283f9a4467a diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index 7ed6a96..2d9dd19 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -86,6 +86,7 @@ def upload( ] ] | Omit = omit, + selected_fields_schema: Dict[str, file_upload_params.SelectedFieldsSchema] | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, transformation: file_upload_params.Transformation | Omit = omit, use_unique_file_name: bool | Omit = omit, @@ -208,6 +209,14 @@ def upload( response_fields: Array of response field keys to include in the API response body. + selected_fields_schema: This field is included in the response only if the Path policy feature is + available in the plan. It contains schema definitions for the custom metadata + fields selected for the specified file path. Field selection can only be done + when the Path policy feature is enabled. + + Keys are the names of the custom metadata fields; the value object has details + about the custom metadata schema. + tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not exceed 500, and the `%` character is not allowed. If this field is not specified @@ -264,6 +273,7 @@ def upload( "overwrite_file": overwrite_file, "overwrite_tags": overwrite_tags, "response_fields": response_fields, + "selected_fields_schema": selected_fields_schema, "tags": tags, "transformation": transformation, "use_unique_file_name": use_unique_file_name, @@ -339,6 +349,7 @@ async def upload( ] ] | Omit = omit, + selected_fields_schema: Dict[str, file_upload_params.SelectedFieldsSchema] | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, transformation: file_upload_params.Transformation | Omit = omit, use_unique_file_name: bool | Omit = omit, @@ -461,6 +472,14 @@ async def upload( response_fields: Array of response field keys to include in the API response body. + selected_fields_schema: This field is included in the response only if the Path policy feature is + available in the plan. It contains schema definitions for the custom metadata + fields selected for the specified file path. Field selection can only be done + when the Path policy feature is enabled. + + Keys are the names of the custom metadata fields; the value object has details + about the custom metadata schema. + tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not exceed 500, and the `%` character is not allowed. If this field is not specified @@ -517,6 +536,7 @@ async def upload( "overwrite_file": overwrite_file, "overwrite_tags": overwrite_tags, "response_fields": response_fields, + "selected_fields_schema": selected_fields_schema, "tags": tags, "transformation": transformation, "use_unique_file_name": use_unique_file_name, diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index a7168fa..1329966 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -516,6 +516,7 @@ def upload( ] ] | Omit = omit, + selected_fields_schema: Dict[str, file_upload_params.SelectedFieldsSchema] | Omit = omit, signature: str | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, transformation: file_upload_params.Transformation | Omit = omit, @@ -653,6 +654,14 @@ def upload( response_fields: Array of response field keys to include in the API response body. + selected_fields_schema: This field is included in the response only if the Path policy feature is + available in the plan. It contains schema definitions for the custom metadata + fields selected for the specified file path. Field selection can only be done + when the Path policy feature is enabled. + + Keys are the names of the custom metadata fields; the value object has details + about the custom metadata schema. + signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a key. Learn how to create a signature on the page below. This should be in lowercase. @@ -718,6 +727,7 @@ def upload( "overwrite_tags": overwrite_tags, "public_key": public_key, "response_fields": response_fields, + "selected_fields_schema": selected_fields_schema, "signature": signature, "tags": tags, "transformation": transformation, @@ -1188,6 +1198,7 @@ async def upload( ] ] | Omit = omit, + selected_fields_schema: Dict[str, file_upload_params.SelectedFieldsSchema] | Omit = omit, signature: str | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, transformation: file_upload_params.Transformation | Omit = omit, @@ -1325,6 +1336,14 @@ async def upload( response_fields: Array of response field keys to include in the API response body. + selected_fields_schema: This field is included in the response only if the Path policy feature is + available in the plan. It contains schema definitions for the custom metadata + fields selected for the specified file path. Field selection can only be done + when the Path policy feature is enabled. + + Keys are the names of the custom metadata fields; the value object has details + about the custom metadata schema. + signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a key. Learn how to create a signature on the page below. This should be in lowercase. @@ -1390,6 +1409,7 @@ async def upload( "overwrite_tags": overwrite_tags, "public_key": public_key, "response_fields": response_fields, + "selected_fields_schema": selected_fields_schema, "signature": signature, "tags": tags, "transformation": transformation, diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekit/types/beta/v2/file_upload_params.py index b4efce6..2826cb8 100644 --- a/src/imagekit/types/beta/v2/file_upload_params.py +++ b/src/imagekit/types/beta/v2/file_upload_params.py @@ -11,6 +11,7 @@ __all__ = [ "FileUploadParams", + "SelectedFieldsSchema", "Transformation", "TransformationPost", "TransformationPostTransformation", @@ -154,6 +155,17 @@ class FileUploadParams(TypedDict, total=False): ] """Array of response field keys to include in the API response body.""" + selected_fields_schema: Annotated[Dict[str, SelectedFieldsSchema], PropertyInfo(alias="selectedFieldsSchema")] + """ + This field is included in the response only if the Path policy feature is + available in the plan. It contains schema definitions for the custom metadata + fields selected for the specified file path. Field selection can only be done + when the Path policy feature is enabled. + + Keys are the names of the custom metadata fields; the value object has details + about the custom metadata schema. + """ + tags: SequenceNotStr[str] """Set the tags while uploading the file. Provide an array of tag strings (e.g. @@ -195,6 +207,60 @@ class FileUploadParams(TypedDict, total=False): """ +class SelectedFieldsSchema(TypedDict, total=False): + type: Required[Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"]] + """Type of the custom metadata field.""" + + default_value: Annotated[ + Union[str, float, bool, SequenceNotStr[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") + ] + """The default value for this custom metadata field. + + The value should match the `type` of custom metadata field. + """ + + is_value_required: Annotated[bool, PropertyInfo(alias="isValueRequired")] + """Specifies if the custom metadata field is required or not.""" + + max_length: Annotated[float, PropertyInfo(alias="maxLength")] + """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + max_value: Annotated[Union[str, float], PropertyInfo(alias="maxValue")] + """Maximum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + min_length: Annotated[float, PropertyInfo(alias="minLength")] + """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + min_value: Annotated[Union[str, float], PropertyInfo(alias="minValue")] + """Minimum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + read_only: Annotated[bool, PropertyInfo(alias="readOnly")] + """Indicates whether the custom metadata field is read only. + + A read only field cannot be modified after being set. This field is configurable + only via the **Path policy** feature. + """ + + select_options: Annotated[SequenceNotStr[Union[str, float, bool]], PropertyInfo(alias="selectOptions")] + """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" + + select_options_truncated: Annotated[bool, PropertyInfo(alias="selectOptionsTruncated")] + """Specifies if the selectOptions array is truncated. + + It is truncated when number of options are > 100. + """ + + class TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" diff --git a/src/imagekit/types/file.py b/src/imagekit/types/file.py index 69b0b39..1cb247a 100644 --- a/src/imagekit/types/file.py +++ b/src/imagekit/types/file.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional +from typing import Dict, List, Union, Optional from datetime import datetime from typing_extensions import Literal @@ -8,7 +8,7 @@ from .._models import BaseModel -__all__ = ["File", "AITag", "VersionInfo"] +__all__ = ["File", "AITag", "SelectedFieldsSchema", "VersionInfo"] class AITag(BaseModel): @@ -25,6 +25,60 @@ class AITag(BaseModel): """ +class SelectedFieldsSchema(BaseModel): + type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] + """Type of the custom metadata field.""" + + default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( + alias="defaultValue", default=None + ) + """The default value for this custom metadata field. + + The value should match the `type` of custom metadata field. + """ + + is_value_required: Optional[bool] = FieldInfo(alias="isValueRequired", default=None) + """Specifies if the custom metadata field is required or not.""" + + max_length: Optional[float] = FieldInfo(alias="maxLength", default=None) + """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + max_value: Union[str, float, None] = FieldInfo(alias="maxValue", default=None) + """Maximum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + min_length: Optional[float] = FieldInfo(alias="minLength", default=None) + """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + min_value: Union[str, float, None] = FieldInfo(alias="minValue", default=None) + """Minimum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + read_only: Optional[bool] = FieldInfo(alias="readOnly", default=None) + """Indicates whether the custom metadata field is read only. + + A read only field cannot be modified after being set. This field is configurable + only via the **Path policy** feature. + """ + + select_options: Optional[List[Union[str, float, bool]]] = FieldInfo(alias="selectOptions", default=None) + """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" + + select_options_truncated: Optional[bool] = FieldInfo(alias="selectOptionsTruncated", default=None) + """Specifies if the selectOptions array is truncated. + + It is truncated when number of options are > 100. + """ + + class VersionInfo(BaseModel): id: Optional[str] = None """Unique identifier of the file version.""" @@ -87,6 +141,19 @@ class File(BaseModel): name: Optional[str] = None """Name of the asset.""" + selected_fields_schema: Optional[Dict[str, SelectedFieldsSchema]] = FieldInfo( + alias="selectedFieldsSchema", default=None + ) + """ + This field is included in the response only if the Path policy feature is + available in the plan. It contains schema definitions for the custom metadata + fields selected for the specified file path. Field selection can only be done + when the Path policy feature is enabled. + + Keys are the names of the custom metadata fields; the value object has details + about the custom metadata schema. + """ + size: Optional[float] = None """Size of the file in bytes.""" diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index 1c14594..c25bb9e 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -11,6 +11,7 @@ __all__ = [ "FileUploadParams", + "SelectedFieldsSchema", "Transformation", "TransformationPost", "TransformationPostTransformation", @@ -176,6 +177,17 @@ class FileUploadParams(TypedDict, total=False): ] """Array of response field keys to include in the API response body.""" + selected_fields_schema: Annotated[Dict[str, SelectedFieldsSchema], PropertyInfo(alias="selectedFieldsSchema")] + """ + This field is included in the response only if the Path policy feature is + available in the plan. It contains schema definitions for the custom metadata + fields selected for the specified file path. Field selection can only be done + when the Path policy feature is enabled. + + Keys are the names of the custom metadata fields; the value object has details + about the custom metadata schema. + """ + signature: str """ HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a @@ -227,6 +239,60 @@ class FileUploadParams(TypedDict, total=False): """ +class SelectedFieldsSchema(TypedDict, total=False): + type: Required[Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"]] + """Type of the custom metadata field.""" + + default_value: Annotated[ + Union[str, float, bool, SequenceNotStr[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") + ] + """The default value for this custom metadata field. + + The value should match the `type` of custom metadata field. + """ + + is_value_required: Annotated[bool, PropertyInfo(alias="isValueRequired")] + """Specifies if the custom metadata field is required or not.""" + + max_length: Annotated[float, PropertyInfo(alias="maxLength")] + """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + max_value: Annotated[Union[str, float], PropertyInfo(alias="maxValue")] + """Maximum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + min_length: Annotated[float, PropertyInfo(alias="minLength")] + """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + min_value: Annotated[Union[str, float], PropertyInfo(alias="minValue")] + """Minimum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + read_only: Annotated[bool, PropertyInfo(alias="readOnly")] + """Indicates whether the custom metadata field is read only. + + A read only field cannot be modified after being set. This field is configurable + only via the **Path policy** feature. + """ + + select_options: Annotated[SequenceNotStr[Union[str, float, bool]], PropertyInfo(alias="selectOptions")] + """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" + + select_options_truncated: Annotated[bool, PropertyInfo(alias="selectOptionsTruncated")] + """Specifies if the selectOptions array is truncated. + + It is truncated when number of options are > 100. + """ + + class TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" diff --git a/tests/api_resources/beta/v2/test_files.py b/tests/api_resources/beta/v2/test_files.py index e5757ff..ac0cea6 100644 --- a/tests/api_resources/beta/v2/test_files.py +++ b/tests/api_resources/beta/v2/test_files.py @@ -65,6 +65,20 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: overwrite_file=True, overwrite_tags=True, response_fields=["tags", "customCoordinates", "isPrivateFile"], + selected_fields_schema={ + "foo": { + "type": "Text", + "default_value": "string", + "is_value_required": True, + "max_length": 0, + "max_value": "string", + "min_length": 0, + "min_value": "string", + "read_only": True, + "select_options": ["small", "medium", "large", 30, 40, True], + "select_options_truncated": True, + } + }, tags=["t-shirt", "round-neck", "men"], transformation={ "post": [ @@ -167,6 +181,20 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) overwrite_file=True, overwrite_tags=True, response_fields=["tags", "customCoordinates", "isPrivateFile"], + selected_fields_schema={ + "foo": { + "type": "Text", + "default_value": "string", + "is_value_required": True, + "max_length": 0, + "max_value": "string", + "min_length": 0, + "min_value": "string", + "read_only": True, + "select_options": ["small", "medium", "large", 30, 40, True], + "select_options_truncated": True, + } + }, tags=["t-shirt", "round-neck", "men"], transformation={ "post": [ diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 5a9594f..384d38d 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -416,6 +416,20 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: overwrite_tags=True, public_key="publicKey", response_fields=["tags", "customCoordinates", "isPrivateFile"], + selected_fields_schema={ + "foo": { + "type": "Text", + "default_value": "string", + "is_value_required": True, + "max_length": 0, + "max_value": "string", + "min_length": 0, + "min_value": "string", + "read_only": True, + "select_options": ["small", "medium", "large", 30, 40, True], + "select_options_truncated": True, + } + }, signature="signature", tags=["t-shirt", "round-neck", "men"], transformation={ @@ -863,6 +877,20 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) overwrite_tags=True, public_key="publicKey", response_fields=["tags", "customCoordinates", "isPrivateFile"], + selected_fields_schema={ + "foo": { + "type": "Text", + "default_value": "string", + "is_value_required": True, + "max_length": 0, + "max_value": "string", + "min_length": 0, + "min_value": "string", + "read_only": True, + "select_options": ["small", "medium", "large", 30, 40, True], + "select_options_truncated": True, + } + }, signature="signature", tags=["t-shirt", "round-neck", "men"], transformation={ From 4e21e7b8053f2da3122170e1761016935d5a8885 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 07:38:48 +0000 Subject: [PATCH 132/177] docs: correct typo in default value description for custom metadata field --- .stats.yml | 4 ++-- src/imagekit/types/custom_metadata_field.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index bceb847..56e1384 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-7a42233daaf82345cc6d92cc49d4885126176b014c05ea0618c035869319fe53.yml -openapi_spec_hash: c41b1b6062b7c2ea548b16e0462aa358 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-aa4c8e857ae03b12dabf168c83c62f759e2706d69fa4eb77d11519d45a5dada2.yml +openapi_spec_hash: 6ea00242c4685fb6422328f0dd53f9b1 config_hash: e42d7fc3a8c92c35099cc283f9a4467a diff --git a/src/imagekit/types/custom_metadata_field.py b/src/imagekit/types/custom_metadata_field.py index 4c425f7..1d8a866 100644 --- a/src/imagekit/types/custom_metadata_field.py +++ b/src/imagekit/types/custom_metadata_field.py @@ -19,7 +19,7 @@ class Schema(BaseModel): ) """The default value for this custom metadata field. - Date type of default value depends on the field type. + Data type of default value depends on the field type. """ is_value_required: Optional[bool] = FieldInfo(alias="isValueRequired", default=None) From ed7a83f21169c19998696cf9357b79426bedd90b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 07:49:06 +0000 Subject: [PATCH 133/177] feat(api): fix upload API request params --- .stats.yml | 4 +- src/imagekit/resources/beta/v2/files.py | 20 ------ src/imagekit/resources/files/files.py | 20 ------ .../types/beta/v2/file_upload_params.py | 66 ----------------- .../types/beta/v2/file_upload_response.py | 71 ++++++++++++++++++- src/imagekit/types/file_upload_params.py | 66 ----------------- src/imagekit/types/file_upload_response.py | 71 ++++++++++++++++++- .../upload_pre_transform_success_event.py | 70 +++++++++++++++++- tests/api_resources/beta/v2/test_files.py | 28 -------- tests/api_resources/test_files.py | 28 -------- 10 files changed, 209 insertions(+), 235 deletions(-) diff --git a/.stats.yml b/.stats.yml index 56e1384..0c9c486 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-aa4c8e857ae03b12dabf168c83c62f759e2706d69fa4eb77d11519d45a5dada2.yml -openapi_spec_hash: 6ea00242c4685fb6422328f0dd53f9b1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-01aef94bd928f40b7209dc21df71e2312d4bee430119b30ee05d75cf5e1b4801.yml +openapi_spec_hash: 054c332db88b23d362f72583dd24b2aa config_hash: e42d7fc3a8c92c35099cc283f9a4467a diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekit/resources/beta/v2/files.py index 2d9dd19..7ed6a96 100644 --- a/src/imagekit/resources/beta/v2/files.py +++ b/src/imagekit/resources/beta/v2/files.py @@ -86,7 +86,6 @@ def upload( ] ] | Omit = omit, - selected_fields_schema: Dict[str, file_upload_params.SelectedFieldsSchema] | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, transformation: file_upload_params.Transformation | Omit = omit, use_unique_file_name: bool | Omit = omit, @@ -209,14 +208,6 @@ def upload( response_fields: Array of response field keys to include in the API response body. - selected_fields_schema: This field is included in the response only if the Path policy feature is - available in the plan. It contains schema definitions for the custom metadata - fields selected for the specified file path. Field selection can only be done - when the Path policy feature is enabled. - - Keys are the names of the custom metadata fields; the value object has details - about the custom metadata schema. - tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not exceed 500, and the `%` character is not allowed. If this field is not specified @@ -273,7 +264,6 @@ def upload( "overwrite_file": overwrite_file, "overwrite_tags": overwrite_tags, "response_fields": response_fields, - "selected_fields_schema": selected_fields_schema, "tags": tags, "transformation": transformation, "use_unique_file_name": use_unique_file_name, @@ -349,7 +339,6 @@ async def upload( ] ] | Omit = omit, - selected_fields_schema: Dict[str, file_upload_params.SelectedFieldsSchema] | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, transformation: file_upload_params.Transformation | Omit = omit, use_unique_file_name: bool | Omit = omit, @@ -472,14 +461,6 @@ async def upload( response_fields: Array of response field keys to include in the API response body. - selected_fields_schema: This field is included in the response only if the Path policy feature is - available in the plan. It contains schema definitions for the custom metadata - fields selected for the specified file path. Field selection can only be done - when the Path policy feature is enabled. - - Keys are the names of the custom metadata fields; the value object has details - about the custom metadata schema. - tags: Set the tags while uploading the file. Provide an array of tag strings (e.g. `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not exceed 500, and the `%` character is not allowed. If this field is not specified @@ -536,7 +517,6 @@ async def upload( "overwrite_file": overwrite_file, "overwrite_tags": overwrite_tags, "response_fields": response_fields, - "selected_fields_schema": selected_fields_schema, "tags": tags, "transformation": transformation, "use_unique_file_name": use_unique_file_name, diff --git a/src/imagekit/resources/files/files.py b/src/imagekit/resources/files/files.py index 1329966..a7168fa 100644 --- a/src/imagekit/resources/files/files.py +++ b/src/imagekit/resources/files/files.py @@ -516,7 +516,6 @@ def upload( ] ] | Omit = omit, - selected_fields_schema: Dict[str, file_upload_params.SelectedFieldsSchema] | Omit = omit, signature: str | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, transformation: file_upload_params.Transformation | Omit = omit, @@ -654,14 +653,6 @@ def upload( response_fields: Array of response field keys to include in the API response body. - selected_fields_schema: This field is included in the response only if the Path policy feature is - available in the plan. It contains schema definitions for the custom metadata - fields selected for the specified file path. Field selection can only be done - when the Path policy feature is enabled. - - Keys are the names of the custom metadata fields; the value object has details - about the custom metadata schema. - signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a key. Learn how to create a signature on the page below. This should be in lowercase. @@ -727,7 +718,6 @@ def upload( "overwrite_tags": overwrite_tags, "public_key": public_key, "response_fields": response_fields, - "selected_fields_schema": selected_fields_schema, "signature": signature, "tags": tags, "transformation": transformation, @@ -1198,7 +1188,6 @@ async def upload( ] ] | Omit = omit, - selected_fields_schema: Dict[str, file_upload_params.SelectedFieldsSchema] | Omit = omit, signature: str | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, transformation: file_upload_params.Transformation | Omit = omit, @@ -1336,14 +1325,6 @@ async def upload( response_fields: Array of response field keys to include in the API response body. - selected_fields_schema: This field is included in the response only if the Path policy feature is - available in the plan. It contains schema definitions for the custom metadata - fields selected for the specified file path. Field selection can only be done - when the Path policy feature is enabled. - - Keys are the names of the custom metadata fields; the value object has details - about the custom metadata schema. - signature: HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a key. Learn how to create a signature on the page below. This should be in lowercase. @@ -1409,7 +1390,6 @@ async def upload( "overwrite_tags": overwrite_tags, "public_key": public_key, "response_fields": response_fields, - "selected_fields_schema": selected_fields_schema, "signature": signature, "tags": tags, "transformation": transformation, diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekit/types/beta/v2/file_upload_params.py index 2826cb8..b4efce6 100644 --- a/src/imagekit/types/beta/v2/file_upload_params.py +++ b/src/imagekit/types/beta/v2/file_upload_params.py @@ -11,7 +11,6 @@ __all__ = [ "FileUploadParams", - "SelectedFieldsSchema", "Transformation", "TransformationPost", "TransformationPostTransformation", @@ -155,17 +154,6 @@ class FileUploadParams(TypedDict, total=False): ] """Array of response field keys to include in the API response body.""" - selected_fields_schema: Annotated[Dict[str, SelectedFieldsSchema], PropertyInfo(alias="selectedFieldsSchema")] - """ - This field is included in the response only if the Path policy feature is - available in the plan. It contains schema definitions for the custom metadata - fields selected for the specified file path. Field selection can only be done - when the Path policy feature is enabled. - - Keys are the names of the custom metadata fields; the value object has details - about the custom metadata schema. - """ - tags: SequenceNotStr[str] """Set the tags while uploading the file. Provide an array of tag strings (e.g. @@ -207,60 +195,6 @@ class FileUploadParams(TypedDict, total=False): """ -class SelectedFieldsSchema(TypedDict, total=False): - type: Required[Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"]] - """Type of the custom metadata field.""" - - default_value: Annotated[ - Union[str, float, bool, SequenceNotStr[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") - ] - """The default value for this custom metadata field. - - The value should match the `type` of custom metadata field. - """ - - is_value_required: Annotated[bool, PropertyInfo(alias="isValueRequired")] - """Specifies if the custom metadata field is required or not.""" - - max_length: Annotated[float, PropertyInfo(alias="maxLength")] - """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" - - max_value: Annotated[Union[str, float], PropertyInfo(alias="maxValue")] - """Maximum value of the field. - - Only set if field type is `Date` or `Number`. For `Date` type field, the value - will be in ISO8601 string format. For `Number` type field, it will be a numeric - value. - """ - - min_length: Annotated[float, PropertyInfo(alias="minLength")] - """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" - - min_value: Annotated[Union[str, float], PropertyInfo(alias="minValue")] - """Minimum value of the field. - - Only set if field type is `Date` or `Number`. For `Date` type field, the value - will be in ISO8601 string format. For `Number` type field, it will be a numeric - value. - """ - - read_only: Annotated[bool, PropertyInfo(alias="readOnly")] - """Indicates whether the custom metadata field is read only. - - A read only field cannot be modified after being set. This field is configurable - only via the **Path policy** feature. - """ - - select_options: Annotated[SequenceNotStr[Union[str, float, bool]], PropertyInfo(alias="selectOptions")] - """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" - - select_options_truncated: Annotated[bool, PropertyInfo(alias="selectOptionsTruncated")] - """Specifies if the selectOptions array is truncated. - - It is truncated when number of options are > 100. - """ - - class TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" diff --git a/src/imagekit/types/beta/v2/file_upload_response.py b/src/imagekit/types/beta/v2/file_upload_response.py index 08f6ceb..6e554cb 100644 --- a/src/imagekit/types/beta/v2/file_upload_response.py +++ b/src/imagekit/types/beta/v2/file_upload_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional +from typing import Dict, List, Union, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -8,7 +8,7 @@ from ...._models import BaseModel from ...metadata import Metadata -__all__ = ["FileUploadResponse", "AITag", "ExtensionStatus", "VersionInfo"] +__all__ = ["FileUploadResponse", "AITag", "ExtensionStatus", "SelectedFieldsSchema", "VersionInfo"] class AITag(BaseModel): @@ -42,6 +42,60 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) +class SelectedFieldsSchema(BaseModel): + type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] + """Type of the custom metadata field.""" + + default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( + alias="defaultValue", default=None + ) + """The default value for this custom metadata field. + + The value should match the `type` of custom metadata field. + """ + + is_value_required: Optional[bool] = FieldInfo(alias="isValueRequired", default=None) + """Specifies if the custom metadata field is required or not.""" + + max_length: Optional[float] = FieldInfo(alias="maxLength", default=None) + """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + max_value: Union[str, float, None] = FieldInfo(alias="maxValue", default=None) + """Maximum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + min_length: Optional[float] = FieldInfo(alias="minLength", default=None) + """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + min_value: Union[str, float, None] = FieldInfo(alias="minValue", default=None) + """Minimum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + read_only: Optional[bool] = FieldInfo(alias="readOnly", default=None) + """Indicates whether the custom metadata field is read only. + + A read only field cannot be modified after being set. This field is configurable + only via the **Path policy** feature. + """ + + select_options: Optional[List[Union[str, float, bool]]] = FieldInfo(alias="selectOptions", default=None) + """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" + + select_options_truncated: Optional[bool] = FieldInfo(alias="selectOptionsTruncated", default=None) + """Specifies if the selectOptions array is truncated. + + It is truncated when number of options are > 100. + """ + + class VersionInfo(BaseModel): id: Optional[str] = None """Unique identifier of the file version.""" @@ -150,6 +204,19 @@ class FileUploadResponse(BaseModel): name: Optional[str] = None """Name of the asset.""" + selected_fields_schema: Optional[Dict[str, SelectedFieldsSchema]] = FieldInfo( + alias="selectedFieldsSchema", default=None + ) + """ + This field is included in the response only if the Path policy feature is + available in the plan. It contains schema definitions for the custom metadata + fields selected for the specified file path. Field selection can only be done + when the Path policy feature is enabled. + + Keys are the names of the custom metadata fields; the value object has details + about the custom metadata schema. + """ + size: Optional[float] = None """Size of the image file in Bytes.""" diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekit/types/file_upload_params.py index c25bb9e..1c14594 100644 --- a/src/imagekit/types/file_upload_params.py +++ b/src/imagekit/types/file_upload_params.py @@ -11,7 +11,6 @@ __all__ = [ "FileUploadParams", - "SelectedFieldsSchema", "Transformation", "TransformationPost", "TransformationPostTransformation", @@ -177,17 +176,6 @@ class FileUploadParams(TypedDict, total=False): ] """Array of response field keys to include in the API response body.""" - selected_fields_schema: Annotated[Dict[str, SelectedFieldsSchema], PropertyInfo(alias="selectedFieldsSchema")] - """ - This field is included in the response only if the Path policy feature is - available in the plan. It contains schema definitions for the custom metadata - fields selected for the specified file path. Field selection can only be done - when the Path policy feature is enabled. - - Keys are the names of the custom metadata fields; the value object has details - about the custom metadata schema. - """ - signature: str """ HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a @@ -239,60 +227,6 @@ class FileUploadParams(TypedDict, total=False): """ -class SelectedFieldsSchema(TypedDict, total=False): - type: Required[Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"]] - """Type of the custom metadata field.""" - - default_value: Annotated[ - Union[str, float, bool, SequenceNotStr[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") - ] - """The default value for this custom metadata field. - - The value should match the `type` of custom metadata field. - """ - - is_value_required: Annotated[bool, PropertyInfo(alias="isValueRequired")] - """Specifies if the custom metadata field is required or not.""" - - max_length: Annotated[float, PropertyInfo(alias="maxLength")] - """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" - - max_value: Annotated[Union[str, float], PropertyInfo(alias="maxValue")] - """Maximum value of the field. - - Only set if field type is `Date` or `Number`. For `Date` type field, the value - will be in ISO8601 string format. For `Number` type field, it will be a numeric - value. - """ - - min_length: Annotated[float, PropertyInfo(alias="minLength")] - """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" - - min_value: Annotated[Union[str, float], PropertyInfo(alias="minValue")] - """Minimum value of the field. - - Only set if field type is `Date` or `Number`. For `Date` type field, the value - will be in ISO8601 string format. For `Number` type field, it will be a numeric - value. - """ - - read_only: Annotated[bool, PropertyInfo(alias="readOnly")] - """Indicates whether the custom metadata field is read only. - - A read only field cannot be modified after being set. This field is configurable - only via the **Path policy** feature. - """ - - select_options: Annotated[SequenceNotStr[Union[str, float, bool]], PropertyInfo(alias="selectOptions")] - """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" - - select_options_truncated: Annotated[bool, PropertyInfo(alias="selectOptionsTruncated")] - """Specifies if the selectOptions array is truncated. - - It is truncated when number of options are > 100. - """ - - class TransformationPostTransformation(TypedDict, total=False): type: Required[Literal["transformation"]] """Transformation type.""" diff --git a/src/imagekit/types/file_upload_response.py b/src/imagekit/types/file_upload_response.py index 56a1098..f90c5e2 100644 --- a/src/imagekit/types/file_upload_response.py +++ b/src/imagekit/types/file_upload_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional +from typing import Dict, List, Union, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -8,7 +8,7 @@ from .._models import BaseModel from .metadata import Metadata -__all__ = ["FileUploadResponse", "AITag", "ExtensionStatus", "VersionInfo"] +__all__ = ["FileUploadResponse", "AITag", "ExtensionStatus", "SelectedFieldsSchema", "VersionInfo"] class AITag(BaseModel): @@ -42,6 +42,60 @@ class ExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) +class SelectedFieldsSchema(BaseModel): + type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] + """Type of the custom metadata field.""" + + default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( + alias="defaultValue", default=None + ) + """The default value for this custom metadata field. + + The value should match the `type` of custom metadata field. + """ + + is_value_required: Optional[bool] = FieldInfo(alias="isValueRequired", default=None) + """Specifies if the custom metadata field is required or not.""" + + max_length: Optional[float] = FieldInfo(alias="maxLength", default=None) + """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + max_value: Union[str, float, None] = FieldInfo(alias="maxValue", default=None) + """Maximum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + min_length: Optional[float] = FieldInfo(alias="minLength", default=None) + """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + min_value: Union[str, float, None] = FieldInfo(alias="minValue", default=None) + """Minimum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + read_only: Optional[bool] = FieldInfo(alias="readOnly", default=None) + """Indicates whether the custom metadata field is read only. + + A read only field cannot be modified after being set. This field is configurable + only via the **Path policy** feature. + """ + + select_options: Optional[List[Union[str, float, bool]]] = FieldInfo(alias="selectOptions", default=None) + """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" + + select_options_truncated: Optional[bool] = FieldInfo(alias="selectOptionsTruncated", default=None) + """Specifies if the selectOptions array is truncated. + + It is truncated when number of options are > 100. + """ + + class VersionInfo(BaseModel): id: Optional[str] = None """Unique identifier of the file version.""" @@ -150,6 +204,19 @@ class FileUploadResponse(BaseModel): name: Optional[str] = None """Name of the asset.""" + selected_fields_schema: Optional[Dict[str, SelectedFieldsSchema]] = FieldInfo( + alias="selectedFieldsSchema", default=None + ) + """ + This field is included in the response only if the Path policy feature is + available in the plan. It contains schema definitions for the custom metadata + fields selected for the specified file path. Field selection can only be done + when the Path policy feature is enabled. + + Keys are the names of the custom metadata fields; the value object has details + about the custom metadata schema. + """ + size: Optional[float] = None """Size of the image file in Bytes.""" diff --git a/src/imagekit/types/upload_pre_transform_success_event.py b/src/imagekit/types/upload_pre_transform_success_event.py index e29cd64..41e443c 100644 --- a/src/imagekit/types/upload_pre_transform_success_event.py +++ b/src/imagekit/types/upload_pre_transform_success_event.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional +from typing import Dict, List, Union, Optional from datetime import datetime from typing_extensions import Literal @@ -15,6 +15,7 @@ "UploadPreTransformSuccessEventData", "UploadPreTransformSuccessEventDataAITag", "UploadPreTransformSuccessEventDataExtensionStatus", + "UploadPreTransformSuccessEventDataSelectedFieldsSchema", "UploadPreTransformSuccessEventDataVersionInfo", "UploadPreTransformSuccessEventRequest", ] @@ -51,6 +52,60 @@ class UploadPreTransformSuccessEventDataExtensionStatus(BaseModel): remove_bg: Optional[Literal["success", "pending", "failed"]] = FieldInfo(alias="remove-bg", default=None) +class UploadPreTransformSuccessEventDataSelectedFieldsSchema(BaseModel): + type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] + """Type of the custom metadata field.""" + + default_value: Union[str, float, bool, List[Union[str, float, bool]], None] = FieldInfo( + alias="defaultValue", default=None + ) + """The default value for this custom metadata field. + + The value should match the `type` of custom metadata field. + """ + + is_value_required: Optional[bool] = FieldInfo(alias="isValueRequired", default=None) + """Specifies if the custom metadata field is required or not.""" + + max_length: Optional[float] = FieldInfo(alias="maxLength", default=None) + """Maximum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + max_value: Union[str, float, None] = FieldInfo(alias="maxValue", default=None) + """Maximum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + min_length: Optional[float] = FieldInfo(alias="minLength", default=None) + """Minimum length of string. Only set if `type` is set to `Text` or `Textarea`.""" + + min_value: Union[str, float, None] = FieldInfo(alias="minValue", default=None) + """Minimum value of the field. + + Only set if field type is `Date` or `Number`. For `Date` type field, the value + will be in ISO8601 string format. For `Number` type field, it will be a numeric + value. + """ + + read_only: Optional[bool] = FieldInfo(alias="readOnly", default=None) + """Indicates whether the custom metadata field is read only. + + A read only field cannot be modified after being set. This field is configurable + only via the **Path policy** feature. + """ + + select_options: Optional[List[Union[str, float, bool]]] = FieldInfo(alias="selectOptions", default=None) + """An array of allowed values when field type is `SingleSelect` or `MultiSelect`.""" + + select_options_truncated: Optional[bool] = FieldInfo(alias="selectOptionsTruncated", default=None) + """Specifies if the selectOptions array is truncated. + + It is truncated when number of options are > 100. + """ + + class UploadPreTransformSuccessEventDataVersionInfo(BaseModel): id: Optional[str] = None """Unique identifier of the file version.""" @@ -161,6 +216,19 @@ class UploadPreTransformSuccessEventData(BaseModel): name: Optional[str] = None """Name of the asset.""" + selected_fields_schema: Optional[Dict[str, UploadPreTransformSuccessEventDataSelectedFieldsSchema]] = FieldInfo( + alias="selectedFieldsSchema", default=None + ) + """ + This field is included in the response only if the Path policy feature is + available in the plan. It contains schema definitions for the custom metadata + fields selected for the specified file path. Field selection can only be done + when the Path policy feature is enabled. + + Keys are the names of the custom metadata fields; the value object has details + about the custom metadata schema. + """ + size: Optional[float] = None """Size of the image file in Bytes.""" diff --git a/tests/api_resources/beta/v2/test_files.py b/tests/api_resources/beta/v2/test_files.py index ac0cea6..e5757ff 100644 --- a/tests/api_resources/beta/v2/test_files.py +++ b/tests/api_resources/beta/v2/test_files.py @@ -65,20 +65,6 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: overwrite_file=True, overwrite_tags=True, response_fields=["tags", "customCoordinates", "isPrivateFile"], - selected_fields_schema={ - "foo": { - "type": "Text", - "default_value": "string", - "is_value_required": True, - "max_length": 0, - "max_value": "string", - "min_length": 0, - "min_value": "string", - "read_only": True, - "select_options": ["small", "medium", "large", 30, 40, True], - "select_options_truncated": True, - } - }, tags=["t-shirt", "round-neck", "men"], transformation={ "post": [ @@ -181,20 +167,6 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) overwrite_file=True, overwrite_tags=True, response_fields=["tags", "customCoordinates", "isPrivateFile"], - selected_fields_schema={ - "foo": { - "type": "Text", - "default_value": "string", - "is_value_required": True, - "max_length": 0, - "max_value": "string", - "min_length": 0, - "min_value": "string", - "read_only": True, - "select_options": ["small", "medium", "large", 30, 40, True], - "select_options_truncated": True, - } - }, tags=["t-shirt", "round-neck", "men"], transformation={ "post": [ diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 384d38d..5a9594f 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -416,20 +416,6 @@ def test_method_upload_with_all_params(self, client: ImageKit) -> None: overwrite_tags=True, public_key="publicKey", response_fields=["tags", "customCoordinates", "isPrivateFile"], - selected_fields_schema={ - "foo": { - "type": "Text", - "default_value": "string", - "is_value_required": True, - "max_length": 0, - "max_value": "string", - "min_length": 0, - "min_value": "string", - "read_only": True, - "select_options": ["small", "medium", "large", 30, 40, True], - "select_options_truncated": True, - } - }, signature="signature", tags=["t-shirt", "round-neck", "men"], transformation={ @@ -877,20 +863,6 @@ async def test_method_upload_with_all_params(self, async_client: AsyncImageKit) overwrite_tags=True, public_key="publicKey", response_fields=["tags", "customCoordinates", "isPrivateFile"], - selected_fields_schema={ - "foo": { - "type": "Text", - "default_value": "string", - "is_value_required": True, - "max_length": 0, - "max_value": "string", - "min_length": 0, - "min_value": "string", - "read_only": True, - "select_options": ["small", "medium", "large", 30, 40, True], - "select_options_truncated": True, - } - }, signature="signature", tags=["t-shirt", "round-neck", "men"], transformation={ From 4ea1b710a96c9c2ffccbe2f769aa56958f24b02f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 07:36:18 +0000 Subject: [PATCH 134/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 0c9c486..90e5397 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-01aef94bd928f40b7209dc21df71e2312d4bee430119b30ee05d75cf5e1b4801.yml openapi_spec_hash: 054c332db88b23d362f72583dd24b2aa -config_hash: e42d7fc3a8c92c35099cc283f9a4467a +config_hash: 371b1694848e02828dd8db3265557ddf From c2b3f617a61e575d83baa85d3d57e8ba95ff928c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 07:36:41 +0000 Subject: [PATCH 135/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 90e5397..bb92027 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-01aef94bd928f40b7209dc21df71e2312d4bee430119b30ee05d75cf5e1b4801.yml openapi_spec_hash: 054c332db88b23d362f72583dd24b2aa -config_hash: 371b1694848e02828dd8db3265557ddf +config_hash: 719e92ff078b4a030a1480b546be0b7a From a0a2af61eedd3adce24c331c5b8426696c909bc2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 07:48:10 +0000 Subject: [PATCH 136/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index bb92027..8833731 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-01aef94bd928f40b7209dc21df71e2312d4bee430119b30ee05d75cf5e1b4801.yml openapi_spec_hash: 054c332db88b23d362f72583dd24b2aa -config_hash: 719e92ff078b4a030a1480b546be0b7a +config_hash: cb0b86a64fed7f839bb0ef6568a8ba37 From 51d303b4f389b9349e80407167d93c516f2ac9bf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 07:50:27 +0000 Subject: [PATCH 137/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 8833731..b346bb7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-01aef94bd928f40b7209dc21df71e2312d4bee430119b30ee05d75cf5e1b4801.yml openapi_spec_hash: 054c332db88b23d362f72583dd24b2aa -config_hash: cb0b86a64fed7f839bb0ef6568a8ba37 +config_hash: f351b784e512ad36eafbc0641ad61183 From fea9d407e44a701ad11a5db5d7a81d3a9fcd4714 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 09:21:03 +0000 Subject: [PATCH 138/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index b346bb7..3d1832c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-01aef94bd928f40b7209dc21df71e2312d4bee430119b30ee05d75cf5e1b4801.yml openapi_spec_hash: 054c332db88b23d362f72583dd24b2aa -config_hash: f351b784e512ad36eafbc0641ad61183 +config_hash: 8d97605bd07a42f98d8142059b56522c From f8cbecba6cf812590d421f3d158074335f6c8641 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 10:02:21 +0000 Subject: [PATCH 139/177] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3d1832c..ad4cfbf 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-01aef94bd928f40b7209dc21df71e2312d4bee430119b30ee05d75cf5e1b4801.yml -openapi_spec_hash: 054c332db88b23d362f72583dd24b2aa -config_hash: 8d97605bd07a42f98d8142059b56522c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-c7ad6f552b38f2145781847f8b390fa1ec43068d64e45a33012a97a9299edc10.yml +openapi_spec_hash: 50f281e91210ad5018ac7e4eee216f56 +config_hash: 6d15773e29070b9c1d4820e4897f17a5 From 566b5bfbb9b6b501360026d14aedf86e21cb50f9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 5 Oct 2025 13:50:18 +0000 Subject: [PATCH 140/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index ad4cfbf..f035d34 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-c7ad6f552b38f2145781847f8b390fa1ec43068d64e45a33012a97a9299edc10.yml openapi_spec_hash: 50f281e91210ad5018ac7e4eee216f56 -config_hash: 6d15773e29070b9c1d4820e4897f17a5 +config_hash: 74a8263b80c732a2b016177e7d56bb9c From 60087cf6151eb274c08f36c0c8332f81cf6660fc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Oct 2025 03:46:48 +0000 Subject: [PATCH 141/177] chore(internal): codegen related update --- requirements-dev.lock | 2 +- requirements.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index ec7b01b..5edbb82 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -127,7 +127,7 @@ tomli==2.0.2 # via pytest types-deprecated==1.2.15.20250304 # via standardwebhooks -types-python-dateutil==2.9.0.20250822 +types-python-dateutil==2.9.0.20251008 # via standardwebhooks typing-extensions==4.12.2 # via anyio diff --git a/requirements.lock b/requirements.lock index 52c73ee..3faef40 100644 --- a/requirements.lock +++ b/requirements.lock @@ -74,7 +74,7 @@ standardwebhooks==1.0.0 # via imagekit types-deprecated==1.2.15.20250304 # via standardwebhooks -types-python-dateutil==2.9.0.20250822 +types-python-dateutil==2.9.0.20251008 # via standardwebhooks typing-extensions==4.12.2 # via anyio From 2c759dd5c3b2dbcb88eb0ee22bb5fbe24a666575 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Oct 2025 08:48:41 +0000 Subject: [PATCH 142/177] chore(internal): detect missing future annotations with ruff --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 3e0e194..a08a12d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -225,6 +225,8 @@ select = [ "B", # remove unused imports "F401", + # check for missing future annotations + "FA102", # bare except statements "E722", # unused arguments @@ -247,6 +249,8 @@ unfixable = [ "T203", ] +extend-safe-fixes = ["FA102"] + [tool.ruff.lint.flake8-tidy-imports.banned-api] "functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead" From 25fed7993814b46eafd809ecdac3e6b96d64394f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 10:20:29 +0000 Subject: [PATCH 143/177] chore: bump `httpx-aiohttp` version to 0.1.9 --- pyproject.toml | 2 +- requirements-dev.lock | 2 +- requirements.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a08a12d..c10cd5d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ Homepage = "https://github.com/stainless-sdks/imagekit-python" Repository = "https://github.com/stainless-sdks/imagekit-python" [project.optional-dependencies] -aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] +aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"] webhooks = ["standardwebhooks"] [tool.rye] diff --git a/requirements-dev.lock b/requirements-dev.lock index 5edbb82..5eb54b7 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -60,7 +60,7 @@ httpx==0.28.1 # via imagekit # via respx # via standardwebhooks -httpx-aiohttp==0.1.8 +httpx-aiohttp==0.1.9 # via imagekit idna==3.4 # via anyio diff --git a/requirements.lock b/requirements.lock index 3faef40..78b912e 100644 --- a/requirements.lock +++ b/requirements.lock @@ -47,7 +47,7 @@ httpx==0.28.1 # via httpx-aiohttp # via imagekit # via standardwebhooks -httpx-aiohttp==0.1.8 +httpx-aiohttp==0.1.9 # via imagekit idna==3.4 # via anyio From 8529ed6a746f7c11e38a8a1b5e00887b02f34d49 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 09:46:09 +0000 Subject: [PATCH 144/177] feat(api): add GetImageAttributesOptions and ResponsiveImageAttributes schemas; update resource references in main.yaml; remove dummy endpoint --- .stats.yml | 6 +-- api.md | 2 + src/imagekit/types/__init__.py | 2 + src/imagekit/types/shared/__init__.py | 2 + .../shared/get_image_attributes_options.py | 54 +++++++++++++++++++ .../shared/responsive_image_attributes.py | 29 ++++++++++ 6 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 src/imagekit/types/shared/get_image_attributes_options.py create mode 100644 src/imagekit/types/shared/responsive_image_attributes.py diff --git a/.stats.yml b/.stats.yml index f035d34..27ad9e7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-c7ad6f552b38f2145781847f8b390fa1ec43068d64e45a33012a97a9299edc10.yml -openapi_spec_hash: 50f281e91210ad5018ac7e4eee216f56 -config_hash: 74a8263b80c732a2b016177e7d56bb9c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0e4fa3c1f9d8cafecb9671fa76c0ff9156c643e05837804679e5e336bad8f4c1.yml +openapi_spec_hash: 4544b950730b721c252eb519358b8609 +config_hash: 3d7a0bc2844e9fb4797149b233e85770 diff --git a/api.md b/api.md index f815131..2859068 100644 --- a/api.md +++ b/api.md @@ -4,10 +4,12 @@ from imagekit.types import ( BaseOverlay, Extensions, + GetImageAttributesOptions, ImageOverlay, Overlay, OverlayPosition, OverlayTiming, + ResponsiveImageAttributes, SolidColorOverlay, SolidColorOverlayTransformation, SrcOptions, diff --git a/src/imagekit/types/__init__.py b/src/imagekit/types/__init__.py index c686db1..5d26870 100644 --- a/src/imagekit/types/__init__.py +++ b/src/imagekit/types/__init__.py @@ -21,6 +21,8 @@ SolidColorOverlay as SolidColorOverlay, StreamingResolution as StreamingResolution, TransformationPosition as TransformationPosition, + GetImageAttributesOptions as GetImageAttributesOptions, + ResponsiveImageAttributes as ResponsiveImageAttributes, TextOverlayTransformation as TextOverlayTransformation, SubtitleOverlayTransformation as SubtitleOverlayTransformation, SolidColorOverlayTransformation as SolidColorOverlayTransformation, diff --git a/src/imagekit/types/shared/__init__.py b/src/imagekit/types/shared/__init__.py index a91ccbd..49f3e91 100644 --- a/src/imagekit/types/shared/__init__.py +++ b/src/imagekit/types/shared/__init__.py @@ -14,6 +14,8 @@ from .solid_color_overlay import SolidColorOverlay as SolidColorOverlay from .streaming_resolution import StreamingResolution as StreamingResolution from .transformation_position import TransformationPosition as TransformationPosition +from .responsive_image_attributes import ResponsiveImageAttributes as ResponsiveImageAttributes from .text_overlay_transformation import TextOverlayTransformation as TextOverlayTransformation +from .get_image_attributes_options import GetImageAttributesOptions as GetImageAttributesOptions from .subtitle_overlay_transformation import SubtitleOverlayTransformation as SubtitleOverlayTransformation from .solid_color_overlay_transformation import SolidColorOverlayTransformation as SolidColorOverlayTransformation diff --git a/src/imagekit/types/shared/get_image_attributes_options.py b/src/imagekit/types/shared/get_image_attributes_options.py new file mode 100644 index 0000000..4fb27f5 --- /dev/null +++ b/src/imagekit/types/shared/get_image_attributes_options.py @@ -0,0 +1,54 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .src_options import SrcOptions + +__all__ = ["GetImageAttributesOptions"] + + +class GetImageAttributesOptions(SrcOptions): + device_breakpoints: Optional[List[float]] = FieldInfo(alias="deviceBreakpoints", default=None) + """ + Custom list of **device-width breakpoints** in pixels. These define common + screen widths for responsive image generation. + + Defaults to `[640, 750, 828, 1080, 1200, 1920, 2048, 3840]`. Sorted + automatically. + """ + + image_breakpoints: Optional[List[float]] = FieldInfo(alias="imageBreakpoints", default=None) + """ + Custom list of **image-specific breakpoints** in pixels. Useful for generating + small variants (e.g., placeholders or thumbnails). + + Merged with `deviceBreakpoints` before calculating `srcSet`. Defaults to + `[16, 32, 48, 64, 96, 128, 256, 384]`. Sorted automatically. + """ + + sizes: Optional[str] = None + """ + The value for the HTML `sizes` attribute (e.g., `"100vw"` or + `"(min-width:768px) 50vw, 100vw"`). + + - If it includes one or more `vw` units, breakpoints smaller than the + corresponding percentage of the smallest device width are excluded. + - If it contains no `vw` units, the full breakpoint list is used. + + Enables a width-based strategy and generates `w` descriptors in `srcSet`. + """ + + width: Optional[float] = None + """ + The intended display width of the image in pixels, used **only when the `sizes` + attribute is not provided**. + + Triggers a DPR-based strategy (1x and 2x variants) and generates `x` descriptors + in `srcSet`. + + Ignored if `sizes` is present. + """ diff --git a/src/imagekit/types/shared/responsive_image_attributes.py b/src/imagekit/types/shared/responsive_image_attributes.py new file mode 100644 index 0000000..54aca7f --- /dev/null +++ b/src/imagekit/types/shared/responsive_image_attributes.py @@ -0,0 +1,29 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["ResponsiveImageAttributes"] + + +class ResponsiveImageAttributes(BaseModel): + src: str + """URL for the _largest_ candidate (assigned to plain `src`).""" + + sizes: Optional[str] = None + """`sizes` returned (or synthesised as `100vw`). + + The value for the HTML `sizes` attribute. + """ + + src_set: Optional[str] = FieldInfo(alias="srcSet", default=None) + """Candidate set with `w` or `x` descriptors. + + Multiple image URLs separated by commas, each with a descriptor. + """ + + width: Optional[float] = None + """Width as a number (if `width` was provided in the input options).""" From 06871f368d53706e7065119f4fb613d878825b71 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:14:19 +0000 Subject: [PATCH 145/177] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 27ad9e7..e27f9d4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-0e4fa3c1f9d8cafecb9671fa76c0ff9156c643e05837804679e5e336bad8f4c1.yml -openapi_spec_hash: 4544b950730b721c252eb519358b8609 -config_hash: 3d7a0bc2844e9fb4797149b233e85770 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml +openapi_spec_hash: a9aa620376fce66532c84f9364209b0b +config_hash: bb7229ef61cee50cd6c1ac02a5a74e81 From 5e47c2ff59c75ba7e4649f8c7fa3ea87a14f1ce2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:43:26 +0000 Subject: [PATCH 146/177] fix(client): close streams without requiring full consumption --- src/imagekit/_streaming.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/imagekit/_streaming.py b/src/imagekit/_streaming.py index 7fadf2a..8c39578 100644 --- a/src/imagekit/_streaming.py +++ b/src/imagekit/_streaming.py @@ -57,9 +57,8 @@ def __stream__(self) -> Iterator[_T]: for sse in iterator: yield process_data(data=sse.json(), cast_to=cast_to, response=response) - # Ensure the entire stream is consumed - for _sse in iterator: - ... + # As we might not fully consume the response stream, we need to close it explicitly + response.close() def __enter__(self) -> Self: return self @@ -121,9 +120,8 @@ async def __stream__(self) -> AsyncIterator[_T]: async for sse in iterator: yield process_data(data=sse.json(), cast_to=cast_to, response=response) - # Ensure the entire stream is consumed - async for _sse in iterator: - ... + # As we might not fully consume the response stream, we need to close it explicitly + await response.aclose() async def __aenter__(self) -> Self: return self From a1cfb1f5f0ea68e9dcb0e9a68197fec531ad8d99 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 18:38:19 +0000 Subject: [PATCH 147/177] chore(internal): codegen related update --- requirements-dev.lock | 4 ++-- requirements.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 5eb54b7..c11088c 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -34,7 +34,7 @@ certifi==2023.7.22 # via httpx colorlog==6.7.0 # via nox -deprecated==1.2.18 +deprecated==1.3.0 # via standardwebhooks dirty-equals==0.6.0 distlib==0.3.7 @@ -142,7 +142,7 @@ typing-inspection==0.4.1 # via pydantic virtualenv==20.24.5 # via nox -wrapt==1.17.3 +wrapt==2.0.0 # via deprecated yarl==1.20.0 # via aiohttp diff --git a/requirements.lock b/requirements.lock index 78b912e..88cce54 100644 --- a/requirements.lock +++ b/requirements.lock @@ -30,7 +30,7 @@ attrs==25.3.0 certifi==2023.7.22 # via httpcore # via httpx -deprecated==1.2.18 +deprecated==1.3.0 # via standardwebhooks distro==1.8.0 # via imagekit @@ -85,7 +85,7 @@ typing-extensions==4.12.2 # via typing-inspection typing-inspection==0.4.1 # via pydantic -wrapt==1.17.3 +wrapt==2.0.0 # via deprecated yarl==1.20.0 # via aiohttp From bfa6f22b7b3bc6c7f0df123672f5fe67e5eadaba Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 05:32:10 +0000 Subject: [PATCH 148/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index e27f9d4..df4337d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml openapi_spec_hash: a9aa620376fce66532c84f9364209b0b -config_hash: bb7229ef61cee50cd6c1ac02a5a74e81 +config_hash: d7961ccc7e3cafdf8f56d6c89c3c7d62 From d4b1fe20fae802e7c80149b39f235b4ea5274075 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 05:32:57 +0000 Subject: [PATCH 149/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index df4337d..43d92dd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml openapi_spec_hash: a9aa620376fce66532c84f9364209b0b -config_hash: d7961ccc7e3cafdf8f56d6c89c3c7d62 +config_hash: c2c1c0a5c85d678e5aa8996f3637b616 From 6e6162a04613a41746845fa03eefaa130ed97535 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 05:45:34 +0000 Subject: [PATCH 150/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 43d92dd..ae3aead 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml openapi_spec_hash: a9aa620376fce66532c84f9364209b0b -config_hash: c2c1c0a5c85d678e5aa8996f3637b616 +config_hash: eb4cf65a4c6b26a2901076eff5810d5d From f033fec92f4811efa9e0cc49a7af95a5a96d0bc0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:52:21 +0000 Subject: [PATCH 151/177] chore(internal): codegen related update --- requirements-dev.lock | 2 +- requirements.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index c11088c..0d7df2b 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -34,7 +34,7 @@ certifi==2023.7.22 # via httpx colorlog==6.7.0 # via nox -deprecated==1.3.0 +deprecated==1.3.1 # via standardwebhooks dirty-equals==0.6.0 distlib==0.3.7 diff --git a/requirements.lock b/requirements.lock index 88cce54..309802f 100644 --- a/requirements.lock +++ b/requirements.lock @@ -30,7 +30,7 @@ attrs==25.3.0 certifi==2023.7.22 # via httpcore # via httpx -deprecated==1.3.0 +deprecated==1.3.1 # via standardwebhooks distro==1.8.0 # via imagekit From 9bc3deb52373e25bd9c6bdc530d5ec13a1cd25d0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 11:02:08 +0000 Subject: [PATCH 152/177] chore(internal/tests): avoid race condition with implicit client cleanup --- tests/test_client.py | 376 +++++++++++++++++++++++-------------------- 1 file changed, 202 insertions(+), 174 deletions(-) diff --git a/tests/test_client.py b/tests/test_client.py index ab2dfce..8651828 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -60,55 +60,53 @@ def _get_open_connections(client: ImageKit | AsyncImageKit) -> int: class TestImageKit: - client = ImageKit(base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True) - @pytest.mark.respx(base_url=base_url) - def test_raw_response(self, respx_mock: MockRouter) -> None: + def test_raw_response(self, respx_mock: MockRouter, client: ImageKit) -> None: respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = self.client.post("/foo", cast_to=httpx.Response) + response = client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} @pytest.mark.respx(base_url=base_url) - def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + def test_raw_response_for_binary(self, respx_mock: MockRouter, client: ImageKit) -> None: respx_mock.post("/foo").mock( return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') ) - response = self.client.post("/foo", cast_to=httpx.Response) + response = client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} - def test_copy(self) -> None: - copied = self.client.copy() - assert id(copied) != id(self.client) + def test_copy(self, client: ImageKit) -> None: + copied = client.copy() + assert id(copied) != id(client) - copied = self.client.copy(private_key="another My Private Key") + copied = client.copy(private_key="another My Private Key") assert copied.private_key == "another My Private Key" - assert self.client.private_key == "My Private Key" + assert client.private_key == "My Private Key" - copied = self.client.copy(password="another My Password") + copied = client.copy(password="another My Password") assert copied.password == "another My Password" - assert self.client.password == "My Password" + assert client.password == "My Password" - def test_copy_default_options(self) -> None: + def test_copy_default_options(self, client: ImageKit) -> None: # options that have a default are overridden correctly - copied = self.client.copy(max_retries=7) + copied = client.copy(max_retries=7) assert copied.max_retries == 7 - assert self.client.max_retries == 2 + assert client.max_retries == 2 copied2 = copied.copy(max_retries=6) assert copied2.max_retries == 6 assert copied.max_retries == 7 # timeout - assert isinstance(self.client.timeout, httpx.Timeout) - copied = self.client.copy(timeout=None) + assert isinstance(client.timeout, httpx.Timeout) + copied = client.copy(timeout=None) assert copied.timeout is None - assert isinstance(self.client.timeout, httpx.Timeout) + assert isinstance(client.timeout, httpx.Timeout) def test_copy_default_headers(self) -> None: client = ImageKit( @@ -147,6 +145,7 @@ def test_copy_default_headers(self) -> None: match="`default_headers` and `set_default_headers` arguments are mutually exclusive", ): client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) + client.close() def test_copy_default_query(self) -> None: client = ImageKit( @@ -188,13 +187,15 @@ def test_copy_default_query(self) -> None: ): client.copy(set_default_query={}, default_query={"foo": "Bar"}) - def test_copy_signature(self) -> None: + client.close() + + def test_copy_signature(self, client: ImageKit) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( # mypy doesn't like that we access the `__init__` property. - self.client.__init__, # type: ignore[misc] + client.__init__, # type: ignore[misc] ) - copy_signature = inspect.signature(self.client.copy) + copy_signature = inspect.signature(client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} for name in init_signature.parameters.keys(): @@ -205,12 +206,12 @@ def test_copy_signature(self) -> None: assert copy_param is not None, f"copy() signature is missing the {name} param" @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") - def test_copy_build_request(self) -> None: + def test_copy_build_request(self, client: ImageKit) -> None: options = FinalRequestOptions(method="get", url="/foo") def build_request(options: FinalRequestOptions) -> None: - client = self.client.copy() - client._build_request(options) + client_copy = client.copy() + client_copy._build_request(options) # ensure that the machinery is warmed up before tracing starts. build_request(options) @@ -267,14 +268,12 @@ def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.Statistic print(frame) raise AssertionError() - def test_request_timeout(self) -> None: - request = self.client._build_request(FinalRequestOptions(method="get", url="/foo")) + def test_request_timeout(self, client: ImageKit) -> None: + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT - request = self.client._build_request( - FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) - ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0))) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(100.0) @@ -291,6 +290,8 @@ def test_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(0) + client.close() + def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used with httpx.Client(timeout=None) as http_client: @@ -306,6 +307,8 @@ def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(None) + client.close() + # no timeout given to the httpx client should not use the httpx default with httpx.Client() as http_client: client = ImageKit( @@ -320,6 +323,8 @@ def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT + client.close() + # explicitly passing the default timeout currently results in it being ignored with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = ImageKit( @@ -334,6 +339,8 @@ def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT # our default + client.close() + async def test_invalid_http_client(self) -> None: with pytest.raises(TypeError, match="Invalid `http_client` arg"): async with httpx.AsyncClient() as http_client: @@ -346,18 +353,18 @@ async def test_invalid_http_client(self) -> None: ) def test_default_headers_option(self) -> None: - client = ImageKit( + test_client = ImageKit( base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True, default_headers={"X-Foo": "bar"}, ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" assert request.headers.get("x-stainless-lang") == "python" - client2 = ImageKit( + test_client2 = ImageKit( base_url=base_url, private_key=private_key, password=password, @@ -367,10 +374,13 @@ def test_default_headers_option(self) -> None: "X-Stainless-Lang": "my-overriding-header", }, ) - request = client2._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "stainless" assert request.headers.get("x-stainless-lang") == "my-overriding-header" + test_client.close() + test_client2.close() + def test_validate_headers(self) -> None: client = ImageKit( base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True @@ -410,8 +420,10 @@ def test_default_query_option(self) -> None: url = httpx.URL(request.url) assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} - def test_request_extra_json(self) -> None: - request = self.client._build_request( + client.close() + + def test_request_extra_json(self, client: ImageKit) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -422,7 +434,7 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": False} - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -433,7 +445,7 @@ def test_request_extra_json(self) -> None: assert data == {"baz": False} # `extra_json` takes priority over `json_data` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -444,8 +456,8 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": None} - def test_request_extra_headers(self) -> None: - request = self.client._build_request( + def test_request_extra_headers(self, client: ImageKit) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -455,7 +467,7 @@ def test_request_extra_headers(self) -> None: assert request.headers.get("X-Foo") == "Foo" # `extra_headers` takes priority over `default_headers` when keys clash - request = self.client.with_options(default_headers={"X-Bar": "true"})._build_request( + request = client.with_options(default_headers={"X-Bar": "true"})._build_request( FinalRequestOptions( method="post", url="/foo", @@ -466,8 +478,8 @@ def test_request_extra_headers(self) -> None: ) assert request.headers.get("X-Bar") == "false" - def test_request_extra_query(self) -> None: - request = self.client._build_request( + def test_request_extra_query(self, client: ImageKit) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -480,7 +492,7 @@ def test_request_extra_query(self) -> None: assert params == {"my_query_param": "Foo"} # if both `query` and `extra_query` are given, they are merged - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -494,7 +506,7 @@ def test_request_extra_query(self) -> None: assert params == {"bar": "1", "foo": "2"} # `extra_query` takes priority over `query` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -537,7 +549,7 @@ def test_multipart_repeating_array(self, client: ImageKit) -> None: ] @pytest.mark.respx(base_url=base_url) - def test_basic_union_response(self, respx_mock: MockRouter) -> None: + def test_basic_union_response(self, respx_mock: MockRouter, client: ImageKit) -> None: class Model1(BaseModel): name: str @@ -546,12 +558,12 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" @pytest.mark.respx(base_url=base_url) - def test_union_response_different_types(self, respx_mock: MockRouter) -> None: + def test_union_response_different_types(self, respx_mock: MockRouter, client: ImageKit) -> None: """Union of objects with the same field name using a different type""" class Model1(BaseModel): @@ -562,18 +574,18 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) - response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) assert response.foo == 1 @pytest.mark.respx(base_url=base_url) - def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter) -> None: + def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter, client: ImageKit) -> None: """ Response that sets Content-Type to something other than application/json but returns json data """ @@ -589,7 +601,7 @@ class Model(BaseModel): ) ) - response = self.client.get("/foo", cast_to=Model) + response = client.get("/foo", cast_to=Model) assert isinstance(response, Model) assert response.foo == 2 @@ -606,6 +618,8 @@ def test_base_url_setter(self) -> None: assert client.base_url == "https://example.com/from_setter/" + client.close() + def test_base_url_env(self) -> None: with update_env(IMAGE_KIT_BASE_URL="http://localhost:5000/from/env"): client = ImageKit(private_key=private_key, password=password, _strict_response_validation=True) @@ -639,6 +653,7 @@ def test_base_url_trailing_slash(self, client: ImageKit) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + client.close() @pytest.mark.parametrize( "client", @@ -668,6 +683,7 @@ def test_base_url_no_trailing_slash(self, client: ImageKit) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + client.close() @pytest.mark.parametrize( "client", @@ -697,39 +713,40 @@ def test_absolute_request_url(self, client: ImageKit) -> None: ), ) assert request.url == "https://myapi.com/foo" + client.close() def test_copied_client_does_not_close_http(self) -> None: - client = ImageKit( + test_client = ImageKit( base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) - assert not client.is_closed() + assert not test_client.is_closed() - copied = client.copy() - assert copied is not client + copied = test_client.copy() + assert copied is not test_client del copied - assert not client.is_closed() + assert not test_client.is_closed() def test_client_context_manager(self) -> None: - client = ImageKit( + test_client = ImageKit( base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) - with client as c2: - assert c2 is client + with test_client as c2: + assert c2 is test_client assert not c2.is_closed() - assert not client.is_closed() - assert client.is_closed() + assert not test_client.is_closed() + assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) - def test_client_response_validation_error(self, respx_mock: MockRouter) -> None: + def test_client_response_validation_error(self, respx_mock: MockRouter, client: ImageKit) -> None: class Model(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) with pytest.raises(APIResponseValidationError) as exc: - self.client.get("/foo", cast_to=Model) + client.get("/foo", cast_to=Model) assert isinstance(exc.value.__cause__, ValidationError) @@ -757,13 +774,16 @@ class Model(BaseModel): with pytest.raises(APIResponseValidationError): strict_client.get("/foo", cast_to=Model) - client = ImageKit( + non_strict_client = ImageKit( base_url=base_url, private_key=private_key, password=password, _strict_response_validation=False ) - response = client.get("/foo", cast_to=Model) + response = non_strict_client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] + strict_client.close() + non_strict_client.close() + @pytest.mark.parametrize( "remaining_retries,retry_after,timeout", [ @@ -786,11 +806,9 @@ class Model(BaseModel): ], ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: - client = ImageKit( - base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True - ) - + def test_parse_retry_after_header( + self, remaining_retries: int, retry_after: str, timeout: float, client: ImageKit + ) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = client._calculate_retry_timeout(remaining_retries, options, headers) @@ -804,7 +822,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien with pytest.raises(APITimeoutError): client.files.with_streaming_response.upload(file=b"raw file contents", file_name="fileName").__enter__() - assert _get_open_connections(self.client) == 0 + assert _get_open_connections(client) == 0 @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -813,7 +831,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client with pytest.raises(APIStatusError): client.files.with_streaming_response.upload(file=b"raw file contents", file_name="fileName").__enter__() - assert _get_open_connections(self.client) == 0 + assert _get_open_connections(client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @@ -919,89 +937,81 @@ def test_default_client_creation(self) -> None: ) @pytest.mark.respx(base_url=base_url) - def test_follow_redirects(self, respx_mock: MockRouter) -> None: + def test_follow_redirects(self, respx_mock: MockRouter, client: ImageKit) -> None: # Test that the default follow_redirects=True allows following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) - response = self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + response = client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) assert response.status_code == 200 assert response.json() == {"status": "ok"} @pytest.mark.respx(base_url=base_url) - def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + def test_follow_redirects_disabled(self, respx_mock: MockRouter, client: ImageKit) -> None: # Test that follow_redirects=False prevents following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) with pytest.raises(APIStatusError) as exc_info: - self.client.post( - "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response - ) + client.post("/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response) assert exc_info.value.response.status_code == 302 assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" class TestAsyncImageKit: - client = AsyncImageKit( - base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True - ) - @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio - async def test_raw_response(self, respx_mock: MockRouter) -> None: + async def test_raw_response(self, respx_mock: MockRouter, async_client: AsyncImageKit) -> None: respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = await self.client.post("/foo", cast_to=httpx.Response) + response = await async_client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio - async def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + async def test_raw_response_for_binary(self, respx_mock: MockRouter, async_client: AsyncImageKit) -> None: respx_mock.post("/foo").mock( return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') ) - response = await self.client.post("/foo", cast_to=httpx.Response) + response = await async_client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} - def test_copy(self) -> None: - copied = self.client.copy() - assert id(copied) != id(self.client) + def test_copy(self, async_client: AsyncImageKit) -> None: + copied = async_client.copy() + assert id(copied) != id(async_client) - copied = self.client.copy(private_key="another My Private Key") + copied = async_client.copy(private_key="another My Private Key") assert copied.private_key == "another My Private Key" - assert self.client.private_key == "My Private Key" + assert async_client.private_key == "My Private Key" - copied = self.client.copy(password="another My Password") + copied = async_client.copy(password="another My Password") assert copied.password == "another My Password" - assert self.client.password == "My Password" + assert async_client.password == "My Password" - def test_copy_default_options(self) -> None: + def test_copy_default_options(self, async_client: AsyncImageKit) -> None: # options that have a default are overridden correctly - copied = self.client.copy(max_retries=7) + copied = async_client.copy(max_retries=7) assert copied.max_retries == 7 - assert self.client.max_retries == 2 + assert async_client.max_retries == 2 copied2 = copied.copy(max_retries=6) assert copied2.max_retries == 6 assert copied.max_retries == 7 # timeout - assert isinstance(self.client.timeout, httpx.Timeout) - copied = self.client.copy(timeout=None) + assert isinstance(async_client.timeout, httpx.Timeout) + copied = async_client.copy(timeout=None) assert copied.timeout is None - assert isinstance(self.client.timeout, httpx.Timeout) + assert isinstance(async_client.timeout, httpx.Timeout) - def test_copy_default_headers(self) -> None: + async def test_copy_default_headers(self) -> None: client = AsyncImageKit( base_url=base_url, private_key=private_key, @@ -1038,8 +1048,9 @@ def test_copy_default_headers(self) -> None: match="`default_headers` and `set_default_headers` arguments are mutually exclusive", ): client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) + await client.close() - def test_copy_default_query(self) -> None: + async def test_copy_default_query(self) -> None: client = AsyncImageKit( base_url=base_url, private_key=private_key, @@ -1079,13 +1090,15 @@ def test_copy_default_query(self) -> None: ): client.copy(set_default_query={}, default_query={"foo": "Bar"}) - def test_copy_signature(self) -> None: + await client.close() + + def test_copy_signature(self, async_client: AsyncImageKit) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( # mypy doesn't like that we access the `__init__` property. - self.client.__init__, # type: ignore[misc] + async_client.__init__, # type: ignore[misc] ) - copy_signature = inspect.signature(self.client.copy) + copy_signature = inspect.signature(async_client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} for name in init_signature.parameters.keys(): @@ -1096,12 +1109,12 @@ def test_copy_signature(self) -> None: assert copy_param is not None, f"copy() signature is missing the {name} param" @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") - def test_copy_build_request(self) -> None: + def test_copy_build_request(self, async_client: AsyncImageKit) -> None: options = FinalRequestOptions(method="get", url="/foo") def build_request(options: FinalRequestOptions) -> None: - client = self.client.copy() - client._build_request(options) + client_copy = async_client.copy() + client_copy._build_request(options) # ensure that the machinery is warmed up before tracing starts. build_request(options) @@ -1158,12 +1171,12 @@ def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.Statistic print(frame) raise AssertionError() - async def test_request_timeout(self) -> None: - request = self.client._build_request(FinalRequestOptions(method="get", url="/foo")) + async def test_request_timeout(self, async_client: AsyncImageKit) -> None: + request = async_client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT - request = self.client._build_request( + request = async_client._build_request( FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) ) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore @@ -1182,6 +1195,8 @@ async def test_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(0) + await client.close() + async def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used async with httpx.AsyncClient(timeout=None) as http_client: @@ -1197,6 +1212,8 @@ async def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(None) + await client.close() + # no timeout given to the httpx client should not use the httpx default async with httpx.AsyncClient() as http_client: client = AsyncImageKit( @@ -1211,6 +1228,8 @@ async def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT + await client.close() + # explicitly passing the default timeout currently results in it being ignored async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = AsyncImageKit( @@ -1225,6 +1244,8 @@ async def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT # our default + await client.close() + def test_invalid_http_client(self) -> None: with pytest.raises(TypeError, match="Invalid `http_client` arg"): with httpx.Client() as http_client: @@ -1236,19 +1257,19 @@ def test_invalid_http_client(self) -> None: http_client=cast(Any, http_client), ) - def test_default_headers_option(self) -> None: - client = AsyncImageKit( + async def test_default_headers_option(self) -> None: + test_client = AsyncImageKit( base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True, default_headers={"X-Foo": "bar"}, ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" assert request.headers.get("x-stainless-lang") == "python" - client2 = AsyncImageKit( + test_client2 = AsyncImageKit( base_url=base_url, private_key=private_key, password=password, @@ -1258,10 +1279,13 @@ def test_default_headers_option(self) -> None: "X-Stainless-Lang": "my-overriding-header", }, ) - request = client2._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "stainless" assert request.headers.get("x-stainless-lang") == "my-overriding-header" + await test_client.close() + await test_client2.close() + def test_validate_headers(self) -> None: client = AsyncImageKit( base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True @@ -1281,7 +1305,7 @@ def test_validate_headers(self) -> None: ) _ = client2 - def test_default_query_option(self) -> None: + async def test_default_query_option(self) -> None: client = AsyncImageKit( base_url=base_url, private_key=private_key, @@ -1303,8 +1327,10 @@ def test_default_query_option(self) -> None: url = httpx.URL(request.url) assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} - def test_request_extra_json(self) -> None: - request = self.client._build_request( + await client.close() + + def test_request_extra_json(self, client: ImageKit) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1315,7 +1341,7 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": False} - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1326,7 +1352,7 @@ def test_request_extra_json(self) -> None: assert data == {"baz": False} # `extra_json` takes priority over `json_data` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1337,8 +1363,8 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": None} - def test_request_extra_headers(self) -> None: - request = self.client._build_request( + def test_request_extra_headers(self, client: ImageKit) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1348,7 +1374,7 @@ def test_request_extra_headers(self) -> None: assert request.headers.get("X-Foo") == "Foo" # `extra_headers` takes priority over `default_headers` when keys clash - request = self.client.with_options(default_headers={"X-Bar": "true"})._build_request( + request = client.with_options(default_headers={"X-Bar": "true"})._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1359,8 +1385,8 @@ def test_request_extra_headers(self) -> None: ) assert request.headers.get("X-Bar") == "false" - def test_request_extra_query(self) -> None: - request = self.client._build_request( + def test_request_extra_query(self, client: ImageKit) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1373,7 +1399,7 @@ def test_request_extra_query(self) -> None: assert params == {"my_query_param": "Foo"} # if both `query` and `extra_query` are given, they are merged - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1387,7 +1413,7 @@ def test_request_extra_query(self) -> None: assert params == {"bar": "1", "foo": "2"} # `extra_query` takes priority over `query` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1430,7 +1456,7 @@ def test_multipart_repeating_array(self, async_client: AsyncImageKit) -> None: ] @pytest.mark.respx(base_url=base_url) - async def test_basic_union_response(self, respx_mock: MockRouter) -> None: + async def test_basic_union_response(self, respx_mock: MockRouter, async_client: AsyncImageKit) -> None: class Model1(BaseModel): name: str @@ -1439,12 +1465,12 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" @pytest.mark.respx(base_url=base_url) - async def test_union_response_different_types(self, respx_mock: MockRouter) -> None: + async def test_union_response_different_types(self, respx_mock: MockRouter, async_client: AsyncImageKit) -> None: """Union of objects with the same field name using a different type""" class Model1(BaseModel): @@ -1455,18 +1481,20 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) - response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) assert response.foo == 1 @pytest.mark.respx(base_url=base_url) - async def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter) -> None: + async def test_non_application_json_content_type_for_json_data( + self, respx_mock: MockRouter, async_client: AsyncImageKit + ) -> None: """ Response that sets Content-Type to something other than application/json but returns json data """ @@ -1482,11 +1510,11 @@ class Model(BaseModel): ) ) - response = await self.client.get("/foo", cast_to=Model) + response = await async_client.get("/foo", cast_to=Model) assert isinstance(response, Model) assert response.foo == 2 - def test_base_url_setter(self) -> None: + async def test_base_url_setter(self) -> None: client = AsyncImageKit( base_url="https://example.com/from_init", private_key=private_key, @@ -1499,7 +1527,9 @@ def test_base_url_setter(self) -> None: assert client.base_url == "https://example.com/from_setter/" - def test_base_url_env(self) -> None: + await client.close() + + async def test_base_url_env(self) -> None: with update_env(IMAGE_KIT_BASE_URL="http://localhost:5000/from/env"): client = AsyncImageKit(private_key=private_key, password=password, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" @@ -1523,7 +1553,7 @@ def test_base_url_env(self) -> None: ], ids=["standard", "custom http client"], ) - def test_base_url_trailing_slash(self, client: AsyncImageKit) -> None: + async def test_base_url_trailing_slash(self, client: AsyncImageKit) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1532,6 +1562,7 @@ def test_base_url_trailing_slash(self, client: AsyncImageKit) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + await client.close() @pytest.mark.parametrize( "client", @@ -1552,7 +1583,7 @@ def test_base_url_trailing_slash(self, client: AsyncImageKit) -> None: ], ids=["standard", "custom http client"], ) - def test_base_url_no_trailing_slash(self, client: AsyncImageKit) -> None: + async def test_base_url_no_trailing_slash(self, client: AsyncImageKit) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1561,6 +1592,7 @@ def test_base_url_no_trailing_slash(self, client: AsyncImageKit) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + await client.close() @pytest.mark.parametrize( "client", @@ -1581,7 +1613,7 @@ def test_base_url_no_trailing_slash(self, client: AsyncImageKit) -> None: ], ids=["standard", "custom http client"], ) - def test_absolute_request_url(self, client: AsyncImageKit) -> None: + async def test_absolute_request_url(self, client: AsyncImageKit) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1590,41 +1622,41 @@ def test_absolute_request_url(self, client: AsyncImageKit) -> None: ), ) assert request.url == "https://myapi.com/foo" + await client.close() async def test_copied_client_does_not_close_http(self) -> None: - client = AsyncImageKit( + test_client = AsyncImageKit( base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) - assert not client.is_closed() + assert not test_client.is_closed() - copied = client.copy() - assert copied is not client + copied = test_client.copy() + assert copied is not test_client del copied await asyncio.sleep(0.2) - assert not client.is_closed() + assert not test_client.is_closed() async def test_client_context_manager(self) -> None: - client = AsyncImageKit( + test_client = AsyncImageKit( base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True ) - async with client as c2: - assert c2 is client + async with test_client as c2: + assert c2 is test_client assert not c2.is_closed() - assert not client.is_closed() - assert client.is_closed() + assert not test_client.is_closed() + assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio - async def test_client_response_validation_error(self, respx_mock: MockRouter) -> None: + async def test_client_response_validation_error(self, respx_mock: MockRouter, async_client: AsyncImageKit) -> None: class Model(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) with pytest.raises(APIResponseValidationError) as exc: - await self.client.get("/foo", cast_to=Model) + await async_client.get("/foo", cast_to=Model) assert isinstance(exc.value.__cause__, ValidationError) @@ -1639,7 +1671,6 @@ async def test_client_max_retries_validation(self) -> None: ) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio async def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: class Model(BaseModel): name: str @@ -1653,13 +1684,16 @@ class Model(BaseModel): with pytest.raises(APIResponseValidationError): await strict_client.get("/foo", cast_to=Model) - client = AsyncImageKit( + non_strict_client = AsyncImageKit( base_url=base_url, private_key=private_key, password=password, _strict_response_validation=False ) - response = await client.get("/foo", cast_to=Model) + response = await non_strict_client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] + await strict_client.close() + await non_strict_client.close() + @pytest.mark.parametrize( "remaining_retries,retry_after,timeout", [ @@ -1682,15 +1716,12 @@ class Model(BaseModel): ], ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - @pytest.mark.asyncio - async def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: - client = AsyncImageKit( - base_url=base_url, private_key=private_key, password=password, _strict_response_validation=True - ) - + async def test_parse_retry_after_header( + self, remaining_retries: int, retry_after: str, timeout: float, async_client: AsyncImageKit + ) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) - calculated = client._calculate_retry_timeout(remaining_retries, options, headers) + calculated = async_client._calculate_retry_timeout(remaining_retries, options, headers) assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @@ -1705,7 +1736,7 @@ async def test_retrying_timeout_errors_doesnt_leak( file=b"raw file contents", file_name="fileName" ).__aenter__() - assert _get_open_connections(self.client) == 0 + assert _get_open_connections(async_client) == 0 @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -1718,12 +1749,11 @@ async def test_retrying_status_errors_doesnt_leak( await async_client.files.with_streaming_response.upload( file=b"raw file contents", file_name="fileName" ).__aenter__() - assert _get_open_connections(self.client) == 0 + assert _get_open_connections(async_client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio @pytest.mark.parametrize("failure_mode", ["status", "exception"]) async def test_retries_taken( self, @@ -1755,7 +1785,6 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio async def test_omit_retry_count_header( self, async_client: AsyncImageKit, failures_before_success: int, respx_mock: MockRouter ) -> None: @@ -1781,7 +1810,6 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio async def test_overwrite_retry_count_header( self, async_client: AsyncImageKit, failures_before_success: int, respx_mock: MockRouter ) -> None: @@ -1831,26 +1859,26 @@ async def test_default_client_creation(self) -> None: ) @pytest.mark.respx(base_url=base_url) - async def test_follow_redirects(self, respx_mock: MockRouter) -> None: + async def test_follow_redirects(self, respx_mock: MockRouter, async_client: AsyncImageKit) -> None: # Test that the default follow_redirects=True allows following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) - response = await self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + response = await async_client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) assert response.status_code == 200 assert response.json() == {"status": "ok"} @pytest.mark.respx(base_url=base_url) - async def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + async def test_follow_redirects_disabled(self, respx_mock: MockRouter, async_client: AsyncImageKit) -> None: # Test that follow_redirects=False prevents following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) with pytest.raises(APIStatusError) as exc_info: - await self.client.post( + await async_client.post( "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response ) From 3017c3ed442a347706f6f828effc76508f2531d6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 10:30:20 +0000 Subject: [PATCH 153/177] chore(internal): codegen related update --- requirements-dev.lock | 2 +- requirements.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 0d7df2b..6c97b6c 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -125,7 +125,7 @@ time-machine==2.9.0 tomli==2.0.2 # via mypy # via pytest -types-deprecated==1.2.15.20250304 +types-deprecated==1.3.1.20251101 # via standardwebhooks types-python-dateutil==2.9.0.20251008 # via standardwebhooks diff --git a/requirements.lock b/requirements.lock index 309802f..ae94a34 100644 --- a/requirements.lock +++ b/requirements.lock @@ -72,7 +72,7 @@ sniffio==1.3.0 # via imagekit standardwebhooks==1.0.0 # via imagekit -types-deprecated==1.2.15.20250304 +types-deprecated==1.3.1.20251101 # via standardwebhooks types-python-dateutil==2.9.0.20251008 # via standardwebhooks From 6f9128f6c51997c5f8029661d158e21235f25461 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 16:11:36 +0000 Subject: [PATCH 154/177] chore(internal): grammar fix (it's -> its) --- src/imagekit/_utils/_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imagekit/_utils/_utils.py b/src/imagekit/_utils/_utils.py index 50d5926..eec7f4a 100644 --- a/src/imagekit/_utils/_utils.py +++ b/src/imagekit/_utils/_utils.py @@ -133,7 +133,7 @@ def is_given(obj: _T | NotGiven | Omit) -> TypeGuard[_T]: # Type safe methods for narrowing types with TypeVars. # The default narrowing for isinstance(obj, dict) is dict[unknown, unknown], # however this cause Pyright to rightfully report errors. As we know we don't -# care about the contained types we can safely use `object` in it's place. +# care about the contained types we can safely use `object` in its place. # # There are two separate functions defined, `is_*` and `is_*_t` for different use cases. # `is_*` is for when you're dealing with an unknown input From 1e80c8a28a65bf514badd6454d35b19c60d4c618 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 7 Nov 2025 04:09:22 +0000 Subject: [PATCH 155/177] chore(internal): codegen related update --- requirements-dev.lock | 2 +- requirements.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 6c97b6c..a1ae872 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -142,7 +142,7 @@ typing-inspection==0.4.1 # via pydantic virtualenv==20.24.5 # via nox -wrapt==2.0.0 +wrapt==2.0.1 # via deprecated yarl==1.20.0 # via aiohttp diff --git a/requirements.lock b/requirements.lock index ae94a34..1e7ea2d 100644 --- a/requirements.lock +++ b/requirements.lock @@ -85,7 +85,7 @@ typing-extensions==4.12.2 # via typing-inspection typing-inspection==0.4.1 # via pydantic -wrapt==2.0.0 +wrapt==2.0.1 # via deprecated yarl==1.20.0 # via aiohttp From ea0616d89c0d593b294926c36d238f536d301617 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 11:29:09 +0000 Subject: [PATCH 156/177] chore(package): drop Python 3.8 support --- README.md | 4 ++-- pyproject.toml | 5 ++--- requirements-dev.lock | 2 +- requirements.lock | 2 +- src/imagekit/_utils/_sync.py | 34 +++------------------------------- 5 files changed, 9 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 32ac1bd..b05ec1b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![PyPI version](https://img.shields.io/pypi/v/imagekit.svg?label=pypi%20(stable))](https://pypi.org/project/imagekit/) -The Image Kit Python library provides convenient access to the Image Kit REST API from any Python 3.8+ +The Image Kit Python library provides convenient access to the Image Kit REST API from any Python 3.9+ application. The library includes type definitions for all request params and response fields, and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx). @@ -435,7 +435,7 @@ print(imagekit.__version__) ## Requirements -Python 3.8 or higher. +Python 3.9 or higher. ## Contributing diff --git a/pyproject.toml b/pyproject.toml index c10cd5d..3c01ca0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,11 +15,10 @@ dependencies = [ "distro>=1.7.0, <2", "sniffio", ] -requires-python = ">= 3.8" +requires-python = ">= 3.9" classifiers = [ "Typing :: Typed", "Intended Audience :: Developers", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -142,7 +141,7 @@ filterwarnings = [ # there are a couple of flags that are still disabled by # default in strict mode as they are experimental and niche. typeCheckingMode = "strict" -pythonVersion = "3.8" +pythonVersion = "3.9" exclude = [ "_dev", diff --git a/requirements-dev.lock b/requirements-dev.lock index a1ae872..a46a62b 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -127,7 +127,7 @@ tomli==2.0.2 # via pytest types-deprecated==1.3.1.20251101 # via standardwebhooks -types-python-dateutil==2.9.0.20251008 +types-python-dateutil==2.9.0.20251108 # via standardwebhooks typing-extensions==4.12.2 # via anyio diff --git a/requirements.lock b/requirements.lock index 1e7ea2d..c531693 100644 --- a/requirements.lock +++ b/requirements.lock @@ -74,7 +74,7 @@ standardwebhooks==1.0.0 # via imagekit types-deprecated==1.3.1.20251101 # via standardwebhooks -types-python-dateutil==2.9.0.20251008 +types-python-dateutil==2.9.0.20251108 # via standardwebhooks typing-extensions==4.12.2 # via anyio diff --git a/src/imagekit/_utils/_sync.py b/src/imagekit/_utils/_sync.py index ad7ec71..f6027c1 100644 --- a/src/imagekit/_utils/_sync.py +++ b/src/imagekit/_utils/_sync.py @@ -1,10 +1,8 @@ from __future__ import annotations -import sys import asyncio import functools -import contextvars -from typing import Any, TypeVar, Callable, Awaitable +from typing import TypeVar, Callable, Awaitable from typing_extensions import ParamSpec import anyio @@ -15,34 +13,11 @@ T_ParamSpec = ParamSpec("T_ParamSpec") -if sys.version_info >= (3, 9): - _asyncio_to_thread = asyncio.to_thread -else: - # backport of https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread - # for Python 3.8 support - async def _asyncio_to_thread( - func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs - ) -> Any: - """Asynchronously run function *func* in a separate thread. - - Any *args and **kwargs supplied for this function are directly passed - to *func*. Also, the current :class:`contextvars.Context` is propagated, - allowing context variables from the main thread to be accessed in the - separate thread. - - Returns a coroutine that can be awaited to get the eventual result of *func*. - """ - loop = asyncio.events.get_running_loop() - ctx = contextvars.copy_context() - func_call = functools.partial(ctx.run, func, *args, **kwargs) - return await loop.run_in_executor(None, func_call) - - async def to_thread( func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs ) -> T_Retval: if sniffio.current_async_library() == "asyncio": - return await _asyncio_to_thread(func, *args, **kwargs) + return await asyncio.to_thread(func, *args, **kwargs) return await anyio.to_thread.run_sync( functools.partial(func, *args, **kwargs), @@ -53,10 +28,7 @@ async def to_thread( def asyncify(function: Callable[T_ParamSpec, T_Retval]) -> Callable[T_ParamSpec, Awaitable[T_Retval]]: """ Take a blocking function and create an async one that receives the same - positional and keyword arguments. For python version 3.9 and above, it uses - asyncio.to_thread to run the function in a separate thread. For python version - 3.8, it uses locally defined copy of the asyncio.to_thread function which was - introduced in python 3.9. + positional and keyword arguments. Usage: From 0a23688acef5511496850be0d27722b7f3bfe62d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 13:36:48 +0000 Subject: [PATCH 157/177] fix: compat with Python 3.14 --- src/imagekit/_models.py | 11 ++++++++--- tests/test_models.py | 8 ++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/imagekit/_models.py b/src/imagekit/_models.py index 6a3cd1d..fcec2cf 100644 --- a/src/imagekit/_models.py +++ b/src/imagekit/_models.py @@ -2,6 +2,7 @@ import os import inspect +import weakref from typing import TYPE_CHECKING, Any, Type, Union, Generic, TypeVar, Callable, Optional, cast from datetime import date, datetime from typing_extensions import ( @@ -573,6 +574,9 @@ class CachedDiscriminatorType(Protocol): __discriminator__: DiscriminatorDetails +DISCRIMINATOR_CACHE: weakref.WeakKeyDictionary[type, DiscriminatorDetails] = weakref.WeakKeyDictionary() + + class DiscriminatorDetails: field_name: str """The name of the discriminator field in the variant class, e.g. @@ -615,8 +619,9 @@ def __init__( def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, ...]) -> DiscriminatorDetails | None: - if isinstance(union, CachedDiscriminatorType): - return union.__discriminator__ + cached = DISCRIMINATOR_CACHE.get(union) + if cached is not None: + return cached discriminator_field_name: str | None = None @@ -669,7 +674,7 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, discriminator_field=discriminator_field_name, discriminator_alias=discriminator_alias, ) - cast(CachedDiscriminatorType, union).__discriminator__ = details + DISCRIMINATOR_CACHE.setdefault(union, details) return details diff --git a/tests/test_models.py b/tests/test_models.py index 3f73b94..0a3b02a 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -9,7 +9,7 @@ from imagekit._utils import PropertyInfo from imagekit._compat import PYDANTIC_V1, parse_obj, model_dump, model_json -from imagekit._models import BaseModel, construct_type +from imagekit._models import DISCRIMINATOR_CACHE, BaseModel, construct_type class BasicModel(BaseModel): @@ -809,7 +809,7 @@ class B(BaseModel): UnionType = cast(Any, Union[A, B]) - assert not hasattr(UnionType, "__discriminator__") + assert not DISCRIMINATOR_CACHE.get(UnionType) m = construct_type( value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[UnionType, PropertyInfo(discriminator="type")]) @@ -818,7 +818,7 @@ class B(BaseModel): assert m.type == "b" assert m.data == "foo" # type: ignore[comparison-overlap] - discriminator = UnionType.__discriminator__ + discriminator = DISCRIMINATOR_CACHE.get(UnionType) assert discriminator is not None m = construct_type( @@ -830,7 +830,7 @@ class B(BaseModel): # if the discriminator details object stays the same between invocations then # we hit the cache - assert UnionType.__discriminator__ is discriminator + assert DISCRIMINATOR_CACHE.get(UnionType) is discriminator @pytest.mark.skipif(PYDANTIC_V1, reason="TypeAliasType is not supported in Pydantic v1") From 698ac5833f3b4c505b2eae35a85d6658c75341d7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:36:32 +0000 Subject: [PATCH 158/177] fix(compat): update signatures of `model_dump` and `model_dump_json` for Pydantic v1 --- src/imagekit/_models.py | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/imagekit/_models.py b/src/imagekit/_models.py index fcec2cf..ca9500b 100644 --- a/src/imagekit/_models.py +++ b/src/imagekit/_models.py @@ -257,15 +257,16 @@ def model_dump( mode: Literal["json", "python"] | str = "python", include: IncEx | None = None, exclude: IncEx | None = None, + context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, + exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, - context: dict[str, Any] | None = None, - serialize_as_any: bool = False, fallback: Callable[[Any], Any] | None = None, + serialize_as_any: bool = False, ) -> dict[str, Any]: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump @@ -273,16 +274,24 @@ def model_dump( Args: mode: The mode in which `to_python` should run. - If mode is 'json', the dictionary will only contain JSON serializable types. - If mode is 'python', the dictionary may contain any Python objects. - include: A list of fields to include in the output. - exclude: A list of fields to exclude from the output. + If mode is 'json', the output will only contain JSON serializable types. + If mode is 'python', the output may contain non-JSON-serializable Python objects. + include: A set of fields to include in the output. + exclude: A set of fields to exclude from the output. + context: Additional context to pass to the serializer. by_alias: Whether to use the field's alias in the dictionary key if defined. - exclude_unset: Whether to exclude fields that are unset or None from the output. - exclude_defaults: Whether to exclude fields that are set to their default value from the output. - exclude_none: Whether to exclude fields that have a value of `None` from the output. - round_trip: Whether to enable serialization and deserialization round-trip support. - warnings: Whether to log warnings when invalid fields are encountered. + exclude_unset: Whether to exclude fields that have not been explicitly set. + exclude_defaults: Whether to exclude fields that are set to their default value. + exclude_none: Whether to exclude fields that have a value of `None`. + exclude_computed_fields: Whether to exclude computed fields. + While this can be useful for round-tripping, it is usually recommended to use the dedicated + `round_trip` parameter instead. + round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T]. + warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, + "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError]. + fallback: A function to call when an unknown value is encountered. If not provided, + a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised. + serialize_as_any: Whether to serialize fields with duck-typing serialization behavior. Returns: A dictionary representation of the model. @@ -299,6 +308,8 @@ def model_dump( raise ValueError("serialize_as_any is only supported in Pydantic v2") if fallback is not None: raise ValueError("fallback is only supported in Pydantic v2") + if exclude_computed_fields != False: + raise ValueError("exclude_computed_fields is only supported in Pydantic v2") dumped = super().dict( # pyright: ignore[reportDeprecated] include=include, exclude=exclude, @@ -315,15 +326,17 @@ def model_dump_json( self, *, indent: int | None = None, + ensure_ascii: bool = False, include: IncEx | None = None, exclude: IncEx | None = None, + context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, + exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, - context: dict[str, Any] | None = None, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, ) -> str: @@ -355,6 +368,10 @@ def model_dump_json( raise ValueError("serialize_as_any is only supported in Pydantic v2") if fallback is not None: raise ValueError("fallback is only supported in Pydantic v2") + if ensure_ascii != False: + raise ValueError("ensure_ascii is only supported in Pydantic v2") + if exclude_computed_fields != False: + raise ValueError("exclude_computed_fields is only supported in Pydantic v2") return super().json( # type: ignore[reportDeprecated] indent=indent, include=include, From fb434eb93deede9fe23a889226f0451c9e88b169 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 16 Nov 2025 23:32:26 +0000 Subject: [PATCH 159/177] chore(internal): codegen related update --- requirements-dev.lock | 2 +- requirements.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index a46a62b..4c534e5 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -127,7 +127,7 @@ tomli==2.0.2 # via pytest types-deprecated==1.3.1.20251101 # via standardwebhooks -types-python-dateutil==2.9.0.20251108 +types-python-dateutil==2.9.0.20251115 # via standardwebhooks typing-extensions==4.12.2 # via anyio diff --git a/requirements.lock b/requirements.lock index c531693..649c1ff 100644 --- a/requirements.lock +++ b/requirements.lock @@ -74,7 +74,7 @@ standardwebhooks==1.0.0 # via imagekit types-deprecated==1.3.1.20251101 # via standardwebhooks -types-python-dateutil==2.9.0.20251108 +types-python-dateutil==2.9.0.20251115 # via standardwebhooks typing-extensions==4.12.2 # via anyio From bfc9f4159e84440e6a10e7791e2ebbf6ef141710 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 16:52:35 +0000 Subject: [PATCH 160/177] chore: add Python 3.14 classifier and testing --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 3c01ca0..9d4c5b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Operating System :: OS Independent", "Operating System :: POSIX", "Operating System :: MacOS", From 131553a26dba487ccca02280f382bec8583208f7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 27 Nov 2025 16:49:45 +0000 Subject: [PATCH 161/177] fix: ensure streams are always closed --- src/imagekit/_streaming.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/imagekit/_streaming.py b/src/imagekit/_streaming.py index 8c39578..c4a0e31 100644 --- a/src/imagekit/_streaming.py +++ b/src/imagekit/_streaming.py @@ -54,11 +54,12 @@ def __stream__(self) -> Iterator[_T]: process_data = self._client._process_response_data iterator = self._iter_events() - for sse in iterator: - yield process_data(data=sse.json(), cast_to=cast_to, response=response) - - # As we might not fully consume the response stream, we need to close it explicitly - response.close() + try: + for sse in iterator: + yield process_data(data=sse.json(), cast_to=cast_to, response=response) + finally: + # Ensure the response is closed even if the consumer doesn't read all data + response.close() def __enter__(self) -> Self: return self @@ -117,11 +118,12 @@ async def __stream__(self) -> AsyncIterator[_T]: process_data = self._client._process_response_data iterator = self._iter_events() - async for sse in iterator: - yield process_data(data=sse.json(), cast_to=cast_to, response=response) - - # As we might not fully consume the response stream, we need to close it explicitly - await response.aclose() + try: + async for sse in iterator: + yield process_data(data=sse.json(), cast_to=cast_to, response=response) + finally: + # Ensure the response is closed even if the consumer doesn't read all data + await response.aclose() async def __aenter__(self) -> Self: return self From 6efe6f36776841c4290d55e5af70f1ec01eef9cd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:45:44 +0000 Subject: [PATCH 162/177] chore(deps): mypy 1.18.1 has a regression, pin to 1.17 --- pyproject.toml | 2 +- requirements-dev.lock | 4 +++- requirements.lock | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9d4c5b4..097e2c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,7 @@ managed = true # version pins are in requirements-dev.lock dev-dependencies = [ "pyright==1.1.399", - "mypy", + "mypy==1.17", "respx", "pytest", "pytest-asyncio", diff --git a/requirements-dev.lock b/requirements-dev.lock index 4c534e5..84605da 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -76,7 +76,7 @@ mdurl==0.1.2 multidict==6.4.4 # via aiohttp # via yarl -mypy==1.14.1 +mypy==1.17.0 mypy-extensions==1.0.0 # via mypy nodeenv==1.8.0 @@ -85,6 +85,8 @@ nox==2023.4.22 packaging==23.2 # via nox # via pytest +pathspec==0.12.1 + # via mypy platformdirs==3.11.0 # via virtualenv pluggy==1.5.0 diff --git a/requirements.lock b/requirements.lock index 649c1ff..d5fc369 100644 --- a/requirements.lock +++ b/requirements.lock @@ -59,9 +59,9 @@ multidict==6.4.4 propcache==0.3.1 # via aiohttp # via yarl -pydantic==2.11.9 +pydantic==2.12.5 # via imagekit -pydantic-core==2.33.2 +pydantic-core==2.41.5 # via pydantic python-dateutil==2.9.0.post0 # via standardwebhooks @@ -76,14 +76,14 @@ types-deprecated==1.3.1.20251101 # via standardwebhooks types-python-dateutil==2.9.0.20251115 # via standardwebhooks -typing-extensions==4.12.2 +typing-extensions==4.15.0 # via anyio # via imagekit # via multidict # via pydantic # via pydantic-core # via typing-inspection -typing-inspection==0.4.1 +typing-inspection==0.4.2 # via pydantic wrapt==2.0.1 # via deprecated From e5dabb0edd146220aa8ac827f4ecf5eb6207abd4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 11:09:18 +0000 Subject: [PATCH 163/177] chore: update lockfile --- pyproject.toml | 14 +++--- requirements-dev.lock | 108 +++++++++++++++++++++++------------------- requirements.lock | 31 ++++++------ 3 files changed, 83 insertions(+), 70 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 097e2c7..f8292d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,14 +7,16 @@ license = "Apache-2.0" authors = [ { name = "Image Kit", email = "developer@imagekit.io" }, ] + dependencies = [ - "httpx>=0.23.0, <1", - "pydantic>=1.9.0, <3", - "typing-extensions>=4.10, <5", - "anyio>=3.5.0, <5", - "distro>=1.7.0, <2", - "sniffio", + "httpx>=0.23.0, <1", + "pydantic>=1.9.0, <3", + "typing-extensions>=4.10, <5", + "anyio>=3.5.0, <5", + "distro>=1.7.0, <2", + "sniffio", ] + requires-python = ">= 3.9" classifiers = [ "Typing :: Typed", diff --git a/requirements-dev.lock b/requirements-dev.lock index 84605da..60a0cd8 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -12,43 +12,48 @@ -e file:. aiohappyeyeballs==2.6.1 # via aiohttp -aiohttp==3.12.8 +aiohttp==3.13.2 # via httpx-aiohttp # via imagekit -aiosignal==1.3.2 +aiosignal==1.4.0 # via aiohttp -annotated-types==0.6.0 +annotated-types==0.7.0 # via pydantic -anyio==4.4.0 +anyio==4.12.0 # via httpx # via imagekit -argcomplete==3.1.2 +argcomplete==3.6.3 # via nox async-timeout==5.0.1 # via aiohttp -attrs==25.3.0 +attrs==25.4.0 # via aiohttp + # via nox # via standardwebhooks -certifi==2023.7.22 +backports-asyncio-runner==1.2.0 + # via pytest-asyncio +certifi==2025.11.12 # via httpcore # via httpx -colorlog==6.7.0 +colorlog==6.10.1 + # via nox +dependency-groups==1.3.1 # via nox deprecated==1.3.1 # via standardwebhooks -dirty-equals==0.6.0 -distlib==0.3.7 +dirty-equals==0.11 +distlib==0.4.0 # via virtualenv -distro==1.8.0 +distro==1.9.0 # via imagekit -exceptiongroup==1.2.2 +exceptiongroup==1.3.1 # via anyio # via pytest -execnet==2.1.1 +execnet==2.1.2 # via pytest-xdist -filelock==3.12.4 +filelock==3.19.1 # via virtualenv -frozenlist==1.6.2 +frozenlist==1.8.0 # via aiohttp # via aiosignal h11==0.16.0 @@ -62,91 +67,96 @@ httpx==0.28.1 # via standardwebhooks httpx-aiohttp==0.1.9 # via imagekit -idna==3.4 +humanize==4.13.0 + # via nox +idna==3.11 # via anyio # via httpx # via yarl -importlib-metadata==7.0.0 -iniconfig==2.0.0 +importlib-metadata==8.7.0 +iniconfig==2.1.0 # via pytest markdown-it-py==3.0.0 # via rich mdurl==0.1.2 # via markdown-it-py -multidict==6.4.4 +multidict==6.7.0 # via aiohttp # via yarl mypy==1.17.0 -mypy-extensions==1.0.0 +mypy-extensions==1.1.0 # via mypy -nodeenv==1.8.0 +nodeenv==1.9.1 # via pyright -nox==2023.4.22 -packaging==23.2 +nox==2025.11.12 +packaging==25.0 + # via dependency-groups # via nox # via pytest pathspec==0.12.1 # via mypy -platformdirs==3.11.0 +platformdirs==4.4.0 # via virtualenv -pluggy==1.5.0 +pluggy==1.6.0 # via pytest -propcache==0.3.1 +propcache==0.4.1 # via aiohttp # via yarl -pydantic==2.11.9 +pydantic==2.12.5 # via imagekit -pydantic-core==2.33.2 +pydantic-core==2.41.5 # via pydantic -pygments==2.18.0 +pygments==2.19.2 + # via pytest # via rich pyright==1.1.399 -pytest==8.3.3 +pytest==8.4.2 # via pytest-asyncio # via pytest-xdist -pytest-asyncio==0.24.0 -pytest-xdist==3.7.0 -python-dateutil==2.8.2 +pytest-asyncio==1.2.0 +pytest-xdist==3.8.0 +python-dateutil==2.9.0.post0 # via standardwebhooks # via time-machine -pytz==2023.3.post1 - # via dirty-equals respx==0.22.0 -rich==13.7.1 -ruff==0.9.4 -setuptools==68.2.2 - # via nodeenv -six==1.16.0 +rich==14.2.0 +ruff==0.14.7 +six==1.17.0 # via python-dateutil -sniffio==1.3.0 - # via anyio +sniffio==1.3.1 # via imagekit standardwebhooks==1.0.0 # via imagekit -time-machine==2.9.0 -tomli==2.0.2 +time-machine==2.19.0 +tomli==2.3.0 + # via dependency-groups # via mypy + # via nox # via pytest types-deprecated==1.3.1.20251101 # via standardwebhooks types-python-dateutil==2.9.0.20251115 # via standardwebhooks -typing-extensions==4.12.2 +typing-extensions==4.15.0 + # via aiosignal # via anyio + # via exceptiongroup # via imagekit # via multidict # via mypy # via pydantic # via pydantic-core # via pyright + # via pytest-asyncio # via typing-inspection -typing-inspection==0.4.1 + # via virtualenv +typing-inspection==0.4.2 # via pydantic -virtualenv==20.24.5 +virtualenv==20.35.4 # via nox wrapt==2.0.1 # via deprecated -yarl==1.20.0 +yarl==1.22.0 # via aiohttp -zipp==3.17.0 +zipp==3.23.0 # via importlib-metadata diff --git a/requirements.lock b/requirements.lock index d5fc369..e27dab0 100644 --- a/requirements.lock +++ b/requirements.lock @@ -12,31 +12,31 @@ -e file:. aiohappyeyeballs==2.6.1 # via aiohttp -aiohttp==3.12.8 +aiohttp==3.13.2 # via httpx-aiohttp # via imagekit -aiosignal==1.3.2 +aiosignal==1.4.0 # via aiohttp -annotated-types==0.6.0 +annotated-types==0.7.0 # via pydantic -anyio==4.4.0 +anyio==4.12.0 # via httpx # via imagekit async-timeout==5.0.1 # via aiohttp -attrs==25.3.0 +attrs==25.4.0 # via aiohttp # via standardwebhooks -certifi==2023.7.22 +certifi==2025.11.12 # via httpcore # via httpx deprecated==1.3.1 # via standardwebhooks -distro==1.8.0 +distro==1.9.0 # via imagekit -exceptiongroup==1.2.2 +exceptiongroup==1.3.1 # via anyio -frozenlist==1.6.2 +frozenlist==1.8.0 # via aiohttp # via aiosignal h11==0.16.0 @@ -49,14 +49,14 @@ httpx==0.28.1 # via standardwebhooks httpx-aiohttp==0.1.9 # via imagekit -idna==3.4 +idna==3.11 # via anyio # via httpx # via yarl -multidict==6.4.4 +multidict==6.7.0 # via aiohttp # via yarl -propcache==0.3.1 +propcache==0.4.1 # via aiohttp # via yarl pydantic==2.12.5 @@ -67,8 +67,7 @@ python-dateutil==2.9.0.post0 # via standardwebhooks six==1.17.0 # via python-dateutil -sniffio==1.3.0 - # via anyio +sniffio==1.3.1 # via imagekit standardwebhooks==1.0.0 # via imagekit @@ -77,7 +76,9 @@ types-deprecated==1.3.1.20251101 types-python-dateutil==2.9.0.20251115 # via standardwebhooks typing-extensions==4.15.0 + # via aiosignal # via anyio + # via exceptiongroup # via imagekit # via multidict # via pydantic @@ -87,5 +88,5 @@ typing-inspection==0.4.2 # via pydantic wrapt==2.0.1 # via deprecated -yarl==1.20.0 +yarl==1.22.0 # via aiohttp From 4cc96f7a52bd41ad1a2322d90ca9416289a90524 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 13:28:03 +0000 Subject: [PATCH 164/177] chore(internal): codegen related update --- .../types/unsafe_unwrap_webhook_event.py | 22 +++++++++++-------- src/imagekit/types/unwrap_webhook_event.py | 22 +++++++++++-------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/imagekit/types/unsafe_unwrap_webhook_event.py b/src/imagekit/types/unsafe_unwrap_webhook_event.py index c04c98a..9ed05b3 100644 --- a/src/imagekit/types/unsafe_unwrap_webhook_event.py +++ b/src/imagekit/types/unsafe_unwrap_webhook_event.py @@ -1,8 +1,9 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union -from typing_extensions import TypeAlias +from typing_extensions import Annotated, TypeAlias +from .._utils import PropertyInfo from .upload_pre_transform_error_event import UploadPreTransformErrorEvent from .video_transformation_error_event import VideoTransformationErrorEvent from .video_transformation_ready_event import VideoTransformationReadyEvent @@ -13,12 +14,15 @@ __all__ = ["UnsafeUnwrapWebhookEvent"] -UnsafeUnwrapWebhookEvent: TypeAlias = Union[ - VideoTransformationAcceptedEvent, - VideoTransformationReadyEvent, - VideoTransformationErrorEvent, - UploadPreTransformSuccessEvent, - UploadPreTransformErrorEvent, - UploadPostTransformSuccessEvent, - UploadPostTransformErrorEvent, +UnsafeUnwrapWebhookEvent: TypeAlias = Annotated[ + Union[ + VideoTransformationAcceptedEvent, + VideoTransformationReadyEvent, + VideoTransformationErrorEvent, + UploadPreTransformSuccessEvent, + UploadPreTransformErrorEvent, + UploadPostTransformSuccessEvent, + UploadPostTransformErrorEvent, + ], + PropertyInfo(discriminator="type"), ] diff --git a/src/imagekit/types/unwrap_webhook_event.py b/src/imagekit/types/unwrap_webhook_event.py index dddf005..e67355f 100644 --- a/src/imagekit/types/unwrap_webhook_event.py +++ b/src/imagekit/types/unwrap_webhook_event.py @@ -1,8 +1,9 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Union -from typing_extensions import TypeAlias +from typing_extensions import Annotated, TypeAlias +from .._utils import PropertyInfo from .upload_pre_transform_error_event import UploadPreTransformErrorEvent from .video_transformation_error_event import VideoTransformationErrorEvent from .video_transformation_ready_event import VideoTransformationReadyEvent @@ -13,12 +14,15 @@ __all__ = ["UnwrapWebhookEvent"] -UnwrapWebhookEvent: TypeAlias = Union[ - VideoTransformationAcceptedEvent, - VideoTransformationReadyEvent, - VideoTransformationErrorEvent, - UploadPreTransformSuccessEvent, - UploadPreTransformErrorEvent, - UploadPostTransformSuccessEvent, - UploadPostTransformErrorEvent, +UnwrapWebhookEvent: TypeAlias = Annotated[ + Union[ + VideoTransformationAcceptedEvent, + VideoTransformationReadyEvent, + VideoTransformationErrorEvent, + UploadPreTransformSuccessEvent, + UploadPreTransformErrorEvent, + UploadPostTransformSuccessEvent, + UploadPostTransformErrorEvent, + ], + PropertyInfo(discriminator="type"), ] From ed150ba07f86e4bde1efeab25736053cc4cdafa2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 21:23:48 +0000 Subject: [PATCH 165/177] chore(docs): use environment variables for authentication in code snippets --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b05ec1b..1bce528 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/stainless-sdks/imageki Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: ```python +import os import asyncio from imagekit import DefaultAioHttpClient from imagekit import AsyncImageKit @@ -99,8 +100,12 @@ from imagekit import AsyncImageKit async def main() -> None: async with AsyncImageKit( - private_key="My Private Key", - password="My Password", + private_key=os.environ.get( + "IMAGEKIT_PRIVATE_KEY" + ), # This is the default and can be omitted + password=os.environ.get( + "OPTIONAL_IMAGEKIT_IGNORES_THIS" + ), # This is the default and can be omitted http_client=DefaultAioHttpClient(), ) as client: response = await client.files.upload( From e31d9a9e21dc70d4324467f93da188b1b8de3f2c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 09:58:06 +0000 Subject: [PATCH 166/177] feat(api): update package names for Python and PHP targets in configuration --- .stats.yml | 2 +- CONTRIBUTING.md | 2 +- README.md | 52 ++++---- api.md | 116 +++++++++--------- pyproject.toml | 12 +- requirements-dev.lock | 18 +-- requirements.lock | 18 +-- scripts/lint | 2 +- src/{imagekit => imagekitio}/__init__.py | 4 +- src/{imagekit => imagekitio}/_base_client.py | 2 +- src/{imagekit => imagekitio}/_client.py | 0 src/{imagekit => imagekitio}/_compat.py | 0 src/{imagekit => imagekitio}/_constants.py | 0 src/{imagekit => imagekitio}/_exceptions.py | 0 src/{imagekit => imagekitio}/_files.py | 0 src/{imagekit => imagekitio}/_models.py | 0 src/{imagekit => imagekitio}/_qs.py | 0 src/{imagekit => imagekitio}/_resource.py | 0 src/{imagekit => imagekitio}/_response.py | 10 +- src/{imagekit => imagekitio}/_streaming.py | 0 src/{imagekit => imagekitio}/_types.py | 2 +- .../_utils/__init__.py | 0 .../_utils/_compat.py | 0 .../_utils/_datetime_parse.py | 0 src/{imagekit => imagekitio}/_utils/_logs.py | 4 +- src/{imagekit => imagekitio}/_utils/_proxy.py | 0 .../_utils/_reflection.py | 0 .../_utils/_resources_proxy.py | 8 +- .../_utils/_streams.py | 0 src/{imagekit => imagekitio}/_utils/_sync.py | 0 .../_utils/_transform.py | 0 .../_utils/_typing.py | 0 src/{imagekit => imagekitio}/_utils/_utils.py | 0 src/{imagekit => imagekitio}/_version.py | 2 +- src/imagekitio/lib/.keep | 4 + src/{imagekit => imagekitio}/py.typed | 0 .../resources/__init__.py | 0 .../resources/accounts/__init__.py | 0 .../resources/accounts/accounts.py | 0 .../resources/accounts/origins.py | 0 .../resources/accounts/url_endpoints.py | 0 .../resources/accounts/usage.py | 0 .../resources/assets.py | 0 .../resources/beta/__init__.py | 0 .../resources/beta/beta.py | 0 .../resources/beta/v2/__init__.py | 0 .../resources/beta/v2/files.py | 0 .../resources/beta/v2/v2.py | 0 .../resources/cache/__init__.py | 0 .../resources/cache/cache.py | 0 .../resources/cache/invalidation.py | 0 .../resources/custom_metadata_fields.py | 0 .../resources/files/__init__.py | 0 .../resources/files/bulk.py | 0 .../resources/files/files.py | 0 .../resources/files/metadata.py | 0 .../resources/files/versions.py | 0 .../resources/folders/__init__.py | 0 .../resources/folders/folders.py | 0 .../resources/folders/job.py | 0 .../resources/webhooks.py | 4 +- .../types/__init__.py | 0 .../types/accounts/__init__.py | 0 .../types/accounts/origin_create_params.py | 0 .../types/accounts/origin_list_response.py | 0 .../types/accounts/origin_request_param.py | 0 .../types/accounts/origin_response.py | 0 .../types/accounts/origin_update_params.py | 0 .../accounts/url_endpoint_create_params.py | 0 .../accounts/url_endpoint_list_response.py | 0 .../types/accounts/url_endpoint_response.py | 0 .../accounts/url_endpoint_update_params.py | 0 .../types/accounts/usage_get_params.py | 0 .../types/accounts/usage_get_response.py | 0 .../types/asset_list_params.py | 0 .../types/asset_list_response.py | 0 .../types/base_webhook_event.py | 0 .../types/beta/__init__.py | 0 .../types/beta/v2/__init__.py | 0 .../types/beta/v2/file_upload_params.py | 0 .../types/beta/v2/file_upload_response.py | 0 .../types/cache/__init__.py | 0 .../types/cache/invalidation_create_params.py | 0 .../cache/invalidation_create_response.py | 0 .../types/cache/invalidation_get_response.py | 0 .../types/custom_metadata_field.py | 0 .../custom_metadata_field_create_params.py | 0 .../custom_metadata_field_delete_response.py | 0 .../custom_metadata_field_list_params.py | 0 .../custom_metadata_field_list_response.py | 0 .../custom_metadata_field_update_params.py | 0 src/{imagekit => imagekitio}/types/file.py | 0 .../types/file_copy_params.py | 0 .../types/file_copy_response.py | 0 .../types/file_move_params.py | 0 .../types/file_move_response.py | 0 .../types/file_rename_params.py | 0 .../types/file_rename_response.py | 0 .../types/file_update_params.py | 0 .../types/file_update_response.py | 0 .../types/file_upload_params.py | 0 .../types/file_upload_response.py | 0 .../types/files/__init__.py | 0 .../types/files/bulk_add_tags_params.py | 0 .../types/files/bulk_add_tags_response.py | 0 .../types/files/bulk_delete_params.py | 0 .../types/files/bulk_delete_response.py | 0 .../types/files/bulk_remove_ai_tags_params.py | 0 .../files/bulk_remove_ai_tags_response.py | 0 .../types/files/bulk_remove_tags_params.py | 0 .../types/files/bulk_remove_tags_response.py | 0 .../files/metadata_get_from_url_params.py | 0 .../types/files/version_delete_response.py | 0 .../types/files/version_list_response.py | 0 src/{imagekit => imagekitio}/types/folder.py | 0 .../types/folder_copy_params.py | 0 .../types/folder_copy_response.py | 0 .../types/folder_create_params.py | 0 .../types/folder_create_response.py | 0 .../types/folder_delete_params.py | 0 .../types/folder_delete_response.py | 0 .../types/folder_move_params.py | 0 .../types/folder_move_response.py | 0 .../types/folder_rename_params.py | 0 .../types/folder_rename_response.py | 0 .../types/folders/__init__.py | 0 .../types/folders/job_get_response.py | 0 .../types/metadata.py | 0 .../types/shared/__init__.py | 0 .../types/shared/base_overlay.py | 0 .../types/shared/extensions.py | 0 .../shared/get_image_attributes_options.py | 0 .../types/shared/image_overlay.py | 0 .../types/shared/overlay.py | 0 .../types/shared/overlay_position.py | 0 .../types/shared/overlay_timing.py | 0 .../shared/responsive_image_attributes.py | 0 .../types/shared/solid_color_overlay.py | 0 .../solid_color_overlay_transformation.py | 0 .../types/shared/src_options.py | 0 .../types/shared/streaming_resolution.py | 0 .../types/shared/subtitle_overlay.py | 0 .../shared/subtitle_overlay_transformation.py | 0 .../types/shared/text_overlay.py | 0 .../shared/text_overlay_transformation.py | 0 .../types/shared/transformation.py | 0 .../types/shared/transformation_position.py | 0 .../types/shared/video_overlay.py | 0 .../types/shared_params/__init__.py | 0 .../types/shared_params/extensions.py | 0 .../types/unsafe_unwrap_webhook_event.py | 0 .../types/unwrap_webhook_event.py | 0 .../types/update_file_request_param.py | 0 .../upload_post_transform_error_event.py | 0 .../upload_post_transform_success_event.py | 0 .../types/upload_pre_transform_error_event.py | 0 .../upload_pre_transform_success_event.py | 0 .../video_transformation_accepted_event.py | 0 .../types/video_transformation_error_event.py | 0 .../types/video_transformation_ready_event.py | 0 tests/api_resources/accounts/test_origins.py | 4 +- .../accounts/test_url_endpoints.py | 4 +- tests/api_resources/accounts/test_usage.py | 6 +- tests/api_resources/beta/v2/test_files.py | 4 +- .../api_resources/cache/test_invalidation.py | 4 +- tests/api_resources/files/test_bulk.py | 4 +- tests/api_resources/files/test_metadata.py | 4 +- tests/api_resources/files/test_versions.py | 6 +- tests/api_resources/folders/test_job.py | 4 +- tests/api_resources/test_assets.py | 4 +- .../test_custom_metadata_fields.py | 4 +- tests/api_resources/test_files.py | 4 +- tests/api_resources/test_folders.py | 4 +- tests/api_resources/test_webhooks.py | 2 +- tests/conftest.py | 6 +- tests/test_client.py | 44 +++---- tests/test_deepcopy.py | 2 +- tests/test_extract_files.py | 4 +- tests/test_files.py | 2 +- tests/test_models.py | 6 +- tests/test_qs.py | 2 +- tests/test_required_args.py | 2 +- tests/test_response.py | 14 +-- tests/test_streaming.py | 4 +- tests/test_transform.py | 8 +- tests/test_utils/test_datetime_parse.py | 2 +- tests/test_utils/test_proxy.py | 2 +- tests/test_utils/test_typing.py | 2 +- tests/utils.py | 8 +- 189 files changed, 219 insertions(+), 209 deletions(-) rename src/{imagekit => imagekitio}/__init__.py (95%) rename src/{imagekit => imagekitio}/_base_client.py (99%) rename src/{imagekit => imagekitio}/_client.py (100%) rename src/{imagekit => imagekitio}/_compat.py (100%) rename src/{imagekit => imagekitio}/_constants.py (100%) rename src/{imagekit => imagekitio}/_exceptions.py (100%) rename src/{imagekit => imagekitio}/_files.py (100%) rename src/{imagekit => imagekitio}/_models.py (100%) rename src/{imagekit => imagekitio}/_qs.py (100%) rename src/{imagekit => imagekitio}/_resource.py (100%) rename src/{imagekit => imagekitio}/_response.py (98%) rename src/{imagekit => imagekitio}/_streaming.py (100%) rename src/{imagekit => imagekitio}/_types.py (99%) rename src/{imagekit => imagekitio}/_utils/__init__.py (100%) rename src/{imagekit => imagekitio}/_utils/_compat.py (100%) rename src/{imagekit => imagekitio}/_utils/_datetime_parse.py (100%) rename src/{imagekit => imagekitio}/_utils/_logs.py (76%) rename src/{imagekit => imagekitio}/_utils/_proxy.py (100%) rename src/{imagekit => imagekitio}/_utils/_reflection.py (100%) rename src/{imagekit => imagekitio}/_utils/_resources_proxy.py (52%) rename src/{imagekit => imagekitio}/_utils/_streams.py (100%) rename src/{imagekit => imagekitio}/_utils/_sync.py (100%) rename src/{imagekit => imagekitio}/_utils/_transform.py (100%) rename src/{imagekit => imagekitio}/_utils/_typing.py (100%) rename src/{imagekit => imagekitio}/_utils/_utils.py (100%) rename src/{imagekit => imagekitio}/_version.py (81%) create mode 100644 src/imagekitio/lib/.keep rename src/{imagekit => imagekitio}/py.typed (100%) rename src/{imagekit => imagekitio}/resources/__init__.py (100%) rename src/{imagekit => imagekitio}/resources/accounts/__init__.py (100%) rename src/{imagekit => imagekitio}/resources/accounts/accounts.py (100%) rename src/{imagekit => imagekitio}/resources/accounts/origins.py (100%) rename src/{imagekit => imagekitio}/resources/accounts/url_endpoints.py (100%) rename src/{imagekit => imagekitio}/resources/accounts/usage.py (100%) rename src/{imagekit => imagekitio}/resources/assets.py (100%) rename src/{imagekit => imagekitio}/resources/beta/__init__.py (100%) rename src/{imagekit => imagekitio}/resources/beta/beta.py (100%) rename src/{imagekit => imagekitio}/resources/beta/v2/__init__.py (100%) rename src/{imagekit => imagekitio}/resources/beta/v2/files.py (100%) rename src/{imagekit => imagekitio}/resources/beta/v2/v2.py (100%) rename src/{imagekit => imagekitio}/resources/cache/__init__.py (100%) rename src/{imagekit => imagekitio}/resources/cache/cache.py (100%) rename src/{imagekit => imagekitio}/resources/cache/invalidation.py (100%) rename src/{imagekit => imagekitio}/resources/custom_metadata_fields.py (100%) rename src/{imagekit => imagekitio}/resources/files/__init__.py (100%) rename src/{imagekit => imagekitio}/resources/files/bulk.py (100%) rename src/{imagekit => imagekitio}/resources/files/files.py (100%) rename src/{imagekit => imagekitio}/resources/files/metadata.py (100%) rename src/{imagekit => imagekitio}/resources/files/versions.py (100%) rename src/{imagekit => imagekitio}/resources/folders/__init__.py (100%) rename src/{imagekit => imagekitio}/resources/folders/folders.py (100%) rename src/{imagekit => imagekitio}/resources/folders/job.py (100%) rename src/{imagekit => imagekitio}/resources/webhooks.py (92%) rename src/{imagekit => imagekitio}/types/__init__.py (100%) rename src/{imagekit => imagekitio}/types/accounts/__init__.py (100%) rename src/{imagekit => imagekitio}/types/accounts/origin_create_params.py (100%) rename src/{imagekit => imagekitio}/types/accounts/origin_list_response.py (100%) rename src/{imagekit => imagekitio}/types/accounts/origin_request_param.py (100%) rename src/{imagekit => imagekitio}/types/accounts/origin_response.py (100%) rename src/{imagekit => imagekitio}/types/accounts/origin_update_params.py (100%) rename src/{imagekit => imagekitio}/types/accounts/url_endpoint_create_params.py (100%) rename src/{imagekit => imagekitio}/types/accounts/url_endpoint_list_response.py (100%) rename src/{imagekit => imagekitio}/types/accounts/url_endpoint_response.py (100%) rename src/{imagekit => imagekitio}/types/accounts/url_endpoint_update_params.py (100%) rename src/{imagekit => imagekitio}/types/accounts/usage_get_params.py (100%) rename src/{imagekit => imagekitio}/types/accounts/usage_get_response.py (100%) rename src/{imagekit => imagekitio}/types/asset_list_params.py (100%) rename src/{imagekit => imagekitio}/types/asset_list_response.py (100%) rename src/{imagekit => imagekitio}/types/base_webhook_event.py (100%) rename src/{imagekit => imagekitio}/types/beta/__init__.py (100%) rename src/{imagekit => imagekitio}/types/beta/v2/__init__.py (100%) rename src/{imagekit => imagekitio}/types/beta/v2/file_upload_params.py (100%) rename src/{imagekit => imagekitio}/types/beta/v2/file_upload_response.py (100%) rename src/{imagekit => imagekitio}/types/cache/__init__.py (100%) rename src/{imagekit => imagekitio}/types/cache/invalidation_create_params.py (100%) rename src/{imagekit => imagekitio}/types/cache/invalidation_create_response.py (100%) rename src/{imagekit => imagekitio}/types/cache/invalidation_get_response.py (100%) rename src/{imagekit => imagekitio}/types/custom_metadata_field.py (100%) rename src/{imagekit => imagekitio}/types/custom_metadata_field_create_params.py (100%) rename src/{imagekit => imagekitio}/types/custom_metadata_field_delete_response.py (100%) rename src/{imagekit => imagekitio}/types/custom_metadata_field_list_params.py (100%) rename src/{imagekit => imagekitio}/types/custom_metadata_field_list_response.py (100%) rename src/{imagekit => imagekitio}/types/custom_metadata_field_update_params.py (100%) rename src/{imagekit => imagekitio}/types/file.py (100%) rename src/{imagekit => imagekitio}/types/file_copy_params.py (100%) rename src/{imagekit => imagekitio}/types/file_copy_response.py (100%) rename src/{imagekit => imagekitio}/types/file_move_params.py (100%) rename src/{imagekit => imagekitio}/types/file_move_response.py (100%) rename src/{imagekit => imagekitio}/types/file_rename_params.py (100%) rename src/{imagekit => imagekitio}/types/file_rename_response.py (100%) rename src/{imagekit => imagekitio}/types/file_update_params.py (100%) rename src/{imagekit => imagekitio}/types/file_update_response.py (100%) rename src/{imagekit => imagekitio}/types/file_upload_params.py (100%) rename src/{imagekit => imagekitio}/types/file_upload_response.py (100%) rename src/{imagekit => imagekitio}/types/files/__init__.py (100%) rename src/{imagekit => imagekitio}/types/files/bulk_add_tags_params.py (100%) rename src/{imagekit => imagekitio}/types/files/bulk_add_tags_response.py (100%) rename src/{imagekit => imagekitio}/types/files/bulk_delete_params.py (100%) rename src/{imagekit => imagekitio}/types/files/bulk_delete_response.py (100%) rename src/{imagekit => imagekitio}/types/files/bulk_remove_ai_tags_params.py (100%) rename src/{imagekit => imagekitio}/types/files/bulk_remove_ai_tags_response.py (100%) rename src/{imagekit => imagekitio}/types/files/bulk_remove_tags_params.py (100%) rename src/{imagekit => imagekitio}/types/files/bulk_remove_tags_response.py (100%) rename src/{imagekit => imagekitio}/types/files/metadata_get_from_url_params.py (100%) rename src/{imagekit => imagekitio}/types/files/version_delete_response.py (100%) rename src/{imagekit => imagekitio}/types/files/version_list_response.py (100%) rename src/{imagekit => imagekitio}/types/folder.py (100%) rename src/{imagekit => imagekitio}/types/folder_copy_params.py (100%) rename src/{imagekit => imagekitio}/types/folder_copy_response.py (100%) rename src/{imagekit => imagekitio}/types/folder_create_params.py (100%) rename src/{imagekit => imagekitio}/types/folder_create_response.py (100%) rename src/{imagekit => imagekitio}/types/folder_delete_params.py (100%) rename src/{imagekit => imagekitio}/types/folder_delete_response.py (100%) rename src/{imagekit => imagekitio}/types/folder_move_params.py (100%) rename src/{imagekit => imagekitio}/types/folder_move_response.py (100%) rename src/{imagekit => imagekitio}/types/folder_rename_params.py (100%) rename src/{imagekit => imagekitio}/types/folder_rename_response.py (100%) rename src/{imagekit => imagekitio}/types/folders/__init__.py (100%) rename src/{imagekit => imagekitio}/types/folders/job_get_response.py (100%) rename src/{imagekit => imagekitio}/types/metadata.py (100%) rename src/{imagekit => imagekitio}/types/shared/__init__.py (100%) rename src/{imagekit => imagekitio}/types/shared/base_overlay.py (100%) rename src/{imagekit => imagekitio}/types/shared/extensions.py (100%) rename src/{imagekit => imagekitio}/types/shared/get_image_attributes_options.py (100%) rename src/{imagekit => imagekitio}/types/shared/image_overlay.py (100%) rename src/{imagekit => imagekitio}/types/shared/overlay.py (100%) rename src/{imagekit => imagekitio}/types/shared/overlay_position.py (100%) rename src/{imagekit => imagekitio}/types/shared/overlay_timing.py (100%) rename src/{imagekit => imagekitio}/types/shared/responsive_image_attributes.py (100%) rename src/{imagekit => imagekitio}/types/shared/solid_color_overlay.py (100%) rename src/{imagekit => imagekitio}/types/shared/solid_color_overlay_transformation.py (100%) rename src/{imagekit => imagekitio}/types/shared/src_options.py (100%) rename src/{imagekit => imagekitio}/types/shared/streaming_resolution.py (100%) rename src/{imagekit => imagekitio}/types/shared/subtitle_overlay.py (100%) rename src/{imagekit => imagekitio}/types/shared/subtitle_overlay_transformation.py (100%) rename src/{imagekit => imagekitio}/types/shared/text_overlay.py (100%) rename src/{imagekit => imagekitio}/types/shared/text_overlay_transformation.py (100%) rename src/{imagekit => imagekitio}/types/shared/transformation.py (100%) rename src/{imagekit => imagekitio}/types/shared/transformation_position.py (100%) rename src/{imagekit => imagekitio}/types/shared/video_overlay.py (100%) rename src/{imagekit => imagekitio}/types/shared_params/__init__.py (100%) rename src/{imagekit => imagekitio}/types/shared_params/extensions.py (100%) rename src/{imagekit => imagekitio}/types/unsafe_unwrap_webhook_event.py (100%) rename src/{imagekit => imagekitio}/types/unwrap_webhook_event.py (100%) rename src/{imagekit => imagekitio}/types/update_file_request_param.py (100%) rename src/{imagekit => imagekitio}/types/upload_post_transform_error_event.py (100%) rename src/{imagekit => imagekitio}/types/upload_post_transform_success_event.py (100%) rename src/{imagekit => imagekitio}/types/upload_pre_transform_error_event.py (100%) rename src/{imagekit => imagekitio}/types/upload_pre_transform_success_event.py (100%) rename src/{imagekit => imagekitio}/types/video_transformation_accepted_event.py (100%) rename src/{imagekit => imagekitio}/types/video_transformation_error_event.py (100%) rename src/{imagekit => imagekitio}/types/video_transformation_ready_event.py (100%) diff --git a/.stats.yml b/.stats.yml index ae3aead..8577a4c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml openapi_spec_hash: a9aa620376fce66532c84f9364209b0b -config_hash: eb4cf65a4c6b26a2901076eff5810d5d +config_hash: 10b48f323ed534664483af1952174d52 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a133f19..edd1f2b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,7 +36,7 @@ $ pip install -r requirements-dev.lock Most of the SDK is generated code. Modifications to code will be persisted between generations, but may result in merge conflicts between manual patches and changes from the generator. The generator will never -modify the contents of the `src/imagekit/lib/` and `examples/` directories. +modify the contents of the `src/imagekitio/lib/` and `examples/` directories. ## Adding and running examples diff --git a/README.md b/README.md index 1bce528..71aab7e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Image Kit Python API library -[![PyPI version](https://img.shields.io/pypi/v/imagekit.svg?label=pypi%20(stable))](https://pypi.org/project/imagekit/) +[![PyPI version](https://img.shields.io/pypi/v/imagekitio.svg?label=pypi%20(stable))](https://pypi.org/project/imagekitio/) The Image Kit Python library provides convenient access to the Image Kit REST API from any Python 3.9+ application. The library includes type definitions for all request params and response fields, @@ -19,7 +19,7 @@ pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git ``` > [!NOTE] -> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install imagekit` +> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install imagekitio` ## Usage @@ -27,7 +27,7 @@ The full API of this library can be found in [api.md](api.md). ```python import os -from imagekit import ImageKit +from imagekitio import ImageKit client = ImageKit( private_key=os.environ.get("IMAGEKIT_PRIVATE_KEY"), # This is the default and can be omitted @@ -55,7 +55,7 @@ Simply import `AsyncImageKit` instead of `ImageKit` and use `await` with each AP ```python import os import asyncio -from imagekit import AsyncImageKit +from imagekitio import AsyncImageKit client = AsyncImageKit( private_key=os.environ.get("IMAGEKIT_PRIVATE_KEY"), # This is the default and can be omitted @@ -86,7 +86,7 @@ You can enable this by installing `aiohttp`: ```sh # install from this staging repo -pip install 'imagekit[aiohttp] @ git+ssh://git@github.com/stainless-sdks/imagekit-python.git' +pip install 'imagekitio[aiohttp] @ git+ssh://git@github.com/stainless-sdks/imagekit-python.git' ``` Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: @@ -94,8 +94,8 @@ Then you can enable it by instantiating the client with `http_client=DefaultAioH ```python import os import asyncio -from imagekit import DefaultAioHttpClient -from imagekit import AsyncImageKit +from imagekitio import DefaultAioHttpClient +from imagekitio import AsyncImageKit async def main() -> None: @@ -132,7 +132,7 @@ Typed requests and responses provide autocomplete and documentation within your Nested parameters are dictionaries, typed using `TypedDict`, for example: ```python -from imagekit import ImageKit +from imagekitio import ImageKit client = ImageKit() @@ -162,7 +162,7 @@ Request parameters that correspond to file uploads can be passed as `bytes`, or ```python from pathlib import Path -from imagekit import ImageKit +from imagekitio import ImageKit client = ImageKit() @@ -176,16 +176,16 @@ The async client uses the exact same interface. If you pass a [`PathLike`](https ## Handling errors -When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `imagekit.APIConnectionError` is raised. +When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `imagekitio.APIConnectionError` is raised. When the API returns a non-success status code (that is, 4xx or 5xx -response), a subclass of `imagekit.APIStatusError` is raised, containing `status_code` and `response` properties. +response), a subclass of `imagekitio.APIStatusError` is raised, containing `status_code` and `response` properties. -All errors inherit from `imagekit.APIError`. +All errors inherit from `imagekitio.APIError`. ```python -import imagekit -from imagekit import ImageKit +import imagekitio +from imagekitio import ImageKit client = ImageKit() @@ -194,12 +194,12 @@ try: file=b"https://www.example.com/public-url.jpg", file_name="file-name.jpg", ) -except imagekit.APIConnectionError as e: +except imagekitio.APIConnectionError as e: print("The server could not be reached") print(e.__cause__) # an underlying Exception, likely raised within httpx. -except imagekit.RateLimitError as e: +except imagekitio.RateLimitError as e: print("A 429 status code was received; we should back off a bit.") -except imagekit.APIStatusError as e: +except imagekitio.APIStatusError as e: print("Another non-200-range status code was received") print(e.status_code) print(e.response) @@ -227,7 +227,7 @@ Connection errors (for example, due to a network connectivity problem), 408 Requ You can use the `max_retries` option to configure or disable retry settings: ```python -from imagekit import ImageKit +from imagekitio import ImageKit # Configure the default for all requests: client = ImageKit( @@ -248,7 +248,7 @@ By default requests time out after 1 minute. You can configure this with a `time which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object: ```python -from imagekit import ImageKit +from imagekitio import ImageKit # Configure the default for all requests: client = ImageKit( @@ -303,7 +303,7 @@ if response.my_field is None: The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g., ```py -from imagekit import ImageKit +from imagekitio import ImageKit client = ImageKit() response = client.files.with_raw_response.upload( @@ -316,9 +316,9 @@ file = response.parse() # get the object that `files.upload()` would have retur print(file.video_codec) ``` -These methods return an [`APIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekit/_response.py) object. +These methods return an [`APIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekitio/_response.py) object. -The async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekit/_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/stainless-sdks/imagekit-python/tree/main/src/imagekitio/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. #### `.with_streaming_response` @@ -383,7 +383,7 @@ You can directly override the [httpx client](https://www.python-httpx.org/api/#c ```python import httpx -from imagekit import ImageKit, DefaultHttpxClient +from imagekitio import ImageKit, DefaultHttpxClient client = ImageKit( # Or use the `IMAGE_KIT_BASE_URL` env var @@ -406,7 +406,7 @@ client.with_options(http_client=DefaultHttpxClient(...)) By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting. ```py -from imagekit import ImageKit +from imagekitio import ImageKit with ImageKit() as client: # make requests here @@ -434,8 +434,8 @@ If you've upgraded to the latest version but aren't seeing any new features you You can determine the version that is being used at runtime with: ```py -import imagekit -print(imagekit.__version__) +import imagekitio +print(imagekitio.__version__) ``` ## Requirements diff --git a/api.md b/api.md index 2859068..b617936 100644 --- a/api.md +++ b/api.md @@ -1,7 +1,7 @@ # Shared Types ```python -from imagekit.types import ( +from imagekitio.types import ( BaseOverlay, Extensions, GetImageAttributesOptions, @@ -29,7 +29,7 @@ from imagekit.types import ( Types: ```python -from imagekit.types import ( +from imagekitio.types import ( CustomMetadataField, CustomMetadataFieldListResponse, CustomMetadataFieldDeleteResponse, @@ -38,17 +38,17 @@ from imagekit.types import ( Methods: -- client.custom_metadata_fields.create(\*\*params) -> CustomMetadataField -- client.custom_metadata_fields.update(id, \*\*params) -> CustomMetadataField -- client.custom_metadata_fields.list(\*\*params) -> CustomMetadataFieldListResponse -- client.custom_metadata_fields.delete(id) -> CustomMetadataFieldDeleteResponse +- client.custom_metadata_fields.create(\*\*params) -> CustomMetadataField +- client.custom_metadata_fields.update(id, \*\*params) -> CustomMetadataField +- client.custom_metadata_fields.list(\*\*params) -> CustomMetadataFieldListResponse +- client.custom_metadata_fields.delete(id) -> CustomMetadataFieldDeleteResponse # Files Types: ```python -from imagekit.types import ( +from imagekitio.types import ( File, Folder, Metadata, @@ -63,20 +63,20 @@ from imagekit.types import ( Methods: -- client.files.update(file_id, \*\*params) -> FileUpdateResponse -- client.files.delete(file_id) -> None -- client.files.copy(\*\*params) -> FileCopyResponse -- client.files.get(file_id) -> File -- client.files.move(\*\*params) -> FileMoveResponse -- client.files.rename(\*\*params) -> FileRenameResponse -- client.files.upload(\*\*params) -> FileUploadResponse +- client.files.update(file_id, \*\*params) -> FileUpdateResponse +- client.files.delete(file_id) -> None +- client.files.copy(\*\*params) -> FileCopyResponse +- client.files.get(file_id) -> File +- client.files.move(\*\*params) -> FileMoveResponse +- client.files.rename(\*\*params) -> FileRenameResponse +- client.files.upload(\*\*params) -> FileUploadResponse ## Bulk Types: ```python -from imagekit.types.files import ( +from imagekitio.types.files import ( BulkDeleteResponse, BulkAddTagsResponse, BulkRemoveAITagsResponse, @@ -86,44 +86,44 @@ from imagekit.types.files import ( Methods: -- client.files.bulk.delete(\*\*params) -> BulkDeleteResponse -- client.files.bulk.add_tags(\*\*params) -> BulkAddTagsResponse -- client.files.bulk.remove_ai_tags(\*\*params) -> BulkRemoveAITagsResponse -- client.files.bulk.remove_tags(\*\*params) -> BulkRemoveTagsResponse +- client.files.bulk.delete(\*\*params) -> BulkDeleteResponse +- client.files.bulk.add_tags(\*\*params) -> BulkAddTagsResponse +- client.files.bulk.remove_ai_tags(\*\*params) -> BulkRemoveAITagsResponse +- client.files.bulk.remove_tags(\*\*params) -> BulkRemoveTagsResponse ## Versions Types: ```python -from imagekit.types.files import VersionListResponse, VersionDeleteResponse +from imagekitio.types.files import VersionListResponse, VersionDeleteResponse ``` Methods: -- client.files.versions.list(file_id) -> VersionListResponse -- client.files.versions.delete(version_id, \*, file_id) -> VersionDeleteResponse -- client.files.versions.get(version_id, \*, file_id) -> File -- client.files.versions.restore(version_id, \*, file_id) -> File +- client.files.versions.list(file_id) -> VersionListResponse +- client.files.versions.delete(version_id, \*, file_id) -> VersionDeleteResponse +- client.files.versions.get(version_id, \*, file_id) -> File +- client.files.versions.restore(version_id, \*, file_id) -> File ## Metadata Methods: -- client.files.metadata.get(file_id) -> Metadata -- client.files.metadata.get_from_url(\*\*params) -> Metadata +- client.files.metadata.get(file_id) -> Metadata +- client.files.metadata.get_from_url(\*\*params) -> Metadata # Assets Types: ```python -from imagekit.types import AssetListResponse +from imagekitio.types import AssetListResponse ``` Methods: -- client.assets.list(\*\*params) -> AssetListResponse +- client.assets.list(\*\*params) -> AssetListResponse # Cache @@ -132,20 +132,20 @@ Methods: Types: ```python -from imagekit.types.cache import InvalidationCreateResponse, InvalidationGetResponse +from imagekitio.types.cache import InvalidationCreateResponse, InvalidationGetResponse ``` Methods: -- client.cache.invalidation.create(\*\*params) -> InvalidationCreateResponse -- client.cache.invalidation.get(request_id) -> InvalidationGetResponse +- client.cache.invalidation.create(\*\*params) -> InvalidationCreateResponse +- client.cache.invalidation.get(request_id) -> InvalidationGetResponse # Folders Types: ```python -from imagekit.types import ( +from imagekitio.types import ( FolderCreateResponse, FolderDeleteResponse, FolderCopyResponse, @@ -156,23 +156,23 @@ from imagekit.types import ( Methods: -- client.folders.create(\*\*params) -> FolderCreateResponse -- client.folders.delete(\*\*params) -> FolderDeleteResponse -- client.folders.copy(\*\*params) -> FolderCopyResponse -- client.folders.move(\*\*params) -> FolderMoveResponse -- client.folders.rename(\*\*params) -> FolderRenameResponse +- client.folders.create(\*\*params) -> FolderCreateResponse +- client.folders.delete(\*\*params) -> FolderDeleteResponse +- client.folders.copy(\*\*params) -> FolderCopyResponse +- client.folders.move(\*\*params) -> FolderMoveResponse +- client.folders.rename(\*\*params) -> FolderRenameResponse ## Job Types: ```python -from imagekit.types.folders import JobGetResponse +from imagekitio.types.folders import JobGetResponse ``` Methods: -- client.folders.job.get(job_id) -> JobGetResponse +- client.folders.job.get(job_id) -> JobGetResponse # Accounts @@ -181,44 +181,48 @@ Methods: Types: ```python -from imagekit.types.accounts import UsageGetResponse +from imagekitio.types.accounts import UsageGetResponse ``` Methods: -- client.accounts.usage.get(\*\*params) -> UsageGetResponse +- client.accounts.usage.get(\*\*params) -> UsageGetResponse ## Origins Types: ```python -from imagekit.types.accounts import OriginRequest, OriginResponse, OriginListResponse +from imagekitio.types.accounts import OriginRequest, OriginResponse, OriginListResponse ``` Methods: -- client.accounts.origins.create(\*\*params) -> OriginResponse -- client.accounts.origins.update(id, \*\*params) -> OriginResponse -- client.accounts.origins.list() -> OriginListResponse -- client.accounts.origins.delete(id) -> None -- client.accounts.origins.get(id) -> OriginResponse +- client.accounts.origins.create(\*\*params) -> OriginResponse +- client.accounts.origins.update(id, \*\*params) -> OriginResponse +- client.accounts.origins.list() -> OriginListResponse +- client.accounts.origins.delete(id) -> None +- client.accounts.origins.get(id) -> OriginResponse ## URLEndpoints Types: ```python -from imagekit.types.accounts import URLEndpointRequest, URLEndpointResponse, URLEndpointListResponse +from imagekitio.types.accounts import ( + URLEndpointRequest, + URLEndpointResponse, + URLEndpointListResponse, +) ``` Methods: -- client.accounts.url_endpoints.create(\*\*params) -> URLEndpointResponse -- client.accounts.url_endpoints.update(id, \*\*params) -> URLEndpointResponse -- client.accounts.url_endpoints.list() -> URLEndpointListResponse -- client.accounts.url_endpoints.delete(id) -> None -- client.accounts.url_endpoints.get(id) -> URLEndpointResponse +- client.accounts.url_endpoints.create(\*\*params) -> URLEndpointResponse +- client.accounts.url_endpoints.update(id, \*\*params) -> URLEndpointResponse +- client.accounts.url_endpoints.list() -> URLEndpointListResponse +- client.accounts.url_endpoints.delete(id) -> None +- client.accounts.url_endpoints.get(id) -> URLEndpointResponse # Beta @@ -229,19 +233,19 @@ Methods: Types: ```python -from imagekit.types.beta.v2 import FileUploadResponse +from imagekitio.types.beta.v2 import FileUploadResponse ``` Methods: -- client.beta.v2.files.upload(\*\*params) -> FileUploadResponse +- client.beta.v2.files.upload(\*\*params) -> FileUploadResponse # Webhooks Types: ```python -from imagekit.types import ( +from imagekitio.types import ( BaseWebhookEvent, UploadPostTransformErrorEvent, UploadPostTransformSuccessEvent, diff --git a/pyproject.toml b/pyproject.toml index f8292d9..43ba273 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "imagekit" +name = "imagekitio" version = "0.0.1" description = "The official Python library for the ImageKit API" dynamic = ["readme"] @@ -81,14 +81,14 @@ format = { chain = [ "check:ruff" = "ruff check ." "fix:ruff" = "ruff check --fix ." -"check:importable" = "python -c 'import imagekit'" +"check:importable" = "python -c 'import imagekitio'" typecheck = { chain = [ "typecheck:pyright", "typecheck:mypy" ]} "typecheck:pyright" = "pyright" -"typecheck:verify-types" = "pyright --verifytypes imagekit --ignoreexternal" +"typecheck:verify-types" = "pyright --verifytypes imagekitio --ignoreexternal" "typecheck:mypy" = "mypy ." [build-system] @@ -101,7 +101,7 @@ include = [ ] [tool.hatch.build.targets.wheel] -packages = ["src/imagekit"] +packages = ["src/imagekitio"] [tool.hatch.build.targets.sdist] # Basically everything except hidden files/directories (such as .github, .devcontainers, .python-version, etc) @@ -169,7 +169,7 @@ show_error_codes = true # # We also exclude our `tests` as mypy doesn't always infer # types correctly and Pyright will still catch any type errors. -exclude = ['src/imagekit/_files.py', '_dev/.*.py', 'tests/.*'] +exclude = ['src/imagekitio/_files.py', '_dev/.*.py', 'tests/.*'] strict_equality = true implicit_reexport = true @@ -261,7 +261,7 @@ length-sort = true length-sort-straight = true combine-as-imports = true extra-standard-library = ["typing_extensions"] -known-first-party = ["imagekit", "tests"] +known-first-party = ["imagekitio", "tests"] [tool.ruff.lint.per-file-ignores] "bin/**.py" = ["T201", "T203"] diff --git a/requirements-dev.lock b/requirements-dev.lock index 60a0cd8..c34becb 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -14,14 +14,14 @@ aiohappyeyeballs==2.6.1 # via aiohttp aiohttp==3.13.2 # via httpx-aiohttp - # via imagekit + # via imagekitio aiosignal==1.4.0 # via aiohttp annotated-types==0.7.0 # via pydantic anyio==4.12.0 # via httpx - # via imagekit + # via imagekitio argcomplete==3.6.3 # via nox async-timeout==5.0.1 @@ -45,7 +45,7 @@ dirty-equals==0.11 distlib==0.4.0 # via virtualenv distro==1.9.0 - # via imagekit + # via imagekitio exceptiongroup==1.3.1 # via anyio # via pytest @@ -62,11 +62,11 @@ httpcore==1.0.9 # via httpx httpx==0.28.1 # via httpx-aiohttp - # via imagekit + # via imagekitio # via respx # via standardwebhooks httpx-aiohttp==0.1.9 - # via imagekit + # via imagekitio humanize==4.13.0 # via nox idna==3.11 @@ -103,7 +103,7 @@ propcache==0.4.1 # via aiohttp # via yarl pydantic==2.12.5 - # via imagekit + # via imagekitio pydantic-core==2.41.5 # via pydantic pygments==2.19.2 @@ -124,9 +124,9 @@ ruff==0.14.7 six==1.17.0 # via python-dateutil sniffio==1.3.1 - # via imagekit + # via imagekitio standardwebhooks==1.0.0 - # via imagekit + # via imagekitio time-machine==2.19.0 tomli==2.3.0 # via dependency-groups @@ -141,7 +141,7 @@ typing-extensions==4.15.0 # via aiosignal # via anyio # via exceptiongroup - # via imagekit + # via imagekitio # via multidict # via mypy # via pydantic diff --git a/requirements.lock b/requirements.lock index e27dab0..acc82f8 100644 --- a/requirements.lock +++ b/requirements.lock @@ -14,14 +14,14 @@ aiohappyeyeballs==2.6.1 # via aiohttp aiohttp==3.13.2 # via httpx-aiohttp - # via imagekit + # via imagekitio aiosignal==1.4.0 # via aiohttp annotated-types==0.7.0 # via pydantic anyio==4.12.0 # via httpx - # via imagekit + # via imagekitio async-timeout==5.0.1 # via aiohttp attrs==25.4.0 @@ -33,7 +33,7 @@ certifi==2025.11.12 deprecated==1.3.1 # via standardwebhooks distro==1.9.0 - # via imagekit + # via imagekitio exceptiongroup==1.3.1 # via anyio frozenlist==1.8.0 @@ -45,10 +45,10 @@ httpcore==1.0.9 # via httpx httpx==0.28.1 # via httpx-aiohttp - # via imagekit + # via imagekitio # via standardwebhooks httpx-aiohttp==0.1.9 - # via imagekit + # via imagekitio idna==3.11 # via anyio # via httpx @@ -60,7 +60,7 @@ propcache==0.4.1 # via aiohttp # via yarl pydantic==2.12.5 - # via imagekit + # via imagekitio pydantic-core==2.41.5 # via pydantic python-dateutil==2.9.0.post0 @@ -68,9 +68,9 @@ python-dateutil==2.9.0.post0 six==1.17.0 # via python-dateutil sniffio==1.3.1 - # via imagekit + # via imagekitio standardwebhooks==1.0.0 - # via imagekit + # via imagekitio types-deprecated==1.3.1.20251101 # via standardwebhooks types-python-dateutil==2.9.0.20251115 @@ -79,7 +79,7 @@ typing-extensions==4.15.0 # via aiosignal # via anyio # via exceptiongroup - # via imagekit + # via imagekitio # via multidict # via pydantic # via pydantic-core diff --git a/scripts/lint b/scripts/lint index 3a31c2a..eb9a4dd 100755 --- a/scripts/lint +++ b/scripts/lint @@ -8,4 +8,4 @@ echo "==> Running lints" rye run lint echo "==> Making sure it imports" -rye run python -c 'import imagekit' +rye run python -c 'import imagekitio' diff --git a/src/imagekit/__init__.py b/src/imagekitio/__init__.py similarity index 95% rename from src/imagekit/__init__.py rename to src/imagekitio/__init__.py index 335e8f0..9041632 100644 --- a/src/imagekit/__init__.py +++ b/src/imagekitio/__init__.py @@ -93,12 +93,12 @@ # Update the __module__ attribute for exported symbols so that # error messages point to this module instead of the module # it was originally defined in, e.g. -# imagekit._exceptions.NotFoundError -> imagekit.NotFoundError +# imagekitio._exceptions.NotFoundError -> imagekitio.NotFoundError __locals = locals() for __name in __all__: if not __name.startswith("__"): try: - __locals[__name].__module__ = "imagekit" + __locals[__name].__module__ = "imagekitio" except (TypeError, AttributeError): # Some of our exported symbols are builtins which we can't set attributes for. pass diff --git a/src/imagekit/_base_client.py b/src/imagekitio/_base_client.py similarity index 99% rename from src/imagekit/_base_client.py rename to src/imagekitio/_base_client.py index cde8075..384e7c0 100644 --- a/src/imagekit/_base_client.py +++ b/src/imagekitio/_base_client.py @@ -389,7 +389,7 @@ def __init__( if max_retries is None: # pyright: ignore[reportUnnecessaryComparison] raise TypeError( - "max_retries cannot be None. If you want to disable retries, pass `0`; if you want unlimited retries, pass `math.inf` or a very high number; if you want the default behavior, pass `imagekit.DEFAULT_MAX_RETRIES`" + "max_retries cannot be None. If you want to disable retries, pass `0`; if you want unlimited retries, pass `math.inf` or a very high number; if you want the default behavior, pass `imagekitio.DEFAULT_MAX_RETRIES`" ) def _enforce_trailing_slash(self, url: URL) -> URL: diff --git a/src/imagekit/_client.py b/src/imagekitio/_client.py similarity index 100% rename from src/imagekit/_client.py rename to src/imagekitio/_client.py diff --git a/src/imagekit/_compat.py b/src/imagekitio/_compat.py similarity index 100% rename from src/imagekit/_compat.py rename to src/imagekitio/_compat.py diff --git a/src/imagekit/_constants.py b/src/imagekitio/_constants.py similarity index 100% rename from src/imagekit/_constants.py rename to src/imagekitio/_constants.py diff --git a/src/imagekit/_exceptions.py b/src/imagekitio/_exceptions.py similarity index 100% rename from src/imagekit/_exceptions.py rename to src/imagekitio/_exceptions.py diff --git a/src/imagekit/_files.py b/src/imagekitio/_files.py similarity index 100% rename from src/imagekit/_files.py rename to src/imagekitio/_files.py diff --git a/src/imagekit/_models.py b/src/imagekitio/_models.py similarity index 100% rename from src/imagekit/_models.py rename to src/imagekitio/_models.py diff --git a/src/imagekit/_qs.py b/src/imagekitio/_qs.py similarity index 100% rename from src/imagekit/_qs.py rename to src/imagekitio/_qs.py diff --git a/src/imagekit/_resource.py b/src/imagekitio/_resource.py similarity index 100% rename from src/imagekit/_resource.py rename to src/imagekitio/_resource.py diff --git a/src/imagekit/_response.py b/src/imagekitio/_response.py similarity index 98% rename from src/imagekit/_response.py rename to src/imagekitio/_response.py index c7bcdb4..ff8fc4f 100644 --- a/src/imagekit/_response.py +++ b/src/imagekitio/_response.py @@ -217,7 +217,9 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: and not issubclass(origin, BaseModel) and issubclass(origin, pydantic.BaseModel) ): - raise TypeError("Pydantic models must subclass our base model type, e.g. `from imagekit import BaseModel`") + raise TypeError( + "Pydantic models must subclass our base model type, e.g. `from imagekitio import BaseModel`" + ) if ( cast_to is not object @@ -283,7 +285,7 @@ def parse(self, *, to: type[_T] | None = None) -> R | _T: the `to` argument, e.g. ```py - from imagekit import BaseModel + from imagekitio import BaseModel class MyModel(BaseModel): @@ -385,7 +387,7 @@ async def parse(self, *, to: type[_T] | None = None) -> R | _T: the `to` argument, e.g. ```py - from imagekit import BaseModel + from imagekitio import BaseModel class MyModel(BaseModel): @@ -556,7 +558,7 @@ async def stream_to_file( class MissingStreamClassError(TypeError): def __init__(self) -> None: super().__init__( - "The `stream` argument was set to `True` but the `stream_cls` argument was not given. See `imagekit._streaming` for reference", + "The `stream` argument was set to `True` but the `stream_cls` argument was not given. See `imagekitio._streaming` for reference", ) diff --git a/src/imagekit/_streaming.py b/src/imagekitio/_streaming.py similarity index 100% rename from src/imagekit/_streaming.py rename to src/imagekitio/_streaming.py diff --git a/src/imagekit/_types.py b/src/imagekitio/_types.py similarity index 99% rename from src/imagekit/_types.py rename to src/imagekitio/_types.py index ba04a4b..9abd394 100644 --- a/src/imagekit/_types.py +++ b/src/imagekitio/_types.py @@ -92,7 +92,7 @@ # This unfortunately means that you will either have # to import this type and pass it explicitly: # -# from imagekit import NoneType +# from imagekitio import NoneType # client.get('/foo', cast_to=NoneType) # # or build it yourself: diff --git a/src/imagekit/_utils/__init__.py b/src/imagekitio/_utils/__init__.py similarity index 100% rename from src/imagekit/_utils/__init__.py rename to src/imagekitio/_utils/__init__.py diff --git a/src/imagekit/_utils/_compat.py b/src/imagekitio/_utils/_compat.py similarity index 100% rename from src/imagekit/_utils/_compat.py rename to src/imagekitio/_utils/_compat.py diff --git a/src/imagekit/_utils/_datetime_parse.py b/src/imagekitio/_utils/_datetime_parse.py similarity index 100% rename from src/imagekit/_utils/_datetime_parse.py rename to src/imagekitio/_utils/_datetime_parse.py diff --git a/src/imagekit/_utils/_logs.py b/src/imagekitio/_utils/_logs.py similarity index 76% rename from src/imagekit/_utils/_logs.py rename to src/imagekitio/_utils/_logs.py index f896bb6..c383e3e 100644 --- a/src/imagekit/_utils/_logs.py +++ b/src/imagekitio/_utils/_logs.py @@ -1,12 +1,12 @@ import os import logging -logger: logging.Logger = logging.getLogger("imagekit") +logger: logging.Logger = logging.getLogger("imagekitio") httpx_logger: logging.Logger = logging.getLogger("httpx") def _basic_config() -> None: - # e.g. [2023-10-05 14:12:26 - imagekit._base_client:818 - DEBUG] HTTP Request: POST http://127.0.0.1:4010/foo/bar "200 OK" + # e.g. [2023-10-05 14:12:26 - imagekitio._base_client:818 - DEBUG] HTTP Request: POST http://127.0.0.1:4010/foo/bar "200 OK" logging.basicConfig( format="[%(asctime)s - %(name)s:%(lineno)d - %(levelname)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S", diff --git a/src/imagekit/_utils/_proxy.py b/src/imagekitio/_utils/_proxy.py similarity index 100% rename from src/imagekit/_utils/_proxy.py rename to src/imagekitio/_utils/_proxy.py diff --git a/src/imagekit/_utils/_reflection.py b/src/imagekitio/_utils/_reflection.py similarity index 100% rename from src/imagekit/_utils/_reflection.py rename to src/imagekitio/_utils/_reflection.py diff --git a/src/imagekit/_utils/_resources_proxy.py b/src/imagekitio/_utils/_resources_proxy.py similarity index 52% rename from src/imagekit/_utils/_resources_proxy.py rename to src/imagekitio/_utils/_resources_proxy.py index 6421783..5ba9142 100644 --- a/src/imagekit/_utils/_resources_proxy.py +++ b/src/imagekitio/_utils/_resources_proxy.py @@ -7,17 +7,17 @@ class ResourcesProxy(LazyProxy[Any]): - """A proxy for the `imagekit.resources` module. + """A proxy for the `imagekitio.resources` module. - This is used so that we can lazily import `imagekit.resources` only when - needed *and* so that users can just import `imagekit` and reference `imagekit.resources` + This is used so that we can lazily import `imagekitio.resources` only when + needed *and* so that users can just import `imagekitio` and reference `imagekitio.resources` """ @override def __load__(self) -> Any: import importlib - mod = importlib.import_module("imagekit.resources") + mod = importlib.import_module("imagekitio.resources") return mod diff --git a/src/imagekit/_utils/_streams.py b/src/imagekitio/_utils/_streams.py similarity index 100% rename from src/imagekit/_utils/_streams.py rename to src/imagekitio/_utils/_streams.py diff --git a/src/imagekit/_utils/_sync.py b/src/imagekitio/_utils/_sync.py similarity index 100% rename from src/imagekit/_utils/_sync.py rename to src/imagekitio/_utils/_sync.py diff --git a/src/imagekit/_utils/_transform.py b/src/imagekitio/_utils/_transform.py similarity index 100% rename from src/imagekit/_utils/_transform.py rename to src/imagekitio/_utils/_transform.py diff --git a/src/imagekit/_utils/_typing.py b/src/imagekitio/_utils/_typing.py similarity index 100% rename from src/imagekit/_utils/_typing.py rename to src/imagekitio/_utils/_typing.py diff --git a/src/imagekit/_utils/_utils.py b/src/imagekitio/_utils/_utils.py similarity index 100% rename from src/imagekit/_utils/_utils.py rename to src/imagekitio/_utils/_utils.py diff --git a/src/imagekit/_version.py b/src/imagekitio/_version.py similarity index 81% rename from src/imagekit/_version.py rename to src/imagekitio/_version.py index 3eb6f6a..e67f4eb 100644 --- a/src/imagekit/_version.py +++ b/src/imagekitio/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -__title__ = "imagekit" +__title__ = "imagekitio" __version__ = "0.0.1" diff --git a/src/imagekitio/lib/.keep b/src/imagekitio/lib/.keep new file mode 100644 index 0000000..5e2c99f --- /dev/null +++ b/src/imagekitio/lib/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store custom files to expand the SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/src/imagekit/py.typed b/src/imagekitio/py.typed similarity index 100% rename from src/imagekit/py.typed rename to src/imagekitio/py.typed diff --git a/src/imagekit/resources/__init__.py b/src/imagekitio/resources/__init__.py similarity index 100% rename from src/imagekit/resources/__init__.py rename to src/imagekitio/resources/__init__.py diff --git a/src/imagekit/resources/accounts/__init__.py b/src/imagekitio/resources/accounts/__init__.py similarity index 100% rename from src/imagekit/resources/accounts/__init__.py rename to src/imagekitio/resources/accounts/__init__.py diff --git a/src/imagekit/resources/accounts/accounts.py b/src/imagekitio/resources/accounts/accounts.py similarity index 100% rename from src/imagekit/resources/accounts/accounts.py rename to src/imagekitio/resources/accounts/accounts.py diff --git a/src/imagekit/resources/accounts/origins.py b/src/imagekitio/resources/accounts/origins.py similarity index 100% rename from src/imagekit/resources/accounts/origins.py rename to src/imagekitio/resources/accounts/origins.py diff --git a/src/imagekit/resources/accounts/url_endpoints.py b/src/imagekitio/resources/accounts/url_endpoints.py similarity index 100% rename from src/imagekit/resources/accounts/url_endpoints.py rename to src/imagekitio/resources/accounts/url_endpoints.py diff --git a/src/imagekit/resources/accounts/usage.py b/src/imagekitio/resources/accounts/usage.py similarity index 100% rename from src/imagekit/resources/accounts/usage.py rename to src/imagekitio/resources/accounts/usage.py diff --git a/src/imagekit/resources/assets.py b/src/imagekitio/resources/assets.py similarity index 100% rename from src/imagekit/resources/assets.py rename to src/imagekitio/resources/assets.py diff --git a/src/imagekit/resources/beta/__init__.py b/src/imagekitio/resources/beta/__init__.py similarity index 100% rename from src/imagekit/resources/beta/__init__.py rename to src/imagekitio/resources/beta/__init__.py diff --git a/src/imagekit/resources/beta/beta.py b/src/imagekitio/resources/beta/beta.py similarity index 100% rename from src/imagekit/resources/beta/beta.py rename to src/imagekitio/resources/beta/beta.py diff --git a/src/imagekit/resources/beta/v2/__init__.py b/src/imagekitio/resources/beta/v2/__init__.py similarity index 100% rename from src/imagekit/resources/beta/v2/__init__.py rename to src/imagekitio/resources/beta/v2/__init__.py diff --git a/src/imagekit/resources/beta/v2/files.py b/src/imagekitio/resources/beta/v2/files.py similarity index 100% rename from src/imagekit/resources/beta/v2/files.py rename to src/imagekitio/resources/beta/v2/files.py diff --git a/src/imagekit/resources/beta/v2/v2.py b/src/imagekitio/resources/beta/v2/v2.py similarity index 100% rename from src/imagekit/resources/beta/v2/v2.py rename to src/imagekitio/resources/beta/v2/v2.py diff --git a/src/imagekit/resources/cache/__init__.py b/src/imagekitio/resources/cache/__init__.py similarity index 100% rename from src/imagekit/resources/cache/__init__.py rename to src/imagekitio/resources/cache/__init__.py diff --git a/src/imagekit/resources/cache/cache.py b/src/imagekitio/resources/cache/cache.py similarity index 100% rename from src/imagekit/resources/cache/cache.py rename to src/imagekitio/resources/cache/cache.py diff --git a/src/imagekit/resources/cache/invalidation.py b/src/imagekitio/resources/cache/invalidation.py similarity index 100% rename from src/imagekit/resources/cache/invalidation.py rename to src/imagekitio/resources/cache/invalidation.py diff --git a/src/imagekit/resources/custom_metadata_fields.py b/src/imagekitio/resources/custom_metadata_fields.py similarity index 100% rename from src/imagekit/resources/custom_metadata_fields.py rename to src/imagekitio/resources/custom_metadata_fields.py diff --git a/src/imagekit/resources/files/__init__.py b/src/imagekitio/resources/files/__init__.py similarity index 100% rename from src/imagekit/resources/files/__init__.py rename to src/imagekitio/resources/files/__init__.py diff --git a/src/imagekit/resources/files/bulk.py b/src/imagekitio/resources/files/bulk.py similarity index 100% rename from src/imagekit/resources/files/bulk.py rename to src/imagekitio/resources/files/bulk.py diff --git a/src/imagekit/resources/files/files.py b/src/imagekitio/resources/files/files.py similarity index 100% rename from src/imagekit/resources/files/files.py rename to src/imagekitio/resources/files/files.py diff --git a/src/imagekit/resources/files/metadata.py b/src/imagekitio/resources/files/metadata.py similarity index 100% rename from src/imagekit/resources/files/metadata.py rename to src/imagekitio/resources/files/metadata.py diff --git a/src/imagekit/resources/files/versions.py b/src/imagekitio/resources/files/versions.py similarity index 100% rename from src/imagekit/resources/files/versions.py rename to src/imagekitio/resources/files/versions.py diff --git a/src/imagekit/resources/folders/__init__.py b/src/imagekitio/resources/folders/__init__.py similarity index 100% rename from src/imagekit/resources/folders/__init__.py rename to src/imagekitio/resources/folders/__init__.py diff --git a/src/imagekit/resources/folders/folders.py b/src/imagekitio/resources/folders/folders.py similarity index 100% rename from src/imagekit/resources/folders/folders.py rename to src/imagekitio/resources/folders/folders.py diff --git a/src/imagekit/resources/folders/job.py b/src/imagekitio/resources/folders/job.py similarity index 100% rename from src/imagekit/resources/folders/job.py rename to src/imagekitio/resources/folders/job.py diff --git a/src/imagekit/resources/webhooks.py b/src/imagekitio/resources/webhooks.py similarity index 92% rename from src/imagekit/resources/webhooks.py rename to src/imagekitio/resources/webhooks.py index 7c5ed39..a561ade 100644 --- a/src/imagekit/resources/webhooks.py +++ b/src/imagekitio/resources/webhooks.py @@ -28,7 +28,7 @@ def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | try: from standardwebhooks import Webhook except ImportError as exc: - raise ImageKitError("You need to install `imagekit[webhooks]` to use this method") from exc + raise ImageKitError("You need to install `imagekitio[webhooks]` to use this method") from exc if key is None: key = self._client.webhook_secret @@ -65,7 +65,7 @@ def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | try: from standardwebhooks import Webhook except ImportError as exc: - raise ImageKitError("You need to install `imagekit[webhooks]` to use this method") from exc + raise ImageKitError("You need to install `imagekitio[webhooks]` to use this method") from exc if key is None: key = self._client.webhook_secret diff --git a/src/imagekit/types/__init__.py b/src/imagekitio/types/__init__.py similarity index 100% rename from src/imagekit/types/__init__.py rename to src/imagekitio/types/__init__.py diff --git a/src/imagekit/types/accounts/__init__.py b/src/imagekitio/types/accounts/__init__.py similarity index 100% rename from src/imagekit/types/accounts/__init__.py rename to src/imagekitio/types/accounts/__init__.py diff --git a/src/imagekit/types/accounts/origin_create_params.py b/src/imagekitio/types/accounts/origin_create_params.py similarity index 100% rename from src/imagekit/types/accounts/origin_create_params.py rename to src/imagekitio/types/accounts/origin_create_params.py diff --git a/src/imagekit/types/accounts/origin_list_response.py b/src/imagekitio/types/accounts/origin_list_response.py similarity index 100% rename from src/imagekit/types/accounts/origin_list_response.py rename to src/imagekitio/types/accounts/origin_list_response.py diff --git a/src/imagekit/types/accounts/origin_request_param.py b/src/imagekitio/types/accounts/origin_request_param.py similarity index 100% rename from src/imagekit/types/accounts/origin_request_param.py rename to src/imagekitio/types/accounts/origin_request_param.py diff --git a/src/imagekit/types/accounts/origin_response.py b/src/imagekitio/types/accounts/origin_response.py similarity index 100% rename from src/imagekit/types/accounts/origin_response.py rename to src/imagekitio/types/accounts/origin_response.py diff --git a/src/imagekit/types/accounts/origin_update_params.py b/src/imagekitio/types/accounts/origin_update_params.py similarity index 100% rename from src/imagekit/types/accounts/origin_update_params.py rename to src/imagekitio/types/accounts/origin_update_params.py diff --git a/src/imagekit/types/accounts/url_endpoint_create_params.py b/src/imagekitio/types/accounts/url_endpoint_create_params.py similarity index 100% rename from src/imagekit/types/accounts/url_endpoint_create_params.py rename to src/imagekitio/types/accounts/url_endpoint_create_params.py diff --git a/src/imagekit/types/accounts/url_endpoint_list_response.py b/src/imagekitio/types/accounts/url_endpoint_list_response.py similarity index 100% rename from src/imagekit/types/accounts/url_endpoint_list_response.py rename to src/imagekitio/types/accounts/url_endpoint_list_response.py diff --git a/src/imagekit/types/accounts/url_endpoint_response.py b/src/imagekitio/types/accounts/url_endpoint_response.py similarity index 100% rename from src/imagekit/types/accounts/url_endpoint_response.py rename to src/imagekitio/types/accounts/url_endpoint_response.py diff --git a/src/imagekit/types/accounts/url_endpoint_update_params.py b/src/imagekitio/types/accounts/url_endpoint_update_params.py similarity index 100% rename from src/imagekit/types/accounts/url_endpoint_update_params.py rename to src/imagekitio/types/accounts/url_endpoint_update_params.py diff --git a/src/imagekit/types/accounts/usage_get_params.py b/src/imagekitio/types/accounts/usage_get_params.py similarity index 100% rename from src/imagekit/types/accounts/usage_get_params.py rename to src/imagekitio/types/accounts/usage_get_params.py diff --git a/src/imagekit/types/accounts/usage_get_response.py b/src/imagekitio/types/accounts/usage_get_response.py similarity index 100% rename from src/imagekit/types/accounts/usage_get_response.py rename to src/imagekitio/types/accounts/usage_get_response.py diff --git a/src/imagekit/types/asset_list_params.py b/src/imagekitio/types/asset_list_params.py similarity index 100% rename from src/imagekit/types/asset_list_params.py rename to src/imagekitio/types/asset_list_params.py diff --git a/src/imagekit/types/asset_list_response.py b/src/imagekitio/types/asset_list_response.py similarity index 100% rename from src/imagekit/types/asset_list_response.py rename to src/imagekitio/types/asset_list_response.py diff --git a/src/imagekit/types/base_webhook_event.py b/src/imagekitio/types/base_webhook_event.py similarity index 100% rename from src/imagekit/types/base_webhook_event.py rename to src/imagekitio/types/base_webhook_event.py diff --git a/src/imagekit/types/beta/__init__.py b/src/imagekitio/types/beta/__init__.py similarity index 100% rename from src/imagekit/types/beta/__init__.py rename to src/imagekitio/types/beta/__init__.py diff --git a/src/imagekit/types/beta/v2/__init__.py b/src/imagekitio/types/beta/v2/__init__.py similarity index 100% rename from src/imagekit/types/beta/v2/__init__.py rename to src/imagekitio/types/beta/v2/__init__.py diff --git a/src/imagekit/types/beta/v2/file_upload_params.py b/src/imagekitio/types/beta/v2/file_upload_params.py similarity index 100% rename from src/imagekit/types/beta/v2/file_upload_params.py rename to src/imagekitio/types/beta/v2/file_upload_params.py diff --git a/src/imagekit/types/beta/v2/file_upload_response.py b/src/imagekitio/types/beta/v2/file_upload_response.py similarity index 100% rename from src/imagekit/types/beta/v2/file_upload_response.py rename to src/imagekitio/types/beta/v2/file_upload_response.py diff --git a/src/imagekit/types/cache/__init__.py b/src/imagekitio/types/cache/__init__.py similarity index 100% rename from src/imagekit/types/cache/__init__.py rename to src/imagekitio/types/cache/__init__.py diff --git a/src/imagekit/types/cache/invalidation_create_params.py b/src/imagekitio/types/cache/invalidation_create_params.py similarity index 100% rename from src/imagekit/types/cache/invalidation_create_params.py rename to src/imagekitio/types/cache/invalidation_create_params.py diff --git a/src/imagekit/types/cache/invalidation_create_response.py b/src/imagekitio/types/cache/invalidation_create_response.py similarity index 100% rename from src/imagekit/types/cache/invalidation_create_response.py rename to src/imagekitio/types/cache/invalidation_create_response.py diff --git a/src/imagekit/types/cache/invalidation_get_response.py b/src/imagekitio/types/cache/invalidation_get_response.py similarity index 100% rename from src/imagekit/types/cache/invalidation_get_response.py rename to src/imagekitio/types/cache/invalidation_get_response.py diff --git a/src/imagekit/types/custom_metadata_field.py b/src/imagekitio/types/custom_metadata_field.py similarity index 100% rename from src/imagekit/types/custom_metadata_field.py rename to src/imagekitio/types/custom_metadata_field.py diff --git a/src/imagekit/types/custom_metadata_field_create_params.py b/src/imagekitio/types/custom_metadata_field_create_params.py similarity index 100% rename from src/imagekit/types/custom_metadata_field_create_params.py rename to src/imagekitio/types/custom_metadata_field_create_params.py diff --git a/src/imagekit/types/custom_metadata_field_delete_response.py b/src/imagekitio/types/custom_metadata_field_delete_response.py similarity index 100% rename from src/imagekit/types/custom_metadata_field_delete_response.py rename to src/imagekitio/types/custom_metadata_field_delete_response.py diff --git a/src/imagekit/types/custom_metadata_field_list_params.py b/src/imagekitio/types/custom_metadata_field_list_params.py similarity index 100% rename from src/imagekit/types/custom_metadata_field_list_params.py rename to src/imagekitio/types/custom_metadata_field_list_params.py diff --git a/src/imagekit/types/custom_metadata_field_list_response.py b/src/imagekitio/types/custom_metadata_field_list_response.py similarity index 100% rename from src/imagekit/types/custom_metadata_field_list_response.py rename to src/imagekitio/types/custom_metadata_field_list_response.py diff --git a/src/imagekit/types/custom_metadata_field_update_params.py b/src/imagekitio/types/custom_metadata_field_update_params.py similarity index 100% rename from src/imagekit/types/custom_metadata_field_update_params.py rename to src/imagekitio/types/custom_metadata_field_update_params.py diff --git a/src/imagekit/types/file.py b/src/imagekitio/types/file.py similarity index 100% rename from src/imagekit/types/file.py rename to src/imagekitio/types/file.py diff --git a/src/imagekit/types/file_copy_params.py b/src/imagekitio/types/file_copy_params.py similarity index 100% rename from src/imagekit/types/file_copy_params.py rename to src/imagekitio/types/file_copy_params.py diff --git a/src/imagekit/types/file_copy_response.py b/src/imagekitio/types/file_copy_response.py similarity index 100% rename from src/imagekit/types/file_copy_response.py rename to src/imagekitio/types/file_copy_response.py diff --git a/src/imagekit/types/file_move_params.py b/src/imagekitio/types/file_move_params.py similarity index 100% rename from src/imagekit/types/file_move_params.py rename to src/imagekitio/types/file_move_params.py diff --git a/src/imagekit/types/file_move_response.py b/src/imagekitio/types/file_move_response.py similarity index 100% rename from src/imagekit/types/file_move_response.py rename to src/imagekitio/types/file_move_response.py diff --git a/src/imagekit/types/file_rename_params.py b/src/imagekitio/types/file_rename_params.py similarity index 100% rename from src/imagekit/types/file_rename_params.py rename to src/imagekitio/types/file_rename_params.py diff --git a/src/imagekit/types/file_rename_response.py b/src/imagekitio/types/file_rename_response.py similarity index 100% rename from src/imagekit/types/file_rename_response.py rename to src/imagekitio/types/file_rename_response.py diff --git a/src/imagekit/types/file_update_params.py b/src/imagekitio/types/file_update_params.py similarity index 100% rename from src/imagekit/types/file_update_params.py rename to src/imagekitio/types/file_update_params.py diff --git a/src/imagekit/types/file_update_response.py b/src/imagekitio/types/file_update_response.py similarity index 100% rename from src/imagekit/types/file_update_response.py rename to src/imagekitio/types/file_update_response.py diff --git a/src/imagekit/types/file_upload_params.py b/src/imagekitio/types/file_upload_params.py similarity index 100% rename from src/imagekit/types/file_upload_params.py rename to src/imagekitio/types/file_upload_params.py diff --git a/src/imagekit/types/file_upload_response.py b/src/imagekitio/types/file_upload_response.py similarity index 100% rename from src/imagekit/types/file_upload_response.py rename to src/imagekitio/types/file_upload_response.py diff --git a/src/imagekit/types/files/__init__.py b/src/imagekitio/types/files/__init__.py similarity index 100% rename from src/imagekit/types/files/__init__.py rename to src/imagekitio/types/files/__init__.py diff --git a/src/imagekit/types/files/bulk_add_tags_params.py b/src/imagekitio/types/files/bulk_add_tags_params.py similarity index 100% rename from src/imagekit/types/files/bulk_add_tags_params.py rename to src/imagekitio/types/files/bulk_add_tags_params.py diff --git a/src/imagekit/types/files/bulk_add_tags_response.py b/src/imagekitio/types/files/bulk_add_tags_response.py similarity index 100% rename from src/imagekit/types/files/bulk_add_tags_response.py rename to src/imagekitio/types/files/bulk_add_tags_response.py diff --git a/src/imagekit/types/files/bulk_delete_params.py b/src/imagekitio/types/files/bulk_delete_params.py similarity index 100% rename from src/imagekit/types/files/bulk_delete_params.py rename to src/imagekitio/types/files/bulk_delete_params.py diff --git a/src/imagekit/types/files/bulk_delete_response.py b/src/imagekitio/types/files/bulk_delete_response.py similarity index 100% rename from src/imagekit/types/files/bulk_delete_response.py rename to src/imagekitio/types/files/bulk_delete_response.py diff --git a/src/imagekit/types/files/bulk_remove_ai_tags_params.py b/src/imagekitio/types/files/bulk_remove_ai_tags_params.py similarity index 100% rename from src/imagekit/types/files/bulk_remove_ai_tags_params.py rename to src/imagekitio/types/files/bulk_remove_ai_tags_params.py diff --git a/src/imagekit/types/files/bulk_remove_ai_tags_response.py b/src/imagekitio/types/files/bulk_remove_ai_tags_response.py similarity index 100% rename from src/imagekit/types/files/bulk_remove_ai_tags_response.py rename to src/imagekitio/types/files/bulk_remove_ai_tags_response.py diff --git a/src/imagekit/types/files/bulk_remove_tags_params.py b/src/imagekitio/types/files/bulk_remove_tags_params.py similarity index 100% rename from src/imagekit/types/files/bulk_remove_tags_params.py rename to src/imagekitio/types/files/bulk_remove_tags_params.py diff --git a/src/imagekit/types/files/bulk_remove_tags_response.py b/src/imagekitio/types/files/bulk_remove_tags_response.py similarity index 100% rename from src/imagekit/types/files/bulk_remove_tags_response.py rename to src/imagekitio/types/files/bulk_remove_tags_response.py diff --git a/src/imagekit/types/files/metadata_get_from_url_params.py b/src/imagekitio/types/files/metadata_get_from_url_params.py similarity index 100% rename from src/imagekit/types/files/metadata_get_from_url_params.py rename to src/imagekitio/types/files/metadata_get_from_url_params.py diff --git a/src/imagekit/types/files/version_delete_response.py b/src/imagekitio/types/files/version_delete_response.py similarity index 100% rename from src/imagekit/types/files/version_delete_response.py rename to src/imagekitio/types/files/version_delete_response.py diff --git a/src/imagekit/types/files/version_list_response.py b/src/imagekitio/types/files/version_list_response.py similarity index 100% rename from src/imagekit/types/files/version_list_response.py rename to src/imagekitio/types/files/version_list_response.py diff --git a/src/imagekit/types/folder.py b/src/imagekitio/types/folder.py similarity index 100% rename from src/imagekit/types/folder.py rename to src/imagekitio/types/folder.py diff --git a/src/imagekit/types/folder_copy_params.py b/src/imagekitio/types/folder_copy_params.py similarity index 100% rename from src/imagekit/types/folder_copy_params.py rename to src/imagekitio/types/folder_copy_params.py diff --git a/src/imagekit/types/folder_copy_response.py b/src/imagekitio/types/folder_copy_response.py similarity index 100% rename from src/imagekit/types/folder_copy_response.py rename to src/imagekitio/types/folder_copy_response.py diff --git a/src/imagekit/types/folder_create_params.py b/src/imagekitio/types/folder_create_params.py similarity index 100% rename from src/imagekit/types/folder_create_params.py rename to src/imagekitio/types/folder_create_params.py diff --git a/src/imagekit/types/folder_create_response.py b/src/imagekitio/types/folder_create_response.py similarity index 100% rename from src/imagekit/types/folder_create_response.py rename to src/imagekitio/types/folder_create_response.py diff --git a/src/imagekit/types/folder_delete_params.py b/src/imagekitio/types/folder_delete_params.py similarity index 100% rename from src/imagekit/types/folder_delete_params.py rename to src/imagekitio/types/folder_delete_params.py diff --git a/src/imagekit/types/folder_delete_response.py b/src/imagekitio/types/folder_delete_response.py similarity index 100% rename from src/imagekit/types/folder_delete_response.py rename to src/imagekitio/types/folder_delete_response.py diff --git a/src/imagekit/types/folder_move_params.py b/src/imagekitio/types/folder_move_params.py similarity index 100% rename from src/imagekit/types/folder_move_params.py rename to src/imagekitio/types/folder_move_params.py diff --git a/src/imagekit/types/folder_move_response.py b/src/imagekitio/types/folder_move_response.py similarity index 100% rename from src/imagekit/types/folder_move_response.py rename to src/imagekitio/types/folder_move_response.py diff --git a/src/imagekit/types/folder_rename_params.py b/src/imagekitio/types/folder_rename_params.py similarity index 100% rename from src/imagekit/types/folder_rename_params.py rename to src/imagekitio/types/folder_rename_params.py diff --git a/src/imagekit/types/folder_rename_response.py b/src/imagekitio/types/folder_rename_response.py similarity index 100% rename from src/imagekit/types/folder_rename_response.py rename to src/imagekitio/types/folder_rename_response.py diff --git a/src/imagekit/types/folders/__init__.py b/src/imagekitio/types/folders/__init__.py similarity index 100% rename from src/imagekit/types/folders/__init__.py rename to src/imagekitio/types/folders/__init__.py diff --git a/src/imagekit/types/folders/job_get_response.py b/src/imagekitio/types/folders/job_get_response.py similarity index 100% rename from src/imagekit/types/folders/job_get_response.py rename to src/imagekitio/types/folders/job_get_response.py diff --git a/src/imagekit/types/metadata.py b/src/imagekitio/types/metadata.py similarity index 100% rename from src/imagekit/types/metadata.py rename to src/imagekitio/types/metadata.py diff --git a/src/imagekit/types/shared/__init__.py b/src/imagekitio/types/shared/__init__.py similarity index 100% rename from src/imagekit/types/shared/__init__.py rename to src/imagekitio/types/shared/__init__.py diff --git a/src/imagekit/types/shared/base_overlay.py b/src/imagekitio/types/shared/base_overlay.py similarity index 100% rename from src/imagekit/types/shared/base_overlay.py rename to src/imagekitio/types/shared/base_overlay.py diff --git a/src/imagekit/types/shared/extensions.py b/src/imagekitio/types/shared/extensions.py similarity index 100% rename from src/imagekit/types/shared/extensions.py rename to src/imagekitio/types/shared/extensions.py diff --git a/src/imagekit/types/shared/get_image_attributes_options.py b/src/imagekitio/types/shared/get_image_attributes_options.py similarity index 100% rename from src/imagekit/types/shared/get_image_attributes_options.py rename to src/imagekitio/types/shared/get_image_attributes_options.py diff --git a/src/imagekit/types/shared/image_overlay.py b/src/imagekitio/types/shared/image_overlay.py similarity index 100% rename from src/imagekit/types/shared/image_overlay.py rename to src/imagekitio/types/shared/image_overlay.py diff --git a/src/imagekit/types/shared/overlay.py b/src/imagekitio/types/shared/overlay.py similarity index 100% rename from src/imagekit/types/shared/overlay.py rename to src/imagekitio/types/shared/overlay.py diff --git a/src/imagekit/types/shared/overlay_position.py b/src/imagekitio/types/shared/overlay_position.py similarity index 100% rename from src/imagekit/types/shared/overlay_position.py rename to src/imagekitio/types/shared/overlay_position.py diff --git a/src/imagekit/types/shared/overlay_timing.py b/src/imagekitio/types/shared/overlay_timing.py similarity index 100% rename from src/imagekit/types/shared/overlay_timing.py rename to src/imagekitio/types/shared/overlay_timing.py diff --git a/src/imagekit/types/shared/responsive_image_attributes.py b/src/imagekitio/types/shared/responsive_image_attributes.py similarity index 100% rename from src/imagekit/types/shared/responsive_image_attributes.py rename to src/imagekitio/types/shared/responsive_image_attributes.py diff --git a/src/imagekit/types/shared/solid_color_overlay.py b/src/imagekitio/types/shared/solid_color_overlay.py similarity index 100% rename from src/imagekit/types/shared/solid_color_overlay.py rename to src/imagekitio/types/shared/solid_color_overlay.py diff --git a/src/imagekit/types/shared/solid_color_overlay_transformation.py b/src/imagekitio/types/shared/solid_color_overlay_transformation.py similarity index 100% rename from src/imagekit/types/shared/solid_color_overlay_transformation.py rename to src/imagekitio/types/shared/solid_color_overlay_transformation.py diff --git a/src/imagekit/types/shared/src_options.py b/src/imagekitio/types/shared/src_options.py similarity index 100% rename from src/imagekit/types/shared/src_options.py rename to src/imagekitio/types/shared/src_options.py diff --git a/src/imagekit/types/shared/streaming_resolution.py b/src/imagekitio/types/shared/streaming_resolution.py similarity index 100% rename from src/imagekit/types/shared/streaming_resolution.py rename to src/imagekitio/types/shared/streaming_resolution.py diff --git a/src/imagekit/types/shared/subtitle_overlay.py b/src/imagekitio/types/shared/subtitle_overlay.py similarity index 100% rename from src/imagekit/types/shared/subtitle_overlay.py rename to src/imagekitio/types/shared/subtitle_overlay.py diff --git a/src/imagekit/types/shared/subtitle_overlay_transformation.py b/src/imagekitio/types/shared/subtitle_overlay_transformation.py similarity index 100% rename from src/imagekit/types/shared/subtitle_overlay_transformation.py rename to src/imagekitio/types/shared/subtitle_overlay_transformation.py diff --git a/src/imagekit/types/shared/text_overlay.py b/src/imagekitio/types/shared/text_overlay.py similarity index 100% rename from src/imagekit/types/shared/text_overlay.py rename to src/imagekitio/types/shared/text_overlay.py diff --git a/src/imagekit/types/shared/text_overlay_transformation.py b/src/imagekitio/types/shared/text_overlay_transformation.py similarity index 100% rename from src/imagekit/types/shared/text_overlay_transformation.py rename to src/imagekitio/types/shared/text_overlay_transformation.py diff --git a/src/imagekit/types/shared/transformation.py b/src/imagekitio/types/shared/transformation.py similarity index 100% rename from src/imagekit/types/shared/transformation.py rename to src/imagekitio/types/shared/transformation.py diff --git a/src/imagekit/types/shared/transformation_position.py b/src/imagekitio/types/shared/transformation_position.py similarity index 100% rename from src/imagekit/types/shared/transformation_position.py rename to src/imagekitio/types/shared/transformation_position.py diff --git a/src/imagekit/types/shared/video_overlay.py b/src/imagekitio/types/shared/video_overlay.py similarity index 100% rename from src/imagekit/types/shared/video_overlay.py rename to src/imagekitio/types/shared/video_overlay.py diff --git a/src/imagekit/types/shared_params/__init__.py b/src/imagekitio/types/shared_params/__init__.py similarity index 100% rename from src/imagekit/types/shared_params/__init__.py rename to src/imagekitio/types/shared_params/__init__.py diff --git a/src/imagekit/types/shared_params/extensions.py b/src/imagekitio/types/shared_params/extensions.py similarity index 100% rename from src/imagekit/types/shared_params/extensions.py rename to src/imagekitio/types/shared_params/extensions.py diff --git a/src/imagekit/types/unsafe_unwrap_webhook_event.py b/src/imagekitio/types/unsafe_unwrap_webhook_event.py similarity index 100% rename from src/imagekit/types/unsafe_unwrap_webhook_event.py rename to src/imagekitio/types/unsafe_unwrap_webhook_event.py diff --git a/src/imagekit/types/unwrap_webhook_event.py b/src/imagekitio/types/unwrap_webhook_event.py similarity index 100% rename from src/imagekit/types/unwrap_webhook_event.py rename to src/imagekitio/types/unwrap_webhook_event.py diff --git a/src/imagekit/types/update_file_request_param.py b/src/imagekitio/types/update_file_request_param.py similarity index 100% rename from src/imagekit/types/update_file_request_param.py rename to src/imagekitio/types/update_file_request_param.py diff --git a/src/imagekit/types/upload_post_transform_error_event.py b/src/imagekitio/types/upload_post_transform_error_event.py similarity index 100% rename from src/imagekit/types/upload_post_transform_error_event.py rename to src/imagekitio/types/upload_post_transform_error_event.py diff --git a/src/imagekit/types/upload_post_transform_success_event.py b/src/imagekitio/types/upload_post_transform_success_event.py similarity index 100% rename from src/imagekit/types/upload_post_transform_success_event.py rename to src/imagekitio/types/upload_post_transform_success_event.py diff --git a/src/imagekit/types/upload_pre_transform_error_event.py b/src/imagekitio/types/upload_pre_transform_error_event.py similarity index 100% rename from src/imagekit/types/upload_pre_transform_error_event.py rename to src/imagekitio/types/upload_pre_transform_error_event.py diff --git a/src/imagekit/types/upload_pre_transform_success_event.py b/src/imagekitio/types/upload_pre_transform_success_event.py similarity index 100% rename from src/imagekit/types/upload_pre_transform_success_event.py rename to src/imagekitio/types/upload_pre_transform_success_event.py diff --git a/src/imagekit/types/video_transformation_accepted_event.py b/src/imagekitio/types/video_transformation_accepted_event.py similarity index 100% rename from src/imagekit/types/video_transformation_accepted_event.py rename to src/imagekitio/types/video_transformation_accepted_event.py diff --git a/src/imagekit/types/video_transformation_error_event.py b/src/imagekitio/types/video_transformation_error_event.py similarity index 100% rename from src/imagekit/types/video_transformation_error_event.py rename to src/imagekitio/types/video_transformation_error_event.py diff --git a/src/imagekit/types/video_transformation_ready_event.py b/src/imagekitio/types/video_transformation_ready_event.py similarity index 100% rename from src/imagekit/types/video_transformation_ready_event.py rename to src/imagekitio/types/video_transformation_ready_event.py diff --git a/tests/api_resources/accounts/test_origins.py b/tests/api_resources/accounts/test_origins.py index 8afdef4..95b5214 100644 --- a/tests/api_resources/accounts/test_origins.py +++ b/tests/api_resources/accounts/test_origins.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.accounts import OriginResponse, OriginListResponse +from imagekitio.types.accounts import OriginResponse, OriginListResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/api_resources/accounts/test_url_endpoints.py b/tests/api_resources/accounts/test_url_endpoints.py index 714a7c0..954f630 100644 --- a/tests/api_resources/accounts/test_url_endpoints.py +++ b/tests/api_resources/accounts/test_url_endpoints.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.accounts import ( +from imagekitio.types.accounts import ( URLEndpointResponse, URLEndpointListResponse, ) diff --git a/tests/api_resources/accounts/test_usage.py b/tests/api_resources/accounts/test_usage.py index 3d65bf9..f477693 100644 --- a/tests/api_resources/accounts/test_usage.py +++ b/tests/api_resources/accounts/test_usage.py @@ -7,10 +7,10 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit._utils import parse_date -from imagekit.types.accounts import UsageGetResponse +from imagekitio._utils import parse_date +from imagekitio.types.accounts import UsageGetResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/api_resources/beta/v2/test_files.py b/tests/api_resources/beta/v2/test_files.py index e5757ff..d5f6bbd 100644 --- a/tests/api_resources/beta/v2/test_files.py +++ b/tests/api_resources/beta/v2/test_files.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.beta.v2 import FileUploadResponse +from imagekitio.types.beta.v2 import FileUploadResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/api_resources/cache/test_invalidation.py b/tests/api_resources/cache/test_invalidation.py index 4fe9317..e68c2a6 100644 --- a/tests/api_resources/cache/test_invalidation.py +++ b/tests/api_resources/cache/test_invalidation.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.cache import InvalidationGetResponse, InvalidationCreateResponse +from imagekitio.types.cache import InvalidationGetResponse, InvalidationCreateResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/api_resources/files/test_bulk.py b/tests/api_resources/files/test_bulk.py index 3b7c825..150b5b2 100644 --- a/tests/api_resources/files/test_bulk.py +++ b/tests/api_resources/files/test_bulk.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.files import ( +from imagekitio.types.files import ( BulkDeleteResponse, BulkAddTagsResponse, BulkRemoveTagsResponse, diff --git a/tests/api_resources/files/test_metadata.py b/tests/api_resources/files/test_metadata.py index dc0d9f4..eb4007c 100644 --- a/tests/api_resources/files/test_metadata.py +++ b/tests/api_resources/files/test_metadata.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types import Metadata +from imagekitio.types import Metadata base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/api_resources/files/test_versions.py b/tests/api_resources/files/test_versions.py index 1d0121d..13f3c51 100644 --- a/tests/api_resources/files/test_versions.py +++ b/tests/api_resources/files/test_versions.py @@ -7,10 +7,10 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types import File -from imagekit.types.files import VersionListResponse, VersionDeleteResponse +from imagekitio.types import File +from imagekitio.types.files import VersionListResponse, VersionDeleteResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/api_resources/folders/test_job.py b/tests/api_resources/folders/test_job.py index c86539d..2bbc1cf 100644 --- a/tests/api_resources/folders/test_job.py +++ b/tests/api_resources/folders/test_job.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types.folders import JobGetResponse +from imagekitio.types.folders import JobGetResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/api_resources/test_assets.py b/tests/api_resources/test_assets.py index d600600..6958ecd 100644 --- a/tests/api_resources/test_assets.py +++ b/tests/api_resources/test_assets.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types import AssetListResponse +from imagekitio.types import AssetListResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/api_resources/test_custom_metadata_fields.py b/tests/api_resources/test_custom_metadata_fields.py index 53941eb..4c9fed6 100644 --- a/tests/api_resources/test_custom_metadata_fields.py +++ b/tests/api_resources/test_custom_metadata_fields.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types import ( +from imagekitio.types import ( CustomMetadataField, CustomMetadataFieldListResponse, CustomMetadataFieldDeleteResponse, diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 5a9594f..4d3d4aa 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types import ( +from imagekitio.types import ( File, FileCopyResponse, FileMoveResponse, diff --git a/tests/api_resources/test_folders.py b/tests/api_resources/test_folders.py index de14df0..ad5d83f 100644 --- a/tests/api_resources/test_folders.py +++ b/tests/api_resources/test_folders.py @@ -7,9 +7,9 @@ import pytest -from imagekit import ImageKit, AsyncImageKit +from imagekitio import ImageKit, AsyncImageKit from tests.utils import assert_matches_type -from imagekit.types import ( +from imagekitio.types import ( FolderCopyResponse, FolderMoveResponse, FolderCreateResponse, diff --git a/tests/api_resources/test_webhooks.py b/tests/api_resources/test_webhooks.py index 7ed992b..35fbbd1 100644 --- a/tests/api_resources/test_webhooks.py +++ b/tests/api_resources/test_webhooks.py @@ -8,7 +8,7 @@ import pytest import standardwebhooks -from imagekit import ImageKit +from imagekitio import ImageKit base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/conftest.py b/tests/conftest.py index 4471f83..d64313c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,15 +10,15 @@ import pytest from pytest_asyncio import is_async_test -from imagekit import ImageKit, AsyncImageKit, DefaultAioHttpClient -from imagekit._utils import is_dict +from imagekitio import ImageKit, AsyncImageKit, DefaultAioHttpClient +from imagekitio._utils import is_dict if TYPE_CHECKING: from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] pytest.register_assert_rewrite("tests.utils") -logging.getLogger("imagekit").setLevel(logging.DEBUG) +logging.getLogger("imagekitio").setLevel(logging.DEBUG) # automatically add `pytest.mark.asyncio()` to all of our async tests diff --git a/tests/test_client.py b/tests/test_client.py index 8651828..73532a8 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -18,12 +18,12 @@ from respx import MockRouter from pydantic import ValidationError -from imagekit import ImageKit, AsyncImageKit, APIResponseValidationError -from imagekit._types import Omit -from imagekit._utils import asyncify -from imagekit._models import BaseModel, FinalRequestOptions -from imagekit._exceptions import ImageKitError, APIStatusError, APITimeoutError, APIResponseValidationError -from imagekit._base_client import ( +from imagekitio import ImageKit, AsyncImageKit, APIResponseValidationError +from imagekitio._types import Omit +from imagekitio._utils import asyncify +from imagekitio._models import BaseModel, FinalRequestOptions +from imagekitio._exceptions import ImageKitError, APIStatusError, APITimeoutError, APIResponseValidationError +from imagekitio._base_client import ( DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, BaseClient, @@ -246,10 +246,10 @@ def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.Statistic # to_raw_response_wrapper leaks through the @functools.wraps() decorator. # # removing the decorator fixes the leak for reasons we don't understand. - "imagekit/_legacy_response.py", - "imagekit/_response.py", + "imagekitio/_legacy_response.py", + "imagekitio/_response.py", # pydantic.BaseModel.model_dump || pydantic.BaseModel.dict leak memory for some reason. - "imagekit/_compat.py", + "imagekitio/_compat.py", # Standard library leaks we don't care about. "/logging/__init__.py", ] @@ -814,7 +814,7 @@ def test_parse_retry_after_header( calculated = client._calculate_retry_timeout(remaining_retries, options, headers) assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] - @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("imagekitio._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: ImageKit) -> None: respx_mock.post("/api/v1/files/upload").mock(side_effect=httpx.TimeoutException("Test timeout error")) @@ -824,7 +824,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien assert _get_open_connections(client) == 0 - @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("imagekitio._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: ImageKit) -> None: respx_mock.post("/api/v1/files/upload").mock(return_value=httpx.Response(500)) @@ -834,7 +834,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client assert _get_open_connections(client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("imagekitio._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @pytest.mark.parametrize("failure_mode", ["status", "exception"]) def test_retries_taken( @@ -865,7 +865,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("imagekitio._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_omit_retry_count_header( self, client: ImageKit, failures_before_success: int, respx_mock: MockRouter @@ -890,7 +890,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("imagekitio._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_overwrite_retry_count_header( self, client: ImageKit, failures_before_success: int, respx_mock: MockRouter @@ -1149,10 +1149,10 @@ def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.Statistic # to_raw_response_wrapper leaks through the @functools.wraps() decorator. # # removing the decorator fixes the leak for reasons we don't understand. - "imagekit/_legacy_response.py", - "imagekit/_response.py", + "imagekitio/_legacy_response.py", + "imagekitio/_response.py", # pydantic.BaseModel.model_dump || pydantic.BaseModel.dict leak memory for some reason. - "imagekit/_compat.py", + "imagekitio/_compat.py", # Standard library leaks we don't care about. "/logging/__init__.py", ] @@ -1724,7 +1724,7 @@ async def test_parse_retry_after_header( calculated = async_client._calculate_retry_timeout(remaining_retries, options, headers) assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] - @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("imagekitio._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retrying_timeout_errors_doesnt_leak( self, respx_mock: MockRouter, async_client: AsyncImageKit @@ -1738,7 +1738,7 @@ async def test_retrying_timeout_errors_doesnt_leak( assert _get_open_connections(async_client) == 0 - @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("imagekitio._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retrying_status_errors_doesnt_leak( self, respx_mock: MockRouter, async_client: AsyncImageKit @@ -1752,7 +1752,7 @@ async def test_retrying_status_errors_doesnt_leak( assert _get_open_connections(async_client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("imagekitio._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @pytest.mark.parametrize("failure_mode", ["status", "exception"]) async def test_retries_taken( @@ -1783,7 +1783,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("imagekitio._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_omit_retry_count_header( self, async_client: AsyncImageKit, failures_before_success: int, respx_mock: MockRouter @@ -1808,7 +1808,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("imagekit._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("imagekitio._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_overwrite_retry_count_header( self, async_client: AsyncImageKit, failures_before_success: int, respx_mock: MockRouter diff --git a/tests/test_deepcopy.py b/tests/test_deepcopy.py index 0a12266..d0caf5c 100644 --- a/tests/test_deepcopy.py +++ b/tests/test_deepcopy.py @@ -1,4 +1,4 @@ -from imagekit._utils import deepcopy_minimal +from imagekitio._utils import deepcopy_minimal def assert_different_identities(obj1: object, obj2: object) -> None: diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index d55e402..396cbd0 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -4,8 +4,8 @@ import pytest -from imagekit._types import FileTypes -from imagekit._utils import extract_files +from imagekitio._types import FileTypes +from imagekitio._utils import extract_files def test_removes_files_from_input() -> None: diff --git a/tests/test_files.py b/tests/test_files.py index d37ddba..79dc2ef 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -4,7 +4,7 @@ import pytest from dirty_equals import IsDict, IsList, IsBytes, IsTuple -from imagekit._files import to_httpx_files, async_to_httpx_files +from imagekitio._files import to_httpx_files, async_to_httpx_files readme_path = Path(__file__).parent.parent.joinpath("README.md") diff --git a/tests/test_models.py b/tests/test_models.py index 0a3b02a..561b983 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -7,9 +7,9 @@ import pydantic from pydantic import Field -from imagekit._utils import PropertyInfo -from imagekit._compat import PYDANTIC_V1, parse_obj, model_dump, model_json -from imagekit._models import DISCRIMINATOR_CACHE, BaseModel, construct_type +from imagekitio._utils import PropertyInfo +from imagekitio._compat import PYDANTIC_V1, parse_obj, model_dump, model_json +from imagekitio._models import DISCRIMINATOR_CACHE, BaseModel, construct_type class BasicModel(BaseModel): diff --git a/tests/test_qs.py b/tests/test_qs.py index 4e08d86..cfc5985 100644 --- a/tests/test_qs.py +++ b/tests/test_qs.py @@ -4,7 +4,7 @@ import pytest -from imagekit._qs import Querystring, stringify +from imagekitio._qs import Querystring, stringify def test_empty() -> None: diff --git a/tests/test_required_args.py b/tests/test_required_args.py index e066b2a..e7cde47 100644 --- a/tests/test_required_args.py +++ b/tests/test_required_args.py @@ -2,7 +2,7 @@ import pytest -from imagekit._utils import required_args +from imagekitio._utils import required_args def test_too_many_positional_params() -> None: diff --git a/tests/test_response.py b/tests/test_response.py index 0a41606..30b86cc 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -6,8 +6,8 @@ import pytest import pydantic -from imagekit import ImageKit, BaseModel, AsyncImageKit -from imagekit._response import ( +from imagekitio import ImageKit, BaseModel, AsyncImageKit +from imagekitio._response import ( APIResponse, BaseAPIResponse, AsyncAPIResponse, @@ -15,8 +15,8 @@ AsyncBinaryAPIResponse, extract_response_type, ) -from imagekit._streaming import Stream -from imagekit._base_client import FinalRequestOptions +from imagekitio._streaming import Stream +from imagekitio._base_client import FinalRequestOptions class ConcreteBaseAPIResponse(APIResponse[bytes]): ... @@ -37,7 +37,7 @@ def test_extract_response_type_direct_classes() -> None: def test_extract_response_type_direct_class_missing_type_arg() -> None: with pytest.raises( RuntimeError, - match="Expected type to have a type argument at index 0 but it did not", + match="Expected type to have a type argument at index 0 but it did not", ): extract_response_type(AsyncAPIResponse) @@ -68,7 +68,7 @@ def test_response_parse_mismatched_basemodel(client: ImageKit) -> None: with pytest.raises( TypeError, - match="Pydantic models must subclass our base model type, e.g. `from imagekit import BaseModel`", + match="Pydantic models must subclass our base model type, e.g. `from imagekitio import BaseModel`", ): response.parse(to=PydanticModel) @@ -86,7 +86,7 @@ async def test_async_response_parse_mismatched_basemodel(async_client: AsyncImag with pytest.raises( TypeError, - match="Pydantic models must subclass our base model type, e.g. `from imagekit import BaseModel`", + match="Pydantic models must subclass our base model type, e.g. `from imagekitio import BaseModel`", ): await response.parse(to=PydanticModel) diff --git a/tests/test_streaming.py b/tests/test_streaming.py index fa1795d..7db128c 100644 --- a/tests/test_streaming.py +++ b/tests/test_streaming.py @@ -5,8 +5,8 @@ import httpx import pytest -from imagekit import ImageKit, AsyncImageKit -from imagekit._streaming import Stream, AsyncStream, ServerSentEvent +from imagekitio import ImageKit, AsyncImageKit +from imagekitio._streaming import Stream, AsyncStream, ServerSentEvent @pytest.mark.asyncio diff --git a/tests/test_transform.py b/tests/test_transform.py index 2d745f5..3520530 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -8,15 +8,15 @@ import pytest -from imagekit._types import Base64FileInput, omit, not_given -from imagekit._utils import ( +from imagekitio._types import Base64FileInput, omit, not_given +from imagekitio._utils import ( PropertyInfo, transform as _transform, parse_datetime, async_transform as _async_transform, ) -from imagekit._compat import PYDANTIC_V1 -from imagekit._models import BaseModel +from imagekitio._compat import PYDANTIC_V1 +from imagekitio._models import BaseModel _T = TypeVar("_T") diff --git a/tests/test_utils/test_datetime_parse.py b/tests/test_utils/test_datetime_parse.py index 959bb47..2e5023a 100644 --- a/tests/test_utils/test_datetime_parse.py +++ b/tests/test_utils/test_datetime_parse.py @@ -8,7 +8,7 @@ import pytest -from imagekit._utils import parse_date, parse_datetime +from imagekitio._utils import parse_date, parse_datetime def create_tz(minutes: int) -> timezone: diff --git a/tests/test_utils/test_proxy.py b/tests/test_utils/test_proxy.py index f6fec33..2c44f18 100644 --- a/tests/test_utils/test_proxy.py +++ b/tests/test_utils/test_proxy.py @@ -2,7 +2,7 @@ from typing import Any from typing_extensions import override -from imagekit._utils import LazyProxy +from imagekitio._utils import LazyProxy class RecursiveLazyProxy(LazyProxy[Any]): diff --git a/tests/test_utils/test_typing.py b/tests/test_utils/test_typing.py index 3d41f5d..b44f290 100644 --- a/tests/test_utils/test_typing.py +++ b/tests/test_utils/test_typing.py @@ -2,7 +2,7 @@ from typing import Generic, TypeVar, cast -from imagekit._utils import extract_type_var_from_base +from imagekitio._utils import extract_type_var_from_base _T = TypeVar("_T") _T2 = TypeVar("_T2") diff --git a/tests/utils.py b/tests/utils.py index 3701958..d73dadf 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -8,8 +8,8 @@ from datetime import date, datetime from typing_extensions import Literal, get_args, get_origin, assert_type -from imagekit._types import Omit, NoneType -from imagekit._utils import ( +from imagekitio._types import Omit, NoneType +from imagekitio._utils import ( is_dict, is_list, is_list_type, @@ -19,8 +19,8 @@ is_annotated_type, is_type_alias_type, ) -from imagekit._compat import PYDANTIC_V1, field_outer_type, get_model_fields -from imagekit._models import BaseModel +from imagekitio._compat import PYDANTIC_V1, field_outer_type, get_model_fields +from imagekitio._models import BaseModel BaseModelT = TypeVar("BaseModelT", bound=BaseModel) From dfa409f92c8ac171b922fead03606b4528524b62 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 12:31:37 +0000 Subject: [PATCH 167/177] feat(api): manual updates --- .stats.yml | 4 +- api.md | 6 + src/imagekitio/_client.py | 10 +- src/imagekitio/resources/__init__.py | 14 + src/imagekitio/resources/dummy.py | 345 ++++ src/imagekitio/types/__init__.py | 1 + src/imagekitio/types/dummy_create_params.py | 124 ++ .../types/shared_params/__init__.py | 18 + .../types/shared_params/base_overlay.py | 16 + .../get_image_attributes_options.py | 54 + .../types/shared_params/image_overlay.py | 38 + src/imagekitio/types/shared_params/overlay.py | 23 + .../types/shared_params/overlay_position.py | 34 + .../types/shared_params/overlay_timing.py | 35 + .../responsive_image_attributes.py | 29 + .../shared_params/solid_color_overlay.py | 32 + .../solid_color_overlay_transformation.py | 53 + .../types/shared_params/src_options.py | 76 + .../shared_params/streaming_resolution.py | 9 + .../types/shared_params/subtitle_overlay.py | 34 + .../subtitle_overlay_transformation.py | 74 + .../types/shared_params/text_overlay.py | 37 + .../text_overlay_transformation.py | 99 ++ .../types/shared_params/transformation.py | 424 +++++ .../shared_params/transformation_position.py | 9 + .../types/shared_params/video_overlay.py | 36 + tests/api_resources/test_dummy.py | 1444 +++++++++++++++++ 27 files changed, 3075 insertions(+), 3 deletions(-) create mode 100644 src/imagekitio/resources/dummy.py create mode 100644 src/imagekitio/types/dummy_create_params.py create mode 100644 src/imagekitio/types/shared_params/base_overlay.py create mode 100644 src/imagekitio/types/shared_params/get_image_attributes_options.py create mode 100644 src/imagekitio/types/shared_params/image_overlay.py create mode 100644 src/imagekitio/types/shared_params/overlay.py create mode 100644 src/imagekitio/types/shared_params/overlay_position.py create mode 100644 src/imagekitio/types/shared_params/overlay_timing.py create mode 100644 src/imagekitio/types/shared_params/responsive_image_attributes.py create mode 100644 src/imagekitio/types/shared_params/solid_color_overlay.py create mode 100644 src/imagekitio/types/shared_params/solid_color_overlay_transformation.py create mode 100644 src/imagekitio/types/shared_params/src_options.py create mode 100644 src/imagekitio/types/shared_params/streaming_resolution.py create mode 100644 src/imagekitio/types/shared_params/subtitle_overlay.py create mode 100644 src/imagekitio/types/shared_params/subtitle_overlay_transformation.py create mode 100644 src/imagekitio/types/shared_params/text_overlay.py create mode 100644 src/imagekitio/types/shared_params/text_overlay_transformation.py create mode 100644 src/imagekitio/types/shared_params/transformation.py create mode 100644 src/imagekitio/types/shared_params/transformation_position.py create mode 100644 src/imagekitio/types/shared_params/video_overlay.py create mode 100644 tests/api_resources/test_dummy.py diff --git a/.stats.yml b/.stats.yml index 8577a4c..a0c1a4e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 42 +configured_endpoints: 43 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml openapi_spec_hash: a9aa620376fce66532c84f9364209b0b -config_hash: 10b48f323ed534664483af1952174d52 +config_hash: fd112bd17c0c8e9f81a50d0e15ea70d6 diff --git a/api.md b/api.md index b617936..c88d631 100644 --- a/api.md +++ b/api.md @@ -24,6 +24,12 @@ from imagekitio.types import ( ) ``` +# Dummy + +Methods: + +- client.dummy.create(\*\*params) -> None + # CustomMetadataFields Types: diff --git a/src/imagekitio/_client.py b/src/imagekitio/_client.py index 85e1ff5..39a76e0 100644 --- a/src/imagekitio/_client.py +++ b/src/imagekitio/_client.py @@ -23,7 +23,7 @@ ) from ._utils import is_given, get_async_library from ._version import __version__ -from .resources import assets, webhooks, custom_metadata_fields +from .resources import dummy, assets, webhooks, custom_metadata_fields from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import ImageKitError, APIStatusError from ._base_client import ( @@ -50,6 +50,7 @@ class ImageKit(SyncAPIClient): + dummy: dummy.DummyResource custom_metadata_fields: custom_metadata_fields.CustomMetadataFieldsResource files: files.FilesResource assets: assets.AssetsResource @@ -131,6 +132,7 @@ def __init__( _strict_response_validation=_strict_response_validation, ) + self.dummy = dummy.DummyResource(self) self.custom_metadata_fields = custom_metadata_fields.CustomMetadataFieldsResource(self) self.files = files.FilesResource(self) self.assets = assets.AssetsResource(self) @@ -268,6 +270,7 @@ def _make_status_error( class AsyncImageKit(AsyncAPIClient): + dummy: dummy.AsyncDummyResource custom_metadata_fields: custom_metadata_fields.AsyncCustomMetadataFieldsResource files: files.AsyncFilesResource assets: assets.AsyncAssetsResource @@ -349,6 +352,7 @@ def __init__( _strict_response_validation=_strict_response_validation, ) + self.dummy = dummy.AsyncDummyResource(self) self.custom_metadata_fields = custom_metadata_fields.AsyncCustomMetadataFieldsResource(self) self.files = files.AsyncFilesResource(self) self.assets = assets.AsyncAssetsResource(self) @@ -487,6 +491,7 @@ def _make_status_error( class ImageKitWithRawResponse: def __init__(self, client: ImageKit) -> None: + self.dummy = dummy.DummyResourceWithRawResponse(client.dummy) self.custom_metadata_fields = custom_metadata_fields.CustomMetadataFieldsResourceWithRawResponse( client.custom_metadata_fields ) @@ -500,6 +505,7 @@ def __init__(self, client: ImageKit) -> None: class AsyncImageKitWithRawResponse: def __init__(self, client: AsyncImageKit) -> None: + self.dummy = dummy.AsyncDummyResourceWithRawResponse(client.dummy) self.custom_metadata_fields = custom_metadata_fields.AsyncCustomMetadataFieldsResourceWithRawResponse( client.custom_metadata_fields ) @@ -513,6 +519,7 @@ def __init__(self, client: AsyncImageKit) -> None: class ImageKitWithStreamedResponse: def __init__(self, client: ImageKit) -> None: + self.dummy = dummy.DummyResourceWithStreamingResponse(client.dummy) self.custom_metadata_fields = custom_metadata_fields.CustomMetadataFieldsResourceWithStreamingResponse( client.custom_metadata_fields ) @@ -526,6 +533,7 @@ def __init__(self, client: ImageKit) -> None: class AsyncImageKitWithStreamedResponse: def __init__(self, client: AsyncImageKit) -> None: + self.dummy = dummy.AsyncDummyResourceWithStreamingResponse(client.dummy) self.custom_metadata_fields = custom_metadata_fields.AsyncCustomMetadataFieldsResourceWithStreamingResponse( client.custom_metadata_fields ) diff --git a/src/imagekitio/resources/__init__.py b/src/imagekitio/resources/__init__.py index 39999ec..e9d0986 100644 --- a/src/imagekitio/resources/__init__.py +++ b/src/imagekitio/resources/__init__.py @@ -16,6 +16,14 @@ CacheResourceWithStreamingResponse, AsyncCacheResourceWithStreamingResponse, ) +from .dummy import ( + DummyResource, + AsyncDummyResource, + DummyResourceWithRawResponse, + AsyncDummyResourceWithRawResponse, + DummyResourceWithStreamingResponse, + AsyncDummyResourceWithStreamingResponse, +) from .files import ( FilesResource, AsyncFilesResource, @@ -59,6 +67,12 @@ ) __all__ = [ + "DummyResource", + "AsyncDummyResource", + "DummyResourceWithRawResponse", + "AsyncDummyResourceWithRawResponse", + "DummyResourceWithStreamingResponse", + "AsyncDummyResourceWithStreamingResponse", "CustomMetadataFieldsResource", "AsyncCustomMetadataFieldsResource", "CustomMetadataFieldsResourceWithRawResponse", diff --git a/src/imagekitio/resources/dummy.py b/src/imagekitio/resources/dummy.py new file mode 100644 index 0000000..aa44452 --- /dev/null +++ b/src/imagekitio/resources/dummy.py @@ -0,0 +1,345 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..types import dummy_create_params +from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.shared_params.overlay import Overlay +from ..types.shared_params.extensions import Extensions +from ..types.shared_params.src_options import SrcOptions +from ..types.shared_params.base_overlay import BaseOverlay +from ..types.shared_params.text_overlay import TextOverlay +from ..types.shared.streaming_resolution import StreamingResolution +from ..types.shared_params.image_overlay import ImageOverlay +from ..types.shared_params.video_overlay import VideoOverlay +from ..types.shared_params.overlay_timing import OverlayTiming +from ..types.shared_params.transformation import Transformation +from ..types.shared.transformation_position import TransformationPosition +from ..types.shared_params.overlay_position import OverlayPosition +from ..types.shared_params.subtitle_overlay import SubtitleOverlay +from ..types.shared_params.solid_color_overlay import SolidColorOverlay +from ..types.shared_params.responsive_image_attributes import ResponsiveImageAttributes +from ..types.shared_params.text_overlay_transformation import TextOverlayTransformation +from ..types.shared_params.get_image_attributes_options import GetImageAttributesOptions +from ..types.shared_params.subtitle_overlay_transformation import SubtitleOverlayTransformation +from ..types.shared_params.solid_color_overlay_transformation import SolidColorOverlayTransformation + +__all__ = ["DummyResource", "AsyncDummyResource"] + + +class DummyResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> DummyResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return DummyResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DummyResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return DummyResourceWithStreamingResponse(self) + + def create( + self, + *, + base_overlay: BaseOverlay | Omit = omit, + extensions: Extensions | Omit = omit, + get_image_attributes_options: GetImageAttributesOptions | Omit = omit, + image_overlay: ImageOverlay | Omit = omit, + overlay: Overlay | Omit = omit, + overlay_position: OverlayPosition | Omit = omit, + overlay_timing: OverlayTiming | Omit = omit, + responsive_image_attributes: ResponsiveImageAttributes | Omit = omit, + solid_color_overlay: SolidColorOverlay | Omit = omit, + solid_color_overlay_transformation: SolidColorOverlayTransformation | Omit = omit, + src_options: SrcOptions | Omit = omit, + streaming_resolution: StreamingResolution | Omit = omit, + subtitle_overlay: SubtitleOverlay | Omit = omit, + subtitle_overlay_transformation: SubtitleOverlayTransformation | Omit = omit, + text_overlay: TextOverlay | Omit = omit, + text_overlay_transformation: TextOverlayTransformation | Omit = omit, + transformation: Transformation | Omit = omit, + transformation_position: TransformationPosition | Omit = omit, + video_overlay: VideoOverlay | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Internal test endpoint for SDK generation purposes only. + + This endpoint + demonstrates usage of all shared models defined in the Stainless configuration + and is not intended for public consumption. + + Args: + extensions: Array of extensions to be applied to the asset. Each extension can be configured + with specific parameters based on the extension type. + + get_image_attributes_options: Options for generating responsive image attributes including `src`, `srcSet`, + and `sizes` for HTML `` elements. This schema extends `SrcOptions` to add + support for responsive image generation with breakpoints. + + overlay: Specifies an overlay to be applied on the parent image or video. ImageKit + supports overlays including images, text, videos, subtitles, and solid colors. + See + [Overlay using layers](https://imagekit.io/docs/transformations#overlay-using-layers). + + responsive_image_attributes: Resulting set of attributes suitable for an HTML `` element. Useful for + enabling responsive image loading with `srcSet` and `sizes`. + + src_options: Options for generating ImageKit URLs with transformations. See the + [Transformations guide](https://imagekit.io/docs/transformations). + + streaming_resolution: Available streaming resolutions for + [adaptive bitrate streaming](https://imagekit.io/docs/adaptive-bitrate-streaming) + + subtitle_overlay_transformation: Subtitle styling options. + [Learn more](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + from the docs. + + transformation: The SDK provides easy-to-use names for transformations. These names are + converted to the corresponding transformation string before being added to the + URL. SDKs are updated regularly to support new transformations. If you want to + use a transformation that is not supported by the SDK, You can use the `raw` + parameter to pass the transformation string directly. See the + [Transformations documentation](https://imagekit.io/docs/transformations). + + transformation_position: By default, the transformation string is added as a query parameter in the URL, + e.g., `?tr=w-100,h-100`. If you want to add the transformation string in the + path of the URL, set this to `path`. Learn more in the + [Transformations guide](https://imagekit.io/docs/transformations). + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + "/v1/dummy/test", + body=maybe_transform( + { + "base_overlay": base_overlay, + "extensions": extensions, + "get_image_attributes_options": get_image_attributes_options, + "image_overlay": image_overlay, + "overlay": overlay, + "overlay_position": overlay_position, + "overlay_timing": overlay_timing, + "responsive_image_attributes": responsive_image_attributes, + "solid_color_overlay": solid_color_overlay, + "solid_color_overlay_transformation": solid_color_overlay_transformation, + "src_options": src_options, + "streaming_resolution": streaming_resolution, + "subtitle_overlay": subtitle_overlay, + "subtitle_overlay_transformation": subtitle_overlay_transformation, + "text_overlay": text_overlay, + "text_overlay_transformation": text_overlay_transformation, + "transformation": transformation, + "transformation_position": transformation_position, + "video_overlay": video_overlay, + }, + dummy_create_params.DummyCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncDummyResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncDummyResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + """ + return AsyncDummyResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDummyResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + """ + return AsyncDummyResourceWithStreamingResponse(self) + + async def create( + self, + *, + base_overlay: BaseOverlay | Omit = omit, + extensions: Extensions | Omit = omit, + get_image_attributes_options: GetImageAttributesOptions | Omit = omit, + image_overlay: ImageOverlay | Omit = omit, + overlay: Overlay | Omit = omit, + overlay_position: OverlayPosition | Omit = omit, + overlay_timing: OverlayTiming | Omit = omit, + responsive_image_attributes: ResponsiveImageAttributes | Omit = omit, + solid_color_overlay: SolidColorOverlay | Omit = omit, + solid_color_overlay_transformation: SolidColorOverlayTransformation | Omit = omit, + src_options: SrcOptions | Omit = omit, + streaming_resolution: StreamingResolution | Omit = omit, + subtitle_overlay: SubtitleOverlay | Omit = omit, + subtitle_overlay_transformation: SubtitleOverlayTransformation | Omit = omit, + text_overlay: TextOverlay | Omit = omit, + text_overlay_transformation: TextOverlayTransformation | Omit = omit, + transformation: Transformation | Omit = omit, + transformation_position: TransformationPosition | Omit = omit, + video_overlay: VideoOverlay | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Internal test endpoint for SDK generation purposes only. + + This endpoint + demonstrates usage of all shared models defined in the Stainless configuration + and is not intended for public consumption. + + Args: + extensions: Array of extensions to be applied to the asset. Each extension can be configured + with specific parameters based on the extension type. + + get_image_attributes_options: Options for generating responsive image attributes including `src`, `srcSet`, + and `sizes` for HTML `` elements. This schema extends `SrcOptions` to add + support for responsive image generation with breakpoints. + + overlay: Specifies an overlay to be applied on the parent image or video. ImageKit + supports overlays including images, text, videos, subtitles, and solid colors. + See + [Overlay using layers](https://imagekit.io/docs/transformations#overlay-using-layers). + + responsive_image_attributes: Resulting set of attributes suitable for an HTML `` element. Useful for + enabling responsive image loading with `srcSet` and `sizes`. + + src_options: Options for generating ImageKit URLs with transformations. See the + [Transformations guide](https://imagekit.io/docs/transformations). + + streaming_resolution: Available streaming resolutions for + [adaptive bitrate streaming](https://imagekit.io/docs/adaptive-bitrate-streaming) + + subtitle_overlay_transformation: Subtitle styling options. + [Learn more](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + from the docs. + + transformation: The SDK provides easy-to-use names for transformations. These names are + converted to the corresponding transformation string before being added to the + URL. SDKs are updated regularly to support new transformations. If you want to + use a transformation that is not supported by the SDK, You can use the `raw` + parameter to pass the transformation string directly. See the + [Transformations documentation](https://imagekit.io/docs/transformations). + + transformation_position: By default, the transformation string is added as a query parameter in the URL, + e.g., `?tr=w-100,h-100`. If you want to add the transformation string in the + path of the URL, set this to `path`. Learn more in the + [Transformations guide](https://imagekit.io/docs/transformations). + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + "/v1/dummy/test", + body=await async_maybe_transform( + { + "base_overlay": base_overlay, + "extensions": extensions, + "get_image_attributes_options": get_image_attributes_options, + "image_overlay": image_overlay, + "overlay": overlay, + "overlay_position": overlay_position, + "overlay_timing": overlay_timing, + "responsive_image_attributes": responsive_image_attributes, + "solid_color_overlay": solid_color_overlay, + "solid_color_overlay_transformation": solid_color_overlay_transformation, + "src_options": src_options, + "streaming_resolution": streaming_resolution, + "subtitle_overlay": subtitle_overlay, + "subtitle_overlay_transformation": subtitle_overlay_transformation, + "text_overlay": text_overlay, + "text_overlay_transformation": text_overlay_transformation, + "transformation": transformation, + "transformation_position": transformation_position, + "video_overlay": video_overlay, + }, + dummy_create_params.DummyCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class DummyResourceWithRawResponse: + def __init__(self, dummy: DummyResource) -> None: + self._dummy = dummy + + self.create = to_raw_response_wrapper( + dummy.create, + ) + + +class AsyncDummyResourceWithRawResponse: + def __init__(self, dummy: AsyncDummyResource) -> None: + self._dummy = dummy + + self.create = async_to_raw_response_wrapper( + dummy.create, + ) + + +class DummyResourceWithStreamingResponse: + def __init__(self, dummy: DummyResource) -> None: + self._dummy = dummy + + self.create = to_streamed_response_wrapper( + dummy.create, + ) + + +class AsyncDummyResourceWithStreamingResponse: + def __init__(self, dummy: AsyncDummyResource) -> None: + self._dummy = dummy + + self.create = async_to_streamed_response_wrapper( + dummy.create, + ) diff --git a/src/imagekitio/types/__init__.py b/src/imagekitio/types/__init__.py index 5d26870..dfbbb78 100644 --- a/src/imagekitio/types/__init__.py +++ b/src/imagekitio/types/__init__.py @@ -40,6 +40,7 @@ from .folder_copy_params import FolderCopyParams as FolderCopyParams from .folder_move_params import FolderMoveParams as FolderMoveParams from .asset_list_response import AssetListResponse as AssetListResponse +from .dummy_create_params import DummyCreateParams as DummyCreateParams from .file_rename_response import FileRenameResponse as FileRenameResponse from .file_update_response import FileUpdateResponse as FileUpdateResponse from .file_upload_response import FileUploadResponse as FileUploadResponse diff --git a/src/imagekitio/types/dummy_create_params.py b/src/imagekitio/types/dummy_create_params.py new file mode 100644 index 0000000..e21a396 --- /dev/null +++ b/src/imagekitio/types/dummy_create_params.py @@ -0,0 +1,124 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo +from .shared_params.extensions import Extensions +from .shared_params.base_overlay import BaseOverlay +from .shared_params.text_overlay import TextOverlay +from .shared.streaming_resolution import StreamingResolution +from .shared_params.overlay_timing import OverlayTiming +from .shared.transformation_position import TransformationPosition +from .shared_params.overlay_position import OverlayPosition +from .shared_params.subtitle_overlay import SubtitleOverlay +from .shared_params.solid_color_overlay import SolidColorOverlay +from .shared_params.responsive_image_attributes import ResponsiveImageAttributes +from .shared_params.text_overlay_transformation import TextOverlayTransformation +from .shared_params.subtitle_overlay_transformation import SubtitleOverlayTransformation +from .shared_params.solid_color_overlay_transformation import SolidColorOverlayTransformation + +__all__ = ["DummyCreateParams"] + + +class DummyCreateParams(TypedDict, total=False): + base_overlay: Annotated[BaseOverlay, PropertyInfo(alias="baseOverlay")] + + extensions: Extensions + """Array of extensions to be applied to the asset. + + Each extension can be configured with specific parameters based on the extension + type. + """ + + get_image_attributes_options: Annotated[ + "GetImageAttributesOptions", PropertyInfo(alias="getImageAttributesOptions") + ] + """ + Options for generating responsive image attributes including `src`, `srcSet`, + and `sizes` for HTML `` elements. This schema extends `SrcOptions` to add + support for responsive image generation with breakpoints. + """ + + image_overlay: Annotated["ImageOverlay", PropertyInfo(alias="imageOverlay")] + + overlay: "Overlay" + """Specifies an overlay to be applied on the parent image or video. + + ImageKit supports overlays including images, text, videos, subtitles, and solid + colors. See + [Overlay using layers](https://imagekit.io/docs/transformations#overlay-using-layers). + """ + + overlay_position: Annotated[OverlayPosition, PropertyInfo(alias="overlayPosition")] + + overlay_timing: Annotated[OverlayTiming, PropertyInfo(alias="overlayTiming")] + + responsive_image_attributes: Annotated[ResponsiveImageAttributes, PropertyInfo(alias="responsiveImageAttributes")] + """ + Resulting set of attributes suitable for an HTML `` element. Useful for + enabling responsive image loading with `srcSet` and `sizes`. + """ + + solid_color_overlay: Annotated[SolidColorOverlay, PropertyInfo(alias="solidColorOverlay")] + + solid_color_overlay_transformation: Annotated[ + SolidColorOverlayTransformation, PropertyInfo(alias="solidColorOverlayTransformation") + ] + + src_options: Annotated["SrcOptions", PropertyInfo(alias="srcOptions")] + """Options for generating ImageKit URLs with transformations. + + See the [Transformations guide](https://imagekit.io/docs/transformations). + """ + + streaming_resolution: Annotated[StreamingResolution, PropertyInfo(alias="streamingResolution")] + """ + Available streaming resolutions for + [adaptive bitrate streaming](https://imagekit.io/docs/adaptive-bitrate-streaming) + """ + + subtitle_overlay: Annotated[SubtitleOverlay, PropertyInfo(alias="subtitleOverlay")] + + subtitle_overlay_transformation: Annotated[ + SubtitleOverlayTransformation, PropertyInfo(alias="subtitleOverlayTransformation") + ] + """Subtitle styling options. + + [Learn more](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + from the docs. + """ + + text_overlay: Annotated[TextOverlay, PropertyInfo(alias="textOverlay")] + + text_overlay_transformation: Annotated[TextOverlayTransformation, PropertyInfo(alias="textOverlayTransformation")] + + transformation: "Transformation" + """The SDK provides easy-to-use names for transformations. + + These names are converted to the corresponding transformation string before + being added to the URL. SDKs are updated regularly to support new + transformations. If you want to use a transformation that is not supported by + the SDK, You can use the `raw` parameter to pass the transformation string + directly. See the + [Transformations documentation](https://imagekit.io/docs/transformations). + """ + + transformation_position: Annotated[TransformationPosition, PropertyInfo(alias="transformationPosition")] + """ + By default, the transformation string is added as a query parameter in the URL, + e.g., `?tr=w-100,h-100`. If you want to add the transformation string in the + path of the URL, set this to `path`. Learn more in the + [Transformations guide](https://imagekit.io/docs/transformations). + """ + + video_overlay: Annotated["VideoOverlay", PropertyInfo(alias="videoOverlay")] + + +from .shared_params.overlay import Overlay +from .shared_params.src_options import SrcOptions +from .shared_params.image_overlay import ImageOverlay +from .shared_params.video_overlay import VideoOverlay +from .shared_params.transformation import Transformation +from .shared_params.get_image_attributes_options import GetImageAttributesOptions diff --git a/src/imagekitio/types/shared_params/__init__.py b/src/imagekitio/types/shared_params/__init__.py index 165dee4..49f3e91 100644 --- a/src/imagekitio/types/shared_params/__init__.py +++ b/src/imagekitio/types/shared_params/__init__.py @@ -1,3 +1,21 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .overlay import Overlay as Overlay from .extensions import Extensions as Extensions +from .src_options import SrcOptions as SrcOptions +from .base_overlay import BaseOverlay as BaseOverlay +from .text_overlay import TextOverlay as TextOverlay +from .image_overlay import ImageOverlay as ImageOverlay +from .video_overlay import VideoOverlay as VideoOverlay +from .overlay_timing import OverlayTiming as OverlayTiming +from .transformation import Transformation as Transformation +from .overlay_position import OverlayPosition as OverlayPosition +from .subtitle_overlay import SubtitleOverlay as SubtitleOverlay +from .solid_color_overlay import SolidColorOverlay as SolidColorOverlay +from .streaming_resolution import StreamingResolution as StreamingResolution +from .transformation_position import TransformationPosition as TransformationPosition +from .responsive_image_attributes import ResponsiveImageAttributes as ResponsiveImageAttributes +from .text_overlay_transformation import TextOverlayTransformation as TextOverlayTransformation +from .get_image_attributes_options import GetImageAttributesOptions as GetImageAttributesOptions +from .subtitle_overlay_transformation import SubtitleOverlayTransformation as SubtitleOverlayTransformation +from .solid_color_overlay_transformation import SolidColorOverlayTransformation as SolidColorOverlayTransformation diff --git a/src/imagekitio/types/shared_params/base_overlay.py b/src/imagekitio/types/shared_params/base_overlay.py new file mode 100644 index 0000000..bf3bf1e --- /dev/null +++ b/src/imagekitio/types/shared_params/base_overlay.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +from .overlay_timing import OverlayTiming +from .overlay_position import OverlayPosition + +__all__ = ["BaseOverlay"] + + +class BaseOverlay(TypedDict, total=False): + position: OverlayPosition + + timing: OverlayTiming diff --git a/src/imagekitio/types/shared_params/get_image_attributes_options.py b/src/imagekitio/types/shared_params/get_image_attributes_options.py new file mode 100644 index 0000000..37c7c1e --- /dev/null +++ b/src/imagekitio/types/shared_params/get_image_attributes_options.py @@ -0,0 +1,54 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Annotated + +from ..._utils import PropertyInfo +from .src_options import SrcOptions + +__all__ = ["GetImageAttributesOptions"] + + +class GetImageAttributesOptions(SrcOptions, total=False): + device_breakpoints: Annotated[Iterable[float], PropertyInfo(alias="deviceBreakpoints")] + """ + Custom list of **device-width breakpoints** in pixels. These define common + screen widths for responsive image generation. + + Defaults to `[640, 750, 828, 1080, 1200, 1920, 2048, 3840]`. Sorted + automatically. + """ + + image_breakpoints: Annotated[Iterable[float], PropertyInfo(alias="imageBreakpoints")] + """ + Custom list of **image-specific breakpoints** in pixels. Useful for generating + small variants (e.g., placeholders or thumbnails). + + Merged with `deviceBreakpoints` before calculating `srcSet`. Defaults to + `[16, 32, 48, 64, 96, 128, 256, 384]`. Sorted automatically. + """ + + sizes: str + """ + The value for the HTML `sizes` attribute (e.g., `"100vw"` or + `"(min-width:768px) 50vw, 100vw"`). + + - If it includes one or more `vw` units, breakpoints smaller than the + corresponding percentage of the smallest device width are excluded. + - If it contains no `vw` units, the full breakpoint list is used. + + Enables a width-based strategy and generates `w` descriptors in `srcSet`. + """ + + width: float + """ + The intended display width of the image in pixels, used **only when the `sizes` + attribute is not provided**. + + Triggers a DPR-based strategy (1x and 2x variants) and generates `x` descriptors + in `srcSet`. + + Ignored if `sizes` is present. + """ diff --git a/src/imagekitio/types/shared_params/image_overlay.py b/src/imagekitio/types/shared_params/image_overlay.py new file mode 100644 index 0000000..3b7d74e --- /dev/null +++ b/src/imagekitio/types/shared_params/image_overlay.py @@ -0,0 +1,38 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required + +from .base_overlay import BaseOverlay + +__all__ = ["ImageOverlay"] + + +class ImageOverlay(BaseOverlay, total=False): + input: Required[str] + """Specifies the relative path to the image used as an overlay.""" + + type: Required[Literal["image"]] + + encoding: Literal["auto", "plain", "base64"] + """ + The input path can be included in the layer as either `i-{input}` or + `ie-{base64_encoded_input}`. By default, the SDK determines the appropriate + format automatically. To always use base64 encoding (`ie-{base64}`), set this + parameter to `base64`. To always use plain text (`i-{input}`), set it to + `plain`. + """ + + transformation: Iterable["Transformation"] + """Array of transformations to be applied to the overlay image. + + Supported transformations depends on the base/parent asset. See overlays on + [Images](https://imagekit.io/docs/add-overlays-on-images#list-of-supported-image-transformations-in-image-layers) + and + [Videos](https://imagekit.io/docs/add-overlays-on-videos#list-of-transformations-supported-on-image-overlay). + """ + + +from .transformation import Transformation diff --git a/src/imagekitio/types/shared_params/overlay.py b/src/imagekitio/types/shared_params/overlay.py new file mode 100644 index 0000000..ed4e79a --- /dev/null +++ b/src/imagekitio/types/shared_params/overlay.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Union +from typing_extensions import TypeAlias, TypeAliasType + +from ..._compat import PYDANTIC_V1 +from .text_overlay import TextOverlay +from .subtitle_overlay import SubtitleOverlay +from .solid_color_overlay import SolidColorOverlay + +__all__ = ["Overlay"] + +if TYPE_CHECKING or not PYDANTIC_V1: + Overlay = TypeAliasType( + "Overlay", Union[TextOverlay, "ImageOverlay", "VideoOverlay", SubtitleOverlay, SolidColorOverlay] + ) +else: + Overlay: TypeAlias = Union[TextOverlay, "ImageOverlay", "VideoOverlay", SubtitleOverlay, SolidColorOverlay] + +from .image_overlay import ImageOverlay +from .video_overlay import VideoOverlay diff --git a/src/imagekitio/types/shared_params/overlay_position.py b/src/imagekitio/types/shared_params/overlay_position.py new file mode 100644 index 0000000..f74e3e1 --- /dev/null +++ b/src/imagekitio/types/shared_params/overlay_position.py @@ -0,0 +1,34 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, TypedDict + +__all__ = ["OverlayPosition"] + + +class OverlayPosition(TypedDict, total=False): + focus: Literal["center", "top", "left", "bottom", "right", "top_left", "top_right", "bottom_left", "bottom_right"] + """ + Specifies the position of the overlay relative to the parent image or video. + Maps to `lfo` in the URL. + """ + + x: Union[float, str] + """ + Specifies the x-coordinate of the top-left corner of the base asset where the + overlay's top-left corner will be positioned. It also accepts arithmetic + expressions such as `bw_mul_0.4` or `bw_sub_cw`. Maps to `lx` in the URL. Learn + about + [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + """ + + y: Union[float, str] + """ + Specifies the y-coordinate of the top-left corner of the base asset where the + overlay's top-left corner will be positioned. It also accepts arithmetic + expressions such as `bh_mul_0.4` or `bh_sub_ch`. Maps to `ly` in the URL. Learn + about + [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + """ diff --git a/src/imagekitio/types/shared_params/overlay_timing.py b/src/imagekitio/types/shared_params/overlay_timing.py new file mode 100644 index 0000000..4f766d1 --- /dev/null +++ b/src/imagekitio/types/shared_params/overlay_timing.py @@ -0,0 +1,35 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import TypedDict + +__all__ = ["OverlayTiming"] + + +class OverlayTiming(TypedDict, total=False): + duration: Union[float, str] + """ + Specifies the duration (in seconds) during which the overlay should appear on + the base video. Accepts a positive number up to two decimal places (e.g., `20` + or `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. + Applies only if the base asset is a video. Maps to `ldu` in the URL. + """ + + end: Union[float, str] + """ + Specifies the end time (in seconds) for when the overlay should disappear from + the base video. If both end and duration are provided, duration is ignored. + Accepts a positive number up to two decimal places (e.g., `20` or `20.50`) and + arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. Applies only if + the base asset is a video. Maps to `leo` in the URL. + """ + + start: Union[float, str] + """ + Specifies the start time (in seconds) for when the overlay should appear on the + base video. Accepts a positive number up to two decimal places (e.g., `20` or + `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. + Applies only if the base asset is a video. Maps to `lso` in the URL. + """ diff --git a/src/imagekitio/types/shared_params/responsive_image_attributes.py b/src/imagekitio/types/shared_params/responsive_image_attributes.py new file mode 100644 index 0000000..b108252 --- /dev/null +++ b/src/imagekitio/types/shared_params/responsive_image_attributes.py @@ -0,0 +1,29 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ResponsiveImageAttributes"] + + +class ResponsiveImageAttributes(TypedDict, total=False): + src: Required[str] + """URL for the _largest_ candidate (assigned to plain `src`).""" + + sizes: str + """`sizes` returned (or synthesised as `100vw`). + + The value for the HTML `sizes` attribute. + """ + + src_set: Annotated[str, PropertyInfo(alias="srcSet")] + """Candidate set with `w` or `x` descriptors. + + Multiple image URLs separated by commas, each with a descriptor. + """ + + width: float + """Width as a number (if `width` was provided in the input options).""" diff --git a/src/imagekitio/types/shared_params/solid_color_overlay.py b/src/imagekitio/types/shared_params/solid_color_overlay.py new file mode 100644 index 0000000..35f36b1 --- /dev/null +++ b/src/imagekitio/types/shared_params/solid_color_overlay.py @@ -0,0 +1,32 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required + +from .base_overlay import BaseOverlay +from .solid_color_overlay_transformation import SolidColorOverlayTransformation + +__all__ = ["SolidColorOverlay"] + + +class SolidColorOverlay(BaseOverlay, total=False): + color: Required[str] + """ + Specifies the color of the block using an RGB hex code (e.g., `FF0000`), an RGBA + code (e.g., `FFAABB50`), or a color name (e.g., `red`). If an 8-character value + is provided, the last two characters represent the opacity level (from `00` for + 0.00 to `99` for 0.99). + """ + + type: Required[Literal["solidColor"]] + + transformation: Iterable[SolidColorOverlayTransformation] + """Control width and height of the solid color overlay. + + Supported transformations depend on the base/parent asset. See overlays on + [Images](https://imagekit.io/docs/add-overlays-on-images#apply-transformation-on-solid-color-overlay) + and + [Videos](https://imagekit.io/docs/add-overlays-on-videos#apply-transformations-on-solid-color-block-overlay). + """ diff --git a/src/imagekitio/types/shared_params/solid_color_overlay_transformation.py b/src/imagekitio/types/shared_params/solid_color_overlay_transformation.py new file mode 100644 index 0000000..8bfcca7 --- /dev/null +++ b/src/imagekitio/types/shared_params/solid_color_overlay_transformation.py @@ -0,0 +1,53 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, TypedDict + +__all__ = ["SolidColorOverlayTransformation"] + + +class SolidColorOverlayTransformation(TypedDict, total=False): + alpha: float + """Specifies the transparency level of the solid color overlay. + + Accepts integers from `1` to `9`. + """ + + background: str + """Specifies the background color of the solid color overlay. + + Accepts an RGB hex code (e.g., `FF0000`), an RGBA code (e.g., `FFAABB50`), or a + color name. + """ + + gradient: Union[Literal[True], str] + """Creates a linear gradient with two colors. + + Pass `true` for a default gradient, or provide a string for a custom gradient. + Only works if the base asset is an image. See + [gradient](https://imagekit.io/docs/effects-and-enhancements#gradient---e-gradient). + """ + + height: Union[float, str] + """Controls the height of the solid color overlay. + + Accepts a numeric value or an arithmetic expression. Learn about + [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + """ + + radius: Union[float, Literal["max"]] + """Specifies the corner radius of the solid color overlay. + + Set to `max` for circular or oval shape. See + [radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). + """ + + width: Union[float, str] + """Controls the width of the solid color overlay. + + Accepts a numeric value or an arithmetic expression (e.g., `bw_mul_0.2` or + `bh_div_2`). Learn about + [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + """ diff --git a/src/imagekitio/types/shared_params/src_options.py b/src/imagekitio/types/shared_params/src_options.py new file mode 100644 index 0000000..a10f3bb --- /dev/null +++ b/src/imagekitio/types/shared_params/src_options.py @@ -0,0 +1,76 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Iterable +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo +from ..shared.transformation_position import TransformationPosition + +__all__ = ["SrcOptions"] + + +class SrcOptions(TypedDict, total=False): + src: Required[str] + """Accepts a relative or absolute path of the resource. + + If a relative path is provided, it is appended to the `urlEndpoint`. If an + absolute path is provided, `urlEndpoint` is ignored. + """ + + url_endpoint: Required[Annotated[str, PropertyInfo(alias="urlEndpoint")]] + """ + Get your urlEndpoint from the + [ImageKit dashboard](https://imagekit.io/dashboard/url-endpoints). + """ + + expires_in: Annotated[float, PropertyInfo(alias="expiresIn")] + """When you want the signed URL to expire, specified in seconds. + + If `expiresIn` is anything above 0, the URL will always be signed even if + `signed` is set to false. If not specified and `signed` is `true`, the signed + URL will not expire (valid indefinitely). + + Example: Setting `expiresIn: 3600` will make the URL expire 1 hour from + generation time. After the expiry time, the signed URL will no longer be valid + and ImageKit will return a 401 Unauthorized status code. + + [Learn more](https://imagekit.io/docs/media-delivery-basic-security#how-to-generate-signed-urls). + """ + + query_parameters: Annotated[Dict[str, str], PropertyInfo(alias="queryParameters")] + """ + These are additional query parameters that you want to add to the final URL. + They can be any query parameters and not necessarily related to ImageKit. This + is especially useful if you want to add a versioning parameter to your URLs. + """ + + signed: bool + """Whether to sign the URL or not. + + Set this to `true` if you want to generate a signed URL. If `signed` is `true` + and `expiresIn` is not specified, the signed URL will not expire (valid + indefinitely). Note: If `expiresIn` is set to any value above 0, the URL will + always be signed regardless of this setting. + [Learn more](https://imagekit.io/docs/media-delivery-basic-security#how-to-generate-signed-urls). + """ + + transformation: Iterable["Transformation"] + """An array of objects specifying the transformations to be applied in the URL. + + If more than one transformation is specified, they are applied in the order they + are specified as chained transformations. See + [Chained transformations](https://imagekit.io/docs/transformations#chained-transformations). + """ + + transformation_position: Annotated[TransformationPosition, PropertyInfo(alias="transformationPosition")] + """ + By default, the transformation string is added as a query parameter in the URL, + e.g., `?tr=w-100,h-100`. If you want to add the transformation string in the + path of the URL, set this to `path`. Learn more in the + [Transformations guide](https://imagekit.io/docs/transformations). + """ + + +from .transformation import Transformation diff --git a/src/imagekitio/types/shared_params/streaming_resolution.py b/src/imagekitio/types/shared_params/streaming_resolution.py new file mode 100644 index 0000000..ac32902 --- /dev/null +++ b/src/imagekitio/types/shared_params/streaming_resolution.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypeAlias + +__all__ = ["StreamingResolution"] + +StreamingResolution: TypeAlias = Literal["240", "360", "480", "720", "1080", "1440", "2160"] diff --git a/src/imagekitio/types/shared_params/subtitle_overlay.py b/src/imagekitio/types/shared_params/subtitle_overlay.py new file mode 100644 index 0000000..71e885e --- /dev/null +++ b/src/imagekitio/types/shared_params/subtitle_overlay.py @@ -0,0 +1,34 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required + +from .base_overlay import BaseOverlay +from .subtitle_overlay_transformation import SubtitleOverlayTransformation + +__all__ = ["SubtitleOverlay"] + + +class SubtitleOverlay(BaseOverlay, total=False): + input: Required[str] + """Specifies the relative path to the subtitle file used as an overlay.""" + + type: Required[Literal["subtitle"]] + + encoding: Literal["auto", "plain", "base64"] + """ + The input path can be included in the layer as either `i-{input}` or + `ie-{base64_encoded_input}`. By default, the SDK determines the appropriate + format automatically. To always use base64 encoding (`ie-{base64}`), set this + parameter to `base64`. To always use plain text (`i-{input}`), set it to + `plain`. + """ + + transformation: Iterable[SubtitleOverlayTransformation] + """Control styling of the subtitle. + + See + [Styling subtitles](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer). + """ diff --git a/src/imagekitio/types/shared_params/subtitle_overlay_transformation.py b/src/imagekitio/types/shared_params/subtitle_overlay_transformation.py new file mode 100644 index 0000000..ad74239 --- /dev/null +++ b/src/imagekitio/types/shared_params/subtitle_overlay_transformation.py @@ -0,0 +1,74 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["SubtitleOverlayTransformation"] + + +class SubtitleOverlayTransformation(TypedDict, total=False): + background: str + """ + Specifies the subtitle background color using a standard color name, an RGB + color code (e.g., FF0000), or an RGBA color code (e.g., FFAABB50). + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ + + color: str + """ + Sets the font color of the subtitle text using a standard color name, an RGB + color code (e.g., FF0000), or an RGBA color code (e.g., FFAABB50). + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ + + font_family: Annotated[str, PropertyInfo(alias="fontFamily")] + """Font family for subtitles. + + Refer to the + [supported fonts](https://imagekit.io/docs/add-overlays-on-images#supported-text-font-list). + """ + + font_outline: Annotated[str, PropertyInfo(alias="fontOutline")] + """Sets the font outline of the subtitle text. + + Requires the outline width (an integer) and the outline color (as an RGB color + code, RGBA color code, or standard web color name) separated by an underscore. + Example: `fol-2_blue` (outline width of 2px and outline color blue), + `fol-2_A1CCDD` (outline width of 2px and outline color `#A1CCDD`) and + `fol-2_A1CCDD50` (outline width of 2px and outline color `#A1CCDD` at 50% + opacity). + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ + + font_shadow: Annotated[str, PropertyInfo(alias="fontShadow")] + """Sets the font shadow for the subtitle text. + + Requires the shadow color (as an RGB color code, RGBA color code, or standard + web color name) and shadow indent (an integer) separated by an underscore. + Example: `fsh-blue_2` (shadow color blue, indent of 2px), `fsh-A1CCDD_3` (shadow + color `#A1CCDD`, indent of 3px), `fsh-A1CCDD50_3` (shadow color `#A1CCDD` at 50% + opacity, indent of 3px). + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ + + font_size: Annotated[float, PropertyInfo(alias="fontSize")] + """Sets the font size of subtitle text. + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ + + typography: Literal["b", "i", "b_i"] + """Sets the typography style of the subtitle text. + + Supports values are `b` for bold, `i` for italics, and `b_i` for bold with + italics. + + [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + """ diff --git a/src/imagekitio/types/shared_params/text_overlay.py b/src/imagekitio/types/shared_params/text_overlay.py new file mode 100644 index 0000000..62ebe4c --- /dev/null +++ b/src/imagekitio/types/shared_params/text_overlay.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required + +from .base_overlay import BaseOverlay +from .text_overlay_transformation import TextOverlayTransformation + +__all__ = ["TextOverlay"] + + +class TextOverlay(BaseOverlay, total=False): + text: Required[str] + """Specifies the text to be displayed in the overlay. + + The SDK automatically handles special characters and encoding. + """ + + type: Required[Literal["text"]] + + encoding: Literal["auto", "plain", "base64"] + """ + Text can be included in the layer as either `i-{input}` (plain text) or + `ie-{base64_encoded_input}` (base64). By default, the SDK selects the + appropriate format based on the input text. To always use base64 + (`ie-{base64}`), set this parameter to `base64`. To always use plain text + (`i-{input}`), set it to `plain`. + """ + + transformation: Iterable[TextOverlayTransformation] + """Control styling of the text overlay. + + See + [Text overlays](https://imagekit.io/docs/add-overlays-on-images#text-overlay). + """ diff --git a/src/imagekitio/types/shared_params/text_overlay_transformation.py b/src/imagekitio/types/shared_params/text_overlay_transformation.py new file mode 100644 index 0000000..5f05fbd --- /dev/null +++ b/src/imagekitio/types/shared_params/text_overlay_transformation.py @@ -0,0 +1,99 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["TextOverlayTransformation"] + + +class TextOverlayTransformation(TypedDict, total=False): + alpha: float + """Specifies the transparency level of the text overlay. + + Accepts integers from `1` to `9`. + """ + + background: str + """ + Specifies the background color of the text overlay. Accepts an RGB hex code, an + RGBA code, or a color name. + """ + + flip: Literal["h", "v", "h_v", "v_h"] + """Flip the text overlay horizontally, vertically, or both.""" + + font_color: Annotated[str, PropertyInfo(alias="fontColor")] + """Specifies the font color of the overlaid text. + + Accepts an RGB hex code (e.g., `FF0000`), an RGBA code (e.g., `FFAABB50`), or a + color name. + """ + + font_family: Annotated[str, PropertyInfo(alias="fontFamily")] + """Specifies the font family of the overlaid text. + + Choose from the supported fonts list or use a custom font. See + [Supported fonts](https://imagekit.io/docs/add-overlays-on-images#supported-text-font-list) + and + [Custom font](https://imagekit.io/docs/add-overlays-on-images#change-font-family-in-text-overlay). + """ + + font_size: Annotated[Union[float, str], PropertyInfo(alias="fontSize")] + """Specifies the font size of the overlaid text. + + Accepts a numeric value or an arithmetic expression. + """ + + inner_alignment: Annotated[Literal["left", "right", "center"], PropertyInfo(alias="innerAlignment")] + """ + Specifies the inner alignment of the text when width is more than the text + length. + """ + + line_height: Annotated[Union[float, str], PropertyInfo(alias="lineHeight")] + """Specifies the line height of the text overlay. + + Accepts integer values representing line height in points. It can also accept + [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations) + such as `bw_mul_0.2`, or `bh_div_20`. + """ + + padding: Union[float, str] + """ + Specifies the padding around the overlaid text. Can be provided as a single + positive integer or multiple values separated by underscores (following CSS + shorthand order). Arithmetic expressions are also accepted. + """ + + radius: Union[float, Literal["max"]] + """ + Specifies the corner radius of the text overlay. Set to `max` to achieve a + circular or oval shape. + """ + + rotation: Union[float, str] + """ + Specifies the rotation angle of the text overlay. Accepts a numeric value for + clockwise rotation or a string prefixed with "N" for counter-clockwise rotation. + """ + + typography: str + """Specifies the typography style of the text. Supported values: + + - Single styles: `b` (bold), `i` (italic), `strikethrough`. + - Combinations: Any combination separated by underscores, e.g., `b_i`, + `b_i_strikethrough`. + """ + + width: Union[float, str] + """Specifies the maximum width (in pixels) of the overlaid text. + + The text wraps automatically, and arithmetic expressions (e.g., `bw_mul_0.2` or + `bh_div_2`) are supported. Useful when used in conjunction with the + `background`. Learn about + [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + """ diff --git a/src/imagekitio/types/shared_params/transformation.py b/src/imagekitio/types/shared_params/transformation.py new file mode 100644 index 0000000..1f474a5 --- /dev/null +++ b/src/imagekitio/types/shared_params/transformation.py @@ -0,0 +1,424 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo +from ..shared.streaming_resolution import StreamingResolution + +__all__ = ["Transformation"] + + +class Transformation(TypedDict, total=False): + ai_change_background: Annotated[str, PropertyInfo(alias="aiChangeBackground")] + """Uses AI to change the background. + + Provide a text prompt or a base64-encoded prompt, e.g., `prompt-snow road` or + `prompte-[urlencoded_base64_encoded_text]`. Not supported inside overlay. See + [AI Change Background](https://imagekit.io/docs/ai-transformations#change-background-e-changebg). + """ + + ai_drop_shadow: Annotated[Union[Literal[True], str], PropertyInfo(alias="aiDropShadow")] + """ + Adds an AI-based drop shadow around a foreground object on a transparent or + removed background. Optionally, control the direction, elevation, and saturation + of the light source (e.g., `az-45` to change light direction). Pass `true` for + the default drop shadow, or provide a string for a custom drop shadow. Supported + inside overlay. See + [AI Drop Shadow](https://imagekit.io/docs/ai-transformations#ai-drop-shadow-e-dropshadow). + """ + + ai_edit: Annotated[str, PropertyInfo(alias="aiEdit")] + """Uses AI to edit images based on a text prompt. + + Provide a text prompt or a base64-encoded prompt, e.g., `prompt-snow road` or + `prompte-[urlencoded_base64_encoded_text]`. Not supported inside overlay. + See [AI Edit](https://imagekit.io/docs/ai-transformations#edit-image-e-edit). + """ + + ai_remove_background: Annotated[Literal[True], PropertyInfo(alias="aiRemoveBackground")] + """Applies ImageKit's in-house background removal. + + Supported inside overlay. See + [AI Background Removal](https://imagekit.io/docs/ai-transformations#imagekit-background-removal-e-bgremove). + """ + + ai_remove_background_external: Annotated[Literal[True], PropertyInfo(alias="aiRemoveBackgroundExternal")] + """Uses third-party background removal. + + Note: It is recommended to use aiRemoveBackground, ImageKit's in-house solution, + which is more cost-effective. Supported inside overlay. See + [External Background Removal](https://imagekit.io/docs/ai-transformations#background-removal-e-removedotbg). + """ + + ai_retouch: Annotated[Literal[True], PropertyInfo(alias="aiRetouch")] + """Performs AI-based retouching to improve faces or product shots. + + Not supported inside overlay. See + [AI Retouch](https://imagekit.io/docs/ai-transformations#retouch-e-retouch). + """ + + ai_upscale: Annotated[Literal[True], PropertyInfo(alias="aiUpscale")] + """Upscales images beyond their original dimensions using AI. + + Not supported inside overlay. See + [AI Upscale](https://imagekit.io/docs/ai-transformations#upscale-e-upscale). + """ + + ai_variation: Annotated[Literal[True], PropertyInfo(alias="aiVariation")] + """Generates a variation of an image using AI. + + This produces a new image with slight variations from the original, such as + changes in color, texture, and other visual elements, while preserving the + structure and essence of the original image. Not supported inside overlay. See + [AI Generate Variations](https://imagekit.io/docs/ai-transformations#generate-variations-of-an-image-e-genvar). + """ + + aspect_ratio: Annotated[Union[float, str], PropertyInfo(alias="aspectRatio")] + """Specifies the aspect ratio for the output, e.g., "ar-4-3". + + Typically used with either width or height (but not both). For example: + aspectRatio = `4:3`, `4_3`, or an expression like `iar_div_2`. See + [Image resize and crop – Aspect ratio](https://imagekit.io/docs/image-resize-and-crop#aspect-ratio---ar). + """ + + audio_codec: Annotated[Literal["aac", "opus", "none"], PropertyInfo(alias="audioCodec")] + """Specifies the audio codec, e.g., `aac`, `opus`, or `none`. + + See [Audio codec](https://imagekit.io/docs/video-optimization#audio-codec---ac). + """ + + background: str + """ + Specifies the background to be used in conjunction with certain cropping + strategies when resizing an image. + + - A solid color: e.g., `red`, `F3F3F3`, `AAFF0010`. See + [Solid color background](https://imagekit.io/docs/effects-and-enhancements#solid-color-background). + - A blurred background: e.g., `blurred`, `blurred_25_N15`, etc. See + [Blurred background](https://imagekit.io/docs/effects-and-enhancements#blurred-background). + - Expand the image boundaries using generative fill: `genfill`. Not supported + inside overlay. Optionally, control the background scene by passing a text + prompt: `genfill[:-prompt-${text}]` or + `genfill[:-prompte-${urlencoded_base64_encoded_text}]`. See + [Generative fill background](https://imagekit.io/docs/ai-transformations#generative-fill-bg-genfill). + """ + + blur: float + """Specifies the Gaussian blur level. + + Accepts an integer value between 1 and 100, or an expression like `bl-10`. See + [Blur](https://imagekit.io/docs/effects-and-enhancements#blur---bl). + """ + + border: str + """Adds a border to the output media. + + Accepts a string in the format `_` (e.g., `5_FFF000` for + a 5px yellow border), or an expression like `ih_div_20_FF00FF`. See + [Border](https://imagekit.io/docs/effects-and-enhancements#border---b). + """ + + color_profile: Annotated[bool, PropertyInfo(alias="colorProfile")] + """ + Indicates whether the output image should retain the original color profile. See + [Color profile](https://imagekit.io/docs/image-optimization#color-profile---cp). + """ + + contrast_stretch: Annotated[Literal[True], PropertyInfo(alias="contrastStretch")] + """ + Automatically enhances the contrast of an image (contrast stretch). See + [Contrast Stretch](https://imagekit.io/docs/effects-and-enhancements#contrast-stretch---e-contrast). + """ + + crop: Literal["force", "at_max", "at_max_enlarge", "at_least", "maintain_ratio"] + """Crop modes for image resizing. + + See + [Crop modes & focus](https://imagekit.io/docs/image-resize-and-crop#crop-crop-modes--focus). + """ + + crop_mode: Annotated[Literal["pad_resize", "extract", "pad_extract"], PropertyInfo(alias="cropMode")] + """Additional crop modes for image resizing. + + See + [Crop modes & focus](https://imagekit.io/docs/image-resize-and-crop#crop-crop-modes--focus). + """ + + default_image: Annotated[str, PropertyInfo(alias="defaultImage")] + """ + Specifies a fallback image if the resource is not found, e.g., a URL or file + path. See + [Default image](https://imagekit.io/docs/image-transformation#default-image---di). + """ + + dpr: float + """ + Accepts values between 0.1 and 5, or `auto` for automatic device pixel ratio + (DPR) calculation. See + [DPR](https://imagekit.io/docs/image-resize-and-crop#dpr---dpr). + """ + + duration: Union[float, str] + """Specifies the duration (in seconds) for trimming videos, e.g., `5` or `10.5`. + + Typically used with startOffset to indicate the length from the start offset. + Arithmetic expressions are supported. See + [Trim videos – Duration](https://imagekit.io/docs/trim-videos#duration---du). + """ + + end_offset: Annotated[Union[float, str], PropertyInfo(alias="endOffset")] + """Specifies the end offset (in seconds) for trimming videos, e.g., `5` or `10.5`. + + Typically used with startOffset to define a time window. Arithmetic expressions + are supported. See + [Trim videos – End offset](https://imagekit.io/docs/trim-videos#end-offset---eo). + """ + + flip: Literal["h", "v", "h_v", "v_h"] + """Flips or mirrors an image either horizontally, vertically, or both. + + Acceptable values: `h` (horizontal), `v` (vertical), `h_v` (horizontal and + vertical), or `v_h`. See + [Flip](https://imagekit.io/docs/effects-and-enhancements#flip---fl). + """ + + focus: str + """ + Refines padding and cropping behavior for pad resize, maintain ratio, and + extract crop modes. Supports manual positions and coordinate-based focus. With + AI-based cropping, you can automatically keep key subjects in frame—such as + faces or detected objects (e.g., `fo-face`, `fo-person`, `fo-car`)— while + resizing. + + - See [Focus](https://imagekit.io/docs/image-resize-and-crop#focus---fo). + - [Object aware cropping](https://imagekit.io/docs/image-resize-and-crop#object-aware-cropping---fo-object-name) + """ + + format: Literal["auto", "webp", "jpg", "jpeg", "png", "gif", "svg", "mp4", "webm", "avif", "orig"] + """ + Specifies the output format for images or videos, e.g., `jpg`, `png`, `webp`, + `mp4`, or `auto`. You can also pass `orig` for images to return the original + format. ImageKit automatically delivers images and videos in the optimal format + based on device support unless overridden by the dashboard settings or the + format parameter. See + [Image format](https://imagekit.io/docs/image-optimization#format---f) and + [Video format](https://imagekit.io/docs/video-optimization#format---f). + """ + + gradient: Union[Literal[True], str] + """Creates a linear gradient with two colors. + + Pass `true` for a default gradient, or provide a string for a custom gradient. + See + [Gradient](https://imagekit.io/docs/effects-and-enhancements#gradient---e-gradient). + """ + + grayscale: Literal[True] + """Enables a grayscale effect for images. + + See + [Grayscale](https://imagekit.io/docs/effects-and-enhancements#grayscale---e-grayscale). + """ + + height: Union[float, str] + """Specifies the height of the output. + + If a value between 0 and 1 is provided, it is treated as a percentage (e.g., + `0.5` represents 50% of the original height). You can also supply arithmetic + expressions (e.g., `ih_mul_0.5`). Height transformation – + [Images](https://imagekit.io/docs/image-resize-and-crop#height---h) · + [Videos](https://imagekit.io/docs/video-resize-and-crop#height---h) + """ + + lossless: bool + """ + Specifies whether the output image (in JPEG or PNG) should be compressed + losslessly. See + [Lossless compression](https://imagekit.io/docs/image-optimization#lossless-webp-and-png---lo). + """ + + metadata: bool + """By default, ImageKit removes all metadata during automatic image compression. + + Set this to true to preserve metadata. See + [Image metadata](https://imagekit.io/docs/image-optimization#image-metadata---md). + """ + + named: str + """Named transformation reference. + + See + [Named transformations](https://imagekit.io/docs/transformations#named-transformations). + """ + + opacity: float + """Specifies the opacity level of the output image. + + See [Opacity](https://imagekit.io/docs/effects-and-enhancements#opacity---o). + """ + + original: bool + """ + If set to true, serves the original file without applying any transformations. + See + [Deliver original file as-is](https://imagekit.io/docs/core-delivery-features#deliver-original-file-as-is---orig-true). + """ + + overlay: "Overlay" + """Specifies an overlay to be applied on the parent image or video. + + ImageKit supports overlays including images, text, videos, subtitles, and solid + colors. See + [Overlay using layers](https://imagekit.io/docs/transformations#overlay-using-layers). + """ + + page: Union[float, str] + """ + Extracts a specific page or frame from multi-page or layered files (PDF, PSD, + AI). For example, specify by number (e.g., `2`), a range (e.g., `3-4` for the + 2nd and 3rd layers), or by name (e.g., `name-layer-4` for a PSD layer). See + [Thumbnail extraction](https://imagekit.io/docs/vector-and-animated-images#get-thumbnail-from-psd-pdf-ai-eps-and-animated-files). + """ + + progressive: bool + """Specifies whether the output JPEG image should be rendered progressively. + + Progressive loading begins with a low-quality, pixelated version of the full + image, which gradually improves to provide a faster perceived load time. See + [Progressive images](https://imagekit.io/docs/image-optimization#progressive-image---pr). + """ + + quality: float + """ + Specifies the quality of the output image for lossy formats such as JPEG, WebP, + and AVIF. A higher quality value results in a larger file size with better + quality, while a lower value produces a smaller file size with reduced quality. + See [Quality](https://imagekit.io/docs/image-optimization#quality---q). + """ + + radius: Union[float, Literal["max"]] + """ + Specifies the corner radius for rounded corners (e.g., 20) or `max` for circular + or oval shape. See + [Radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). + """ + + raw: str + """Pass any transformation not directly supported by the SDK. + + This transformation string is appended to the URL as provided. + """ + + rotation: Union[float, str] + """Specifies the rotation angle in degrees. + + Positive values rotate the image clockwise; you can also use, for example, `N40` + for counterclockwise rotation or `auto` to use the orientation specified in the + image's EXIF data. For videos, only the following values are supported: 0, 90, + 180, 270, or 360. See + [Rotate](https://imagekit.io/docs/effects-and-enhancements#rotate---rt). + """ + + shadow: Union[Literal[True], str] + """Adds a shadow beneath solid objects in an image with a transparent background. + + For AI-based drop shadows, refer to aiDropShadow. Pass `true` for a default + shadow, or provide a string for a custom shadow. See + [Shadow](https://imagekit.io/docs/effects-and-enhancements#shadow---e-shadow). + """ + + sharpen: Union[Literal[True], float] + """Sharpens the input image, highlighting edges and finer details. + + Pass `true` for default sharpening, or provide a numeric value for custom + sharpening. See + [Sharpen](https://imagekit.io/docs/effects-and-enhancements#sharpen---e-sharpen). + """ + + start_offset: Annotated[Union[float, str], PropertyInfo(alias="startOffset")] + """Specifies the start offset (in seconds) for trimming videos, e.g., `5` or + `10.5`. + + Arithmetic expressions are also supported. See + [Trim videos – Start offset](https://imagekit.io/docs/trim-videos#start-offset---so). + """ + + streaming_resolutions: Annotated[List[StreamingResolution], PropertyInfo(alias="streamingResolutions")] + """ + An array of resolutions for adaptive bitrate streaming, e.g., [`240`, `360`, + `480`, `720`, `1080`]. See + [Adaptive Bitrate Streaming](https://imagekit.io/docs/adaptive-bitrate-streaming). + """ + + trim: Union[Literal[True], float] + """Useful for images with a solid or nearly solid background and a central object. + + This parameter trims the background, leaving only the central object in the + output image. See + [Trim edges](https://imagekit.io/docs/effects-and-enhancements#trim-edges---t). + """ + + unsharp_mask: Annotated[Union[Literal[True], str], PropertyInfo(alias="unsharpMask")] + """Applies Unsharp Masking (USM), an image sharpening technique. + + Pass `true` for a default unsharp mask, or provide a string for a custom unsharp + mask. See + [Unsharp Mask](https://imagekit.io/docs/effects-and-enhancements#unsharp-mask---e-usm). + """ + + video_codec: Annotated[Literal["h264", "vp9", "av1", "none"], PropertyInfo(alias="videoCodec")] + """Specifies the video codec, e.g., `h264`, `vp9`, `av1`, or `none`. + + See [Video codec](https://imagekit.io/docs/video-optimization#video-codec---vc). + """ + + width: Union[float, str] + """Specifies the width of the output. + + If a value between 0 and 1 is provided, it is treated as a percentage (e.g., + `0.4` represents 40% of the original width). You can also supply arithmetic + expressions (e.g., `iw_div_2`). Width transformation – + [Images](https://imagekit.io/docs/image-resize-and-crop#width---w) · + [Videos](https://imagekit.io/docs/video-resize-and-crop#width---w) + """ + + x: Union[float, str] + """Focus using cropped image coordinates - X coordinate. + + See + [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + """ + + x_center: Annotated[Union[float, str], PropertyInfo(alias="xCenter")] + """Focus using cropped image coordinates - X center coordinate. + + See + [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + """ + + y: Union[float, str] + """Focus using cropped image coordinates - Y coordinate. + + See + [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + """ + + y_center: Annotated[Union[float, str], PropertyInfo(alias="yCenter")] + """Focus using cropped image coordinates - Y center coordinate. + + See + [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + """ + + zoom: float + """ + Accepts a numeric value that determines how much to zoom in or out of the + cropped area. It should be used in conjunction with fo-face or fo-. + See [Zoom](https://imagekit.io/docs/image-resize-and-crop#zoom---z). + """ + + +from .overlay import Overlay diff --git a/src/imagekitio/types/shared_params/transformation_position.py b/src/imagekitio/types/shared_params/transformation_position.py new file mode 100644 index 0000000..3959993 --- /dev/null +++ b/src/imagekitio/types/shared_params/transformation_position.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypeAlias + +__all__ = ["TransformationPosition"] + +TransformationPosition: TypeAlias = Literal["path", "query"] diff --git a/src/imagekitio/types/shared_params/video_overlay.py b/src/imagekitio/types/shared_params/video_overlay.py new file mode 100644 index 0000000..6c020fa --- /dev/null +++ b/src/imagekitio/types/shared_params/video_overlay.py @@ -0,0 +1,36 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required + +from .base_overlay import BaseOverlay + +__all__ = ["VideoOverlay"] + + +class VideoOverlay(BaseOverlay, total=False): + input: Required[str] + """Specifies the relative path to the video used as an overlay.""" + + type: Required[Literal["video"]] + + encoding: Literal["auto", "plain", "base64"] + """ + The input path can be included in the layer as either `i-{input}` or + `ie-{base64_encoded_input}`. By default, the SDK determines the appropriate + format automatically. To always use base64 encoding (`ie-{base64}`), set this + parameter to `base64`. To always use plain text (`i-{input}`), set it to + `plain`. + """ + + transformation: Iterable["Transformation"] + """Array of transformation to be applied to the overlay video. + + Except `streamingResolutions`, all other video transformations are supported. + See [Video transformations](https://imagekit.io/docs/video-transformation). + """ + + +from .transformation import Transformation diff --git a/tests/api_resources/test_dummy.py b/tests/api_resources/test_dummy.py new file mode 100644 index 0000000..bf19fc3 --- /dev/null +++ b/tests/api_resources/test_dummy.py @@ -0,0 +1,1444 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from imagekitio import ImageKit, AsyncImageKit + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestDummy: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create(self, client: ImageKit) -> None: + dummy = client.dummy.create() + assert dummy is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: ImageKit) -> None: + dummy = client.dummy.create( + base_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + }, + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + get_image_attributes_options={ + "src": "/my-image.jpg", + "url_endpoint": "https://ik.imagekit.io/demo", + "expires_in": 0, + "query_parameters": {"foo": "string"}, + "signed": True, + "transformation": [ + { + "ai_change_background": "aiChangeBackground", + "ai_drop_shadow": True, + "ai_edit": "aiEdit", + "ai_remove_background": True, + "ai_remove_background_external": True, + "ai_retouch": True, + "ai_upscale": True, + "ai_variation": True, + "aspect_ratio": "4:3", + "audio_codec": "aac", + "background": "red", + "blur": 10, + "border": "5_FF0000", + "color_profile": True, + "contrast_stretch": True, + "crop": "force", + "crop_mode": "pad_resize", + "default_image": "defaultImage", + "dpr": 2, + "duration": 0, + "end_offset": 0, + "flip": "h", + "focus": "center", + "format": "auto", + "gradient": True, + "grayscale": True, + "height": 200, + "lossless": True, + "metadata": True, + "named": "named", + "opacity": 0, + "original": True, + "overlay": { + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + "page": 0, + "progressive": True, + "quality": 80, + "radius": 20, + "raw": "raw", + "rotation": 90, + "shadow": True, + "sharpen": True, + "start_offset": 0, + "streaming_resolutions": ["240"], + "trim": True, + "unsharp_mask": True, + "video_codec": "h264", + "width": 300, + "x": 0, + "x_center": 0, + "y": 0, + "y_center": 0, + "zoom": 0, + } + ], + "transformation_position": "path", + "device_breakpoints": [640, 750, 828, 1080, 1200, 1920, 2048, 3840], + "image_breakpoints": [16, 32, 48, 64, 96, 128, 256, 384], + "sizes": "(min-width: 768px) 50vw, 100vw", + "width": 400, + }, + image_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "input": "input", + "type": "image", + "encoding": "auto", + "transformation": [ + { + "ai_change_background": "aiChangeBackground", + "ai_drop_shadow": True, + "ai_edit": "aiEdit", + "ai_remove_background": True, + "ai_remove_background_external": True, + "ai_retouch": True, + "ai_upscale": True, + "ai_variation": True, + "aspect_ratio": "4:3", + "audio_codec": "aac", + "background": "red", + "blur": 10, + "border": "5_FF0000", + "color_profile": True, + "contrast_stretch": True, + "crop": "force", + "crop_mode": "pad_resize", + "default_image": "defaultImage", + "dpr": 2, + "duration": 0, + "end_offset": 0, + "flip": "h", + "focus": "center", + "format": "auto", + "gradient": True, + "grayscale": True, + "height": 200, + "lossless": True, + "metadata": True, + "named": "named", + "opacity": 0, + "original": True, + "overlay": { + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + "page": 0, + "progressive": True, + "quality": 80, + "radius": 20, + "raw": "raw", + "rotation": 90, + "shadow": True, + "sharpen": True, + "start_offset": 0, + "streaming_resolutions": ["240"], + "trim": True, + "unsharp_mask": True, + "video_codec": "h264", + "width": 300, + "x": 0, + "x_center": 0, + "y": 0, + "y_center": 0, + "zoom": 0, + } + ], + }, + overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + overlay_position={ + "focus": "center", + "x": 0, + "y": 0, + }, + overlay_timing={ + "duration": 0, + "end": 0, + "start": 0, + }, + responsive_image_attributes={ + "src": "https://ik.imagekit.io/demo/image.jpg?tr=w-3840", + "sizes": "100vw", + "src_set": "https://ik.imagekit.io/demo/image.jpg?tr=w-640 640w, https://ik.imagekit.io/demo/image.jpg?tr=w-1080 1080w, https://ik.imagekit.io/demo/image.jpg?tr=w-1920 1920w", + "width": 400, + }, + solid_color_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "color": "color", + "type": "solidColor", + "transformation": [ + { + "alpha": 1, + "background": "background", + "gradient": True, + "height": 0, + "radius": 0, + "width": 0, + } + ], + }, + solid_color_overlay_transformation={ + "alpha": 1, + "background": "background", + "gradient": True, + "height": 0, + "radius": 0, + "width": 0, + }, + src_options={ + "src": "/my-image.jpg", + "url_endpoint": "https://ik.imagekit.io/demo", + "expires_in": 0, + "query_parameters": {"foo": "string"}, + "signed": True, + "transformation": [ + { + "ai_change_background": "aiChangeBackground", + "ai_drop_shadow": True, + "ai_edit": "aiEdit", + "ai_remove_background": True, + "ai_remove_background_external": True, + "ai_retouch": True, + "ai_upscale": True, + "ai_variation": True, + "aspect_ratio": "4:3", + "audio_codec": "aac", + "background": "red", + "blur": 10, + "border": "5_FF0000", + "color_profile": True, + "contrast_stretch": True, + "crop": "force", + "crop_mode": "pad_resize", + "default_image": "defaultImage", + "dpr": 2, + "duration": 0, + "end_offset": 0, + "flip": "h", + "focus": "center", + "format": "auto", + "gradient": True, + "grayscale": True, + "height": 200, + "lossless": True, + "metadata": True, + "named": "named", + "opacity": 0, + "original": True, + "overlay": { + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + "page": 0, + "progressive": True, + "quality": 80, + "radius": 20, + "raw": "raw", + "rotation": 90, + "shadow": True, + "sharpen": True, + "start_offset": 0, + "streaming_resolutions": ["240"], + "trim": True, + "unsharp_mask": True, + "video_codec": "h264", + "width": 300, + "x": 0, + "x_center": 0, + "y": 0, + "y_center": 0, + "zoom": 0, + } + ], + "transformation_position": "path", + }, + streaming_resolution="240", + subtitle_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "input": "input", + "type": "subtitle", + "encoding": "auto", + "transformation": [ + { + "background": "background", + "color": "color", + "font_family": "fontFamily", + "font_outline": "fontOutline", + "font_shadow": "fontShadow", + "font_size": 0, + "typography": "b", + } + ], + }, + subtitle_overlay_transformation={ + "background": "background", + "color": "color", + "font_family": "fontFamily", + "font_outline": "fontOutline", + "font_shadow": "fontShadow", + "font_size": 0, + "typography": "b", + }, + text_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + text_overlay_transformation={ + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + }, + transformation={ + "ai_change_background": "aiChangeBackground", + "ai_drop_shadow": True, + "ai_edit": "aiEdit", + "ai_remove_background": True, + "ai_remove_background_external": True, + "ai_retouch": True, + "ai_upscale": True, + "ai_variation": True, + "aspect_ratio": "4:3", + "audio_codec": "aac", + "background": "red", + "blur": 10, + "border": "5_FF0000", + "color_profile": True, + "contrast_stretch": True, + "crop": "force", + "crop_mode": "pad_resize", + "default_image": "defaultImage", + "dpr": 2, + "duration": 0, + "end_offset": 0, + "flip": "h", + "focus": "center", + "format": "auto", + "gradient": True, + "grayscale": True, + "height": 200, + "lossless": True, + "metadata": True, + "named": "named", + "opacity": 0, + "original": True, + "overlay": { + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + "page": 0, + "progressive": True, + "quality": 80, + "radius": 20, + "raw": "raw", + "rotation": 90, + "shadow": True, + "sharpen": True, + "start_offset": 0, + "streaming_resolutions": ["240"], + "trim": True, + "unsharp_mask": True, + "video_codec": "h264", + "width": 300, + "x": 0, + "x_center": 0, + "y": 0, + "y_center": 0, + "zoom": 0, + }, + transformation_position="path", + video_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "input": "input", + "type": "video", + "encoding": "auto", + "transformation": [ + { + "ai_change_background": "aiChangeBackground", + "ai_drop_shadow": True, + "ai_edit": "aiEdit", + "ai_remove_background": True, + "ai_remove_background_external": True, + "ai_retouch": True, + "ai_upscale": True, + "ai_variation": True, + "aspect_ratio": "4:3", + "audio_codec": "aac", + "background": "red", + "blur": 10, + "border": "5_FF0000", + "color_profile": True, + "contrast_stretch": True, + "crop": "force", + "crop_mode": "pad_resize", + "default_image": "defaultImage", + "dpr": 2, + "duration": 0, + "end_offset": 0, + "flip": "h", + "focus": "center", + "format": "auto", + "gradient": True, + "grayscale": True, + "height": 200, + "lossless": True, + "metadata": True, + "named": "named", + "opacity": 0, + "original": True, + "overlay": { + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + "page": 0, + "progressive": True, + "quality": 80, + "radius": 20, + "raw": "raw", + "rotation": 90, + "shadow": True, + "sharpen": True, + "start_offset": 0, + "streaming_resolutions": ["240"], + "trim": True, + "unsharp_mask": True, + "video_codec": "h264", + "width": 300, + "x": 0, + "x_center": 0, + "y": 0, + "y_center": 0, + "zoom": 0, + } + ], + }, + ) + assert dummy is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create(self, client: ImageKit) -> None: + response = client.dummy.with_raw_response.create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dummy = response.parse() + assert dummy is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create(self, client: ImageKit) -> None: + with client.dummy.with_streaming_response.create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dummy = response.parse() + assert dummy is None + + assert cast(Any, response.is_closed) is True + + +class TestAsyncDummy: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncImageKit) -> None: + dummy = await async_client.dummy.create() + assert dummy is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncImageKit) -> None: + dummy = await async_client.dummy.create( + base_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + }, + extensions=[ + { + "name": "remove-bg", + "options": { + "add_shadow": True, + "bg_color": "bg_color", + "bg_image_url": "bg_image_url", + "semitransparency": True, + }, + }, + { + "max_tags": 5, + "min_confidence": 95, + "name": "google-auto-tagging", + }, + {"name": "ai-auto-description"}, + ], + get_image_attributes_options={ + "src": "/my-image.jpg", + "url_endpoint": "https://ik.imagekit.io/demo", + "expires_in": 0, + "query_parameters": {"foo": "string"}, + "signed": True, + "transformation": [ + { + "ai_change_background": "aiChangeBackground", + "ai_drop_shadow": True, + "ai_edit": "aiEdit", + "ai_remove_background": True, + "ai_remove_background_external": True, + "ai_retouch": True, + "ai_upscale": True, + "ai_variation": True, + "aspect_ratio": "4:3", + "audio_codec": "aac", + "background": "red", + "blur": 10, + "border": "5_FF0000", + "color_profile": True, + "contrast_stretch": True, + "crop": "force", + "crop_mode": "pad_resize", + "default_image": "defaultImage", + "dpr": 2, + "duration": 0, + "end_offset": 0, + "flip": "h", + "focus": "center", + "format": "auto", + "gradient": True, + "grayscale": True, + "height": 200, + "lossless": True, + "metadata": True, + "named": "named", + "opacity": 0, + "original": True, + "overlay": { + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + "page": 0, + "progressive": True, + "quality": 80, + "radius": 20, + "raw": "raw", + "rotation": 90, + "shadow": True, + "sharpen": True, + "start_offset": 0, + "streaming_resolutions": ["240"], + "trim": True, + "unsharp_mask": True, + "video_codec": "h264", + "width": 300, + "x": 0, + "x_center": 0, + "y": 0, + "y_center": 0, + "zoom": 0, + } + ], + "transformation_position": "path", + "device_breakpoints": [640, 750, 828, 1080, 1200, 1920, 2048, 3840], + "image_breakpoints": [16, 32, 48, 64, 96, 128, 256, 384], + "sizes": "(min-width: 768px) 50vw, 100vw", + "width": 400, + }, + image_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "input": "input", + "type": "image", + "encoding": "auto", + "transformation": [ + { + "ai_change_background": "aiChangeBackground", + "ai_drop_shadow": True, + "ai_edit": "aiEdit", + "ai_remove_background": True, + "ai_remove_background_external": True, + "ai_retouch": True, + "ai_upscale": True, + "ai_variation": True, + "aspect_ratio": "4:3", + "audio_codec": "aac", + "background": "red", + "blur": 10, + "border": "5_FF0000", + "color_profile": True, + "contrast_stretch": True, + "crop": "force", + "crop_mode": "pad_resize", + "default_image": "defaultImage", + "dpr": 2, + "duration": 0, + "end_offset": 0, + "flip": "h", + "focus": "center", + "format": "auto", + "gradient": True, + "grayscale": True, + "height": 200, + "lossless": True, + "metadata": True, + "named": "named", + "opacity": 0, + "original": True, + "overlay": { + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + "page": 0, + "progressive": True, + "quality": 80, + "radius": 20, + "raw": "raw", + "rotation": 90, + "shadow": True, + "sharpen": True, + "start_offset": 0, + "streaming_resolutions": ["240"], + "trim": True, + "unsharp_mask": True, + "video_codec": "h264", + "width": 300, + "x": 0, + "x_center": 0, + "y": 0, + "y_center": 0, + "zoom": 0, + } + ], + }, + overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + overlay_position={ + "focus": "center", + "x": 0, + "y": 0, + }, + overlay_timing={ + "duration": 0, + "end": 0, + "start": 0, + }, + responsive_image_attributes={ + "src": "https://ik.imagekit.io/demo/image.jpg?tr=w-3840", + "sizes": "100vw", + "src_set": "https://ik.imagekit.io/demo/image.jpg?tr=w-640 640w, https://ik.imagekit.io/demo/image.jpg?tr=w-1080 1080w, https://ik.imagekit.io/demo/image.jpg?tr=w-1920 1920w", + "width": 400, + }, + solid_color_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "color": "color", + "type": "solidColor", + "transformation": [ + { + "alpha": 1, + "background": "background", + "gradient": True, + "height": 0, + "radius": 0, + "width": 0, + } + ], + }, + solid_color_overlay_transformation={ + "alpha": 1, + "background": "background", + "gradient": True, + "height": 0, + "radius": 0, + "width": 0, + }, + src_options={ + "src": "/my-image.jpg", + "url_endpoint": "https://ik.imagekit.io/demo", + "expires_in": 0, + "query_parameters": {"foo": "string"}, + "signed": True, + "transformation": [ + { + "ai_change_background": "aiChangeBackground", + "ai_drop_shadow": True, + "ai_edit": "aiEdit", + "ai_remove_background": True, + "ai_remove_background_external": True, + "ai_retouch": True, + "ai_upscale": True, + "ai_variation": True, + "aspect_ratio": "4:3", + "audio_codec": "aac", + "background": "red", + "blur": 10, + "border": "5_FF0000", + "color_profile": True, + "contrast_stretch": True, + "crop": "force", + "crop_mode": "pad_resize", + "default_image": "defaultImage", + "dpr": 2, + "duration": 0, + "end_offset": 0, + "flip": "h", + "focus": "center", + "format": "auto", + "gradient": True, + "grayscale": True, + "height": 200, + "lossless": True, + "metadata": True, + "named": "named", + "opacity": 0, + "original": True, + "overlay": { + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + "page": 0, + "progressive": True, + "quality": 80, + "radius": 20, + "raw": "raw", + "rotation": 90, + "shadow": True, + "sharpen": True, + "start_offset": 0, + "streaming_resolutions": ["240"], + "trim": True, + "unsharp_mask": True, + "video_codec": "h264", + "width": 300, + "x": 0, + "x_center": 0, + "y": 0, + "y_center": 0, + "zoom": 0, + } + ], + "transformation_position": "path", + }, + streaming_resolution="240", + subtitle_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "input": "input", + "type": "subtitle", + "encoding": "auto", + "transformation": [ + { + "background": "background", + "color": "color", + "font_family": "fontFamily", + "font_outline": "fontOutline", + "font_shadow": "fontShadow", + "font_size": 0, + "typography": "b", + } + ], + }, + subtitle_overlay_transformation={ + "background": "background", + "color": "color", + "font_family": "fontFamily", + "font_outline": "fontOutline", + "font_shadow": "fontShadow", + "font_size": 0, + "typography": "b", + }, + text_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + text_overlay_transformation={ + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + }, + transformation={ + "ai_change_background": "aiChangeBackground", + "ai_drop_shadow": True, + "ai_edit": "aiEdit", + "ai_remove_background": True, + "ai_remove_background_external": True, + "ai_retouch": True, + "ai_upscale": True, + "ai_variation": True, + "aspect_ratio": "4:3", + "audio_codec": "aac", + "background": "red", + "blur": 10, + "border": "5_FF0000", + "color_profile": True, + "contrast_stretch": True, + "crop": "force", + "crop_mode": "pad_resize", + "default_image": "defaultImage", + "dpr": 2, + "duration": 0, + "end_offset": 0, + "flip": "h", + "focus": "center", + "format": "auto", + "gradient": True, + "grayscale": True, + "height": 200, + "lossless": True, + "metadata": True, + "named": "named", + "opacity": 0, + "original": True, + "overlay": { + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + "page": 0, + "progressive": True, + "quality": 80, + "radius": 20, + "raw": "raw", + "rotation": 90, + "shadow": True, + "sharpen": True, + "start_offset": 0, + "streaming_resolutions": ["240"], + "trim": True, + "unsharp_mask": True, + "video_codec": "h264", + "width": 300, + "x": 0, + "x_center": 0, + "y": 0, + "y_center": 0, + "zoom": 0, + }, + transformation_position="path", + video_overlay={ + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "input": "input", + "type": "video", + "encoding": "auto", + "transformation": [ + { + "ai_change_background": "aiChangeBackground", + "ai_drop_shadow": True, + "ai_edit": "aiEdit", + "ai_remove_background": True, + "ai_remove_background_external": True, + "ai_retouch": True, + "ai_upscale": True, + "ai_variation": True, + "aspect_ratio": "4:3", + "audio_codec": "aac", + "background": "red", + "blur": 10, + "border": "5_FF0000", + "color_profile": True, + "contrast_stretch": True, + "crop": "force", + "crop_mode": "pad_resize", + "default_image": "defaultImage", + "dpr": 2, + "duration": 0, + "end_offset": 0, + "flip": "h", + "focus": "center", + "format": "auto", + "gradient": True, + "grayscale": True, + "height": 200, + "lossless": True, + "metadata": True, + "named": "named", + "opacity": 0, + "original": True, + "overlay": { + "position": { + "focus": "center", + "x": 0, + "y": 0, + }, + "timing": { + "duration": 0, + "end": 0, + "start": 0, + }, + "text": "text", + "type": "text", + "encoding": "auto", + "transformation": [ + { + "alpha": 1, + "background": "background", + "flip": "h", + "font_color": "fontColor", + "font_family": "fontFamily", + "font_size": 0, + "inner_alignment": "left", + "line_height": 0, + "padding": 0, + "radius": 0, + "rotation": 0, + "typography": "typography", + "width": 0, + } + ], + }, + "page": 0, + "progressive": True, + "quality": 80, + "radius": 20, + "raw": "raw", + "rotation": 90, + "shadow": True, + "sharpen": True, + "start_offset": 0, + "streaming_resolutions": ["240"], + "trim": True, + "unsharp_mask": True, + "video_codec": "h264", + "width": 300, + "x": 0, + "x_center": 0, + "y": 0, + "y_center": 0, + "zoom": 0, + } + ], + }, + ) + assert dummy is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncImageKit) -> None: + response = await async_client.dummy.with_raw_response.create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dummy = await response.parse() + assert dummy is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncImageKit) -> None: + async with async_client.dummy.with_streaming_response.create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dummy = await response.parse() + assert dummy is None + + assert cast(Any, response.is_closed) is True From a734cd01451ec1dd26381fa3d8d03bdbe734faf4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 18:40:36 +0000 Subject: [PATCH 168/177] fix(types): allow pyright to infer TypedDict types within SequenceNotStr --- src/imagekitio/_types.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/imagekitio/_types.py b/src/imagekitio/_types.py index 9abd394..714fee2 100644 --- a/src/imagekitio/_types.py +++ b/src/imagekitio/_types.py @@ -243,6 +243,9 @@ class HttpxSendArgs(TypedDict, total=False): if TYPE_CHECKING: # This works because str.__contains__ does not accept object (either in typeshed or at runtime) # https://github.com/hauntsaninja/useful_types/blob/5e9710f3875107d068e7679fd7fec9cfab0eff3b/useful_types/__init__.py#L285 + # + # Note: index() and count() methods are intentionally omitted to allow pyright to properly + # infer TypedDict types when dict literals are used in lists assigned to SequenceNotStr. class SequenceNotStr(Protocol[_T_co]): @overload def __getitem__(self, index: SupportsIndex, /) -> _T_co: ... @@ -251,8 +254,6 @@ def __getitem__(self, index: slice, /) -> Sequence[_T_co]: ... def __contains__(self, value: object, /) -> bool: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T_co]: ... - def index(self, value: Any, start: int = 0, stop: int = ..., /) -> int: ... - def count(self, value: Any, /) -> int: ... def __reversed__(self) -> Iterator[_T_co]: ... else: # just point this to a normal `Sequence` at runtime to avoid having to special case From 4ac5301f2d86be28f440f16ccbc701f10c841b80 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 19:28:36 +0000 Subject: [PATCH 169/177] chore: add missing docstrings --- .../types/accounts/url_endpoint_response.py | 2 ++ .../types/beta/v2/file_upload_params.py | 11 +++++++++++ .../types/beta/v2/file_upload_response.py | 14 ++++++++++++++ src/imagekitio/types/custom_metadata_field.py | 4 ++++ .../custom_metadata_field_update_params.py | 5 +++++ src/imagekitio/types/file.py | 4 ++++ src/imagekitio/types/file_update_params.py | 2 ++ src/imagekitio/types/file_update_response.py | 2 ++ src/imagekitio/types/file_upload_params.py | 11 +++++++++++ src/imagekitio/types/file_upload_response.py | 14 ++++++++++++++ src/imagekitio/types/folder_copy_response.py | 2 ++ src/imagekitio/types/folder_move_response.py | 2 ++ .../types/folder_rename_response.py | 2 ++ src/imagekitio/types/metadata.py | 12 ++++++++++++ .../shared/get_image_attributes_options.py | 5 +++++ .../shared/responsive_image_attributes.py | 5 +++++ src/imagekitio/types/shared/src_options.py | 5 +++++ .../shared/subtitle_overlay_transformation.py | 5 +++++ src/imagekitio/types/shared/transformation.py | 8 ++++++++ .../get_image_attributes_options.py | 5 +++++ .../responsive_image_attributes.py | 5 +++++ .../types/shared_params/src_options.py | 5 +++++ .../subtitle_overlay_transformation.py | 5 +++++ .../types/shared_params/transformation.py | 8 ++++++++ .../types/update_file_request_param.py | 2 ++ .../upload_post_transform_error_event.py | 5 +++++ .../upload_post_transform_success_event.py | 5 +++++ .../types/upload_pre_transform_error_event.py | 5 +++++ .../upload_pre_transform_success_event.py | 19 +++++++++++++++++++ .../video_transformation_accepted_event.py | 13 +++++++++++++ .../types/video_transformation_error_event.py | 13 +++++++++++++ .../types/video_transformation_ready_event.py | 16 ++++++++++++++++ 32 files changed, 221 insertions(+) diff --git a/src/imagekitio/types/accounts/url_endpoint_response.py b/src/imagekitio/types/accounts/url_endpoint_response.py index c868c7c..c2bcadc 100644 --- a/src/imagekitio/types/accounts/url_endpoint_response.py +++ b/src/imagekitio/types/accounts/url_endpoint_response.py @@ -32,6 +32,8 @@ class URLRewriterAkamai(BaseModel): class URLEndpointResponse(BaseModel): + """URL‑endpoint object as returned by the API.""" + id: str """Unique identifier for the URL-endpoint. diff --git a/src/imagekitio/types/beta/v2/file_upload_params.py b/src/imagekitio/types/beta/v2/file_upload_params.py index b4efce6..7f75be2 100644 --- a/src/imagekitio/types/beta/v2/file_upload_params.py +++ b/src/imagekitio/types/beta/v2/file_upload_params.py @@ -248,6 +248,17 @@ class TransformationPostAbs(TypedDict, total=False): class Transformation(TypedDict, total=False): + """Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + """ + post: Iterable[TransformationPost] """List of transformations to apply _after_ the file is uploaded. diff --git a/src/imagekitio/types/beta/v2/file_upload_response.py b/src/imagekitio/types/beta/v2/file_upload_response.py index 6e554cb..46cb755 100644 --- a/src/imagekitio/types/beta/v2/file_upload_response.py +++ b/src/imagekitio/types/beta/v2/file_upload_response.py @@ -27,6 +27,16 @@ class AITag(BaseModel): class ExtensionStatus(BaseModel): + """ + Extension names with their processing status at the time of completion of the request. It could have one of the following status values: + + `success`: The extension has been successfully applied. + `failed`: The extension has failed and will not be retried. + `pending`: The extension will finish processing in some time. On completion, the final status (success / failed) will be sent to the `webhookUrl` provided. + + If no extension was requested, then this parameter is not returned. + """ + ai_auto_description: Optional[Literal["success", "pending", "failed"]] = FieldInfo( alias="ai-auto-description", default=None ) @@ -97,6 +107,8 @@ class SelectedFieldsSchema(BaseModel): class VersionInfo(BaseModel): + """An object containing the file or file version's `id` (versionId) and `name`.""" + id: Optional[str] = None """Unique identifier of the file version.""" @@ -105,6 +117,8 @@ class VersionInfo(BaseModel): class FileUploadResponse(BaseModel): + """Object containing details of a successful upload.""" + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the uploaded file by auto tagging.""" diff --git a/src/imagekitio/types/custom_metadata_field.py b/src/imagekitio/types/custom_metadata_field.py index 1d8a866..1ebde72 100644 --- a/src/imagekitio/types/custom_metadata_field.py +++ b/src/imagekitio/types/custom_metadata_field.py @@ -11,6 +11,8 @@ class Schema(BaseModel): + """An object that describes the rules for the custom metadata field value.""" + type: Literal["Text", "Textarea", "Number", "Date", "Boolean", "SingleSelect", "MultiSelect"] """Type of the custom metadata field.""" @@ -52,6 +54,8 @@ class Schema(BaseModel): class CustomMetadataField(BaseModel): + """Object containing details of a custom metadata field.""" + id: str """Unique identifier for the custom metadata field. Use this to update the field.""" diff --git a/src/imagekitio/types/custom_metadata_field_update_params.py b/src/imagekitio/types/custom_metadata_field_update_params.py index 96792a7..fbb9eff 100644 --- a/src/imagekitio/types/custom_metadata_field_update_params.py +++ b/src/imagekitio/types/custom_metadata_field_update_params.py @@ -31,6 +31,11 @@ class CustomMetadataFieldUpdateParams(TypedDict, total=False): class Schema(TypedDict, total=False): + """An object that describes the rules for the custom metadata key. + + This parameter is required if `label` is not provided. Note: `type` cannot be updated and will be ignored if sent with the `schema`. The schema will be validated as per the existing `type`. + """ + default_value: Annotated[ Union[str, float, bool, SequenceNotStr[Union[str, float, bool]]], PropertyInfo(alias="defaultValue") ] diff --git a/src/imagekitio/types/file.py b/src/imagekitio/types/file.py index 1cb247a..d4a1573 100644 --- a/src/imagekitio/types/file.py +++ b/src/imagekitio/types/file.py @@ -80,6 +80,8 @@ class SelectedFieldsSchema(BaseModel): class VersionInfo(BaseModel): + """An object with details of the file version.""" + id: Optional[str] = None """Unique identifier of the file version.""" @@ -88,6 +90,8 @@ class VersionInfo(BaseModel): class File(BaseModel): + """Object containing details of a file or file version.""" + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the file by auto tagging.""" diff --git a/src/imagekitio/types/file_update_params.py b/src/imagekitio/types/file_update_params.py index 233492c..503bafe 100644 --- a/src/imagekitio/types/file_update_params.py +++ b/src/imagekitio/types/file_update_params.py @@ -70,6 +70,8 @@ class ChangePublicationStatus(TypedDict, total=False): class ChangePublicationStatusPublish(TypedDict, total=False): + """Configure the publication status of a file and its versions.""" + is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] """Set to `true` to publish the file. Set to `false` to unpublish the file.""" diff --git a/src/imagekitio/types/file_update_response.py b/src/imagekitio/types/file_update_response.py index 34b9731..936e336 100644 --- a/src/imagekitio/types/file_update_response.py +++ b/src/imagekitio/types/file_update_response.py @@ -28,4 +28,6 @@ class FileUpdateResponseExtensionStatus(BaseModel): class FileUpdateResponse(File): + """Object containing details of a file or file version.""" + extension_status: Optional[FileUpdateResponseExtensionStatus] = FieldInfo(alias="extensionStatus", default=None) diff --git a/src/imagekitio/types/file_upload_params.py b/src/imagekitio/types/file_upload_params.py index 1c14594..1dd9a23 100644 --- a/src/imagekitio/types/file_upload_params.py +++ b/src/imagekitio/types/file_upload_params.py @@ -280,6 +280,17 @@ class TransformationPostAbs(TypedDict, total=False): class Transformation(TypedDict, total=False): + """Configure pre-processing (`pre`) and post-processing (`post`) transformations. + + - `pre` — applied before the file is uploaded to the Media Library. + Useful for reducing file size or applying basic optimizations upfront (e.g., resize, compress). + + - `post` — applied immediately after upload. + Ideal for generating transformed versions (like video encodes or thumbnails) in advance, so they're ready for delivery without delay. + + You can mix and match any combination of post-processing types. + """ + post: Iterable[TransformationPost] """List of transformations to apply _after_ the file is uploaded. diff --git a/src/imagekitio/types/file_upload_response.py b/src/imagekitio/types/file_upload_response.py index f90c5e2..e99dc77 100644 --- a/src/imagekitio/types/file_upload_response.py +++ b/src/imagekitio/types/file_upload_response.py @@ -27,6 +27,16 @@ class AITag(BaseModel): class ExtensionStatus(BaseModel): + """ + Extension names with their processing status at the time of completion of the request. It could have one of the following status values: + + `success`: The extension has been successfully applied. + `failed`: The extension has failed and will not be retried. + `pending`: The extension will finish processing in some time. On completion, the final status (success / failed) will be sent to the `webhookUrl` provided. + + If no extension was requested, then this parameter is not returned. + """ + ai_auto_description: Optional[Literal["success", "pending", "failed"]] = FieldInfo( alias="ai-auto-description", default=None ) @@ -97,6 +107,8 @@ class SelectedFieldsSchema(BaseModel): class VersionInfo(BaseModel): + """An object containing the file or file version's `id` (versionId) and `name`.""" + id: Optional[str] = None """Unique identifier of the file version.""" @@ -105,6 +117,8 @@ class VersionInfo(BaseModel): class FileUploadResponse(BaseModel): + """Object containing details of a successful upload.""" + ai_tags: Optional[List[AITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the uploaded file by auto tagging.""" diff --git a/src/imagekitio/types/folder_copy_response.py b/src/imagekitio/types/folder_copy_response.py index 6ca3b1a..69c34c1 100644 --- a/src/imagekitio/types/folder_copy_response.py +++ b/src/imagekitio/types/folder_copy_response.py @@ -8,6 +8,8 @@ class FolderCopyResponse(BaseModel): + """Job submitted successfully. A `jobId` will be returned.""" + job_id: str = FieldInfo(alias="jobId") """Unique identifier of the bulk job. diff --git a/src/imagekitio/types/folder_move_response.py b/src/imagekitio/types/folder_move_response.py index a2ff321..d3fe1d8 100644 --- a/src/imagekitio/types/folder_move_response.py +++ b/src/imagekitio/types/folder_move_response.py @@ -8,6 +8,8 @@ class FolderMoveResponse(BaseModel): + """Job submitted successfully. A `jobId` will be returned.""" + job_id: str = FieldInfo(alias="jobId") """Unique identifier of the bulk job. diff --git a/src/imagekitio/types/folder_rename_response.py b/src/imagekitio/types/folder_rename_response.py index f6b4d37..d3319b7 100644 --- a/src/imagekitio/types/folder_rename_response.py +++ b/src/imagekitio/types/folder_rename_response.py @@ -8,6 +8,8 @@ class FolderRenameResponse(BaseModel): + """Job submitted successfully. A `jobId` will be returned.""" + job_id: str = FieldInfo(alias="jobId") """Unique identifier of the bulk job. diff --git a/src/imagekitio/types/metadata.py b/src/imagekitio/types/metadata.py index 85bb814..87ac334 100644 --- a/src/imagekitio/types/metadata.py +++ b/src/imagekitio/types/metadata.py @@ -10,6 +10,8 @@ class ExifExif(BaseModel): + """Object containing Exif details.""" + aperture_value: Optional[float] = FieldInfo(alias="ApertureValue", default=None) color_space: Optional[int] = FieldInfo(alias="ColorSpace", default=None) @@ -64,10 +66,14 @@ class ExifExif(BaseModel): class ExifGps(BaseModel): + """Object containing GPS information.""" + gps_version_id: Optional[List[int]] = FieldInfo(alias="GPSVersionID", default=None) class ExifImage(BaseModel): + """Object containing EXIF image information.""" + exif_offset: Optional[int] = FieldInfo(alias="ExifOffset", default=None) gps_info: Optional[int] = FieldInfo(alias="GPSInfo", default=None) @@ -92,12 +98,16 @@ class ExifImage(BaseModel): class ExifInteroperability(BaseModel): + """JSON object.""" + interop_index: Optional[str] = FieldInfo(alias="InteropIndex", default=None) interop_version: Optional[str] = FieldInfo(alias="InteropVersion", default=None) class ExifThumbnail(BaseModel): + """Object containing Thumbnail information.""" + compression: Optional[int] = FieldInfo(alias="Compression", default=None) resolution_unit: Optional[int] = FieldInfo(alias="ResolutionUnit", default=None) @@ -131,6 +141,8 @@ class Exif(BaseModel): class Metadata(BaseModel): + """JSON object containing metadata.""" + audio_codec: Optional[str] = FieldInfo(alias="audioCodec", default=None) """The audio codec used in the video (only for video).""" diff --git a/src/imagekitio/types/shared/get_image_attributes_options.py b/src/imagekitio/types/shared/get_image_attributes_options.py index 4fb27f5..2203f5f 100644 --- a/src/imagekitio/types/shared/get_image_attributes_options.py +++ b/src/imagekitio/types/shared/get_image_attributes_options.py @@ -12,6 +12,11 @@ class GetImageAttributesOptions(SrcOptions): + """ + Options for generating responsive image attributes including `src`, `srcSet`, and `sizes` for HTML `` elements. + This schema extends `SrcOptions` to add support for responsive image generation with breakpoints. + """ + device_breakpoints: Optional[List[float]] = FieldInfo(alias="deviceBreakpoints", default=None) """ Custom list of **device-width breakpoints** in pixels. These define common diff --git a/src/imagekitio/types/shared/responsive_image_attributes.py b/src/imagekitio/types/shared/responsive_image_attributes.py index 54aca7f..3e9c0ed 100644 --- a/src/imagekitio/types/shared/responsive_image_attributes.py +++ b/src/imagekitio/types/shared/responsive_image_attributes.py @@ -10,6 +10,11 @@ class ResponsiveImageAttributes(BaseModel): + """ + Resulting set of attributes suitable for an HTML `` element. + Useful for enabling responsive image loading with `srcSet` and `sizes`. + """ + src: str """URL for the _largest_ candidate (assigned to plain `src`).""" diff --git a/src/imagekitio/types/shared/src_options.py b/src/imagekitio/types/shared/src_options.py index 981860d..7f83328 100644 --- a/src/imagekitio/types/shared/src_options.py +++ b/src/imagekitio/types/shared/src_options.py @@ -13,6 +13,11 @@ class SrcOptions(BaseModel): + """Options for generating ImageKit URLs with transformations. + + See the [Transformations guide](https://imagekit.io/docs/transformations). + """ + src: str """Accepts a relative or absolute path of the resource. diff --git a/src/imagekitio/types/shared/subtitle_overlay_transformation.py b/src/imagekitio/types/shared/subtitle_overlay_transformation.py index fb692be..2f7c739 100644 --- a/src/imagekitio/types/shared/subtitle_overlay_transformation.py +++ b/src/imagekitio/types/shared/subtitle_overlay_transformation.py @@ -11,6 +11,11 @@ class SubtitleOverlayTransformation(BaseModel): + """Subtitle styling options. + + [Learn more](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) from the docs. + """ + background: Optional[str] = None """ Specifies the subtitle background color using a standard color name, an RGB diff --git a/src/imagekitio/types/shared/transformation.py b/src/imagekitio/types/shared/transformation.py index 970d9e9..c0f42d1 100644 --- a/src/imagekitio/types/shared/transformation.py +++ b/src/imagekitio/types/shared/transformation.py @@ -14,6 +14,14 @@ class Transformation(BaseModel): + """The SDK provides easy-to-use names for transformations. + + These names are converted to the corresponding transformation string before being added to the URL. + SDKs are updated regularly to support new transformations. If you want to use a transformation that is not supported by the SDK, + You can use the `raw` parameter to pass the transformation string directly. + See the [Transformations documentation](https://imagekit.io/docs/transformations). + """ + ai_change_background: Optional[str] = FieldInfo(alias="aiChangeBackground", default=None) """Uses AI to change the background. diff --git a/src/imagekitio/types/shared_params/get_image_attributes_options.py b/src/imagekitio/types/shared_params/get_image_attributes_options.py index 37c7c1e..e8bf8b6 100644 --- a/src/imagekitio/types/shared_params/get_image_attributes_options.py +++ b/src/imagekitio/types/shared_params/get_image_attributes_options.py @@ -12,6 +12,11 @@ class GetImageAttributesOptions(SrcOptions, total=False): + """ + Options for generating responsive image attributes including `src`, `srcSet`, and `sizes` for HTML `` elements. + This schema extends `SrcOptions` to add support for responsive image generation with breakpoints. + """ + device_breakpoints: Annotated[Iterable[float], PropertyInfo(alias="deviceBreakpoints")] """ Custom list of **device-width breakpoints** in pixels. These define common diff --git a/src/imagekitio/types/shared_params/responsive_image_attributes.py b/src/imagekitio/types/shared_params/responsive_image_attributes.py index b108252..fbf901c 100644 --- a/src/imagekitio/types/shared_params/responsive_image_attributes.py +++ b/src/imagekitio/types/shared_params/responsive_image_attributes.py @@ -10,6 +10,11 @@ class ResponsiveImageAttributes(TypedDict, total=False): + """ + Resulting set of attributes suitable for an HTML `` element. + Useful for enabling responsive image loading with `srcSet` and `sizes`. + """ + src: Required[str] """URL for the _largest_ candidate (assigned to plain `src`).""" diff --git a/src/imagekitio/types/shared_params/src_options.py b/src/imagekitio/types/shared_params/src_options.py index a10f3bb..cd262e5 100644 --- a/src/imagekitio/types/shared_params/src_options.py +++ b/src/imagekitio/types/shared_params/src_options.py @@ -12,6 +12,11 @@ class SrcOptions(TypedDict, total=False): + """Options for generating ImageKit URLs with transformations. + + See the [Transformations guide](https://imagekit.io/docs/transformations). + """ + src: Required[str] """Accepts a relative or absolute path of the resource. diff --git a/src/imagekitio/types/shared_params/subtitle_overlay_transformation.py b/src/imagekitio/types/shared_params/subtitle_overlay_transformation.py index ad74239..08b8de5 100644 --- a/src/imagekitio/types/shared_params/subtitle_overlay_transformation.py +++ b/src/imagekitio/types/shared_params/subtitle_overlay_transformation.py @@ -10,6 +10,11 @@ class SubtitleOverlayTransformation(TypedDict, total=False): + """Subtitle styling options. + + [Learn more](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) from the docs. + """ + background: str """ Specifies the subtitle background color using a standard color name, an RGB diff --git a/src/imagekitio/types/shared_params/transformation.py b/src/imagekitio/types/shared_params/transformation.py index 1f474a5..a48ddf8 100644 --- a/src/imagekitio/types/shared_params/transformation.py +++ b/src/imagekitio/types/shared_params/transformation.py @@ -12,6 +12,14 @@ class Transformation(TypedDict, total=False): + """The SDK provides easy-to-use names for transformations. + + These names are converted to the corresponding transformation string before being added to the URL. + SDKs are updated regularly to support new transformations. If you want to use a transformation that is not supported by the SDK, + You can use the `raw` parameter to pass the transformation string directly. + See the [Transformations documentation](https://imagekit.io/docs/transformations). + """ + ai_change_background: Annotated[str, PropertyInfo(alias="aiChangeBackground")] """Uses AI to change the background. diff --git a/src/imagekitio/types/update_file_request_param.py b/src/imagekitio/types/update_file_request_param.py index e72b585..8b90827 100644 --- a/src/imagekitio/types/update_file_request_param.py +++ b/src/imagekitio/types/update_file_request_param.py @@ -65,6 +65,8 @@ class UpdateFileDetails(TypedDict, total=False): class ChangePublicationStatusPublish(TypedDict, total=False): + """Configure the publication status of a file and its versions.""" + is_published: Required[Annotated[bool, PropertyInfo(alias="isPublished")]] """Set to `true` to publish the file. Set to `false` to unpublish the file.""" diff --git a/src/imagekitio/types/upload_post_transform_error_event.py b/src/imagekitio/types/upload_post_transform_error_event.py index 3b3c332..8f0a4ce 100644 --- a/src/imagekitio/types/upload_post_transform_error_event.py +++ b/src/imagekitio/types/upload_post_transform_error_event.py @@ -63,6 +63,11 @@ class UploadPostTransformErrorEventRequest(BaseModel): class UploadPostTransformErrorEvent(BaseWebhookEvent): + """Triggered when a post-transformation fails. + + The original file remains available, but the requested transformation could not be generated. + """ + created_at: datetime """Timestamp of when the event occurred in ISO8601 format.""" diff --git a/src/imagekitio/types/upload_post_transform_success_event.py b/src/imagekitio/types/upload_post_transform_success_event.py index 5026cfc..10e4ad7 100644 --- a/src/imagekitio/types/upload_post_transform_success_event.py +++ b/src/imagekitio/types/upload_post_transform_success_event.py @@ -47,6 +47,11 @@ class UploadPostTransformSuccessEventRequest(BaseModel): class UploadPostTransformSuccessEvent(BaseWebhookEvent): + """Triggered when a post-transformation completes successfully. + + The transformed version of the file is now ready and can be accessed via the provided URL. Note that each post-transformation generates a separate webhook event. + """ + created_at: datetime """Timestamp of when the event occurred in ISO8601 format.""" diff --git a/src/imagekitio/types/upload_pre_transform_error_event.py b/src/imagekitio/types/upload_pre_transform_error_event.py index 6140795..de90789 100644 --- a/src/imagekitio/types/upload_pre_transform_error_event.py +++ b/src/imagekitio/types/upload_pre_transform_error_event.py @@ -43,6 +43,11 @@ class UploadPreTransformErrorEventRequest(BaseModel): class UploadPreTransformErrorEvent(BaseWebhookEvent): + """Triggered when a pre-transformation fails. + + The file upload may have been accepted, but the requested transformation could not be applied. + """ + created_at: datetime """Timestamp of when the event occurred in ISO8601 format.""" diff --git a/src/imagekitio/types/upload_pre_transform_success_event.py b/src/imagekitio/types/upload_pre_transform_success_event.py index 41e443c..8584f86 100644 --- a/src/imagekitio/types/upload_pre_transform_success_event.py +++ b/src/imagekitio/types/upload_pre_transform_success_event.py @@ -37,6 +37,16 @@ class UploadPreTransformSuccessEventDataAITag(BaseModel): class UploadPreTransformSuccessEventDataExtensionStatus(BaseModel): + """ + Extension names with their processing status at the time of completion of the request. It could have one of the following status values: + + `success`: The extension has been successfully applied. + `failed`: The extension has failed and will not be retried. + `pending`: The extension will finish processing in some time. On completion, the final status (success / failed) will be sent to the `webhookUrl` provided. + + If no extension was requested, then this parameter is not returned. + """ + ai_auto_description: Optional[Literal["success", "pending", "failed"]] = FieldInfo( alias="ai-auto-description", default=None ) @@ -107,6 +117,8 @@ class UploadPreTransformSuccessEventDataSelectedFieldsSchema(BaseModel): class UploadPreTransformSuccessEventDataVersionInfo(BaseModel): + """An object containing the file or file version's `id` (versionId) and `name`.""" + id: Optional[str] = None """Unique identifier of the file version.""" @@ -115,6 +127,8 @@ class UploadPreTransformSuccessEventDataVersionInfo(BaseModel): class UploadPreTransformSuccessEventData(BaseModel): + """Object containing details of a successful upload.""" + ai_tags: Optional[List[UploadPreTransformSuccessEventDataAITag]] = FieldInfo(alias="AITags", default=None) """An array of tags assigned to the uploaded file by auto tagging.""" @@ -264,6 +278,11 @@ class UploadPreTransformSuccessEventRequest(BaseModel): class UploadPreTransformSuccessEvent(BaseWebhookEvent): + """Triggered when a pre-transformation completes successfully. + + The file has been processed with the requested transformation and is now available in the Media Library. + """ + created_at: datetime """Timestamp of when the event occurred in ISO8601 format.""" diff --git a/src/imagekitio/types/video_transformation_accepted_event.py b/src/imagekitio/types/video_transformation_accepted_event.py index 18ff4df..4ddb83c 100644 --- a/src/imagekitio/types/video_transformation_accepted_event.py +++ b/src/imagekitio/types/video_transformation_accepted_event.py @@ -18,11 +18,15 @@ class VideoTransformationAcceptedEventDataAsset(BaseModel): + """Information about the source video asset being transformed.""" + url: str """URL to download or access the source video file.""" class VideoTransformationAcceptedEventDataTransformationOptions(BaseModel): + """Configuration options for video transformations.""" + audio_codec: Optional[Literal["aac", "opus"]] = None """Audio codec used for encoding (aac or opus).""" @@ -46,6 +50,8 @@ class VideoTransformationAcceptedEventDataTransformationOptions(BaseModel): class VideoTransformationAcceptedEventDataTransformation(BaseModel): + """Base information about a video transformation request.""" + type: Literal["video-transformation", "gif-to-video", "video-thumbnail"] """Type of video transformation: @@ -68,6 +74,8 @@ class VideoTransformationAcceptedEventData(BaseModel): class VideoTransformationAcceptedEventRequest(BaseModel): + """Information about the original request that triggered the video transformation.""" + url: str """Full URL of the transformation request that was submitted.""" @@ -79,6 +87,11 @@ class VideoTransformationAcceptedEventRequest(BaseModel): class VideoTransformationAcceptedEvent(BaseWebhookEvent): + """Triggered when a new video transformation request is accepted for processing. + + This event confirms that ImageKit has received and queued your transformation request. Use this for debugging and tracking transformation lifecycle. + """ + created_at: datetime """Timestamp when the event was created in ISO8601 format.""" diff --git a/src/imagekitio/types/video_transformation_error_event.py b/src/imagekitio/types/video_transformation_error_event.py index 7e1970e..788142f 100644 --- a/src/imagekitio/types/video_transformation_error_event.py +++ b/src/imagekitio/types/video_transformation_error_event.py @@ -19,11 +19,15 @@ class VideoTransformationErrorEventDataAsset(BaseModel): + """Information about the source video asset being transformed.""" + url: str """URL to download or access the source video file.""" class VideoTransformationErrorEventDataTransformationError(BaseModel): + """Details about the transformation error.""" + reason: Literal["encoding_failed", "download_failed", "internal_server_error"] """Specific reason for the transformation failure: @@ -34,6 +38,8 @@ class VideoTransformationErrorEventDataTransformationError(BaseModel): class VideoTransformationErrorEventDataTransformationOptions(BaseModel): + """Configuration options for video transformations.""" + audio_codec: Optional[Literal["aac", "opus"]] = None """Audio codec used for encoding (aac or opus).""" @@ -81,6 +87,8 @@ class VideoTransformationErrorEventData(BaseModel): class VideoTransformationErrorEventRequest(BaseModel): + """Information about the original request that triggered the video transformation.""" + url: str """Full URL of the transformation request that was submitted.""" @@ -92,6 +100,11 @@ class VideoTransformationErrorEventRequest(BaseModel): class VideoTransformationErrorEvent(BaseWebhookEvent): + """Triggered when an error occurs during video encoding. + + Listen to this webhook to log error reasons and debug issues. Check your origin and URL endpoint settings if the reason is related to download failure. For other errors, contact ImageKit support. + """ + created_at: datetime """Timestamp when the event was created in ISO8601 format.""" diff --git a/src/imagekitio/types/video_transformation_ready_event.py b/src/imagekitio/types/video_transformation_ready_event.py index 1b52dcd..a711a9e 100644 --- a/src/imagekitio/types/video_transformation_ready_event.py +++ b/src/imagekitio/types/video_transformation_ready_event.py @@ -21,11 +21,15 @@ class VideoTransformationReadyEventDataAsset(BaseModel): + """Information about the source video asset being transformed.""" + url: str """URL to download or access the source video file.""" class VideoTransformationReadyEventDataTransformationOptions(BaseModel): + """Configuration options for video transformations.""" + audio_codec: Optional[Literal["aac", "opus"]] = None """Audio codec used for encoding (aac or opus).""" @@ -49,6 +53,8 @@ class VideoTransformationReadyEventDataTransformationOptions(BaseModel): class VideoTransformationReadyEventDataTransformationOutputVideoMetadata(BaseModel): + """Metadata of the output video file.""" + bitrate: int """Bitrate of the output video in bits per second.""" @@ -63,6 +69,8 @@ class VideoTransformationReadyEventDataTransformationOutputVideoMetadata(BaseMod class VideoTransformationReadyEventDataTransformationOutput(BaseModel): + """Information about the transformed output video.""" + url: str """URL to access the transformed video.""" @@ -95,6 +103,8 @@ class VideoTransformationReadyEventData(BaseModel): class VideoTransformationReadyEventRequest(BaseModel): + """Information about the original request that triggered the video transformation.""" + url: str """Full URL of the transformation request that was submitted.""" @@ -106,6 +116,8 @@ class VideoTransformationReadyEventRequest(BaseModel): class VideoTransformationReadyEventTimings(BaseModel): + """Performance metrics for the transformation process.""" + download_duration: Optional[int] = None """ Time spent downloading the source video from your origin or media library, in @@ -117,6 +129,10 @@ class VideoTransformationReadyEventTimings(BaseModel): class VideoTransformationReadyEvent(BaseWebhookEvent): + """ + Triggered when video encoding is finished and the transformed resource is ready to be served. This is the key event to listen for - update your database or CMS flags when you receive this so your application can start showing the transformed video to users. + """ + created_at: datetime """Timestamp when the event was created in ISO8601 format.""" From a150a6cb409776d0269fa0d104fd5d1f2bef3756 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 11:54:04 +0000 Subject: [PATCH 170/177] chore: update SDK settings --- .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 | 14 ++-- bin/check-release-environment | 21 ++++++ pyproject.toml | 6 +- release-please-config.json | 66 +++++++++++++++++++ src/imagekitio/_files.py | 2 +- src/imagekitio/_version.py | 2 +- src/imagekitio/resources/accounts/accounts.py | 8 +-- src/imagekitio/resources/accounts/origins.py | 8 +-- .../resources/accounts/url_endpoints.py | 8 +-- src/imagekitio/resources/accounts/usage.py | 8 +-- src/imagekitio/resources/assets.py | 8 +-- src/imagekitio/resources/beta/beta.py | 8 +-- src/imagekitio/resources/beta/v2/files.py | 8 +-- src/imagekitio/resources/beta/v2/v2.py | 8 +-- src/imagekitio/resources/cache/cache.py | 8 +-- .../resources/cache/invalidation.py | 8 +-- .../resources/custom_metadata_fields.py | 8 +-- src/imagekitio/resources/dummy.py | 8 +-- src/imagekitio/resources/files/bulk.py | 8 +-- src/imagekitio/resources/files/files.py | 8 +-- src/imagekitio/resources/files/metadata.py | 8 +-- src/imagekitio/resources/files/versions.py | 8 +-- src/imagekitio/resources/folders/folders.py | 8 +-- src/imagekitio/resources/folders/job.py | 8 +-- 29 files changed, 229 insertions(+), 87 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..08adafc --- /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/imagekit-developer/imagekit-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.44.0' + RYE_INSTALL_OPTION: '--yes' + + - name: Publish to PyPI + run: | + bash ./bin/publish-pypi + env: + PYPI_TOKEN: ${{ secrets.IMAGE_KIT_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..c36a89d --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,21 @@ +name: Release Doctor +on: + pull_request: + branches: + - master + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'imagekit-developer/imagekit-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.IMAGE_KIT_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..1332969 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1" +} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index a0c1a4e..26cba71 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 43 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml openapi_spec_hash: a9aa620376fce66532c84f9364209b0b -config_hash: fd112bd17c0c8e9f81a50d0e15ea70d6 +config_hash: 2a4d7992f6d3a0db0e9a430d513d94e6 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index edd1f2b..a6c5c7c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,7 +62,7 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git +$ pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git ``` Alternatively, you can build from source and install the wheel file: @@ -120,7 +120,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/imagekit-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/imagekit-developer/imagekit-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 71aab7e..43e871f 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ The REST API documentation can be found on [imagekit.io](https://imagekit.io/doc ## Installation ```sh -# install from this staging repo -pip install git+ssh://git@github.com/stainless-sdks/imagekit-python.git +# install from the production repo +pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git ``` > [!NOTE] @@ -85,8 +85,8 @@ By default, the async client uses `httpx` for HTTP requests. However, for improv You can enable this by installing `aiohttp`: ```sh -# install from this staging repo -pip install 'imagekitio[aiohttp] @ git+ssh://git@github.com/stainless-sdks/imagekit-python.git' +# install from the production repo +pip install 'imagekitio[aiohttp] @ git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git' ``` Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: @@ -316,9 +316,9 @@ file = response.parse() # get the object that `files.upload()` would have retur print(file.video_codec) ``` -These methods return an [`APIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekitio/_response.py) object. +These methods return an [`APIResponse`](https://github.com/imagekit-developer/imagekit-python/tree/master/src/imagekitio/_response.py) object. -The async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/imagekit-python/tree/main/src/imagekitio/_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/imagekit-developer/imagekit-python/tree/master/src/imagekitio/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. #### `.with_streaming_response` @@ -425,7 +425,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/imagekit-python/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/imagekit-developer/imagekit-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..b845b0f --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +errors=() + +if [ -z "${PYPI_TOKEN}" ]; then + errors+=("The 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 43ba273..48f905f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,8 +37,8 @@ classifiers = [ ] [project.urls] -Homepage = "https://github.com/stainless-sdks/imagekit-python" -Repository = "https://github.com/stainless-sdks/imagekit-python" +Homepage = "https://github.com/imagekit-developer/imagekit-python" +Repository = "https://github.com/imagekit-developer/imagekit-python" [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"] @@ -127,7 +127,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/imagekit-python/tree/main/\g<2>)' +replacement = '[\1](https://github.com/imagekit-developer/imagekit-python/tree/master/\g<2>)' [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..cd36a97 --- /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/imagekitio/_version.py" + ] +} \ No newline at end of file diff --git a/src/imagekitio/_files.py b/src/imagekitio/_files.py index 3cf7941..331bc44 100644 --- a/src/imagekitio/_files.py +++ b/src/imagekitio/_files.py @@ -34,7 +34,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None: if not is_file_content(obj): prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" raise RuntimeError( - f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/stainless-sdks/imagekit-python/tree/main#file-uploads" + f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/imagekit-developer/imagekit-python/tree/master#file-uploads" ) from None diff --git a/src/imagekitio/_version.py b/src/imagekitio/_version.py index e67f4eb..2df83f1 100644 --- a/src/imagekitio/_version.py +++ b/src/imagekitio/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "imagekitio" -__version__ = "0.0.1" +__version__ = "0.0.1" # x-release-please-version diff --git a/src/imagekitio/resources/accounts/accounts.py b/src/imagekitio/resources/accounts/accounts.py index dba376c..461e8cf 100644 --- a/src/imagekitio/resources/accounts/accounts.py +++ b/src/imagekitio/resources/accounts/accounts.py @@ -51,7 +51,7 @@ def with_raw_response(self) -> AccountsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AccountsResourceWithRawResponse(self) @@ -60,7 +60,7 @@ def with_streaming_response(self) -> AccountsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AccountsResourceWithStreamingResponse(self) @@ -84,7 +84,7 @@ def with_raw_response(self) -> AsyncAccountsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncAccountsResourceWithRawResponse(self) @@ -93,7 +93,7 @@ def with_streaming_response(self) -> AsyncAccountsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncAccountsResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/accounts/origins.py b/src/imagekitio/resources/accounts/origins.py index 15354aa..27dc7af 100644 --- a/src/imagekitio/resources/accounts/origins.py +++ b/src/imagekitio/resources/accounts/origins.py @@ -32,7 +32,7 @@ def with_raw_response(self) -> OriginsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return OriginsResourceWithRawResponse(self) @@ -41,7 +41,7 @@ def with_streaming_response(self) -> OriginsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return OriginsResourceWithStreamingResponse(self) @@ -1094,7 +1094,7 @@ def with_raw_response(self) -> AsyncOriginsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncOriginsResourceWithRawResponse(self) @@ -1103,7 +1103,7 @@ def with_streaming_response(self) -> AsyncOriginsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncOriginsResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/accounts/url_endpoints.py b/src/imagekitio/resources/accounts/url_endpoints.py index b5d9f36..ab8d422 100644 --- a/src/imagekitio/resources/accounts/url_endpoints.py +++ b/src/imagekitio/resources/accounts/url_endpoints.py @@ -29,7 +29,7 @@ def with_raw_response(self) -> URLEndpointsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return URLEndpointsResourceWithRawResponse(self) @@ -38,7 +38,7 @@ def with_streaming_response(self) -> URLEndpointsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return URLEndpointsResourceWithStreamingResponse(self) @@ -273,7 +273,7 @@ def with_raw_response(self) -> AsyncURLEndpointsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncURLEndpointsResourceWithRawResponse(self) @@ -282,7 +282,7 @@ def with_streaming_response(self) -> AsyncURLEndpointsResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncURLEndpointsResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/accounts/usage.py b/src/imagekitio/resources/accounts/usage.py index c044c9b..b35d3c9 100644 --- a/src/imagekitio/resources/accounts/usage.py +++ b/src/imagekitio/resources/accounts/usage.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> UsageResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return UsageResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> UsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return UsageResourceWithStreamingResponse(self) @@ -104,7 +104,7 @@ def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncUsageResourceWithRawResponse(self) @@ -113,7 +113,7 @@ def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncUsageResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/assets.py b/src/imagekitio/resources/assets.py index 18828fb..1d239da 100644 --- a/src/imagekitio/resources/assets.py +++ b/src/imagekitio/resources/assets.py @@ -30,7 +30,7 @@ def with_raw_response(self) -> AssetsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AssetsResourceWithRawResponse(self) @@ -39,7 +39,7 @@ def with_streaming_response(self) -> AssetsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AssetsResourceWithStreamingResponse(self) @@ -163,7 +163,7 @@ def with_raw_response(self) -> AsyncAssetsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncAssetsResourceWithRawResponse(self) @@ -172,7 +172,7 @@ def with_streaming_response(self) -> AsyncAssetsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncAssetsResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/beta/beta.py b/src/imagekitio/resources/beta/beta.py index e37c117..01e43aa 100644 --- a/src/imagekitio/resources/beta/beta.py +++ b/src/imagekitio/resources/beta/beta.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> BetaResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return BetaResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> BetaResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return BetaResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncBetaResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncBetaResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncBetaResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncBetaResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/beta/v2/files.py b/src/imagekitio/resources/beta/v2/files.py index 7ed6a96..eb9d3ed 100644 --- a/src/imagekitio/resources/beta/v2/files.py +++ b/src/imagekitio/resources/beta/v2/files.py @@ -42,7 +42,7 @@ def with_raw_response(self) -> FilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @@ -51,7 +51,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) @@ -295,7 +295,7 @@ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @@ -304,7 +304,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/beta/v2/v2.py b/src/imagekitio/resources/beta/v2/v2.py index f552e26..2fb9830 100644 --- a/src/imagekitio/resources/beta/v2/v2.py +++ b/src/imagekitio/resources/beta/v2/v2.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> V2ResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return V2ResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> V2ResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return V2ResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncV2ResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncV2ResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncV2ResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncV2ResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/cache/cache.py b/src/imagekitio/resources/cache/cache.py index 47016b0..936b39f 100644 --- a/src/imagekitio/resources/cache/cache.py +++ b/src/imagekitio/resources/cache/cache.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> CacheResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return CacheResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> CacheResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return CacheResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncCacheResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncCacheResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncCacheResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncCacheResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/cache/invalidation.py b/src/imagekitio/resources/cache/invalidation.py index f1f6c72..9c95dc8 100644 --- a/src/imagekitio/resources/cache/invalidation.py +++ b/src/imagekitio/resources/cache/invalidation.py @@ -29,7 +29,7 @@ def with_raw_response(self) -> InvalidationResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return InvalidationResourceWithRawResponse(self) @@ -38,7 +38,7 @@ def with_streaming_response(self) -> InvalidationResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return InvalidationResourceWithStreamingResponse(self) @@ -120,7 +120,7 @@ def with_raw_response(self) -> AsyncInvalidationResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncInvalidationResourceWithRawResponse(self) @@ -129,7 +129,7 @@ def with_streaming_response(self) -> AsyncInvalidationResourceWithStreamingRespo """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncInvalidationResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/custom_metadata_fields.py b/src/imagekitio/resources/custom_metadata_fields.py index 0c56e03..467e52a 100644 --- a/src/imagekitio/resources/custom_metadata_fields.py +++ b/src/imagekitio/resources/custom_metadata_fields.py @@ -34,7 +34,7 @@ def with_raw_response(self) -> CustomMetadataFieldsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return CustomMetadataFieldsResourceWithRawResponse(self) @@ -43,7 +43,7 @@ def with_streaming_response(self) -> CustomMetadataFieldsResourceWithStreamingRe """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return CustomMetadataFieldsResourceWithStreamingResponse(self) @@ -252,7 +252,7 @@ def with_raw_response(self) -> AsyncCustomMetadataFieldsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncCustomMetadataFieldsResourceWithRawResponse(self) @@ -261,7 +261,7 @@ def with_streaming_response(self) -> AsyncCustomMetadataFieldsResourceWithStream """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncCustomMetadataFieldsResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/dummy.py b/src/imagekitio/resources/dummy.py index aa44452..072340e 100644 --- a/src/imagekitio/resources/dummy.py +++ b/src/imagekitio/resources/dummy.py @@ -46,7 +46,7 @@ def with_raw_response(self) -> DummyResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return DummyResourceWithRawResponse(self) @@ -55,7 +55,7 @@ def with_streaming_response(self) -> DummyResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return DummyResourceWithStreamingResponse(self) @@ -181,7 +181,7 @@ def with_raw_response(self) -> AsyncDummyResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncDummyResourceWithRawResponse(self) @@ -190,7 +190,7 @@ def with_streaming_response(self) -> AsyncDummyResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncDummyResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/files/bulk.py b/src/imagekitio/resources/files/bulk.py index cd525b8..43c02cb 100644 --- a/src/imagekitio/resources/files/bulk.py +++ b/src/imagekitio/resources/files/bulk.py @@ -31,7 +31,7 @@ def with_raw_response(self) -> BulkResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return BulkResourceWithRawResponse(self) @@ -40,7 +40,7 @@ def with_streaming_response(self) -> BulkResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return BulkResourceWithStreamingResponse(self) @@ -227,7 +227,7 @@ def with_raw_response(self) -> AsyncBulkResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncBulkResourceWithRawResponse(self) @@ -236,7 +236,7 @@ def with_streaming_response(self) -> AsyncBulkResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncBulkResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/files/files.py b/src/imagekitio/resources/files/files.py index a7168fa..d99ba84 100644 --- a/src/imagekitio/resources/files/files.py +++ b/src/imagekitio/resources/files/files.py @@ -90,7 +90,7 @@ def with_raw_response(self) -> FilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @@ -99,7 +99,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) @@ -762,7 +762,7 @@ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @@ -771,7 +771,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/files/metadata.py b/src/imagekitio/resources/files/metadata.py index 1648e6e..d9e0541 100644 --- a/src/imagekitio/resources/files/metadata.py +++ b/src/imagekitio/resources/files/metadata.py @@ -28,7 +28,7 @@ def with_raw_response(self) -> MetadataResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return MetadataResourceWithRawResponse(self) @@ -37,7 +37,7 @@ def with_streaming_response(self) -> MetadataResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return MetadataResourceWithStreamingResponse(self) @@ -125,7 +125,7 @@ def with_raw_response(self) -> AsyncMetadataResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncMetadataResourceWithRawResponse(self) @@ -134,7 +134,7 @@ def with_streaming_response(self) -> AsyncMetadataResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncMetadataResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/files/versions.py b/src/imagekitio/resources/files/versions.py index b2df5cb..e6479e1 100644 --- a/src/imagekitio/resources/files/versions.py +++ b/src/imagekitio/resources/files/versions.py @@ -28,7 +28,7 @@ def with_raw_response(self) -> VersionsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return VersionsResourceWithRawResponse(self) @@ -37,7 +37,7 @@ def with_streaming_response(self) -> VersionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return VersionsResourceWithStreamingResponse(self) @@ -194,7 +194,7 @@ def with_raw_response(self) -> AsyncVersionsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncVersionsResourceWithRawResponse(self) @@ -203,7 +203,7 @@ def with_streaming_response(self) -> AsyncVersionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncVersionsResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/folders/folders.py b/src/imagekitio/resources/folders/folders.py index a5fdf81..d986fd7 100644 --- a/src/imagekitio/resources/folders/folders.py +++ b/src/imagekitio/resources/folders/folders.py @@ -50,7 +50,7 @@ def with_raw_response(self) -> FoldersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return FoldersResourceWithRawResponse(self) @@ -59,7 +59,7 @@ def with_streaming_response(self) -> FoldersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return FoldersResourceWithStreamingResponse(self) @@ -337,7 +337,7 @@ def with_raw_response(self) -> AsyncFoldersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncFoldersResourceWithRawResponse(self) @@ -346,7 +346,7 @@ def with_streaming_response(self) -> AsyncFoldersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncFoldersResourceWithStreamingResponse(self) diff --git a/src/imagekitio/resources/folders/job.py b/src/imagekitio/resources/folders/job.py index f731d08..5ccbd3b 100644 --- a/src/imagekitio/resources/folders/job.py +++ b/src/imagekitio/resources/folders/job.py @@ -26,7 +26,7 @@ def with_raw_response(self) -> JobResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return JobResourceWithRawResponse(self) @@ -35,7 +35,7 @@ def with_streaming_response(self) -> JobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return JobResourceWithStreamingResponse(self) @@ -80,7 +80,7 @@ def with_raw_response(self) -> AsyncJobResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/imagekit-developer/imagekit-python#accessing-raw-response-data-eg-headers """ return AsyncJobResourceWithRawResponse(self) @@ -89,7 +89,7 @@ def with_streaming_response(self) -> AsyncJobResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/imagekit-python#with_streaming_response + For more information, see https://www.github.com/imagekit-developer/imagekit-python#with_streaming_response """ return AsyncJobResourceWithStreamingResponse(self) From 26e68c9c7cb5481f65ca6e360f33684a2e046c26 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 11:55:24 +0000 Subject: [PATCH 171/177] feat(api): python publish true --- .stats.yml | 2 +- README.md | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 26cba71..f9a8004 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 43 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml openapi_spec_hash: a9aa620376fce66532c84f9364209b0b -config_hash: 2a4d7992f6d3a0db0e9a430d513d94e6 +config_hash: b4f610d4f53fe5bb17b35cf77a7521ea diff --git a/README.md b/README.md index 43e871f..29a8c93 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,10 @@ The REST API documentation can be found on [imagekit.io](https://imagekit.io/doc ## Installation ```sh -# install from the production repo -pip install git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git +# install from PyPI +pip install imagekitio ``` -> [!NOTE] -> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install imagekitio` - ## Usage The full API of this library can be found in [api.md](api.md). @@ -85,8 +82,8 @@ By default, the async client uses `httpx` for HTTP requests. However, for improv You can enable this by installing `aiohttp`: ```sh -# install from the production repo -pip install 'imagekitio[aiohttp] @ git+ssh://git@github.com/imagekit-developer/imagekit-python#master.git' +# install from PyPI +pip install imagekitio[aiohttp] ``` Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: From aec905866a8f0044fd17c0c4c6d7fcd31a20da8f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 12:00:52 +0000 Subject: [PATCH 172/177] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index f9a8004..333dfb4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 43 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml openapi_spec_hash: a9aa620376fce66532c84f9364209b0b -config_hash: b4f610d4f53fe5bb17b35cf77a7521ea +config_hash: 71cab8223bb5610c6c7ca6e9c4cc1f89 From 5572aa8aaffdde3f9c5225f5e18aed2f391b07d3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 13 Dec 2025 09:51:35 +0000 Subject: [PATCH 173/177] chore(internal): version bump --- .release-please-manifest.json | 2 +- pyproject.toml | 2 +- src/imagekitio/_version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1332969..8e76abb 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" + ".": "5.0.0" } \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 48f905f..9902514 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "imagekitio" -version = "0.0.1" +version = "5.0.0" description = "The official Python library for the ImageKit API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/imagekitio/_version.py b/src/imagekitio/_version.py index 2df83f1..32a263a 100644 --- a/src/imagekitio/_version.py +++ b/src/imagekitio/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "imagekitio" -__version__ = "0.0.1" # x-release-please-version +__version__ = "5.0.0" # x-release-please-version From 96e7431f80f170f37b6be169a3142ed9640baf59 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 19:18:43 +0000 Subject: [PATCH 174/177] chore(internal): add missing files argument to base client --- src/imagekitio/_base_client.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/imagekitio/_base_client.py b/src/imagekitio/_base_client.py index 384e7c0..542a71b 100644 --- a/src/imagekitio/_base_client.py +++ b/src/imagekitio/_base_client.py @@ -1247,9 +1247,12 @@ def patch( *, cast_to: Type[ResponseT], body: Body | None = None, + files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options) + opts = FinalRequestOptions.construct( + method="patch", url=path, json_data=body, files=to_httpx_files(files), **options + ) return self.request(cast_to, opts) def put( @@ -1767,9 +1770,12 @@ async def patch( *, cast_to: Type[ResponseT], body: Body | None = None, + files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options) + opts = FinalRequestOptions.construct( + method="patch", url=path, json_data=body, files=to_httpx_files(files), **options + ) return await self.request(cast_to, opts) async def put( From 8c34ecf6c85b330eab5fa5122b7a269df3805d63 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 17:21:13 +0000 Subject: [PATCH 175/177] chore: speedup initial import --- src/imagekitio/_client.py | 433 ++++++++++++++++++++++++++++++-------- 1 file changed, 340 insertions(+), 93 deletions(-) diff --git a/src/imagekitio/_client.py b/src/imagekitio/_client.py index 39a76e0..efcf3b5 100644 --- a/src/imagekitio/_client.py +++ b/src/imagekitio/_client.py @@ -4,7 +4,7 @@ import os import base64 -from typing import Any, Mapping +from typing import TYPE_CHECKING, Any, Mapping from typing_extensions import Self, override import httpx @@ -22,8 +22,8 @@ not_given, ) from ._utils import is_given, get_async_library +from ._compat import cached_property from ._version import __version__ -from .resources import dummy, assets, webhooks, custom_metadata_fields from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import ImageKitError, APIStatusError from ._base_client import ( @@ -31,11 +31,18 @@ SyncAPIClient, AsyncAPIClient, ) -from .resources.beta import beta -from .resources.cache import cache -from .resources.files import files -from .resources.folders import folders -from .resources.accounts import accounts + +if TYPE_CHECKING: + from .resources import beta, cache, dummy, files, assets, folders, accounts, custom_metadata_fields + from .resources.dummy import DummyResource, AsyncDummyResource + from .resources.assets import AssetsResource, AsyncAssetsResource + from .resources.webhooks import WebhooksResource, AsyncWebhooksResource + from .resources.beta.beta import BetaResource, AsyncBetaResource + from .resources.cache.cache import CacheResource, AsyncCacheResource + from .resources.files.files import FilesResource, AsyncFilesResource + from .resources.folders.folders import FoldersResource, AsyncFoldersResource + from .resources.accounts.accounts import AccountsResource, AsyncAccountsResource + from .resources.custom_metadata_fields import CustomMetadataFieldsResource, AsyncCustomMetadataFieldsResource __all__ = [ "Timeout", @@ -50,18 +57,6 @@ class ImageKit(SyncAPIClient): - dummy: dummy.DummyResource - custom_metadata_fields: custom_metadata_fields.CustomMetadataFieldsResource - files: files.FilesResource - assets: assets.AssetsResource - cache: cache.CacheResource - folders: folders.FoldersResource - accounts: accounts.AccountsResource - beta: beta.BetaResource - webhooks: webhooks.WebhooksResource - with_raw_response: ImageKitWithRawResponse - with_streaming_response: ImageKitWithStreamedResponse - # client options private_key: str password: str | None @@ -132,17 +127,67 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.dummy = dummy.DummyResource(self) - self.custom_metadata_fields = custom_metadata_fields.CustomMetadataFieldsResource(self) - self.files = files.FilesResource(self) - self.assets = assets.AssetsResource(self) - self.cache = cache.CacheResource(self) - self.folders = folders.FoldersResource(self) - self.accounts = accounts.AccountsResource(self) - self.beta = beta.BetaResource(self) - self.webhooks = webhooks.WebhooksResource(self) - self.with_raw_response = ImageKitWithRawResponse(self) - self.with_streaming_response = ImageKitWithStreamedResponse(self) + @cached_property + def dummy(self) -> DummyResource: + from .resources.dummy import DummyResource + + return DummyResource(self) + + @cached_property + def custom_metadata_fields(self) -> CustomMetadataFieldsResource: + from .resources.custom_metadata_fields import CustomMetadataFieldsResource + + return CustomMetadataFieldsResource(self) + + @cached_property + def files(self) -> FilesResource: + from .resources.files import FilesResource + + return FilesResource(self) + + @cached_property + def assets(self) -> AssetsResource: + from .resources.assets import AssetsResource + + return AssetsResource(self) + + @cached_property + def cache(self) -> CacheResource: + from .resources.cache import CacheResource + + return CacheResource(self) + + @cached_property + def folders(self) -> FoldersResource: + from .resources.folders import FoldersResource + + return FoldersResource(self) + + @cached_property + def accounts(self) -> AccountsResource: + from .resources.accounts import AccountsResource + + return AccountsResource(self) + + @cached_property + def beta(self) -> BetaResource: + from .resources.beta import BetaResource + + return BetaResource(self) + + @cached_property + def webhooks(self) -> WebhooksResource: + from .resources.webhooks import WebhooksResource + + return WebhooksResource(self) + + @cached_property + def with_raw_response(self) -> ImageKitWithRawResponse: + return ImageKitWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ImageKitWithStreamedResponse: + return ImageKitWithStreamedResponse(self) @property @override @@ -270,18 +315,6 @@ def _make_status_error( class AsyncImageKit(AsyncAPIClient): - dummy: dummy.AsyncDummyResource - custom_metadata_fields: custom_metadata_fields.AsyncCustomMetadataFieldsResource - files: files.AsyncFilesResource - assets: assets.AsyncAssetsResource - cache: cache.AsyncCacheResource - folders: folders.AsyncFoldersResource - accounts: accounts.AsyncAccountsResource - beta: beta.AsyncBetaResource - webhooks: webhooks.AsyncWebhooksResource - with_raw_response: AsyncImageKitWithRawResponse - with_streaming_response: AsyncImageKitWithStreamedResponse - # client options private_key: str password: str | None @@ -352,17 +385,67 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.dummy = dummy.AsyncDummyResource(self) - self.custom_metadata_fields = custom_metadata_fields.AsyncCustomMetadataFieldsResource(self) - self.files = files.AsyncFilesResource(self) - self.assets = assets.AsyncAssetsResource(self) - self.cache = cache.AsyncCacheResource(self) - self.folders = folders.AsyncFoldersResource(self) - self.accounts = accounts.AsyncAccountsResource(self) - self.beta = beta.AsyncBetaResource(self) - self.webhooks = webhooks.AsyncWebhooksResource(self) - self.with_raw_response = AsyncImageKitWithRawResponse(self) - self.with_streaming_response = AsyncImageKitWithStreamedResponse(self) + @cached_property + def dummy(self) -> AsyncDummyResource: + from .resources.dummy import AsyncDummyResource + + return AsyncDummyResource(self) + + @cached_property + def custom_metadata_fields(self) -> AsyncCustomMetadataFieldsResource: + from .resources.custom_metadata_fields import AsyncCustomMetadataFieldsResource + + return AsyncCustomMetadataFieldsResource(self) + + @cached_property + def files(self) -> AsyncFilesResource: + from .resources.files import AsyncFilesResource + + return AsyncFilesResource(self) + + @cached_property + def assets(self) -> AsyncAssetsResource: + from .resources.assets import AsyncAssetsResource + + return AsyncAssetsResource(self) + + @cached_property + def cache(self) -> AsyncCacheResource: + from .resources.cache import AsyncCacheResource + + return AsyncCacheResource(self) + + @cached_property + def folders(self) -> AsyncFoldersResource: + from .resources.folders import AsyncFoldersResource + + return AsyncFoldersResource(self) + + @cached_property + def accounts(self) -> AsyncAccountsResource: + from .resources.accounts import AsyncAccountsResource + + return AsyncAccountsResource(self) + + @cached_property + def beta(self) -> AsyncBetaResource: + from .resources.beta import AsyncBetaResource + + return AsyncBetaResource(self) + + @cached_property + def webhooks(self) -> AsyncWebhooksResource: + from .resources.webhooks import AsyncWebhooksResource + + return AsyncWebhooksResource(self) + + @cached_property + def with_raw_response(self) -> AsyncImageKitWithRawResponse: + return AsyncImageKitWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncImageKitWithStreamedResponse: + return AsyncImageKitWithStreamedResponse(self) @property @override @@ -490,59 +573,223 @@ def _make_status_error( class ImageKitWithRawResponse: + _client: ImageKit + def __init__(self, client: ImageKit) -> None: - self.dummy = dummy.DummyResourceWithRawResponse(client.dummy) - self.custom_metadata_fields = custom_metadata_fields.CustomMetadataFieldsResourceWithRawResponse( - client.custom_metadata_fields - ) - self.files = files.FilesResourceWithRawResponse(client.files) - self.assets = assets.AssetsResourceWithRawResponse(client.assets) - self.cache = cache.CacheResourceWithRawResponse(client.cache) - self.folders = folders.FoldersResourceWithRawResponse(client.folders) - self.accounts = accounts.AccountsResourceWithRawResponse(client.accounts) - self.beta = beta.BetaResourceWithRawResponse(client.beta) + self._client = client + + @cached_property + def dummy(self) -> dummy.DummyResourceWithRawResponse: + from .resources.dummy import DummyResourceWithRawResponse + + return DummyResourceWithRawResponse(self._client.dummy) + + @cached_property + def custom_metadata_fields(self) -> custom_metadata_fields.CustomMetadataFieldsResourceWithRawResponse: + from .resources.custom_metadata_fields import CustomMetadataFieldsResourceWithRawResponse + + return CustomMetadataFieldsResourceWithRawResponse(self._client.custom_metadata_fields) + + @cached_property + def files(self) -> files.FilesResourceWithRawResponse: + from .resources.files import FilesResourceWithRawResponse + + return FilesResourceWithRawResponse(self._client.files) + + @cached_property + def assets(self) -> assets.AssetsResourceWithRawResponse: + from .resources.assets import AssetsResourceWithRawResponse + + return AssetsResourceWithRawResponse(self._client.assets) + + @cached_property + def cache(self) -> cache.CacheResourceWithRawResponse: + from .resources.cache import CacheResourceWithRawResponse + + return CacheResourceWithRawResponse(self._client.cache) + + @cached_property + def folders(self) -> folders.FoldersResourceWithRawResponse: + from .resources.folders import FoldersResourceWithRawResponse + + return FoldersResourceWithRawResponse(self._client.folders) + + @cached_property + def accounts(self) -> accounts.AccountsResourceWithRawResponse: + from .resources.accounts import AccountsResourceWithRawResponse + + return AccountsResourceWithRawResponse(self._client.accounts) + + @cached_property + def beta(self) -> beta.BetaResourceWithRawResponse: + from .resources.beta import BetaResourceWithRawResponse + + return BetaResourceWithRawResponse(self._client.beta) class AsyncImageKitWithRawResponse: + _client: AsyncImageKit + def __init__(self, client: AsyncImageKit) -> None: - self.dummy = dummy.AsyncDummyResourceWithRawResponse(client.dummy) - self.custom_metadata_fields = custom_metadata_fields.AsyncCustomMetadataFieldsResourceWithRawResponse( - client.custom_metadata_fields - ) - self.files = files.AsyncFilesResourceWithRawResponse(client.files) - self.assets = assets.AsyncAssetsResourceWithRawResponse(client.assets) - self.cache = cache.AsyncCacheResourceWithRawResponse(client.cache) - self.folders = folders.AsyncFoldersResourceWithRawResponse(client.folders) - self.accounts = accounts.AsyncAccountsResourceWithRawResponse(client.accounts) - self.beta = beta.AsyncBetaResourceWithRawResponse(client.beta) + self._client = client + + @cached_property + def dummy(self) -> dummy.AsyncDummyResourceWithRawResponse: + from .resources.dummy import AsyncDummyResourceWithRawResponse + + return AsyncDummyResourceWithRawResponse(self._client.dummy) + + @cached_property + def custom_metadata_fields(self) -> custom_metadata_fields.AsyncCustomMetadataFieldsResourceWithRawResponse: + from .resources.custom_metadata_fields import AsyncCustomMetadataFieldsResourceWithRawResponse + + return AsyncCustomMetadataFieldsResourceWithRawResponse(self._client.custom_metadata_fields) + + @cached_property + def files(self) -> files.AsyncFilesResourceWithRawResponse: + from .resources.files import AsyncFilesResourceWithRawResponse + + return AsyncFilesResourceWithRawResponse(self._client.files) + + @cached_property + def assets(self) -> assets.AsyncAssetsResourceWithRawResponse: + from .resources.assets import AsyncAssetsResourceWithRawResponse + + return AsyncAssetsResourceWithRawResponse(self._client.assets) + + @cached_property + def cache(self) -> cache.AsyncCacheResourceWithRawResponse: + from .resources.cache import AsyncCacheResourceWithRawResponse + + return AsyncCacheResourceWithRawResponse(self._client.cache) + + @cached_property + def folders(self) -> folders.AsyncFoldersResourceWithRawResponse: + from .resources.folders import AsyncFoldersResourceWithRawResponse + + return AsyncFoldersResourceWithRawResponse(self._client.folders) + + @cached_property + def accounts(self) -> accounts.AsyncAccountsResourceWithRawResponse: + from .resources.accounts import AsyncAccountsResourceWithRawResponse + + return AsyncAccountsResourceWithRawResponse(self._client.accounts) + + @cached_property + def beta(self) -> beta.AsyncBetaResourceWithRawResponse: + from .resources.beta import AsyncBetaResourceWithRawResponse + + return AsyncBetaResourceWithRawResponse(self._client.beta) class ImageKitWithStreamedResponse: + _client: ImageKit + def __init__(self, client: ImageKit) -> None: - self.dummy = dummy.DummyResourceWithStreamingResponse(client.dummy) - self.custom_metadata_fields = custom_metadata_fields.CustomMetadataFieldsResourceWithStreamingResponse( - client.custom_metadata_fields - ) - self.files = files.FilesResourceWithStreamingResponse(client.files) - self.assets = assets.AssetsResourceWithStreamingResponse(client.assets) - self.cache = cache.CacheResourceWithStreamingResponse(client.cache) - self.folders = folders.FoldersResourceWithStreamingResponse(client.folders) - self.accounts = accounts.AccountsResourceWithStreamingResponse(client.accounts) - self.beta = beta.BetaResourceWithStreamingResponse(client.beta) + self._client = client + + @cached_property + def dummy(self) -> dummy.DummyResourceWithStreamingResponse: + from .resources.dummy import DummyResourceWithStreamingResponse + + return DummyResourceWithStreamingResponse(self._client.dummy) + + @cached_property + def custom_metadata_fields(self) -> custom_metadata_fields.CustomMetadataFieldsResourceWithStreamingResponse: + from .resources.custom_metadata_fields import CustomMetadataFieldsResourceWithStreamingResponse + + return CustomMetadataFieldsResourceWithStreamingResponse(self._client.custom_metadata_fields) + + @cached_property + def files(self) -> files.FilesResourceWithStreamingResponse: + from .resources.files import FilesResourceWithStreamingResponse + + return FilesResourceWithStreamingResponse(self._client.files) + + @cached_property + def assets(self) -> assets.AssetsResourceWithStreamingResponse: + from .resources.assets import AssetsResourceWithStreamingResponse + + return AssetsResourceWithStreamingResponse(self._client.assets) + + @cached_property + def cache(self) -> cache.CacheResourceWithStreamingResponse: + from .resources.cache import CacheResourceWithStreamingResponse + + return CacheResourceWithStreamingResponse(self._client.cache) + + @cached_property + def folders(self) -> folders.FoldersResourceWithStreamingResponse: + from .resources.folders import FoldersResourceWithStreamingResponse + + return FoldersResourceWithStreamingResponse(self._client.folders) + + @cached_property + def accounts(self) -> accounts.AccountsResourceWithStreamingResponse: + from .resources.accounts import AccountsResourceWithStreamingResponse + + return AccountsResourceWithStreamingResponse(self._client.accounts) + + @cached_property + def beta(self) -> beta.BetaResourceWithStreamingResponse: + from .resources.beta import BetaResourceWithStreamingResponse + + return BetaResourceWithStreamingResponse(self._client.beta) class AsyncImageKitWithStreamedResponse: + _client: AsyncImageKit + def __init__(self, client: AsyncImageKit) -> None: - self.dummy = dummy.AsyncDummyResourceWithStreamingResponse(client.dummy) - self.custom_metadata_fields = custom_metadata_fields.AsyncCustomMetadataFieldsResourceWithStreamingResponse( - client.custom_metadata_fields - ) - self.files = files.AsyncFilesResourceWithStreamingResponse(client.files) - self.assets = assets.AsyncAssetsResourceWithStreamingResponse(client.assets) - self.cache = cache.AsyncCacheResourceWithStreamingResponse(client.cache) - self.folders = folders.AsyncFoldersResourceWithStreamingResponse(client.folders) - self.accounts = accounts.AsyncAccountsResourceWithStreamingResponse(client.accounts) - self.beta = beta.AsyncBetaResourceWithStreamingResponse(client.beta) + self._client = client + + @cached_property + def dummy(self) -> dummy.AsyncDummyResourceWithStreamingResponse: + from .resources.dummy import AsyncDummyResourceWithStreamingResponse + + return AsyncDummyResourceWithStreamingResponse(self._client.dummy) + + @cached_property + def custom_metadata_fields(self) -> custom_metadata_fields.AsyncCustomMetadataFieldsResourceWithStreamingResponse: + from .resources.custom_metadata_fields import AsyncCustomMetadataFieldsResourceWithStreamingResponse + + return AsyncCustomMetadataFieldsResourceWithStreamingResponse(self._client.custom_metadata_fields) + + @cached_property + def files(self) -> files.AsyncFilesResourceWithStreamingResponse: + from .resources.files import AsyncFilesResourceWithStreamingResponse + + return AsyncFilesResourceWithStreamingResponse(self._client.files) + + @cached_property + def assets(self) -> assets.AsyncAssetsResourceWithStreamingResponse: + from .resources.assets import AsyncAssetsResourceWithStreamingResponse + + return AsyncAssetsResourceWithStreamingResponse(self._client.assets) + + @cached_property + def cache(self) -> cache.AsyncCacheResourceWithStreamingResponse: + from .resources.cache import AsyncCacheResourceWithStreamingResponse + + return AsyncCacheResourceWithStreamingResponse(self._client.cache) + + @cached_property + def folders(self) -> folders.AsyncFoldersResourceWithStreamingResponse: + from .resources.folders import AsyncFoldersResourceWithStreamingResponse + + return AsyncFoldersResourceWithStreamingResponse(self._client.folders) + + @cached_property + def accounts(self) -> accounts.AsyncAccountsResourceWithStreamingResponse: + from .resources.accounts import AsyncAccountsResourceWithStreamingResponse + + return AsyncAccountsResourceWithStreamingResponse(self._client.accounts) + + @cached_property + def beta(self) -> beta.AsyncBetaResourceWithStreamingResponse: + from .resources.beta import AsyncBetaResourceWithStreamingResponse + + return AsyncBetaResourceWithStreamingResponse(self._client.beta) Client = ImageKit From 40ff7b13aa81919d062b88426a155cc8fd614134 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 15:47:31 +0000 Subject: [PATCH 176/177] fix: use async_to_httpx_files in patch method --- src/imagekitio/_base_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imagekitio/_base_client.py b/src/imagekitio/_base_client.py index 542a71b..f8b7757 100644 --- a/src/imagekitio/_base_client.py +++ b/src/imagekitio/_base_client.py @@ -1774,7 +1774,7 @@ async def patch( options: RequestOptions = {}, ) -> ResponseT: opts = FinalRequestOptions.construct( - method="patch", url=path, json_data=body, files=to_httpx_files(files), **options + method="patch", url=path, json_data=body, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts) From e668379ead9002732fd2fb91621791a13d3df56d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 21:53:36 +0000 Subject: [PATCH 177/177] chore(internal): add `--fix` argument to lint script --- scripts/lint | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/lint b/scripts/lint index eb9a4dd..d4778c6 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,8 +4,13 @@ set -e cd "$(dirname "$0")/.." -echo "==> Running lints" -rye run lint +if [ "$1" = "--fix" ]; then + echo "==> Running lints with --fix" + rye run fix:ruff +else + echo "==> Running lints" + rye run lint +fi echo "==> Making sure it imports" rye run python -c 'import imagekitio'