mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-06 05:01:14 -07:00
Bump cloudinary from 1.34.0 to 1.39.1 (#2283)
* Bump cloudinary from 1.34.0 to 1.39.1 Bumps [cloudinary](https://github.com/cloudinary/pycloudinary) from 1.34.0 to 1.39.1. - [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.34.0...1.39.1) --- 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.39.1 --------- 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:
parent
24fff60ed4
commit
6c6fa34ba4
12 changed files with 349 additions and 110 deletions
|
@ -38,7 +38,7 @@ CL_BLANK = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAA
|
||||||
URI_SCHEME = "cloudinary"
|
URI_SCHEME = "cloudinary"
|
||||||
API_VERSION = "v1_1"
|
API_VERSION = "v1_1"
|
||||||
|
|
||||||
VERSION = "1.34.0"
|
VERSION = "1.39.1"
|
||||||
|
|
||||||
_USER_PLATFORM_DETAILS = "; ".join((platform(), "Python {}".format(python_version())))
|
_USER_PLATFORM_DETAILS = "; ".join((platform(), "Python {}".format(python_version())))
|
||||||
|
|
||||||
|
@ -741,7 +741,11 @@ class CloudinaryResource(object):
|
||||||
:return: Video tag
|
:return: Video tag
|
||||||
"""
|
"""
|
||||||
public_id = options.get('public_id', self.public_id)
|
public_id = options.get('public_id', self.public_id)
|
||||||
source = re.sub(r"\.({0})$".format("|".join(self.default_source_types())), '', public_id)
|
use_fetch_format = options.get('use_fetch_format', config().use_fetch_format)
|
||||||
|
if not use_fetch_format:
|
||||||
|
source = re.sub(r"\.({0})$".format("|".join(self.default_source_types())), '', public_id)
|
||||||
|
else:
|
||||||
|
source = public_id
|
||||||
|
|
||||||
custom_attributes = options.pop("attributes", dict())
|
custom_attributes = options.pop("attributes", dict())
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@ from cloudinary import utils
|
||||||
from cloudinary.api_client.call_api import (
|
from cloudinary.api_client.call_api import (
|
||||||
call_api,
|
call_api,
|
||||||
call_metadata_api,
|
call_metadata_api,
|
||||||
call_json_api
|
call_json_api,
|
||||||
|
_call_v2_api
|
||||||
)
|
)
|
||||||
from cloudinary.exceptions import (
|
from cloudinary.exceptions import (
|
||||||
BadRequest,
|
BadRequest,
|
||||||
|
@ -54,6 +55,19 @@ def usage(**options):
|
||||||
return call_api("get", uri, {}, **options)
|
return call_api("get", uri, {}, **options)
|
||||||
|
|
||||||
|
|
||||||
|
def config(**options):
|
||||||
|
"""
|
||||||
|
Get account config details.
|
||||||
|
|
||||||
|
:param options: Additional options.
|
||||||
|
:type options: dict, optional
|
||||||
|
:return: Detailed config information.
|
||||||
|
:rtype: Response
|
||||||
|
"""
|
||||||
|
params = only(options, "settings")
|
||||||
|
return call_api("get", ["config"], params, **options)
|
||||||
|
|
||||||
|
|
||||||
def resource_types(**options):
|
def resource_types(**options):
|
||||||
return call_api("get", ["resources"], {}, **options)
|
return call_api("get", ["resources"], {}, **options)
|
||||||
|
|
||||||
|
@ -64,24 +78,22 @@ def resources(**options):
|
||||||
uri = ["resources", resource_type]
|
uri = ["resources", resource_type]
|
||||||
if upload_type:
|
if upload_type:
|
||||||
uri.append(upload_type)
|
uri.append(upload_type)
|
||||||
params = only(options, "next_cursor", "max_results", "prefix", "tags",
|
params = __list_resources_params(**options)
|
||||||
"context", "moderations", "direction", "start_at", "metadata")
|
params.update(only(options, "prefix", "start_at"))
|
||||||
return call_api("get", uri, params, **options)
|
return call_api("get", uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
def resources_by_tag(tag, **options):
|
def resources_by_tag(tag, **options):
|
||||||
resource_type = options.pop("resource_type", "image")
|
resource_type = options.pop("resource_type", "image")
|
||||||
uri = ["resources", resource_type, "tags", tag]
|
uri = ["resources", resource_type, "tags", tag]
|
||||||
params = only(options, "next_cursor", "max_results", "tags",
|
params = __list_resources_params(**options)
|
||||||
"context", "moderations", "direction", "metadata")
|
|
||||||
return call_api("get", uri, params, **options)
|
return call_api("get", uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
def resources_by_moderation(kind, status, **options):
|
def resources_by_moderation(kind, status, **options):
|
||||||
resource_type = options.pop("resource_type", "image")
|
resource_type = options.pop("resource_type", "image")
|
||||||
uri = ["resources", resource_type, "moderations", kind, status]
|
uri = ["resources", resource_type, "moderations", kind, status]
|
||||||
params = only(options, "next_cursor", "max_results", "tags",
|
params = __list_resources_params(**options)
|
||||||
"context", "moderations", "direction", "metadata")
|
|
||||||
return call_api("get", uri, params, **options)
|
return call_api("get", uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,7 +101,7 @@ def resources_by_ids(public_ids, **options):
|
||||||
resource_type = options.pop("resource_type", "image")
|
resource_type = options.pop("resource_type", "image")
|
||||||
upload_type = options.pop("type", "upload")
|
upload_type = options.pop("type", "upload")
|
||||||
uri = ["resources", resource_type, upload_type]
|
uri = ["resources", resource_type, upload_type]
|
||||||
params = dict(only(options, "tags", "moderations", "context"), public_ids=public_ids)
|
params = dict(__resources_params(**options), public_ids=public_ids)
|
||||||
return call_api("get", uri, params, **options)
|
return call_api("get", uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,7 +117,7 @@ def resources_by_asset_folder(asset_folder, **options):
|
||||||
:rtype: Response
|
:rtype: Response
|
||||||
"""
|
"""
|
||||||
uri = ["resources", "by_asset_folder"]
|
uri = ["resources", "by_asset_folder"]
|
||||||
params = only(options, "max_results", "tags", "moderations", "context", "next_cursor")
|
params = __list_resources_params(**options)
|
||||||
params["asset_folder"] = asset_folder
|
params["asset_folder"] = asset_folder
|
||||||
return call_api("get", uri, params, **options)
|
return call_api("get", uri, params, **options)
|
||||||
|
|
||||||
|
@ -125,7 +137,7 @@ def resources_by_asset_ids(asset_ids, **options):
|
||||||
:rtype: Response
|
:rtype: Response
|
||||||
"""
|
"""
|
||||||
uri = ["resources", 'by_asset_ids']
|
uri = ["resources", 'by_asset_ids']
|
||||||
params = dict(only(options, "tags", "moderations", "context"), asset_ids=asset_ids)
|
params = dict(__resources_params(**options), asset_ids=asset_ids)
|
||||||
return call_api("get", uri, params, **options)
|
return call_api("get", uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,15 +159,43 @@ def resources_by_context(key, value=None, **options):
|
||||||
"""
|
"""
|
||||||
resource_type = options.pop("resource_type", "image")
|
resource_type = options.pop("resource_type", "image")
|
||||||
uri = ["resources", resource_type, "context"]
|
uri = ["resources", resource_type, "context"]
|
||||||
params = only(options, "next_cursor", "max_results", "tags",
|
params = __list_resources_params(**options)
|
||||||
"context", "moderations", "direction", "metadata")
|
|
||||||
params["key"] = key
|
params["key"] = key
|
||||||
if value is not None:
|
if value is not None:
|
||||||
params["value"] = value
|
params["value"] = value
|
||||||
return call_api("get", uri, params, **options)
|
return call_api("get", uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
def visual_search(image_url=None, image_asset_id=None, text=None, **options):
|
def __resources_params(**options):
|
||||||
|
"""
|
||||||
|
Prepares optional parameters for resources_* API calls.
|
||||||
|
|
||||||
|
:param options: Additional options
|
||||||
|
:return: Optional parameters
|
||||||
|
|
||||||
|
:internal
|
||||||
|
"""
|
||||||
|
params = only(options, "tags", "context", "metadata", "moderations")
|
||||||
|
params["fields"] = options.get("fields") and utils.encode_list(utils.build_array(options["fields"]))
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
def __list_resources_params(**options):
|
||||||
|
"""
|
||||||
|
Prepares optional parameters for resources_* API calls.
|
||||||
|
|
||||||
|
:param options: Additional options
|
||||||
|
:return: Optional parameters
|
||||||
|
|
||||||
|
:internal
|
||||||
|
"""
|
||||||
|
resources_params = __resources_params(**options)
|
||||||
|
resources_params.update(only(options, "next_cursor", "max_results", "direction"))
|
||||||
|
|
||||||
|
return resources_params
|
||||||
|
|
||||||
|
|
||||||
|
def visual_search(image_url=None, image_asset_id=None, text=None, image_file=None, **options):
|
||||||
"""
|
"""
|
||||||
Find images based on their visual content.
|
Find images based on their visual content.
|
||||||
|
|
||||||
|
@ -165,14 +205,17 @@ def visual_search(image_url=None, image_asset_id=None, text=None, **options):
|
||||||
:type image_asset_id: str
|
:type image_asset_id: str
|
||||||
:param text: A textual description, e.g., "cat"
|
:param text: A textual description, e.g., "cat"
|
||||||
:type text: str
|
:type text: str
|
||||||
|
:param image_file: The image file.
|
||||||
|
:type image_file: str|callable|Path|bytes
|
||||||
:param options: Additional options
|
:param options: Additional options
|
||||||
:type options: dict, optional
|
:type options: dict, optional
|
||||||
:return: Resources (assets) that were found
|
:return: Resources (assets) that were found
|
||||||
:rtype: Response
|
:rtype: Response
|
||||||
"""
|
"""
|
||||||
uri = ["resources", "visual_search"]
|
uri = ["resources", "visual_search"]
|
||||||
params = {"image_url": image_url, "image_asset_id": image_asset_id, "text": text}
|
params = {"image_url": image_url, "image_asset_id": image_asset_id, "text": text,
|
||||||
return call_api("get", uri, params, **options)
|
"image_file": utils.handle_file_parameter(image_file, "file")}
|
||||||
|
return call_api("post", uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
def resource(public_id, **options):
|
def resource(public_id, **options):
|
||||||
|
@ -224,11 +267,11 @@ def update(public_id, **options):
|
||||||
if "tags" in options:
|
if "tags" in options:
|
||||||
params["tags"] = ",".join(utils.build_array(options["tags"]))
|
params["tags"] = ",".join(utils.build_array(options["tags"]))
|
||||||
if "face_coordinates" in options:
|
if "face_coordinates" in options:
|
||||||
params["face_coordinates"] = utils.encode_double_array(
|
params["face_coordinates"] = utils.encode_double_array(options.get("face_coordinates"))
|
||||||
options.get("face_coordinates"))
|
|
||||||
if "custom_coordinates" in options:
|
if "custom_coordinates" in options:
|
||||||
params["custom_coordinates"] = utils.encode_double_array(
|
params["custom_coordinates"] = utils.encode_double_array(options.get("custom_coordinates"))
|
||||||
options.get("custom_coordinates"))
|
if "regions" in options:
|
||||||
|
params["regions"] = utils.json_encode(options.get("regions"))
|
||||||
if "context" in options:
|
if "context" in options:
|
||||||
params["context"] = utils.encode_context(options.get("context"))
|
params["context"] = utils.encode_context(options.get("context"))
|
||||||
if "metadata" in options:
|
if "metadata" in options:
|
||||||
|
@ -656,9 +699,8 @@ def add_metadata_field(field, **options):
|
||||||
|
|
||||||
:rtype: Response
|
:rtype: Response
|
||||||
"""
|
"""
|
||||||
params = only(field, "type", "external_id", "label", "mandatory",
|
|
||||||
"default_value", "validation", "datasource")
|
return call_metadata_api("post", [], __metadata_field_params(field), **options)
|
||||||
return call_metadata_api("post", [], params, **options)
|
|
||||||
|
|
||||||
|
|
||||||
def update_metadata_field(field_external_id, field, **options):
|
def update_metadata_field(field_external_id, field, **options):
|
||||||
|
@ -677,8 +719,13 @@ def update_metadata_field(field_external_id, field, **options):
|
||||||
:rtype: Response
|
:rtype: Response
|
||||||
"""
|
"""
|
||||||
uri = [field_external_id]
|
uri = [field_external_id]
|
||||||
params = only(field, "label", "mandatory", "default_value", "validation")
|
|
||||||
return call_metadata_api("put", uri, params, **options)
|
return call_metadata_api("put", uri, __metadata_field_params(field), **options)
|
||||||
|
|
||||||
|
|
||||||
|
def __metadata_field_params(field):
|
||||||
|
return only(field, "type", "external_id", "label", "mandatory", "restrictions",
|
||||||
|
"default_value", "validation", "datasource")
|
||||||
|
|
||||||
|
|
||||||
def delete_metadata_field(field_external_id, **options):
|
def delete_metadata_field(field_external_id, **options):
|
||||||
|
@ -798,3 +845,18 @@ def reorder_metadata_fields(order_by, direction=None, **options):
|
||||||
uri = ['order']
|
uri = ['order']
|
||||||
params = {'order_by': order_by, 'direction': direction}
|
params = {'order_by': order_by, 'direction': direction}
|
||||||
return call_metadata_api('put', uri, params, **options)
|
return call_metadata_api('put', uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
|
def analyze(input_type, analysis_type, uri=None, **options):
|
||||||
|
"""Analyzes an asset with the requested analysis type.
|
||||||
|
|
||||||
|
:param input_type: The type of input for the asset to analyze ('uri').
|
||||||
|
:param analysis_type: The type of analysis to run ('google_tagging', 'captioning', 'fashion').
|
||||||
|
:param uri: The URI of the asset to analyze.
|
||||||
|
:param options: Additional options.
|
||||||
|
|
||||||
|
:rtype: Response
|
||||||
|
"""
|
||||||
|
api_uri = ['analysis', 'analyze', input_type]
|
||||||
|
params = {'analysis_type': analysis_type, 'uri': uri, 'parameters': options.get("parameters")}
|
||||||
|
return _call_v2_api('post', api_uri, params, **options)
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import cloudinary
|
import cloudinary
|
||||||
from cloudinary.api_client.execute_request import execute_request
|
from cloudinary.api_client.execute_request import execute_request
|
||||||
from cloudinary.provisioning.account_config import account_config
|
from cloudinary.provisioning.account_config import account_config
|
||||||
from cloudinary.utils import get_http_connector
|
from cloudinary.utils import get_http_connector, normalize_params
|
||||||
|
|
||||||
|
|
||||||
PROVISIONING_SUB_PATH = "provisioning"
|
PROVISIONING_SUB_PATH = "provisioning"
|
||||||
ACCOUNT_SUB_PATH = "accounts"
|
ACCOUNT_SUB_PATH = "accounts"
|
||||||
|
@ -28,7 +27,7 @@ def _call_account_api(method, uri, params=None, headers=None, **options):
|
||||||
|
|
||||||
return execute_request(http_connector=_http,
|
return execute_request(http_connector=_http,
|
||||||
method=method,
|
method=method,
|
||||||
params=params,
|
params=normalize_params(params),
|
||||||
headers=headers,
|
headers=headers,
|
||||||
auth=auth,
|
auth=auth,
|
||||||
api_url=provisioning_api_url,
|
api_url=provisioning_api_url,
|
||||||
|
|
|
@ -2,8 +2,7 @@ import json
|
||||||
|
|
||||||
import cloudinary
|
import cloudinary
|
||||||
from cloudinary.api_client.execute_request import execute_request
|
from cloudinary.api_client.execute_request import execute_request
|
||||||
from cloudinary.utils import get_http_connector
|
from cloudinary.utils import get_http_connector, normalize_params
|
||||||
|
|
||||||
|
|
||||||
logger = cloudinary.logger
|
logger = cloudinary.logger
|
||||||
_http = get_http_connector(cloudinary.config(), cloudinary.CERT_KWARGS)
|
_http = get_http_connector(cloudinary.config(), cloudinary.CERT_KWARGS)
|
||||||
|
@ -27,6 +26,10 @@ def call_json_api(method, uri, json_body, **options):
|
||||||
return _call_api(method, uri, body=data, headers={'Content-Type': 'application/json'}, **options)
|
return _call_api(method, uri, body=data, headers={'Content-Type': 'application/json'}, **options)
|
||||||
|
|
||||||
|
|
||||||
|
def _call_v2_api(method, uri, json_body, **options):
|
||||||
|
return call_json_api(method, uri, json_body=json_body, api_version='v2', **options)
|
||||||
|
|
||||||
|
|
||||||
def call_api(method, uri, params, **options):
|
def call_api(method, uri, params, **options):
|
||||||
return _call_api(method, uri, params=params, **options)
|
return _call_api(method, uri, params=params, **options)
|
||||||
|
|
||||||
|
@ -43,10 +46,11 @@ def _call_api(method, uri, params=None, body=None, headers=None, extra_headers=N
|
||||||
oauth_token = options.pop("oauth_token", cloudinary.config().oauth_token)
|
oauth_token = options.pop("oauth_token", cloudinary.config().oauth_token)
|
||||||
|
|
||||||
_validate_authorization(api_key, api_secret, oauth_token)
|
_validate_authorization(api_key, api_secret, oauth_token)
|
||||||
|
|
||||||
api_url = "/".join([prefix, cloudinary.API_VERSION, cloud_name] + uri)
|
|
||||||
auth = {"key": api_key, "secret": api_secret, "oauth_token": oauth_token}
|
auth = {"key": api_key, "secret": api_secret, "oauth_token": oauth_token}
|
||||||
|
|
||||||
|
api_version = options.pop("api_version", cloudinary.API_VERSION)
|
||||||
|
api_url = "/".join([prefix, api_version, cloud_name] + uri)
|
||||||
|
|
||||||
if body is not None:
|
if body is not None:
|
||||||
options["body"] = body
|
options["body"] = body
|
||||||
|
|
||||||
|
@ -55,7 +59,7 @@ def _call_api(method, uri, params=None, body=None, headers=None, extra_headers=N
|
||||||
|
|
||||||
return execute_request(http_connector=_http,
|
return execute_request(http_connector=_http,
|
||||||
method=method,
|
method=method,
|
||||||
params=params,
|
params=normalize_params(params),
|
||||||
headers=headers,
|
headers=headers,
|
||||||
auth=auth,
|
auth=auth,
|
||||||
api_url=api_url,
|
api_url=api_url,
|
||||||
|
|
|
@ -63,9 +63,8 @@ def execute_request(http_connector, method, params, headers, auth, api_url, **op
|
||||||
processed_params = process_params(params)
|
processed_params = process_params(params)
|
||||||
|
|
||||||
api_url = smart_escape(unquote(api_url))
|
api_url = smart_escape(unquote(api_url))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = http_connector.request(method.upper(), api_url, processed_params, req_headers, **kw)
|
response = http_connector.request(method=method.upper(), url=api_url, fields=processed_params, headers=req_headers, **kw)
|
||||||
body = response.data
|
body = response.data
|
||||||
except HTTPError as e:
|
except HTTPError as e:
|
||||||
raise GeneralError("Unexpected error %s" % str(e))
|
raise GeneralError("Unexpected error %s" % str(e))
|
||||||
|
|
|
@ -24,7 +24,7 @@ class HttpClient:
|
||||||
|
|
||||||
def get_json(self, url):
|
def get_json(self, url):
|
||||||
try:
|
try:
|
||||||
response = self._http_client.request("GET", url, timeout=self.timeout)
|
response = self._http_client.request(method="GET", url=url, timeout=self.timeout)
|
||||||
body = response.data
|
body = response.data
|
||||||
except HTTPError as e:
|
except HTTPError as e:
|
||||||
raise GeneralError("Unexpected error %s" % str(e))
|
raise GeneralError("Unexpected error %s" % str(e))
|
||||||
|
|
|
@ -2,4 +2,5 @@ from .account_config import AccountConfig, account_config, reset_config
|
||||||
from .account import (sub_accounts, create_sub_account, delete_sub_account, sub_account, update_sub_account,
|
from .account import (sub_accounts, create_sub_account, delete_sub_account, sub_account, update_sub_account,
|
||||||
user_groups, create_user_group, update_user_group, delete_user_group, user_group,
|
user_groups, create_user_group, update_user_group, delete_user_group, user_group,
|
||||||
add_user_to_group, remove_user_from_group, user_group_users, user_in_user_groups,
|
add_user_to_group, remove_user_from_group, user_group_users, user_in_user_groups,
|
||||||
users, create_user, delete_user, user, update_user, Role)
|
users, create_user, delete_user, user, update_user, access_keys, generate_access_key,
|
||||||
|
update_access_key, delete_access_key, Role)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from cloudinary.api_client.call_account_api import _call_account_api
|
from cloudinary.api_client.call_account_api import _call_account_api
|
||||||
from cloudinary.utils import encode_list
|
from cloudinary.utils import encode_list
|
||||||
|
|
||||||
|
|
||||||
SUB_ACCOUNTS_SUB_PATH = "sub_accounts"
|
SUB_ACCOUNTS_SUB_PATH = "sub_accounts"
|
||||||
USERS_SUB_PATH = "users"
|
USERS_SUB_PATH = "users"
|
||||||
USER_GROUPS_SUB_PATH = "user_groups"
|
USER_GROUPS_SUB_PATH = "user_groups"
|
||||||
|
ACCESS_KEYS = "access_keys"
|
||||||
|
|
||||||
|
|
||||||
class Role(object):
|
class Role(object):
|
||||||
|
@ -123,7 +123,8 @@ def update_sub_account(sub_account_id, name=None, cloud_name=None, custom_attrib
|
||||||
return _call_account_api("put", uri, params=params, **options)
|
return _call_account_api("put", uri, params=params, **options)
|
||||||
|
|
||||||
|
|
||||||
def users(user_ids=None, sub_account_id=None, pending=None, prefix=None, **options):
|
def users(user_ids=None, sub_account_id=None, pending=None, prefix=None, last_login=None, from_date=None, to_date=None,
|
||||||
|
**options):
|
||||||
"""
|
"""
|
||||||
List all users
|
List all users
|
||||||
:param user_ids: The ids of the users to fetch
|
:param user_ids: The ids of the users to fetch
|
||||||
|
@ -136,6 +137,13 @@ def users(user_ids=None, sub_account_id=None, pending=None, prefix=None, **optio
|
||||||
:type pending: bool, optional
|
:type pending: bool, optional
|
||||||
:param prefix: User prefix
|
:param prefix: User prefix
|
||||||
:type prefix: str, optional
|
:type prefix: str, optional
|
||||||
|
:param last_login: Return only users that last logged in in the specified range of dates (true),
|
||||||
|
users that didn't last logged in in that range (false), or all users (None).
|
||||||
|
:type last_login: bool, optional
|
||||||
|
:param from_date: Last login start date.
|
||||||
|
:type from_date: datetime, optional
|
||||||
|
:param to_date: Last login end date.
|
||||||
|
:type to_date: datetime, optional
|
||||||
:param options: Generic advanced options dict, see online documentation.
|
:param options: Generic advanced options dict, see online documentation.
|
||||||
:type options: dict, optional
|
:type options: dict, optional
|
||||||
:return: List of users associated with the account
|
:return: List of users associated with the account
|
||||||
|
@ -146,7 +154,10 @@ def users(user_ids=None, sub_account_id=None, pending=None, prefix=None, **optio
|
||||||
params = {"ids": user_ids,
|
params = {"ids": user_ids,
|
||||||
"sub_account_id": sub_account_id,
|
"sub_account_id": sub_account_id,
|
||||||
"pending": pending,
|
"pending": pending,
|
||||||
"prefix": prefix}
|
"prefix": prefix,
|
||||||
|
"last_login": last_login,
|
||||||
|
"from": from_date,
|
||||||
|
"to": to_date}
|
||||||
return _call_account_api("get", uri, params=params, **options)
|
return _call_account_api("get", uri, params=params, **options)
|
||||||
|
|
||||||
|
|
||||||
|
@ -351,7 +362,7 @@ def user_in_user_groups(user_id, **options):
|
||||||
"""
|
"""
|
||||||
Get all user groups a user belongs to
|
Get all user groups a user belongs to
|
||||||
:param user_id: The id of user
|
:param user_id: The id of user
|
||||||
:param user_id: str
|
:type user_id: str
|
||||||
:param options: Generic advanced options dict, see online documentation
|
:param options: Generic advanced options dict, see online documentation
|
||||||
:type options: dict, optional
|
:type options: dict, optional
|
||||||
:return: List of groups user is in
|
:return: List of groups user is in
|
||||||
|
@ -359,3 +370,112 @@ def user_in_user_groups(user_id, **options):
|
||||||
"""
|
"""
|
||||||
uri = [USER_GROUPS_SUB_PATH, user_id]
|
uri = [USER_GROUPS_SUB_PATH, user_id]
|
||||||
return _call_account_api("get", uri, {}, **options)
|
return _call_account_api("get", uri, {}, **options)
|
||||||
|
|
||||||
|
|
||||||
|
def access_keys(sub_account_id, page_size=None, page=None, sort_by=None, sort_order=None, **options):
|
||||||
|
"""
|
||||||
|
Get sub account access keys.
|
||||||
|
|
||||||
|
:param sub_account_id: The id of the sub account.
|
||||||
|
:type sub_account_id: str
|
||||||
|
:param page_size: How many entries to display on each page.
|
||||||
|
:type page_size: int
|
||||||
|
:param page: Which page to return (maximum pages: 100). **Default**: All pages are returned.
|
||||||
|
:type page: int
|
||||||
|
:param sort_by: Which response parameter to sort by.
|
||||||
|
**Possible values**: `api_key`, `created_at`, `name`, `enabled`.
|
||||||
|
:type sort_by: str
|
||||||
|
:param sort_order: Control the order of returned keys. **Possible values**: `desc` (default), `asc`.
|
||||||
|
:type sort_order: str
|
||||||
|
:param options: Generic advanced options dict, see online documentation.
|
||||||
|
:type options: dict, optional
|
||||||
|
:return: List of access keys
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
uri = [SUB_ACCOUNTS_SUB_PATH, sub_account_id, ACCESS_KEYS]
|
||||||
|
params = {
|
||||||
|
"page_size": page_size,
|
||||||
|
"page": page,
|
||||||
|
"sort_by": sort_by,
|
||||||
|
"sort_order": sort_order,
|
||||||
|
}
|
||||||
|
return _call_account_api("get", uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_access_key(sub_account_id, name=None, enabled=None, **options):
|
||||||
|
"""
|
||||||
|
Generate a new access key.
|
||||||
|
|
||||||
|
:param sub_account_id: The id of the sub account.
|
||||||
|
:type sub_account_id: str
|
||||||
|
:param name: The name of the new access key.
|
||||||
|
:type name: str
|
||||||
|
:param enabled: Whether the new access key is enabled or disabled.
|
||||||
|
:type enabled: bool
|
||||||
|
:param options: Generic advanced options dict, see online documentation.
|
||||||
|
:type options: dict, optional
|
||||||
|
:return: Access key details
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
uri = [SUB_ACCOUNTS_SUB_PATH, sub_account_id, ACCESS_KEYS]
|
||||||
|
params = {
|
||||||
|
"name": name,
|
||||||
|
"enabled": enabled,
|
||||||
|
}
|
||||||
|
return _call_account_api("post", uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
|
def update_access_key(sub_account_id, api_key, name=None, enabled=None, dedicated_for=None, **options):
|
||||||
|
"""
|
||||||
|
Update the name and/or status of an existing access key.
|
||||||
|
|
||||||
|
:param sub_account_id: The id of the sub account.
|
||||||
|
:type sub_account_id: str
|
||||||
|
:param api_key: The API key of the access key.
|
||||||
|
:type api_key: str|int
|
||||||
|
:param name: The updated name of the access key.
|
||||||
|
:type name: str
|
||||||
|
:param enabled: Enable or disable the access key.
|
||||||
|
:type enabled: bool
|
||||||
|
:param dedicated_for: Designates the access key for a specific purpose while allowing it to be used for
|
||||||
|
other purposes, as well. This action replaces any previously assigned key.
|
||||||
|
**Possible values**: `webhooks`
|
||||||
|
:type dedicated_for: str
|
||||||
|
:param options: Generic advanced options dict, see online documentation.
|
||||||
|
:type options: dict, optional
|
||||||
|
:return: Access key details
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
uri = [SUB_ACCOUNTS_SUB_PATH, sub_account_id, ACCESS_KEYS, str(api_key)]
|
||||||
|
params = {
|
||||||
|
"name": name,
|
||||||
|
"enabled": enabled,
|
||||||
|
"dedicated_for": dedicated_for,
|
||||||
|
}
|
||||||
|
return _call_account_api("put", uri, params, **options)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_access_key(sub_account_id, api_key=None, name=None, **options):
|
||||||
|
"""
|
||||||
|
Delete an existing access key by api_key or by name.
|
||||||
|
|
||||||
|
:param sub_account_id: The id of the sub account.
|
||||||
|
:type sub_account_id: str
|
||||||
|
:param api_key: The API key of the access key.
|
||||||
|
:type api_key: str|int
|
||||||
|
:param name: The name of the access key.
|
||||||
|
:type name: str
|
||||||
|
:param options: Generic advanced options dict, see online documentation.
|
||||||
|
:type options: dict, optional
|
||||||
|
:return: Operation status.
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
uri = [SUB_ACCOUNTS_SUB_PATH, sub_account_id, ACCESS_KEYS]
|
||||||
|
|
||||||
|
if api_key is not None:
|
||||||
|
uri.append(str(api_key))
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"name": name
|
||||||
|
}
|
||||||
|
return _call_account_api("delete", uri, params, **options)
|
||||||
|
|
|
@ -3,8 +3,8 @@ import json
|
||||||
|
|
||||||
import cloudinary
|
import cloudinary
|
||||||
from cloudinary.api_client.call_api import call_json_api
|
from cloudinary.api_client.call_api import call_json_api
|
||||||
from cloudinary.utils import unique, unsigned_download_url_prefix, build_distribution_domain, base64url_encode, \
|
from cloudinary.utils import (unique, build_distribution_domain, base64url_encode, json_encode, compute_hex_hash,
|
||||||
json_encode, compute_hex_hash, SIGNATURE_SHA256
|
SIGNATURE_SHA256, build_array)
|
||||||
|
|
||||||
|
|
||||||
class Search(object):
|
class Search(object):
|
||||||
|
@ -16,6 +16,7 @@ class Search(object):
|
||||||
'sort_by': lambda x: next(iter(x)),
|
'sort_by': lambda x: next(iter(x)),
|
||||||
'aggregate': None,
|
'aggregate': None,
|
||||||
'with_field': None,
|
'with_field': None,
|
||||||
|
'fields': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
_ttl = 300 # Used for search URLs
|
_ttl = 300 # Used for search URLs
|
||||||
|
@ -57,6 +58,11 @@ class Search(object):
|
||||||
self._add("with_field", value)
|
self._add("with_field", value)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def fields(self, value):
|
||||||
|
"""Request which fields to return in the result set."""
|
||||||
|
self._add("fields", value)
|
||||||
|
return self
|
||||||
|
|
||||||
def ttl(self, ttl):
|
def ttl(self, ttl):
|
||||||
"""
|
"""
|
||||||
Sets the time to live of the search URL.
|
Sets the time to live of the search URL.
|
||||||
|
@ -133,5 +139,5 @@ class Search(object):
|
||||||
def _add(self, name, value):
|
def _add(self, name, value):
|
||||||
if name not in self.query:
|
if name not in self.query:
|
||||||
self.query[name] = []
|
self.query[name] = []
|
||||||
self.query[name].append(value)
|
self.query[name].extend(build_array(value))
|
||||||
return self
|
return self
|
||||||
|
|
|
@ -23,11 +23,6 @@ try: # Python 2.7+
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from urllib3.packages.ordered_dict import OrderedDict
|
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():
|
if is_appengine_sandbox():
|
||||||
# AppEngineManager uses AppEngine's URLFetch API behind the scenes
|
# AppEngineManager uses AppEngine's URLFetch API behind the scenes
|
||||||
_http = AppEngineManager()
|
_http = AppEngineManager()
|
||||||
|
@ -503,32 +498,7 @@ def call_api(action, params, http_headers=None, return_error=False, unsigned=Fal
|
||||||
|
|
||||||
if file:
|
if file:
|
||||||
filename = options.get("filename") # Custom filename provided by user (relevant only for streams and files)
|
filename = options.get("filename") # Custom filename provided by user (relevant only for streams and files)
|
||||||
|
param_list.append(("file", utils.handle_file_parameter(file, filename)))
|
||||||
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
|
|
||||||
data = file
|
|
||||||
else:
|
|
||||||
# file path
|
|
||||||
name = filename or file
|
|
||||||
with open(file, "rb") as opened:
|
|
||||||
data = opened.read()
|
|
||||||
elif hasattr(file, 'read') and callable(file.read):
|
|
||||||
# stream
|
|
||||||
data = file.read()
|
|
||||||
name = filename or (file.name if hasattr(file, 'name') and isinstance(file.name, str) else "stream")
|
|
||||||
elif isinstance(file, tuple):
|
|
||||||
name, data = file
|
|
||||||
else:
|
|
||||||
# Not a string, not a stream
|
|
||||||
name = filename or "file"
|
|
||||||
data = file
|
|
||||||
|
|
||||||
param_list.append(("file", (name, data) if name else data))
|
|
||||||
|
|
||||||
kw = {}
|
kw = {}
|
||||||
if timeout is not None:
|
if timeout is not None:
|
||||||
|
@ -536,7 +506,7 @@ def call_api(action, params, http_headers=None, return_error=False, unsigned=Fal
|
||||||
|
|
||||||
code = 200
|
code = 200
|
||||||
try:
|
try:
|
||||||
response = _http.request("POST", api_url, param_list, headers, **kw)
|
response = _http.request(method="POST", url=api_url, fields=param_list, headers=headers, **kw)
|
||||||
except HTTPError as e:
|
except HTTPError as e:
|
||||||
raise Error("Unexpected error - {0!r}".format(e))
|
raise Error("Unexpected error - {0!r}".format(e))
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
|
|
|
@ -25,6 +25,11 @@ from cloudinary import auth_token
|
||||||
from cloudinary.api_client.tcp_keep_alive_manager import TCPKeepAlivePoolManager, TCPKeepAliveProxyManager
|
from cloudinary.api_client.tcp_keep_alive_manager import TCPKeepAlivePoolManager, TCPKeepAliveProxyManager
|
||||||
from cloudinary.compat import PY3, to_bytes, to_bytearray, to_string, string_types, urlparse
|
from cloudinary.compat import PY3, to_bytes, to_bytearray, to_string, string_types, urlparse
|
||||||
|
|
||||||
|
try: # Python 3.4+
|
||||||
|
from pathlib import Path as PathLibPathType
|
||||||
|
except ImportError:
|
||||||
|
PathLibPathType = None
|
||||||
|
|
||||||
VAR_NAME_RE = r'(\$\([a-zA-Z]\w+\))'
|
VAR_NAME_RE = r'(\$\([a-zA-Z]\w+\))'
|
||||||
|
|
||||||
urlencode = six.moves.urllib.parse.urlencode
|
urlencode = six.moves.urllib.parse.urlencode
|
||||||
|
@ -127,6 +132,7 @@ __SERIALIZED_UPLOAD_PARAMS = [
|
||||||
"allowed_formats",
|
"allowed_formats",
|
||||||
"face_coordinates",
|
"face_coordinates",
|
||||||
"custom_coordinates",
|
"custom_coordinates",
|
||||||
|
"regions",
|
||||||
"context",
|
"context",
|
||||||
"auto_tagging",
|
"auto_tagging",
|
||||||
"responsive_breakpoints",
|
"responsive_breakpoints",
|
||||||
|
@ -181,12 +187,11 @@ def compute_hex_hash(s, algorithm=SIGNATURE_SHA1):
|
||||||
|
|
||||||
|
|
||||||
def build_array(arg):
|
def build_array(arg):
|
||||||
if isinstance(arg, list):
|
if isinstance(arg, (list, tuple)):
|
||||||
return arg
|
return arg
|
||||||
elif arg is None:
|
elif arg is None:
|
||||||
return []
|
return []
|
||||||
else:
|
return [arg]
|
||||||
return [arg]
|
|
||||||
|
|
||||||
|
|
||||||
def build_list_of_dicts(val):
|
def build_list_of_dicts(val):
|
||||||
|
@ -235,8 +240,7 @@ def encode_double_array(array):
|
||||||
array = build_array(array)
|
array = build_array(array)
|
||||||
if len(array) > 0 and isinstance(array[0], list):
|
if len(array) > 0 and isinstance(array[0], list):
|
||||||
return "|".join([",".join([str(i) for i in build_array(inner)]) for inner in array])
|
return "|".join([",".join([str(i) for i in build_array(inner)]) for inner in array])
|
||||||
else:
|
return encode_list([str(i) for i in array])
|
||||||
return encode_list([str(i) for i in array])
|
|
||||||
|
|
||||||
|
|
||||||
def encode_dict(arg):
|
def encode_dict(arg):
|
||||||
|
@ -246,8 +250,7 @@ def encode_dict(arg):
|
||||||
else:
|
else:
|
||||||
items = arg.iteritems()
|
items = arg.iteritems()
|
||||||
return "|".join((k + "=" + v) for k, v in items)
|
return "|".join((k + "=" + v) for k, v in items)
|
||||||
else:
|
return arg
|
||||||
return arg
|
|
||||||
|
|
||||||
|
|
||||||
def normalize_context_value(value):
|
def normalize_context_value(value):
|
||||||
|
@ -288,9 +291,14 @@ def json_encode(value, sort_keys=False):
|
||||||
Converts value to a json encoded string
|
Converts value to a json encoded string
|
||||||
|
|
||||||
:param value: value to be encoded
|
:param value: value to be encoded
|
||||||
|
:param sort_keys: whether to sort keys
|
||||||
|
|
||||||
:return: JSON encoded string
|
:return: JSON encoded string
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if isinstance(value, str) or value is None:
|
||||||
|
return value
|
||||||
|
|
||||||
return json.dumps(value, default=__json_serializer, separators=(',', ':'), sort_keys=sort_keys)
|
return json.dumps(value, default=__json_serializer, separators=(',', ':'), sort_keys=sort_keys)
|
||||||
|
|
||||||
|
|
||||||
|
@ -309,11 +317,13 @@ def patch_fetch_format(options):
|
||||||
"""
|
"""
|
||||||
When upload type is fetch, remove the format options.
|
When upload type is fetch, remove the format options.
|
||||||
In addition, set the fetch_format options to the format value unless it was already set.
|
In addition, set the fetch_format options to the format value unless it was already set.
|
||||||
Mutates the options parameter!
|
Mutates the "options" parameter!
|
||||||
|
|
||||||
:param options: URL and transformation options
|
:param options: URL and transformation options
|
||||||
"""
|
"""
|
||||||
if options.get("type", "upload") != "fetch":
|
use_fetch_format = options.pop("use_fetch_format", cloudinary.config().use_fetch_format)
|
||||||
|
|
||||||
|
if options.get("type", "upload") != "fetch" and not use_fetch_format:
|
||||||
return
|
return
|
||||||
|
|
||||||
resource_format = options.pop("format", None)
|
resource_format = options.pop("format", None)
|
||||||
|
@ -351,8 +361,7 @@ def generate_transformation_string(**options):
|
||||||
def recurse(bs):
|
def recurse(bs):
|
||||||
if isinstance(bs, dict):
|
if isinstance(bs, dict):
|
||||||
return generate_transformation_string(**bs)[0]
|
return generate_transformation_string(**bs)[0]
|
||||||
else:
|
return generate_transformation_string(transformation=bs)[0]
|
||||||
return generate_transformation_string(transformation=bs)[0]
|
|
||||||
|
|
||||||
base_transformations = list(map(recurse, base_transformations))
|
base_transformations = list(map(recurse, base_transformations))
|
||||||
named_transformation = None
|
named_transformation = None
|
||||||
|
@ -375,7 +384,7 @@ def generate_transformation_string(**options):
|
||||||
flags = ".".join(build_array(options.pop("flags", None)))
|
flags = ".".join(build_array(options.pop("flags", None)))
|
||||||
dpr = options.pop("dpr", cloudinary.config().dpr)
|
dpr = options.pop("dpr", cloudinary.config().dpr)
|
||||||
duration = norm_range_value(options.pop("duration", None))
|
duration = norm_range_value(options.pop("duration", None))
|
||||||
|
|
||||||
so_raw = options.pop("start_offset", None)
|
so_raw = options.pop("start_offset", None)
|
||||||
start_offset = norm_auto_range_value(so_raw)
|
start_offset = norm_auto_range_value(so_raw)
|
||||||
if start_offset == None:
|
if start_offset == None:
|
||||||
|
@ -513,8 +522,7 @@ def split_range(range):
|
||||||
return [range[0], range[-1]]
|
return [range[0], range[-1]]
|
||||||
elif isinstance(range, string_types) and re.match(RANGE_RE, range):
|
elif isinstance(range, string_types) and re.match(RANGE_RE, range):
|
||||||
return range.split("..", 1)
|
return range.split("..", 1)
|
||||||
else:
|
return None
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def norm_range_value(value):
|
def norm_range_value(value):
|
||||||
|
@ -570,6 +578,9 @@ def process_params(params):
|
||||||
processed_params = {}
|
processed_params = {}
|
||||||
for key, value in params.items():
|
for key, value in params.items():
|
||||||
if isinstance(value, list) or isinstance(value, tuple):
|
if isinstance(value, list) or isinstance(value, tuple):
|
||||||
|
if len(value) == 2 and value[0] == "file": # keep file parameter as is.
|
||||||
|
processed_params[key] = value
|
||||||
|
continue
|
||||||
value_list = {"{}[{}]".format(key, i): i_value for i, i_value in enumerate(value)}
|
value_list = {"{}[{}]".format(key, i): i_value for i, i_value in enumerate(value)}
|
||||||
processed_params.update(value_list)
|
processed_params.update(value_list)
|
||||||
elif value is not None:
|
elif value is not None:
|
||||||
|
@ -578,9 +589,28 @@ def process_params(params):
|
||||||
|
|
||||||
|
|
||||||
def cleanup_params(params):
|
def cleanup_params(params):
|
||||||
|
"""
|
||||||
|
Cleans and normalizes parameters when calculating signature in Upload API.
|
||||||
|
|
||||||
|
:param params:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
return dict([(k, __safe_value(v)) for (k, v) in params.items() if v is not None and not v == ""])
|
return dict([(k, __safe_value(v)) for (k, v) in params.items() if v is not None and not v == ""])
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_params(params):
|
||||||
|
"""
|
||||||
|
Normalizes Admin API parameters.
|
||||||
|
|
||||||
|
:param params:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if not params or not isinstance(params, dict):
|
||||||
|
return params
|
||||||
|
|
||||||
|
return dict([(k, __bool_string(v)) for (k, v) in params.items() if v is not None and not v == ""])
|
||||||
|
|
||||||
|
|
||||||
def sign_request(params, options):
|
def sign_request(params, options):
|
||||||
api_key = options.get("api_key", cloudinary.config().api_key)
|
api_key = options.get("api_key", cloudinary.config().api_key)
|
||||||
if not api_key:
|
if not api_key:
|
||||||
|
@ -1086,6 +1116,7 @@ def build_upload_params(**options):
|
||||||
"allowed_formats": options.get("allowed_formats") and encode_list(build_array(options["allowed_formats"])),
|
"allowed_formats": options.get("allowed_formats") and encode_list(build_array(options["allowed_formats"])),
|
||||||
"face_coordinates": encode_double_array(options.get("face_coordinates")),
|
"face_coordinates": encode_double_array(options.get("face_coordinates")),
|
||||||
"custom_coordinates": encode_double_array(options.get("custom_coordinates")),
|
"custom_coordinates": encode_double_array(options.get("custom_coordinates")),
|
||||||
|
"regions": json_encode(options.get("regions")),
|
||||||
"context": encode_context(options.get("context")),
|
"context": encode_context(options.get("context")),
|
||||||
"auto_tagging": options.get("auto_tagging") and str(options.get("auto_tagging")),
|
"auto_tagging": options.get("auto_tagging") and str(options.get("auto_tagging")),
|
||||||
"responsive_breakpoints": generate_responsive_breakpoints_string(options.get("responsive_breakpoints")),
|
"responsive_breakpoints": generate_responsive_breakpoints_string(options.get("responsive_breakpoints")),
|
||||||
|
@ -1101,6 +1132,37 @@ def build_upload_params(**options):
|
||||||
return params
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
def handle_file_parameter(file, filename):
|
||||||
|
if not file:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if PathLibPathType and isinstance(file, PathLibPathType):
|
||||||
|
name = filename or file.name
|
||||||
|
data = file.read_bytes()
|
||||||
|
elif isinstance(file, string_types):
|
||||||
|
if is_remote_url(file):
|
||||||
|
# URL
|
||||||
|
name = None
|
||||||
|
data = file
|
||||||
|
else:
|
||||||
|
# file path
|
||||||
|
name = filename or file
|
||||||
|
with open(file, "rb") as opened:
|
||||||
|
data = opened.read()
|
||||||
|
elif hasattr(file, 'read') and callable(file.read):
|
||||||
|
# stream
|
||||||
|
data = file.read()
|
||||||
|
name = filename or (file.name if hasattr(file, 'name') and isinstance(file.name, str) else "stream")
|
||||||
|
elif isinstance(file, tuple):
|
||||||
|
name, data = file
|
||||||
|
else:
|
||||||
|
# Not a string, not a stream
|
||||||
|
name = filename or "file"
|
||||||
|
data = file
|
||||||
|
|
||||||
|
return (name, data) if name else data
|
||||||
|
|
||||||
|
|
||||||
def build_multi_and_sprite_params(**options):
|
def build_multi_and_sprite_params(**options):
|
||||||
"""
|
"""
|
||||||
Build params for multi, download_multi, generate_sprite, and download_generated_sprite methods
|
Build params for multi, download_multi, generate_sprite, and download_generated_sprite methods
|
||||||
|
@ -1166,8 +1228,21 @@ def __process_text_options(layer, layer_parameter):
|
||||||
|
|
||||||
|
|
||||||
def process_layer(layer, layer_parameter):
|
def process_layer(layer, layer_parameter):
|
||||||
if isinstance(layer, string_types) and layer.startswith("fetch:"):
|
if isinstance(layer, string_types):
|
||||||
layer = {"url": layer[len('fetch:'):]}
|
resource_type = None
|
||||||
|
if layer.startswith("fetch:"):
|
||||||
|
url = layer[len('fetch:'):]
|
||||||
|
elif layer.find(":fetch:", 0, 12) != -1:
|
||||||
|
resource_type, _, url = layer.split(":", 2)
|
||||||
|
else:
|
||||||
|
# nothing to process, a raw string, keep as is.
|
||||||
|
return layer
|
||||||
|
|
||||||
|
# handle remote fetch URL
|
||||||
|
layer = {"url": url, "type": "fetch"}
|
||||||
|
if resource_type:
|
||||||
|
layer["resource_type"] = resource_type
|
||||||
|
|
||||||
if not isinstance(layer, dict):
|
if not isinstance(layer, dict):
|
||||||
return layer
|
return layer
|
||||||
|
|
||||||
|
@ -1176,19 +1251,19 @@ def process_layer(layer, layer_parameter):
|
||||||
type = layer.get("type")
|
type = layer.get("type")
|
||||||
public_id = layer.get("public_id")
|
public_id = layer.get("public_id")
|
||||||
format = layer.get("format")
|
format = layer.get("format")
|
||||||
fetch = layer.get("url")
|
fetch_url = layer.get("url")
|
||||||
components = list()
|
components = list()
|
||||||
|
|
||||||
if text is not None and resource_type is None:
|
if text is not None and resource_type is None:
|
||||||
resource_type = "text"
|
resource_type = "text"
|
||||||
|
|
||||||
if fetch and resource_type is None:
|
if fetch_url and type is None:
|
||||||
resource_type = "fetch"
|
type = "fetch"
|
||||||
|
|
||||||
if public_id is not None and format is not None:
|
if public_id is not None and format is not None:
|
||||||
public_id = public_id + "." + format
|
public_id = public_id + "." + format
|
||||||
|
|
||||||
if public_id is None and resource_type != "text" and resource_type != "fetch":
|
if public_id is None and resource_type != "text" and type != "fetch":
|
||||||
raise ValueError("Must supply public_id for for non-text " + layer_parameter)
|
raise ValueError("Must supply public_id for for non-text " + layer_parameter)
|
||||||
|
|
||||||
if resource_type is not None and resource_type != "image":
|
if resource_type is not None and resource_type != "image":
|
||||||
|
@ -1212,8 +1287,6 @@ def process_layer(layer, layer_parameter):
|
||||||
|
|
||||||
if text is not None:
|
if text is not None:
|
||||||
var_pattern = VAR_NAME_RE
|
var_pattern = VAR_NAME_RE
|
||||||
match = re.findall(var_pattern, text)
|
|
||||||
|
|
||||||
parts = filter(lambda p: p is not None, re.split(var_pattern, text))
|
parts = filter(lambda p: p is not None, re.split(var_pattern, text))
|
||||||
encoded_text = []
|
encoded_text = []
|
||||||
for part in parts:
|
for part in parts:
|
||||||
|
@ -1223,11 +1296,9 @@ def process_layer(layer, layer_parameter):
|
||||||
encoded_text.append(smart_escape(smart_escape(part, r"([,/])")))
|
encoded_text.append(smart_escape(smart_escape(part, r"([,/])")))
|
||||||
|
|
||||||
text = ''.join(encoded_text)
|
text = ''.join(encoded_text)
|
||||||
# text = text.replace("%2C", "%252C")
|
|
||||||
# text = text.replace("/", "%252F")
|
|
||||||
components.append(text)
|
components.append(text)
|
||||||
elif resource_type == "fetch":
|
elif type == "fetch":
|
||||||
b64 = base64_encode_url(fetch)
|
b64 = base64url_encode(fetch_url)
|
||||||
components.append(b64)
|
components.append(b64)
|
||||||
else:
|
else:
|
||||||
public_id = public_id.replace("/", ':')
|
public_id = public_id.replace("/", ':')
|
||||||
|
@ -1359,8 +1430,7 @@ def normalize_expression(expression):
|
||||||
result = re.sub(replaceRE, translate_if, result)
|
result = re.sub(replaceRE, translate_if, result)
|
||||||
result = re.sub('[ _]+', '_', result)
|
result = re.sub('[ _]+', '_', result)
|
||||||
return result
|
return result
|
||||||
else:
|
return expression
|
||||||
return expression
|
|
||||||
|
|
||||||
|
|
||||||
def __join_pair(key, value):
|
def __join_pair(key, value):
|
||||||
|
@ -1368,8 +1438,7 @@ def __join_pair(key, value):
|
||||||
return None
|
return None
|
||||||
elif value is True:
|
elif value is True:
|
||||||
return key
|
return key
|
||||||
else:
|
return u"{0}=\"{1}\"".format(key, value)
|
||||||
return u"{0}=\"{1}\"".format(key, value)
|
|
||||||
|
|
||||||
|
|
||||||
def html_attrs(attrs, only=None):
|
def html_attrs(attrs, only=None):
|
||||||
|
@ -1379,10 +1448,15 @@ def html_attrs(attrs, only=None):
|
||||||
def __safe_value(v):
|
def __safe_value(v):
|
||||||
if isinstance(v, bool):
|
if isinstance(v, bool):
|
||||||
return "1" if v else "0"
|
return "1" if v else "0"
|
||||||
else:
|
return v
|
||||||
return v
|
|
||||||
|
|
||||||
|
|
||||||
|
def __bool_string(v):
|
||||||
|
if isinstance(v, bool):
|
||||||
|
return "true" if v else "false"
|
||||||
|
|
||||||
|
return v
|
||||||
|
|
||||||
def __crc(source):
|
def __crc(source):
|
||||||
return str((zlib.crc32(to_bytearray(source)) & 0xffffffff) % 5 + 1)
|
return str((zlib.crc32(to_bytearray(source)) & 0xffffffff) % 5 + 1)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ bleach==6.1.0
|
||||||
certifi==2024.2.2
|
certifi==2024.2.2
|
||||||
cheroot==10.0.0
|
cheroot==10.0.0
|
||||||
cherrypy==18.9.0
|
cherrypy==18.9.0
|
||||||
cloudinary==1.34.0
|
cloudinary==1.39.1
|
||||||
distro==1.9.0
|
distro==1.9.0
|
||||||
dnspython==2.6.1
|
dnspython==2.6.1
|
||||||
facebook-sdk==3.1.0
|
facebook-sdk==3.1.0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue