Bump cloudinary from 1.32.0 to 1.34.0 (#2109)

* Bump cloudinary from 1.32.0 to 1.34.0

Bumps [cloudinary](https://github.com/cloudinary/pycloudinary) from 1.32.0 to 1.34.0.
- [Release notes](https://github.com/cloudinary/pycloudinary/releases)
- [Changelog](https://github.com/cloudinary/pycloudinary/blob/master/CHANGELOG.md)
- [Commits](https://github.com/cloudinary/pycloudinary/compare/1.32.0...1.34.0)

---
updated-dependencies:
- dependency-name: cloudinary
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update cloudinary==1.34.0

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com>

[skip ci]
This commit is contained in:
dependabot[bot] 2023-08-23 21:56:41 -07:00 committed by GitHub
parent edd8c5fdc3
commit 7266a60343
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 167 additions and 29 deletions

View file

@ -38,7 +38,7 @@ CL_BLANK = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAA
URI_SCHEME = "cloudinary"
API_VERSION = "v1_1"
VERSION = "1.32.0"
VERSION = "1.34.0"
_USER_PLATFORM_DETAILS = "; ".join((platform(), "Python {}".format(python_version())))

View file

@ -155,6 +155,26 @@ def resources_by_context(key, value=None, **options):
return call_api("get", uri, params, **options)
def visual_search(image_url=None, image_asset_id=None, text=None, **options):
"""
Find images based on their visual content.
:param image_url: The URL of an image.
:type image_url: str
:param image_asset_id: The asset_id of an image in your account.
:type image_asset_id: str
:param text: A textual description, e.g., "cat"
:type text: str
:param options: Additional options
:type options: dict, optional
:return: Resources (assets) that were found
:rtype: Response
"""
uri = ["resources", "visual_search"]
params = {"image_url": image_url, "image_asset_id": image_asset_id, "text": text}
return call_api("get", uri, params, **options)
def resource(public_id, **options):
resource_type = options.pop("resource_type", "image")
upload_type = options.pop("type", "upload")
@ -317,6 +337,24 @@ def add_related_assets(public_id, assets_to_relate, resource_type="image", type=
return call_json_api("post", uri, params, **options)
def add_related_assets_by_asset_ids(asset_id, assets_to_relate, **options):
"""
Relates an asset to other assets by asset IDs.
:param asset_id: The asset ID of the asset to update.
:type asset_id: str
:param assets_to_relate: The array of up to 10 asset IDs.
:type assets_to_relate: list[str]
:param options: Additional options.
:type options: dict, optional
:return: The result of the command.
:rtype: dict
"""
uri = ["resources", "related_assets", asset_id]
params = {"assets_to_relate": utils.build_array(assets_to_relate)}
return call_json_api("post", uri, params, **options)
def delete_related_assets(public_id, assets_to_unrelate, resource_type="image", type="upload", **options):
"""
Unrelates an asset from other assets by public IDs.
@ -339,6 +377,24 @@ def delete_related_assets(public_id, assets_to_unrelate, resource_type="image",
return call_json_api("delete", uri, params, **options)
def delete_related_assets_by_asset_ids(asset_id, assets_to_unrelate, **options):
"""
Unrelates an asset from other assets by asset IDs.
:param asset_id: The asset ID of the asset to update.
:type asset_id: str
:param assets_to_unrelate: The array of up to 10 asset IDs.
:type assets_to_unrelate: list[str]
:param options: Additional options.
:type options: dict, optional
:return: The result of the command.
:rtype: dict
"""
uri = ["resources", "related_assets", asset_id]
params = {"assets_to_unrelate": utils.build_array(assets_to_unrelate)}
return call_json_api("delete", uri, params, **options)
def tags(**options):
resource_type = options.pop("resource_type", "image")
uri = ["tags", resource_type]

View file

@ -31,7 +31,7 @@ def call_api(method, uri, params, **options):
return _call_api(method, uri, params=params, **options)
def _call_api(method, uri, params=None, body=None, headers=None, **options):
def _call_api(method, uri, params=None, body=None, headers=None, extra_headers=None, **options):
prefix = options.pop("upload_prefix",
cloudinary.config().upload_prefix) or "https://api.cloudinary.com"
cloud_name = options.pop("cloud_name", cloudinary.config().cloud_name)
@ -50,6 +50,9 @@ def _call_api(method, uri, params=None, body=None, headers=None, **options):
if body is not None:
options["body"] = body
if extra_headers is not None:
headers.update(extra_headers)
return execute_request(http_connector=_http,
method=method,
params=params,

View file

@ -1,7 +1,10 @@
import base64
import json
import cloudinary
from cloudinary.api_client.call_api import call_json_api
from cloudinary.utils import unique
from cloudinary.utils import unique, unsigned_download_url_prefix, build_distribution_domain, base64url_encode, \
json_encode, compute_hex_hash, SIGNATURE_SHA256
class Search(object):
@ -15,7 +18,10 @@ class Search(object):
'with_field': None,
}
_ttl = 300 # Used for search URLs
"""Build and execute a search query."""
def __init__(self):
self.query = {}
@ -51,6 +57,16 @@ class Search(object):
self._add("with_field", value)
return self
def ttl(self, ttl):
"""
Sets the time to live of the search URL.
:param ttl: The time to live in seconds.
:return: self
"""
self._ttl = ttl
return self
def to_json(self):
return json.dumps(self.as_dict())
@ -60,12 +76,6 @@ class Search(object):
uri = [self._endpoint, 'search']
return call_json_api('post', uri, self.as_dict(), **options)
def _add(self, name, value):
if name not in self.query:
self.query[name] = []
self.query[name].append(value)
return self
def as_dict(self):
to_return = {}
@ -77,6 +87,51 @@ class Search(object):
return to_return
def to_url(self, ttl=None, next_cursor=None, **options):
"""
Creates a signed Search URL that can be used on the client side.
:param ttl: The time to live in seconds.
:param next_cursor: Starting position.
:param options: Additional url delivery options.
:return: The resulting search URL.
"""
api_secret = options.get("api_secret", cloudinary.config().api_secret or None)
if not api_secret:
raise ValueError("Must supply api_secret")
if ttl is None:
ttl = self._ttl
query = self.as_dict()
_next_cursor = query.pop("next_cursor", None)
if next_cursor is None:
next_cursor = _next_cursor
b64query = base64url_encode(json_encode(query, sort_keys=True))
prefix = build_distribution_domain(options)
signature = compute_hex_hash("{ttl}{b64query}{api_secret}".format(
ttl=ttl,
b64query=b64query,
api_secret=api_secret
), algorithm=SIGNATURE_SHA256)
return "{prefix}/search/{signature}/{ttl}/{b64query}{next_cursor}".format(
prefix=prefix,
signature=signature,
ttl=ttl,
b64query=b64query,
next_cursor="/{}".format(next_cursor) if next_cursor else "")
def endpoint(self, endpoint):
self._endpoint = endpoint
return self
def _add(self, name, value):
if name not in self.query:
self.query[name] = []
self.query[name].append(value)
return self

View file

@ -472,7 +472,8 @@ def call_cacheable_api(action, params, http_headers=None, return_error=False, un
return result
def call_api(action, params, http_headers=None, return_error=False, unsigned=False, file=None, timeout=None, **options):
def call_api(action, params, http_headers=None, return_error=False, unsigned=False, file=None, timeout=None,
extra_headers=None, **options):
params = utils.cleanup_params(params)
headers = {"User-Agent": cloudinary.get_user_agent()}
@ -480,6 +481,9 @@ def call_api(action, params, http_headers=None, return_error=False, unsigned=Fal
if http_headers is not None:
headers.update(http_headers)
if extra_headers is not None:
headers.update(extra_headers)
oauth_token = options.get("oauth_token", cloudinary.config().oauth_token)
if oauth_token:

View file

@ -92,6 +92,7 @@ __SIMPLE_UPLOAD_PARAMS = [
"eager_notification_url",
"eager_async",
"eval",
"on_success",
"proxy",
"folder",
"asset_folder",
@ -106,6 +107,7 @@ __SIMPLE_UPLOAD_PARAMS = [
"categorization",
"detection",
"similarity_search",
"visual_search",
"background_removal",
"upload_preset",
"phash",
@ -281,7 +283,7 @@ def encode_context(context):
return "|".join(("{}={}".format(k, normalize_context_value(v))) for k, v in iteritems(context))
def json_encode(value):
def json_encode(value, sort_keys=False):
"""
Converts value to a json encoded string
@ -289,7 +291,7 @@ def json_encode(value):
:return: JSON encoded string
"""
return json.dumps(value, default=__json_serializer, separators=(',', ':'))
return json.dumps(value, default=__json_serializer, separators=(',', ':'), sort_keys=sort_keys)
def encode_date_to_usage_api_format(date_obj):
@ -373,8 +375,17 @@ def generate_transformation_string(**options):
flags = ".".join(build_array(options.pop("flags", None)))
dpr = options.pop("dpr", cloudinary.config().dpr)
duration = norm_range_value(options.pop("duration", None))
start_offset = norm_auto_range_value(options.pop("start_offset", None))
end_offset = norm_range_value(options.pop("end_offset", None))
so_raw = options.pop("start_offset", None)
start_offset = norm_auto_range_value(so_raw)
if start_offset == None:
start_offset = so_raw
eo_raw = options.pop("end_offset", None)
end_offset = norm_range_value(eo_raw)
if end_offset == None:
end_offset = eo_raw
offset = split_range(options.pop("offset", None))
if offset:
start_offset = norm_auto_range_value(offset[0])
@ -700,6 +711,25 @@ def unsigned_download_url_prefix(source, cloud_name, private_cdn, cdn_subdomain,
return prefix
def build_distribution_domain(options):
source = options.pop('source', '')
cloud_name = options.pop("cloud_name", cloudinary.config().cloud_name or None)
if cloud_name is None:
raise ValueError("Must supply cloud_name in tag or in configuration")
secure = options.pop("secure", cloudinary.config().secure)
private_cdn = options.pop("private_cdn", cloudinary.config().private_cdn)
cname = options.pop("cname", cloudinary.config().cname)
secure_distribution = options.pop("secure_distribution",
cloudinary.config().secure_distribution)
cdn_subdomain = options.pop("cdn_subdomain", cloudinary.config().cdn_subdomain)
secure_cdn_subdomain = options.pop("secure_cdn_subdomain",
cloudinary.config().secure_cdn_subdomain)
return unsigned_download_url_prefix(
source, cloud_name, private_cdn, cdn_subdomain, secure_cdn_subdomain,
cname, secure, secure_distribution)
def merge(*dict_args):
result = None
for dictionary in dict_args:
@ -728,19 +758,8 @@ def cloudinary_url(source, **options):
version = options.pop("version", None)
format = options.pop("format", None)
cdn_subdomain = options.pop("cdn_subdomain", cloudinary.config().cdn_subdomain)
secure_cdn_subdomain = options.pop("secure_cdn_subdomain",
cloudinary.config().secure_cdn_subdomain)
cname = options.pop("cname", cloudinary.config().cname)
shorten = options.pop("shorten", cloudinary.config().shorten)
cloud_name = options.pop("cloud_name", cloudinary.config().cloud_name or None)
if cloud_name is None:
raise ValueError("Must supply cloud_name in tag or in configuration")
secure = options.pop("secure", cloudinary.config().secure)
private_cdn = options.pop("private_cdn", cloudinary.config().private_cdn)
secure_distribution = options.pop("secure_distribution",
cloudinary.config().secure_distribution)
sign_url = options.pop("sign_url", cloudinary.config().sign_url)
api_secret = options.pop("api_secret", cloudinary.config().api_secret)
url_suffix = options.pop("url_suffix", None)
@ -786,9 +805,9 @@ def cloudinary_url(source, **options):
base64.urlsafe_b64encode(
hash_fn(to_bytes(to_sign + api_secret)).digest())[0:chars_length]) + "--"
prefix = unsigned_download_url_prefix(
source, cloud_name, private_cdn, cdn_subdomain, secure_cdn_subdomain,
cname, secure, secure_distribution)
options["source"] = source
prefix = build_distribution_domain(options)
source = "/".join(__compact(
[prefix, resource_type, type, signature, transformation, version, source]))
if sign_url and auth_token:
@ -999,6 +1018,7 @@ def archive_params(**options):
"skip_transformation_name": options.get("skip_transformation_name"),
"tags": options.get("tags") and build_array(options.get("tags")),
"target_format": options.get("target_format"),
"target_asset_folder": options.get("target_asset_folder"),
"target_public_id": options.get("target_public_id"),
"target_tags": options.get("target_tags") and build_array(options.get("target_tags")),
"timestamp": timestamp,

View file

@ -9,7 +9,7 @@ bleach==6.0.0
certifi==2023.7.22
cheroot==9.0.0
cherrypy==18.8.0
cloudinary==1.32.0
cloudinary==1.34.0
distro==1.8.0
dnspython==2.3.0
facebook-sdk==3.1.0