mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-06 13:11:15 -07:00
Update cloudinary==1.28.0
This commit is contained in:
parent
0325e9327f
commit
dcfd8abddd
7 changed files with 196 additions and 21 deletions
|
@ -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 """
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue