diff --git a/lib/cloudinary/__init__.py b/lib/cloudinary/__init__.py index 5e315049..da7ca9ae 100644 --- a/lib/cloudinary/__init__.py +++ b/lib/cloudinary/__init__.py @@ -1,14 +1,14 @@ from __future__ import absolute_import import abc -from copy import deepcopy -import hashlib -import os -import re import logging import numbers -import certifi +import os +import re +from copy import deepcopy from math import ceil + +import certifi from six import python_2_unicode_compatible, add_metaclass logger = logging.getLogger("Cloudinary") @@ -23,7 +23,7 @@ from cloudinary.cache import responsive_breakpoints_cache from cloudinary.http_client import HttpClient from cloudinary.compat import urlparse, parse_qs -from platform import python_version +from platform import python_version, platform CERT_KWARGS = { 'cert_reqs': 'CERT_REQUIRED', @@ -38,15 +38,17 @@ CL_BLANK = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAA URI_SCHEME = "cloudinary" API_VERSION = "v1_1" -VERSION = "1.29.0" +VERSION = "1.30.0" -USER_AGENT = "CloudinaryPython/{} (Python {})".format(VERSION, python_version()) +_USER_PLATFORM_DETAILS = "; ".join((platform(), "Python {}".format(python_version()))) + +USER_AGENT = "CloudinaryPython/{} ({})".format(VERSION, _USER_PLATFORM_DETAILS) """ :const: USER_AGENT """ USER_PLATFORM = "" """ -Additional information to be passed with the USER_AGENT, e.g. "CloudinaryMagento/1.0.1". -This value is set in platform-specific implementations that use cloudinary_php. +Additional information to be passed with the USER_AGENT, e.g. "CloudinaryCLI/1.2.3". +This value is set in platform-specific implementations that use pycloudinary. The format of the value should be /Version[ (comment)]. @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 diff --git a/lib/cloudinary/api.py b/lib/cloudinary/api.py index 58002254..73d18fa1 100644 --- a/lib/cloudinary/api.py +++ b/lib/cloudinary/api.py @@ -93,6 +93,23 @@ def resources_by_ids(public_ids, **options): return call_api("get", uri, params, **options) +def resources_by_asset_folder(asset_folder, **options): + """ + Returns the details of the resources (assets) under a specified asset_folder. + + :param asset_folder: The Asset Folder of the asset + :type asset_folder: string + :param options: Additional options + :type options: dict, optional + :return: Resources (assets) of a specific asset_folder + :rtype: Response + """ + uri = ["resources", "by_asset_folder"] + params = only(options, "max_results", "tags", "moderations", "context", "next_cursor") + params["asset_folder"] = asset_folder + return call_api("get", uri, params, **options) + + def resources_by_asset_ids(asset_ids, **options): """Retrieves the resources (assets) indicated in the asset IDs. This method does not return deleted assets even if they have been backed up. @@ -131,7 +148,7 @@ def resources_by_context(key, value=None, **options): resource_type = options.pop("resource_type", "image") uri = ["resources", resource_type, "context"] params = only(options, "next_cursor", "max_results", "tags", - "context", "moderations", "direction", "metadata") + "context", "moderations", "direction", "metadata") params["key"] = key if value is not None: params["value"] = value @@ -194,10 +211,18 @@ def update(public_id, **options): options.get("custom_coordinates")) if "context" in options: params["context"] = utils.encode_context(options.get("context")) + if "metadata" in options: + params["metadata"] = utils.encode_context(options.get("metadata")) if "auto_tagging" in options: params["auto_tagging"] = str(options.get("auto_tagging")) if "access_control" in options: params["access_control"] = utils.json_encode(utils.build_list_of_dicts(options.get("access_control"))) + if "asset_folder" in options: + params["asset_folder"] = options.get("asset_folder") + if "display_name" in options: + params["display_name"] = options.get("display_name") + if "unique_display_name" in options: + params["unique_display_name"] = options.get("unique_display_name") return call_api("post", uri, params, **options) diff --git a/lib/cloudinary/auth_token.py b/lib/cloudinary/auth_token.py index 3aaf3844..4f6c1fe1 100644 --- a/lib/cloudinary/auth_token.py +++ b/lib/cloudinary/auth_token.py @@ -30,7 +30,9 @@ def generate(url=None, acl=None, start_time=None, duration=None, token_parts.append("st=%d" % start_time) token_parts.append("exp=%d" % expiration) if acl is not None: - token_parts.append("acl=%s" % _escape_to_lower(acl)) + acl_list = acl if type(acl) is list else [acl] + acl_list = [_escape_to_lower(a) for a in acl_list] + token_parts.append("acl=%s" % "!".join(acl_list)) to_sign = list(token_parts) if url is not None and acl is None: to_sign.append("url=%s" % _escape_to_lower(url)) diff --git a/lib/cloudinary/models.py b/lib/cloudinary/models.py index 5ccb133d..1240150e 100644 --- a/lib/cloudinary/models.py +++ b/lib/cloudinary/models.py @@ -106,7 +106,7 @@ class CloudinaryField(models.Field): value = super(CloudinaryField, self).pre_save(model_instance, add) if isinstance(value, UploadedFile): options = {"type": self.type, "resource_type": self.resource_type} - options.update(self.options) + options.update({key: val(model_instance) if callable(val) else val for key, val in self.options.items()}) if hasattr(value, 'seekable') and value.seekable(): value.seek(0) instance_value = uploader.upload_resource(value, **options) diff --git a/lib/cloudinary/provisioning/account.py b/lib/cloudinary/provisioning/account.py index 6607f101..414c2727 100644 --- a/lib/cloudinary/provisioning/account.py +++ b/lib/cloudinary/provisioning/account.py @@ -65,7 +65,7 @@ def create_sub_account(name, cloud_name=None, custom_attributes=None, enabled=No "cloud_name": cloud_name, "custom_attributes": custom_attributes, "enabled": enabled, - "base_account": base_account} + "base_sub_account_id": base_account} return _call_account_api("POST", uri, params=params, **options) diff --git a/lib/cloudinary/static/html/cloudinary_cors.html b/lib/cloudinary/static/cloudinary/html/cloudinary_cors.html similarity index 100% rename from lib/cloudinary/static/html/cloudinary_cors.html rename to lib/cloudinary/static/cloudinary/html/cloudinary_cors.html diff --git a/lib/cloudinary/static/js/canvas-to-blob.min.js b/lib/cloudinary/static/cloudinary/js/canvas-to-blob.min.js similarity index 100% rename from lib/cloudinary/static/js/canvas-to-blob.min.js rename to lib/cloudinary/static/cloudinary/js/canvas-to-blob.min.js diff --git a/lib/cloudinary/static/js/jquery.cloudinary.js b/lib/cloudinary/static/cloudinary/js/jquery.cloudinary.js similarity index 99% rename from lib/cloudinary/static/js/jquery.cloudinary.js rename to lib/cloudinary/static/cloudinary/js/jquery.cloudinary.js index 998054b9..7b41a0f2 100644 --- a/lib/cloudinary/static/js/jquery.cloudinary.js +++ b/lib/cloudinary/static/cloudinary/js/jquery.cloudinary.js @@ -1093,11 +1093,11 @@ var slice = [].slice, * * If the parameter is an object, * @param {(string|Object)} param - the video codec as either a String or a Hash - * @return {string} the video codec string in the format codec:profile:level + * @return {string} the video codec string in the format codec:profile:level:b_frames * @example - * vc_[ :profile : [level]] + * vc_[ :profile : [level : [b_frames]]] * or - { codec: 'h264', profile: 'basic', level: '3.1' } + { codec: 'h264', profile: 'basic', level: '3.1', b_frames: false } * @ignore */ @@ -1112,6 +1112,9 @@ var slice = [].slice, video += ":" + param['profile']; if ('level' in param) { video += ":" + param['level']; + if ('b_frames' in param && param['b_frames'] === false) { + video += ":bframes_no"; + } } } } diff --git a/lib/cloudinary/static/js/jquery.fileupload-image.js b/lib/cloudinary/static/cloudinary/js/jquery.fileupload-image.js similarity index 100% rename from lib/cloudinary/static/js/jquery.fileupload-image.js rename to lib/cloudinary/static/cloudinary/js/jquery.fileupload-image.js diff --git a/lib/cloudinary/static/js/jquery.fileupload-process.js b/lib/cloudinary/static/cloudinary/js/jquery.fileupload-process.js similarity index 100% rename from lib/cloudinary/static/js/jquery.fileupload-process.js rename to lib/cloudinary/static/cloudinary/js/jquery.fileupload-process.js diff --git a/lib/cloudinary/static/js/jquery.fileupload-validate.js b/lib/cloudinary/static/cloudinary/js/jquery.fileupload-validate.js similarity index 100% rename from lib/cloudinary/static/js/jquery.fileupload-validate.js rename to lib/cloudinary/static/cloudinary/js/jquery.fileupload-validate.js diff --git a/lib/cloudinary/static/js/jquery.fileupload.js b/lib/cloudinary/static/cloudinary/js/jquery.fileupload.js similarity index 100% rename from lib/cloudinary/static/js/jquery.fileupload.js rename to lib/cloudinary/static/cloudinary/js/jquery.fileupload.js diff --git a/lib/cloudinary/static/js/jquery.iframe-transport.js b/lib/cloudinary/static/cloudinary/js/jquery.iframe-transport.js similarity index 100% rename from lib/cloudinary/static/js/jquery.iframe-transport.js rename to lib/cloudinary/static/cloudinary/js/jquery.iframe-transport.js diff --git a/lib/cloudinary/static/js/jquery.ui.widget.js b/lib/cloudinary/static/cloudinary/js/jquery.ui.widget.js similarity index 100% rename from lib/cloudinary/static/js/jquery.ui.widget.js rename to lib/cloudinary/static/cloudinary/js/jquery.ui.widget.js diff --git a/lib/cloudinary/static/js/load-image.all.min.js b/lib/cloudinary/static/cloudinary/js/load-image.all.min.js similarity index 100% rename from lib/cloudinary/static/js/load-image.all.min.js rename to lib/cloudinary/static/cloudinary/js/load-image.all.min.js diff --git a/lib/cloudinary/templates/cloudinary_includes.html b/lib/cloudinary/templates/cloudinary_includes.html index 82361c33..908c41d2 100644 --- a/lib/cloudinary/templates/cloudinary_includes.html +++ b/lib/cloudinary/templates/cloudinary_includes.html @@ -1,14 +1,14 @@ {% load static %} - - - - + + + + {% if processing %} - - - - - + + + + + {% endif %} diff --git a/lib/cloudinary/utils.py b/lib/cloudinary/utils.py index 1fade15b..f7f94512 100644 --- a/lib/cloudinary/utils.py +++ b/lib/cloudinary/utils.py @@ -94,6 +94,8 @@ __SIMPLE_UPLOAD_PARAMS = [ "proxy", "folder", "asset_folder", + "use_asset_folder_as_public_id_prefix", + "unique_display_name", "overwrite", "moderation", "raw_convert", diff --git a/requirements.txt b/requirements.txt index cff0f4b1..406d8c3f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ bleach==5.0.1 certifi==2022.9.24 cheroot==8.6.0 cherrypy==18.8.0 -cloudinary==1.29.0 +cloudinary==1.30.0 distro==1.7.0 dnspython==2.2.1 facebook-sdk==3.1.0