Update cloudinary==1.28.0

This commit is contained in:
JonnyWong16 2021-11-28 14:12:44 -08:00
parent 0325e9327f
commit dcfd8abddd
No known key found for this signature in database
GPG key ID: B1F1F9807184697A
7 changed files with 196 additions and 21 deletions

View file

@ -38,7 +38,7 @@ CL_BLANK = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAA
URI_SCHEME = "cloudinary"
API_VERSION = "v1_1"
VERSION = "1.26.0"
VERSION = "1.28.0"
USER_AGENT = "CloudinaryPython/{} (Python {})".format(VERSION, python_version())
""" :const: USER_AGENT """

View file

@ -93,6 +93,25 @@ def resources_by_ids(public_ids, **options):
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.
See: `Get resources by context API reference
<https://cloudinary.com/documentation/admin_api#get_resources>`_
:param asset_ids: The requested asset IDs.
:type asset_ids: list[str]
:param options: Additional options
:type options: dict, optional
:return: Resources (assets) as indicated in the asset IDs
:rtype: Response
"""
uri = ["resources", 'by_asset_ids']
params = dict(only(options, "tags", "moderations", "context"), asset_ids=asset_ids)
return call_api("get", uri, params, **options)
def resources_by_context(key, value=None, **options):
"""Retrieves resources (assets) with a specified context key.
This method does not return deleted assets even if they have been backed up.
@ -123,10 +142,38 @@ def resource(public_id, **options):
resource_type = options.pop("resource_type", "image")
upload_type = options.pop("type", "upload")
uri = ["resources", resource_type, upload_type, public_id]
params = only(options, "exif", "faces", "colors", "image_metadata", "cinemagraph_analysis",
params = _prepare_asset_details_params(**options)
return call_api("get", uri, params, **options)
def resource_by_asset_id(asset_id, **options):
"""
Returns the details of the specified asset and all its derived assets by asset id.
:param asset_id: The Asset ID of the asset
:type asset_id: string
:param options: Additional options
:type options: dict, optional
:return: Resource (asset) of a specific asset_id
:rtype: Response
"""
uri = ["resources", asset_id]
params = _prepare_asset_details_params(**options)
return call_api("get", uri, params, **options)
def _prepare_asset_details_params(**options):
"""
Prepares optional parameters for resource_by_asset_id API calls.
:param options: Additional options
:return: Optional parameters
:internal
"""
return only(options, "exif", "faces", "colors", "image_metadata", "cinemagraph_analysis",
"pages", "phash", "coordinates", "max_results", "quality_analysis", "derived_next_cursor",
"accessibility_analysis", "versions")
return call_api("get", uri, params, **options)
def update(public_id, **options):
@ -595,3 +642,32 @@ def restore_metadata_field_datasource(field_external_id, entries_external_ids, *
uri = [field_external_id, 'datasource_restore']
params = {"external_ids": entries_external_ids}
return call_metadata_api("post", uri, params, **options)
def reorder_metadata_field_datasource(field_external_id, order_by, direction=None, **options):
"""Reorders metadata field datasource. Currently, supports only value.
:param field_external_id: The ID of the metadata field.
:param order_by: Criteria for the order. Currently, supports only value.
:param direction: Optional (gets either asc or desc).
:param options: Additional options.
:rtype: Response
"""
uri = [field_external_id, 'datasource', 'order']
params = {'order_by': order_by, 'direction': direction}
return call_metadata_api('post', uri, params, **options)
def reorder_metadata_fields(order_by, direction=None, **options):
"""Reorders metadata fields.
:param order_by: Criteria for the order (one of the fields 'label', 'external_id', 'created_at').
:param direction: Optional (gets either asc or desc).
:param options: Additional options.
:rtype: Response
"""
uri = ['order']
params = {'order_by': order_by, 'direction': direction}
return call_metadata_api('put', uri, params, **options)

View file

@ -97,9 +97,7 @@ def sub_account(sub_account_id, **options):
return _call_account_api("get", uri, {}, **options)
def update_sub_account(sub_account_id, name=None, cloud_name=None, custom_attributes=None,
enabled=None, base_account=None,
**options):
def update_sub_account(sub_account_id, name=None, cloud_name=None, custom_attributes=None, enabled=None, **options):
"""
Update a sub account
:param sub_account_id: The id of the sub account
@ -112,8 +110,6 @@ def update_sub_account(sub_account_id, name=None, cloud_name=None, custom_attrib
:type custom_attributes: dict, optional
:param enabled: Whether to create the account as enabled (default is enabled).
:type enabled: bool, optional
:param base_account: ID of sub-account from which to copy settings
:type base_account: str, optional
:param options: Generic advanced options dict, see online documentation
:type options: dict, optional
:return: Updated sub account
@ -123,8 +119,7 @@ def update_sub_account(sub_account_id, name=None, cloud_name=None, custom_attrib
params = {"name": name,
"cloud_name": cloud_name,
"custom_attributes": custom_attributes,
"enabled": enabled,
"base_account": base_account}
"enabled": enabled}
return _call_account_api("put", uri, params=params, **options)

View file

@ -1,10 +1,16 @@
import json
from copy import deepcopy
from cloudinary.api_client.call_api import call_json_api
from cloudinary.utils import unique
class Search:
_KEYS_WITH_UNIQUE_VALUES = {
'sort_by': lambda x: next(iter(x)),
'aggregate': None,
'with_field': None,
}
"""Build and execute a search query."""
def __init__(self):
self.query = {}
@ -42,7 +48,7 @@ class Search:
return self
def to_json(self):
return json.dumps(self.query)
return json.dumps(self.as_dict())
def execute(self, **options):
"""Execute the search and return results."""
@ -57,4 +63,12 @@ class Search:
return self
def as_dict(self):
return deepcopy(self.query)
to_return = {}
for key, value in self.query.items():
if key in self._KEYS_WITH_UNIQUE_VALUES:
value = unique(value, self._KEYS_WITH_UNIQUE_VALUES[key])
to_return[key] = value
return to_return

View file

@ -802,7 +802,7 @@ var slice = [].slice,
function TextLayer(options) {
var keys;
TextLayer.__super__.constructor.call(this, options);
keys = ["resourceType", "resourceType", "fontFamily", "fontSize", "fontWeight", "fontStyle", "textDecoration", "textAlign", "stroke", "letterSpacing", "lineSpacing", "fontHinting", "fontAntialiasing", "text"];
keys = ["resourceType", "resourceType", "fontFamily", "fontSize", "fontWeight", "fontStyle", "textDecoration", "textAlign", "stroke", "letterSpacing", "lineSpacing", "fontHinting", "fontAntialiasing", "text", "textStyle"];
if (options != null) {
keys.forEach((function(_this) {
return function(key) {
@ -886,6 +886,11 @@ var slice = [].slice,
return this;
};
TextLayer.prototype.textStyle = function(textStyle) {
this.options.textStyle = textStyle;
return this;
};
/**
* generate the string representation of the layer
@ -921,6 +926,10 @@ var slice = [].slice,
};
TextLayer.prototype.textStyleIdentifier = function() {
// Note: if a text-style argument is provided as a whole, it overrides everything else, no mix and match.
if (!Util.isEmpty(this.options.textStyle)) {
return this.options.textStyle;
}
var components;
components = [];
if (this.options.fontWeight !== "normal") {

View file

@ -3,15 +3,14 @@ import json
import os
import socket
import certifi
from six import string_types
from urllib3 import PoolManager, ProxyManager
from urllib3.exceptions import HTTPError
import cloudinary
from cloudinary import utils
from cloudinary.exceptions import Error
from cloudinary.cache.responsive_breakpoints_cache import instance as responsive_breakpoints_cache_instance
from cloudinary.exceptions import Error
from cloudinary.utils import build_eager
try:
from urllib3.contrib.appengine import AppEngineManager, is_appengine_sandbox
@ -24,6 +23,11 @@ try: # Python 2.7+
except ImportError:
from urllib3.packages.ordered_dict import OrderedDict
try: # Python 3.4+
from pathlib import Path as PathLibPathType
except ImportError:
PathLibPathType = None
if is_appengine_sandbox():
# AppEngineManager uses AppEngine's URLFetch API behind the scenes
_http = AppEngineManager()
@ -58,7 +62,12 @@ def upload_image(file, **options):
def upload_resource(file, **options):
result = upload_large(file, **options)
upload_func = upload
if hasattr(file, 'size') and file.size > UPLOAD_LARGE_CHUNK_SIZE:
upload_func = upload_large
result = upload_func(file, **options)
return cloudinary.CloudinaryResource(
result["public_id"], version=str(result["version"]),
format=result.get("format"), type=result["type"],
@ -363,6 +372,39 @@ def text(text, **options):
return call_api("text", params, **options)
_SLIDESHOW_PARAMS = [
"notification_url",
"public_id",
"overwrite",
"upload_preset",
]
def create_slideshow(**options):
"""
Creates auto-generated video slideshows.
:param options: The optional parameters. See the upload API documentation.
:return: a dictionary with details about created slideshow
"""
options["resource_type"] = options.get("resource_type", "video")
params = {param_name: options.get(param_name) for param_name in _SLIDESHOW_PARAMS}
serialized_params = {
"timestamp": utils.now(),
"transformation": build_eager(options.get("transformation")),
"manifest_transformation": build_eager(options.get("manifest_transformation")),
"manifest_json": options.get("manifest_json") and utils.json_encode(options.get("manifest_json")),
"tags": options.get("tags") and utils.encode_list(utils.build_array(options["tags"])),
}
params.update(serialized_params)
return call_api("create_slideshow", params, **options)
def _save_responsive_breakpoints_to_cache(result):
"""
Saves responsive breakpoints parsed from upload result to cache
@ -427,7 +469,10 @@ def call_api(action, params, http_headers=None, return_error=False, unsigned=Fal
if file:
filename = options.get("filename") # Custom filename provided by user (relevant only for streams and files)
if isinstance(file, string_types):
if PathLibPathType and isinstance(file, PathLibPathType):
name = filename or file.name
data = file.read_bytes()
elif isinstance(file, string_types):
if utils.is_remote_url(file):
# URL
name = None

View file

@ -70,6 +70,7 @@ __URL_KEYS = [
__SIMPLE_UPLOAD_PARAMS = [
"public_id",
"public_id_prefix",
"callback",
"format",
"type",
@ -80,6 +81,8 @@ __SIMPLE_UPLOAD_PARAMS = [
"colors",
"use_filename",
"unique_filename",
"display_name",
"use_filename_as_display_name",
"discard_original_filename",
"filename_override",
"invalidate",
@ -89,6 +92,7 @@ __SIMPLE_UPLOAD_PARAMS = [
"eval",
"proxy",
"folder",
"asset_folder",
"overwrite",
"moderation",
"raw_convert",
@ -526,6 +530,9 @@ def process_video_codec_param(param):
out_param = out_param + ':' + param['profile']
if 'level' in param:
out_param = out_param + ':' + param['level']
if param.get('b_frames') is False:
out_param = out_param + ':' + 'bframes_no'
return out_param
@ -1089,6 +1096,10 @@ def build_multi_and_sprite_params(**options):
def __process_text_options(layer, layer_parameter):
text_style = str(layer.get("text_style", ""))
if text_style and not text_style.isspace():
return text_style
font_family = layer.get("font_family")
font_size = layer.get("font_size")
keywords = []
@ -1247,7 +1258,7 @@ PREDEFINED_VARS = {
"context": "ctx"
}
replaceRE = "((\\|\\||>=|<=|&&|!=|>|=|<|/|-|\\+|\\*|\\^)(?=[ _])|(\\$_*[^_ ]+)|(?<!\\$)(" + \
replaceRE = "((\\|\\||>=|<=|&&|!=|>|=|<|/|-|\\+|\\*|\\^)(?=[ _])|(\\$_*[^_ ]+)|(?<![\\$:])(" + \
'|'.join(PREDEFINED_VARS.keys()) + "))"
@ -1531,3 +1542,28 @@ def safe_cast(val, casting_fn, default=None):
return casting_fn(val)
except (ValueError, TypeError):
return default
def __id(x):
"""
Identity function. Returns the passed in values.
"""
return x
def unique(collection, key=None):
"""
Removes duplicates from collection using key function
:param collection: The collection to remove duplicates from
:param key: The function to generate key from each element. If not passed, identity function is used
"""
if key is None:
key = __id
to_return = OrderedDict()
for element in collection:
to_return[key(element)] = element
return list(to_return.values())