cloudinary 1.45.0__tar.gz → 1.46.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudinary-1.46.1/LICENSE +21 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/MANIFEST.in +2 -0
- cloudinary-1.46.1/PKG-INFO +221 -0
- cloudinary-1.46.1/README.md +150 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/__init__.py +1 -1
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/api.py +184 -1
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/api_client/call_account_api.py +8 -2
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/api_client/call_api.py +35 -8
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/api_client/execute_request.py +6 -3
- cloudinary-1.46.1/cloudinary/docs/README.md +63 -0
- cloudinary-1.46.1/cloudinary/docs/configure-cloudinary.md +86 -0
- cloudinary-1.46.1/cloudinary/docs/get-credentials.md +149 -0
- cloudinary-1.46.1/cloudinary/docs/import-and-call.md +29 -0
- cloudinary-1.46.1/cloudinary/docs/moderate-upload.md +156 -0
- cloudinary-1.46.1/cloudinary/docs/platform-capabilities.md +130 -0
- cloudinary-1.46.1/cloudinary/docs/search-and-manage-assets.md +189 -0
- cloudinary-1.46.1/cloudinary/docs/sign-browser-upload.md +136 -0
- cloudinary-1.46.1/cloudinary/docs/transform-and-deliver-image.md +148 -0
- cloudinary-1.46.1/cloudinary/docs/transform-and-deliver-video.md +128 -0
- cloudinary-1.46.1/cloudinary/docs/troubleshoot-errors.md +175 -0
- cloudinary-1.46.1/cloudinary/docs/upload-image.md +127 -0
- cloudinary-1.46.1/cloudinary/docs/upload-large-video.md +112 -0
- cloudinary-1.46.1/cloudinary/docs/use-structured-metadata.md +144 -0
- cloudinary-1.46.1/cloudinary/docs/use-with-django.md +178 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/provisioning/__init__.py +1 -1
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/provisioning/account.py +62 -6
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/uploader.py +17 -3
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/utils.py +57 -2
- cloudinary-1.46.1/cloudinary.egg-info/PKG-INFO +221 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary.egg-info/SOURCES.txt +19 -1
- {cloudinary-1.45.0 → cloudinary-1.46.1}/pyproject.toml +7 -4
- {cloudinary-1.45.0 → cloudinary-1.46.1}/setup.py +1 -1
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_api.py +5 -2
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_archive.py +3 -0
- cloudinary-1.46.1/test/test_notifications.py +321 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_provisioning_api.py +191 -15
- cloudinary-1.46.1/test/test_request_id.py +98 -0
- cloudinary-1.46.1/test/test_triggers.py +162 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_uploader.py +24 -1
- cloudinary-1.45.0/LICENSE.txt +0 -5
- cloudinary-1.45.0/PKG-INFO +0 -174
- cloudinary-1.45.0/README.md +0 -119
- cloudinary-1.45.0/cloudinary.egg-info/PKG-INFO +0 -174
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/api_client/__init__.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/api_client/tcp_keep_alive_manager.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/auth_token.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/cache/__init__.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/cache/adapter/__init__.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/cache/adapter/cache_adapter.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/cache/adapter/key_value_cache_adapter.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/cache/responsive_breakpoints_cache.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/cache/storage/__init__.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/cache/storage/file_system_key_value_storage.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/cache/storage/key_value_storage.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/compat.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/exceptions.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/forms.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/http_client.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/models.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/poster/__init__.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/poster/encode.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/poster/streaminghttp.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/provisioning/account_config.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/search.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/search_folders.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/static/cloudinary/html/cloudinary_cors.html +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/static/cloudinary/js/canvas-to-blob.min.js +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/static/cloudinary/js/jquery.cloudinary.js +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/static/cloudinary/js/jquery.fileupload-image.js +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/static/cloudinary/js/jquery.fileupload-process.js +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/static/cloudinary/js/jquery.fileupload-validate.js +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/static/cloudinary/js/jquery.fileupload.js +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/static/cloudinary/js/jquery.iframe-transport.js +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/static/cloudinary/js/jquery.ui.widget.js +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/static/cloudinary/js/load-image.all.min.js +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/templates/cloudinary_direct_upload.html +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/templates/cloudinary_includes.html +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/templates/cloudinary_js_config.html +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/templatetags/__init__.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary/templatetags/cloudinary.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary.egg-info/dependency_links.txt +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary.egg-info/not-zip-safe +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary.egg-info/requires.txt +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/cloudinary.egg-info/top_level.txt +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/setup.cfg +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_api_authorization.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_auth_token.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_cloudinary_resource.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_config.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_expression_normalization.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_http_client.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_image.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_metadata.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_metadata_rules.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_search.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_streaming_profiles.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_utils.py +0 -0
- {cloudinary-1.45.0 → cloudinary-1.46.1}/test/test_video.py +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Cloudinary Ltd.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cloudinary
|
|
3
|
+
Version: 1.46.1
|
|
4
|
+
Summary: Upload, transform, optimize, and manage images and videos with Cloudinary from Python or Django.
|
|
5
|
+
Author-email: Cloudinary <info@cloudinary.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) Cloudinary Ltd.
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://cloudinary.com
|
|
29
|
+
Project-URL: Source, https://github.com/cloudinary/pycloudinary
|
|
30
|
+
Project-URL: Changelog, https://raw.githubusercontent.com/cloudinary/pycloudinary/master/CHANGELOG.md
|
|
31
|
+
Keywords: cloudinary,image,video,upload,crop,resize,filter,transformation,manipulation,cdn
|
|
32
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
33
|
+
Classifier: Environment :: Web Environment
|
|
34
|
+
Classifier: Framework :: Django
|
|
35
|
+
Classifier: Framework :: Django :: 1.11
|
|
36
|
+
Classifier: Framework :: Django :: 2.2
|
|
37
|
+
Classifier: Framework :: Django :: 4.2
|
|
38
|
+
Classifier: Framework :: Django :: 5.0
|
|
39
|
+
Classifier: Framework :: Django :: 5.1
|
|
40
|
+
Classifier: Framework :: Django :: 5.2
|
|
41
|
+
Classifier: Framework :: Django :: 6.0
|
|
42
|
+
Classifier: Intended Audience :: Developers
|
|
43
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
44
|
+
Classifier: Programming Language :: Python
|
|
45
|
+
Classifier: Programming Language :: Python :: 2
|
|
46
|
+
Classifier: Programming Language :: Python :: 2.7
|
|
47
|
+
Classifier: Programming Language :: Python :: 3
|
|
48
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
49
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
50
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
51
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
52
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
53
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
54
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
55
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
56
|
+
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
|
|
57
|
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
58
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Conversion
|
|
59
|
+
Classifier: Topic :: Multimedia :: Video
|
|
60
|
+
Classifier: Topic :: Multimedia :: Video :: Conversion
|
|
61
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
62
|
+
Description-Content-Type: text/markdown
|
|
63
|
+
License-File: LICENSE
|
|
64
|
+
Requires-Dist: six
|
|
65
|
+
Requires-Dist: urllib3>=1.26.5
|
|
66
|
+
Requires-Dist: certifi
|
|
67
|
+
Provides-Extra: dev
|
|
68
|
+
Requires-Dist: tox; extra == "dev"
|
|
69
|
+
Requires-Dist: pytest==4.6; python_version < "3.7" and extra == "dev"
|
|
70
|
+
Requires-Dist: pytest; python_version >= "3.7" and extra == "dev"
|
|
71
|
+
|
|
72
|
+
# Cloudinary Python SDK
|
|
73
|
+
|
|
74
|
+
Upload, transform, optimize, and manage images and videos with Cloudinary from Python or Django — the `cloudinary` package on PyPI.
|
|
75
|
+
|
|
76
|
+
[](https://github.com/cloudinary/pycloudinary/actions/workflows/test.yml)
|
|
77
|
+
[](https://pypi.org/project/cloudinary/)
|
|
78
|
+
[](https://pypi.org/project/cloudinary/)
|
|
79
|
+
[](LICENSE)
|
|
80
|
+
|
|
81
|
+
## Install
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install cloudinary
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Quick start
|
|
88
|
+
|
|
89
|
+
Set your API environment variable (Console > Settings > API Keys):
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
export CLOUDINARY_URL=cloudinary://<api_key>:<api_secret>@<cloud_name>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Upload an image and get an optimized delivery URL:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
import cloudinary
|
|
99
|
+
import cloudinary.uploader # cloudinary.uploader must be imported explicitly
|
|
100
|
+
|
|
101
|
+
# Configuration is read from CLOUDINARY_URL automatically.
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def main():
|
|
105
|
+
# Upload a remote image (a local file path works the same way)
|
|
106
|
+
result = cloudinary.uploader.upload(
|
|
107
|
+
"https://res.cloudinary.com/demo/image/upload/sample.jpg",
|
|
108
|
+
public_id="quickstart-sample",
|
|
109
|
+
)
|
|
110
|
+
print("Uploaded: {0}".format(result["public_id"]))
|
|
111
|
+
|
|
112
|
+
# Build a 400x400 auto-cropped URL with automatic format and quality
|
|
113
|
+
url = cloudinary.CloudinaryImage(result["public_id"]).build_url(
|
|
114
|
+
width=400,
|
|
115
|
+
height=400,
|
|
116
|
+
crop="fill",
|
|
117
|
+
gravity="auto",
|
|
118
|
+
fetch_format="auto",
|
|
119
|
+
quality="auto",
|
|
120
|
+
secure=True,
|
|
121
|
+
)
|
|
122
|
+
print("Optimized URL: {0}".format(url))
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
try:
|
|
127
|
+
main()
|
|
128
|
+
except Exception as error:
|
|
129
|
+
print("Quick start failed: {0}".format(error))
|
|
130
|
+
print("Check that CLOUDINARY_URL is set (Console > Settings > API Keys).")
|
|
131
|
+
raise SystemExit(1)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Save as `quickstart.py` and run `python quickstart.py`. [Create a free account](https://cloudinary.com/users/register_free) if you don't have one — or call `cloudinary.provisioning.create_cloud()` to [provision one without signing up](cloudinary/docs/get-credentials.md).
|
|
135
|
+
|
|
136
|
+
## Common tasks
|
|
137
|
+
|
|
138
|
+
- [Get Cloudinary credentials](cloudinary/docs/get-credentials.md)
|
|
139
|
+
- [Upload an image](cloudinary/docs/upload-image.md)
|
|
140
|
+
- [Upload a large video](cloudinary/docs/upload-large-video.md)
|
|
141
|
+
- [Sign a browser upload](cloudinary/docs/sign-browser-upload.md)
|
|
142
|
+
- [Transform and deliver an image](cloudinary/docs/transform-and-deliver-image.md)
|
|
143
|
+
- [Transform and deliver a video](cloudinary/docs/transform-and-deliver-video.md)
|
|
144
|
+
- [Search and manage assets](cloudinary/docs/search-and-manage-assets.md)
|
|
145
|
+
- [Moderate an upload](cloudinary/docs/moderate-upload.md)
|
|
146
|
+
- [Use structured metadata](cloudinary/docs/use-structured-metadata.md)
|
|
147
|
+
- [Use with Django](cloudinary/docs/use-with-django.md)
|
|
148
|
+
- [Troubleshoot errors](cloudinary/docs/troubleshoot-errors.md)
|
|
149
|
+
|
|
150
|
+
Runnable versions live in [`examples/`](examples/) — each is a complete file you can run directly.
|
|
151
|
+
|
|
152
|
+
## When to use this SDK
|
|
153
|
+
|
|
154
|
+
Use this package in **Python server-side code**, including Django: uploads, signed
|
|
155
|
+
operations, asset administration, search, moderation, and delivery URL generation.
|
|
156
|
+
|
|
157
|
+
For other jobs, better-fitting tools exist:
|
|
158
|
+
|
|
159
|
+
- Browser or frontend framework rendering: the [frontend SDKs](https://cloudinary.com/documentation/frontend_sdks) ([md](https://cloudinary.com/documentation/frontend_sdks.md)).
|
|
160
|
+
- Complete in-browser upload UI: [Upload Widget](https://cloudinary.com/documentation/upload_widget) ([md](https://cloudinary.com/documentation/upload_widget.md)).
|
|
161
|
+
- Text-to-image generation and image-to-video: [platform APIs](https://cloudinary.com/documentation/image_generation_addon) ([md](https://cloudinary.com/documentation/image_generation_addon.md)), not wrapped by this package.
|
|
162
|
+
- Multi-step media workflow automation: [MediaFlows](https://cloudinary.com/documentation/mediaflows_user_guide) ([md](https://cloudinary.com/documentation/mediaflows_user_guide.md)).
|
|
163
|
+
- Interactive agent-driven asset operations: [Cloudinary MCP servers and Skills](https://cloudinary.com/documentation/cloudinary_llm_mcp) ([md](https://cloudinary.com/documentation/cloudinary_llm_mcp.md)).
|
|
164
|
+
|
|
165
|
+
The full capability map — plus the Skills, MCP servers, and CLI worth setting up first —
|
|
166
|
+
is in [cloudinary/docs/platform-capabilities.md](cloudinary/docs/platform-capabilities.md).
|
|
167
|
+
|
|
168
|
+
## Status and compatibility
|
|
169
|
+
|
|
170
|
+
Stable, actively maintained. See [CHANGELOG.md](CHANGELOG.md).
|
|
171
|
+
|
|
172
|
+
| SDK version | Python | Django |
|
|
173
|
+
|-------------|--------|--------|
|
|
174
|
+
| 1.x | 3.10 – 3.14 | 4.2, 5.0, 5.1, 5.2, 6.0 |
|
|
175
|
+
|
|
176
|
+
The table lists what CI tests on every commit. Older Python and Django releases are
|
|
177
|
+
supported on a best-effort basis.
|
|
178
|
+
|
|
179
|
+
## Documentation
|
|
180
|
+
|
|
181
|
+
- [Bundled task docs](cloudinary/docs/README.md) — ship inside the package, version-matched.
|
|
182
|
+
- [Python and Django SDK guide](https://cloudinary.com/documentation/django_integration) — the full documentation ([md](https://cloudinary.com/documentation/django_integration.md)).
|
|
183
|
+
- [Python quick start](https://cloudinary.com/documentation/python_quickstart) — a short end-to-end walkthrough ([md](https://cloudinary.com/documentation/python_quickstart.md)).
|
|
184
|
+
- [Transformation and REST API references](https://cloudinary.com/documentation/cloudinary_references) — syntax and examples for all SDKs ([md](https://cloudinary.com/documentation/cloudinary_references.md)).
|
|
185
|
+
|
|
186
|
+
Documentation links in this README point at the browsable HTML page, with an `(md)`
|
|
187
|
+
companion link that returns the same page as raw Markdown. Inside `cloudinary/docs/` and
|
|
188
|
+
`examples/` the links are Markdown-only, since those files are written to be read by
|
|
189
|
+
coding agents. Either form works for any page: add `.md` for Markdown, drop it for HTML.
|
|
190
|
+
|
|
191
|
+
## For AI coding agents
|
|
192
|
+
|
|
193
|
+
- Contributing to this repo: read [AGENTS.md](AGENTS.md).
|
|
194
|
+
- Using the installed package: the Markdown docs in the installed package's
|
|
195
|
+
`cloudinary/docs/` directory match your installed version and are the source of truth.
|
|
196
|
+
Locate them with
|
|
197
|
+
`python -c "import cloudinary, pathlib; print(pathlib.Path(cloudinary.__file__).parent / 'docs')"`,
|
|
198
|
+
and start with [platform-capabilities](cloudinary/docs/platform-capabilities.md) before
|
|
199
|
+
assuming a feature exists.
|
|
200
|
+
|
|
201
|
+
## Support
|
|
202
|
+
|
|
203
|
+
- SDK bugs and feature requests: [GitHub issues](https://github.com/cloudinary/pycloudinary/issues)
|
|
204
|
+
- Account and platform questions: [Cloudinary support](https://support.cloudinary.com)
|
|
205
|
+
- Sample projects: [`samples/`](samples/) and the
|
|
206
|
+
[Django Photo Album](https://github.com/cloudinary/cloudinary-django-sample)
|
|
207
|
+
- Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
208
|
+
|
|
209
|
+
More resources: [Cloudinary Academy](https://training.cloudinary.com/) for courses,
|
|
210
|
+
[code explorers and feature demos](https://cloudinary.com/documentation/code_explorers_demos_index),
|
|
211
|
+
and the [Cloudinary roadmap](https://cloudinary.com/roadmap).
|
|
212
|
+
|
|
213
|
+
## Security
|
|
214
|
+
|
|
215
|
+
See [SECURITY.md](SECURITY.md) for private vulnerability reporting. Keep your
|
|
216
|
+
`api_secret` in server-side code; for client uploads, use the server-signed pattern in
|
|
217
|
+
[Sign a browser upload](cloudinary/docs/sign-browser-upload.md).
|
|
218
|
+
|
|
219
|
+
## License
|
|
220
|
+
|
|
221
|
+
Released under the MIT license — see [LICENSE](LICENSE). Copyright (c) Cloudinary Ltd.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Cloudinary Python SDK
|
|
2
|
+
|
|
3
|
+
Upload, transform, optimize, and manage images and videos with Cloudinary from Python or Django — the `cloudinary` package on PyPI.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/cloudinary/pycloudinary/actions/workflows/test.yml)
|
|
6
|
+
[](https://pypi.org/project/cloudinary/)
|
|
7
|
+
[](https://pypi.org/project/cloudinary/)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install cloudinary
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
Set your API environment variable (Console > Settings > API Keys):
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
export CLOUDINARY_URL=cloudinary://<api_key>:<api_secret>@<cloud_name>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Upload an image and get an optimized delivery URL:
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
import cloudinary
|
|
28
|
+
import cloudinary.uploader # cloudinary.uploader must be imported explicitly
|
|
29
|
+
|
|
30
|
+
# Configuration is read from CLOUDINARY_URL automatically.
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main():
|
|
34
|
+
# Upload a remote image (a local file path works the same way)
|
|
35
|
+
result = cloudinary.uploader.upload(
|
|
36
|
+
"https://res.cloudinary.com/demo/image/upload/sample.jpg",
|
|
37
|
+
public_id="quickstart-sample",
|
|
38
|
+
)
|
|
39
|
+
print("Uploaded: {0}".format(result["public_id"]))
|
|
40
|
+
|
|
41
|
+
# Build a 400x400 auto-cropped URL with automatic format and quality
|
|
42
|
+
url = cloudinary.CloudinaryImage(result["public_id"]).build_url(
|
|
43
|
+
width=400,
|
|
44
|
+
height=400,
|
|
45
|
+
crop="fill",
|
|
46
|
+
gravity="auto",
|
|
47
|
+
fetch_format="auto",
|
|
48
|
+
quality="auto",
|
|
49
|
+
secure=True,
|
|
50
|
+
)
|
|
51
|
+
print("Optimized URL: {0}".format(url))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
if __name__ == "__main__":
|
|
55
|
+
try:
|
|
56
|
+
main()
|
|
57
|
+
except Exception as error:
|
|
58
|
+
print("Quick start failed: {0}".format(error))
|
|
59
|
+
print("Check that CLOUDINARY_URL is set (Console > Settings > API Keys).")
|
|
60
|
+
raise SystemExit(1)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Save as `quickstart.py` and run `python quickstart.py`. [Create a free account](https://cloudinary.com/users/register_free) if you don't have one — or call `cloudinary.provisioning.create_cloud()` to [provision one without signing up](cloudinary/docs/get-credentials.md).
|
|
64
|
+
|
|
65
|
+
## Common tasks
|
|
66
|
+
|
|
67
|
+
- [Get Cloudinary credentials](cloudinary/docs/get-credentials.md)
|
|
68
|
+
- [Upload an image](cloudinary/docs/upload-image.md)
|
|
69
|
+
- [Upload a large video](cloudinary/docs/upload-large-video.md)
|
|
70
|
+
- [Sign a browser upload](cloudinary/docs/sign-browser-upload.md)
|
|
71
|
+
- [Transform and deliver an image](cloudinary/docs/transform-and-deliver-image.md)
|
|
72
|
+
- [Transform and deliver a video](cloudinary/docs/transform-and-deliver-video.md)
|
|
73
|
+
- [Search and manage assets](cloudinary/docs/search-and-manage-assets.md)
|
|
74
|
+
- [Moderate an upload](cloudinary/docs/moderate-upload.md)
|
|
75
|
+
- [Use structured metadata](cloudinary/docs/use-structured-metadata.md)
|
|
76
|
+
- [Use with Django](cloudinary/docs/use-with-django.md)
|
|
77
|
+
- [Troubleshoot errors](cloudinary/docs/troubleshoot-errors.md)
|
|
78
|
+
|
|
79
|
+
Runnable versions live in [`examples/`](examples/) — each is a complete file you can run directly.
|
|
80
|
+
|
|
81
|
+
## When to use this SDK
|
|
82
|
+
|
|
83
|
+
Use this package in **Python server-side code**, including Django: uploads, signed
|
|
84
|
+
operations, asset administration, search, moderation, and delivery URL generation.
|
|
85
|
+
|
|
86
|
+
For other jobs, better-fitting tools exist:
|
|
87
|
+
|
|
88
|
+
- Browser or frontend framework rendering: the [frontend SDKs](https://cloudinary.com/documentation/frontend_sdks) ([md](https://cloudinary.com/documentation/frontend_sdks.md)).
|
|
89
|
+
- Complete in-browser upload UI: [Upload Widget](https://cloudinary.com/documentation/upload_widget) ([md](https://cloudinary.com/documentation/upload_widget.md)).
|
|
90
|
+
- Text-to-image generation and image-to-video: [platform APIs](https://cloudinary.com/documentation/image_generation_addon) ([md](https://cloudinary.com/documentation/image_generation_addon.md)), not wrapped by this package.
|
|
91
|
+
- Multi-step media workflow automation: [MediaFlows](https://cloudinary.com/documentation/mediaflows_user_guide) ([md](https://cloudinary.com/documentation/mediaflows_user_guide.md)).
|
|
92
|
+
- Interactive agent-driven asset operations: [Cloudinary MCP servers and Skills](https://cloudinary.com/documentation/cloudinary_llm_mcp) ([md](https://cloudinary.com/documentation/cloudinary_llm_mcp.md)).
|
|
93
|
+
|
|
94
|
+
The full capability map — plus the Skills, MCP servers, and CLI worth setting up first —
|
|
95
|
+
is in [cloudinary/docs/platform-capabilities.md](cloudinary/docs/platform-capabilities.md).
|
|
96
|
+
|
|
97
|
+
## Status and compatibility
|
|
98
|
+
|
|
99
|
+
Stable, actively maintained. See [CHANGELOG.md](CHANGELOG.md).
|
|
100
|
+
|
|
101
|
+
| SDK version | Python | Django |
|
|
102
|
+
|-------------|--------|--------|
|
|
103
|
+
| 1.x | 3.10 – 3.14 | 4.2, 5.0, 5.1, 5.2, 6.0 |
|
|
104
|
+
|
|
105
|
+
The table lists what CI tests on every commit. Older Python and Django releases are
|
|
106
|
+
supported on a best-effort basis.
|
|
107
|
+
|
|
108
|
+
## Documentation
|
|
109
|
+
|
|
110
|
+
- [Bundled task docs](cloudinary/docs/README.md) — ship inside the package, version-matched.
|
|
111
|
+
- [Python and Django SDK guide](https://cloudinary.com/documentation/django_integration) — the full documentation ([md](https://cloudinary.com/documentation/django_integration.md)).
|
|
112
|
+
- [Python quick start](https://cloudinary.com/documentation/python_quickstart) — a short end-to-end walkthrough ([md](https://cloudinary.com/documentation/python_quickstart.md)).
|
|
113
|
+
- [Transformation and REST API references](https://cloudinary.com/documentation/cloudinary_references) — syntax and examples for all SDKs ([md](https://cloudinary.com/documentation/cloudinary_references.md)).
|
|
114
|
+
|
|
115
|
+
Documentation links in this README point at the browsable HTML page, with an `(md)`
|
|
116
|
+
companion link that returns the same page as raw Markdown. Inside `cloudinary/docs/` and
|
|
117
|
+
`examples/` the links are Markdown-only, since those files are written to be read by
|
|
118
|
+
coding agents. Either form works for any page: add `.md` for Markdown, drop it for HTML.
|
|
119
|
+
|
|
120
|
+
## For AI coding agents
|
|
121
|
+
|
|
122
|
+
- Contributing to this repo: read [AGENTS.md](AGENTS.md).
|
|
123
|
+
- Using the installed package: the Markdown docs in the installed package's
|
|
124
|
+
`cloudinary/docs/` directory match your installed version and are the source of truth.
|
|
125
|
+
Locate them with
|
|
126
|
+
`python -c "import cloudinary, pathlib; print(pathlib.Path(cloudinary.__file__).parent / 'docs')"`,
|
|
127
|
+
and start with [platform-capabilities](cloudinary/docs/platform-capabilities.md) before
|
|
128
|
+
assuming a feature exists.
|
|
129
|
+
|
|
130
|
+
## Support
|
|
131
|
+
|
|
132
|
+
- SDK bugs and feature requests: [GitHub issues](https://github.com/cloudinary/pycloudinary/issues)
|
|
133
|
+
- Account and platform questions: [Cloudinary support](https://support.cloudinary.com)
|
|
134
|
+
- Sample projects: [`samples/`](samples/) and the
|
|
135
|
+
[Django Photo Album](https://github.com/cloudinary/cloudinary-django-sample)
|
|
136
|
+
- Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
137
|
+
|
|
138
|
+
More resources: [Cloudinary Academy](https://training.cloudinary.com/) for courses,
|
|
139
|
+
[code explorers and feature demos](https://cloudinary.com/documentation/code_explorers_demos_index),
|
|
140
|
+
and the [Cloudinary roadmap](https://cloudinary.com/roadmap).
|
|
141
|
+
|
|
142
|
+
## Security
|
|
143
|
+
|
|
144
|
+
See [SECURITY.md](SECURITY.md) for private vulnerability reporting. Keep your
|
|
145
|
+
`api_secret` in server-side code; for client uploads, use the server-signed pattern in
|
|
146
|
+
[Sign a browser upload](cloudinary/docs/sign-browser-upload.md).
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
Released under the MIT license — see [LICENSE](LICENSE). Copyright (c) Cloudinary Ltd.
|
|
@@ -38,7 +38,7 @@ CL_BLANK = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAA
|
|
|
38
38
|
URI_SCHEME = "cloudinary"
|
|
39
39
|
API_VERSION = "v1_1"
|
|
40
40
|
|
|
41
|
-
VERSION = "1.
|
|
41
|
+
VERSION = "1.46.1"
|
|
42
42
|
|
|
43
43
|
_USER_PLATFORM_DETAILS = "; ".join((platform(), "Python {}".format(python_version())))
|
|
44
44
|
|
|
@@ -1323,6 +1323,189 @@ def update_streaming_profile(name, **options):
|
|
|
1323
1323
|
return call_json_api('PUT', uri, params, **options)
|
|
1324
1324
|
|
|
1325
1325
|
|
|
1326
|
+
def triggers(**options):
|
|
1327
|
+
"""
|
|
1328
|
+
Lists all notification triggers.
|
|
1329
|
+
|
|
1330
|
+
:param options: Additional options.
|
|
1331
|
+
:keyword str event_type: Restricts the list to triggers of a single event type.
|
|
1332
|
+
:return: A dictionary with a "triggers" key and a "total" count.
|
|
1333
|
+
:rtype: Response
|
|
1334
|
+
"""
|
|
1335
|
+
params = {"event_type": options.pop("event_type", None)}
|
|
1336
|
+
return call_json_api("get", ["triggers"], params, **options)
|
|
1337
|
+
|
|
1338
|
+
|
|
1339
|
+
def create_trigger(uri, event_type, uri_type=None, **options):
|
|
1340
|
+
"""
|
|
1341
|
+
Creates a notification trigger.
|
|
1342
|
+
|
|
1343
|
+
:param uri: The destination of the notification. An https:// webhook URL, or a
|
|
1344
|
+
poll:// destination when uri_type is "poll" - either "poll://<channel>"
|
|
1345
|
+
for a named channel or "poll://*" for an anonymous one addressed by batch_id.
|
|
1346
|
+
:type uri: str
|
|
1347
|
+
:param event_type: The event that fires the trigger. One of:
|
|
1348
|
+
"all", "access_control_changed", "bulk_refresh_auto_fetch",
|
|
1349
|
+
"create_folder", "delete", "delete_by_token", "delete_folder",
|
|
1350
|
+
"eager", "error", "explode", "generate_archive", "info",
|
|
1351
|
+
"invalidate_custom_cdn", "moderation", "moderation_summary",
|
|
1352
|
+
"move", "move_or_rename_asset_folder", "multi", "publish",
|
|
1353
|
+
"rename", "report", "resource_context_changed",
|
|
1354
|
+
"resource_display_name_changed", "resource_metadata_changed",
|
|
1355
|
+
"resource_tags_changed", "restore_asset_version", "sprite",
|
|
1356
|
+
"upload".
|
|
1357
|
+
The server owns this list and may extend it; values are passed
|
|
1358
|
+
through unvalidated.
|
|
1359
|
+
:type event_type: str
|
|
1360
|
+
:param uri_type: How the notification is delivered:
|
|
1361
|
+
- "webhook" (the default): delivers the notification as an HTTP POST
|
|
1362
|
+
to the destination URL.
|
|
1363
|
+
- "flow": dispatches the notification to a Cloudinary flow.
|
|
1364
|
+
- "poll": buffers the notification for retrieval with `notifications`
|
|
1365
|
+
instead of an outbound HTTP request.
|
|
1366
|
+
:type uri_type: str, optional
|
|
1367
|
+
:param options: Additional options.
|
|
1368
|
+
:return: The created trigger.
|
|
1369
|
+
:rtype: Response
|
|
1370
|
+
"""
|
|
1371
|
+
params = {"uri": uri, "event_type": event_type, "uri_type": uri_type}
|
|
1372
|
+
return call_json_api("post", ["triggers"], params, **options)
|
|
1373
|
+
|
|
1374
|
+
|
|
1375
|
+
def update_trigger(trigger_id, new_uri, **options):
|
|
1376
|
+
"""
|
|
1377
|
+
Updates the destination URI of an existing trigger.
|
|
1378
|
+
|
|
1379
|
+
:param trigger_id: The ID of the trigger to update.
|
|
1380
|
+
:type trigger_id: str
|
|
1381
|
+
:param new_uri: The new destination URI.
|
|
1382
|
+
:type new_uri: str
|
|
1383
|
+
:param options: Additional options.
|
|
1384
|
+
:return: A dictionary with a "message" key.
|
|
1385
|
+
:rtype: Response
|
|
1386
|
+
"""
|
|
1387
|
+
return call_json_api("put", ["triggers", trigger_id], {"new_uri": new_uri}, **options)
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
def delete_trigger(trigger_id, **options):
|
|
1391
|
+
"""
|
|
1392
|
+
Deletes a notification trigger.
|
|
1393
|
+
|
|
1394
|
+
:param trigger_id: The ID of the trigger to delete.
|
|
1395
|
+
:type trigger_id: str
|
|
1396
|
+
:param options: Additional options.
|
|
1397
|
+
:return: A dictionary with a "message" key.
|
|
1398
|
+
:rtype: Response
|
|
1399
|
+
"""
|
|
1400
|
+
return call_json_api("delete", ["triggers", trigger_id], {}, **options)
|
|
1401
|
+
|
|
1402
|
+
|
|
1403
|
+
def test_trigger(trigger_id, sample_data=None, **options):
|
|
1404
|
+
"""
|
|
1405
|
+
Evaluates a trigger's filter against sample data, without delivering a notification.
|
|
1406
|
+
|
|
1407
|
+
:param trigger_id: The ID of the trigger to test.
|
|
1408
|
+
:type trigger_id: str
|
|
1409
|
+
:param sample_data: The sample notification payload to evaluate the filter against.
|
|
1410
|
+
:type sample_data: dict, optional
|
|
1411
|
+
:param options: Additional options.
|
|
1412
|
+
:return: A dictionary with "trigger_id", "filter_present" and "filter_result" keys.
|
|
1413
|
+
:rtype: Response
|
|
1414
|
+
"""
|
|
1415
|
+
params = {"sample_data": sample_data}
|
|
1416
|
+
return call_json_api("post", ["triggers", trigger_id, "test"], params, **options)
|
|
1417
|
+
|
|
1418
|
+
|
|
1419
|
+
def notifications(channel=None, batch_id=None, max_messages=None, wait_seconds=None,
|
|
1420
|
+
visibility_timeout=None, **options):
|
|
1421
|
+
"""
|
|
1422
|
+
Gets notifications buffered for a poll destination.
|
|
1423
|
+
|
|
1424
|
+
Long-polls exactly one addressing dimension - a named channel or a batch_id. Holds the
|
|
1425
|
+
connection up to wait_seconds, returning as soon as messages are claimed. A claimed
|
|
1426
|
+
message stays invisible for visibility_timeout seconds and is then redelivered, unless
|
|
1427
|
+
it is acknowledged with `ack_notifications` first.
|
|
1428
|
+
|
|
1429
|
+
Each message carries the parsed notification as "payload" and the byte-exact signed
|
|
1430
|
+
bytes, base64url encoded, as "signed_payload". Verify signatures against
|
|
1431
|
+
signed_payload, never against a re-serialization of payload::
|
|
1432
|
+
|
|
1433
|
+
raw = cloudinary.utils.base64url_decode(message["signed_payload"])
|
|
1434
|
+
cloudinary.utils.verify_notification_signature(
|
|
1435
|
+
raw, message["timestamp"], message["signature"])
|
|
1436
|
+
|
|
1437
|
+
:param channel: The named channel to drain ("poll://<channel>" destinations).
|
|
1438
|
+
Mutually exclusive with batch_id.
|
|
1439
|
+
:type channel: str, optional
|
|
1440
|
+
:param batch_id: The batch to drain ("poll://*" anonymous destinations).
|
|
1441
|
+
Mutually exclusive with channel.
|
|
1442
|
+
:type batch_id: str, optional
|
|
1443
|
+
:param max_messages: The maximum number of messages to return. 1-100, default 10.
|
|
1444
|
+
:type max_messages: int, optional
|
|
1445
|
+
:param wait_seconds: The maximum seconds to hold the long-poll open when empty.
|
|
1446
|
+
0-60, default 20.
|
|
1447
|
+
:type wait_seconds: int, optional
|
|
1448
|
+
:param visibility_timeout: The seconds a claimed message stays invisible before
|
|
1449
|
+
redelivery. 1-600, default 30.
|
|
1450
|
+
:type visibility_timeout: int, optional
|
|
1451
|
+
:param options: Additional options.
|
|
1452
|
+
:keyword int timeout: The HTTP timeout, also configurable via `cloudinary.config(timeout=...)`.
|
|
1453
|
+
When set, it must exceed wait_seconds, or the long poll is cut off
|
|
1454
|
+
client-side before the server answers.
|
|
1455
|
+
:return: Zero or more claimed messages, as {"messages": [...]}. The "messages" key is
|
|
1456
|
+
absent when nothing is buffered - read it with .get("messages", []).
|
|
1457
|
+
:rtype: Response
|
|
1458
|
+
:raises ValueError: If neither or both of channel and batch_id are given.
|
|
1459
|
+
"""
|
|
1460
|
+
if bool(channel) == bool(batch_id):
|
|
1461
|
+
raise ValueError("Supply exactly one of 'channel' or 'batch_id'")
|
|
1462
|
+
|
|
1463
|
+
params = {
|
|
1464
|
+
"channel": channel,
|
|
1465
|
+
"batch_id": batch_id,
|
|
1466
|
+
"max_messages": max_messages,
|
|
1467
|
+
"wait_seconds": wait_seconds,
|
|
1468
|
+
"visibility_timeout": visibility_timeout,
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
return __call_notifications_api("get", ["messages"], params, **options)
|
|
1472
|
+
|
|
1473
|
+
|
|
1474
|
+
def ack_notifications(receipt_handles, **options):
|
|
1475
|
+
"""
|
|
1476
|
+
Acknowledges claimed notifications, deleting them from the buffer.
|
|
1477
|
+
|
|
1478
|
+
Unacknowledged notifications are redelivered once their visibility timeout expires.
|
|
1479
|
+
|
|
1480
|
+
:param receipt_handles: The receipt handles of the notifications to acknowledge, as
|
|
1481
|
+
returned by `notifications`. A single handle may be passed as a
|
|
1482
|
+
string. Maximum 100 per call.
|
|
1483
|
+
:type receipt_handles: list[str] or str
|
|
1484
|
+
:param options: Additional options.
|
|
1485
|
+
:return: The result of the call.
|
|
1486
|
+
:rtype: Response
|
|
1487
|
+
"""
|
|
1488
|
+
if isinstance(receipt_handles, string_types):
|
|
1489
|
+
receipt_handles = [receipt_handles]
|
|
1490
|
+
|
|
1491
|
+
return __call_notifications_api("post", ["messages", "ack"],
|
|
1492
|
+
{"receipt_handles": receipt_handles}, **options)
|
|
1493
|
+
|
|
1494
|
+
|
|
1495
|
+
def __call_notifications_api(method, uri, params, **options):
|
|
1496
|
+
"""
|
|
1497
|
+
Private function that assists with performing an API call to the notifications module.
|
|
1498
|
+
|
|
1499
|
+
:param method: The HTTP method. Valid methods: get, post, put, delete
|
|
1500
|
+
:param uri: REST endpoint of the API (without 'notifications' or the cloud name)
|
|
1501
|
+
:param params: Query/body parameters passed to the method
|
|
1502
|
+
:param options: Additional options
|
|
1503
|
+
:rtype: Response
|
|
1504
|
+
:internal
|
|
1505
|
+
"""
|
|
1506
|
+
return _call_v2_api(method, uri, params, module="notifications", **options)
|
|
1507
|
+
|
|
1508
|
+
|
|
1326
1509
|
def only(source, *keys):
|
|
1327
1510
|
"""
|
|
1328
1511
|
Returns a dictionary containing only the specified keys from the source.
|
|
@@ -1384,7 +1567,7 @@ def __delete_resource_params(options, **params):
|
|
|
1384
1567
|
:internal
|
|
1385
1568
|
"""
|
|
1386
1569
|
p = dict(transformations=utils.build_eager(options.get('transformations')),
|
|
1387
|
-
**only(options, "keep_original", "next_cursor", "invalidate"))
|
|
1570
|
+
**only(options, "keep_original", "next_cursor", "invalidate", "batch_id"))
|
|
1388
1571
|
p.update(params)
|
|
1389
1572
|
return p
|
|
1390
1573
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import cloudinary
|
|
2
2
|
from cloudinary.api_client.execute_request import execute_request
|
|
3
3
|
from cloudinary.provisioning.account_config import account_config
|
|
4
|
-
from cloudinary.utils import get_http_connector, normalize_params
|
|
4
|
+
from cloudinary.utils import get_http_connector, json_body, normalize_params
|
|
5
5
|
|
|
6
6
|
PROVISIONING_SUB_PATH = "provisioning"
|
|
7
7
|
ACCOUNT_SUB_PATH = "accounts"
|
|
@@ -46,9 +46,15 @@ def _execute_account_request(method, uri, auth, params=None, headers=None, **opt
|
|
|
46
46
|
api_version = options.pop("api_version", cloudinary.API_VERSION)
|
|
47
47
|
provisioning_api_url = "/".join([prefix, api_version, PROVISIONING_SUB_PATH] + uri)
|
|
48
48
|
|
|
49
|
+
params = normalize_params(params)
|
|
50
|
+
|
|
51
|
+
if method.upper() != "GET":
|
|
52
|
+
options["body"], headers = json_body(params, headers)
|
|
53
|
+
params = None
|
|
54
|
+
|
|
49
55
|
return execute_request(http_connector=_http,
|
|
50
56
|
method=method,
|
|
51
|
-
params=
|
|
57
|
+
params=params,
|
|
52
58
|
headers=headers,
|
|
53
59
|
auth=auth,
|
|
54
60
|
api_url=provisioning_api_url,
|