mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-08-20 13:23:24 -07:00
Update cloudinary to 1.20.0
This commit is contained in:
parent
1c56d9c513
commit
2984629b39
27 changed files with 2865 additions and 923 deletions
|
@ -1,17 +1,17 @@
|
|||
# MIT licensed code copied from https://bitbucket.org/chrisatlee/poster
|
||||
#
|
||||
# Copyright (c) 2011 Chris AtLee
|
||||
#
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
|
@ -28,7 +28,4 @@ New releases of poster will always have a version number that compares greater
|
|||
than an older version of poster.
|
||||
New in version 0.6."""
|
||||
|
||||
import cloudinary.poster.streaminghttp
|
||||
import cloudinary.poster.encode
|
||||
|
||||
version = (0, 8, 2) # Thanks JP!
|
||||
version = (0, 8, 2) # Thanks JP!
|
||||
|
|
|
@ -6,9 +6,17 @@ as multipart/form-data suitable for a HTTP POST or PUT request.
|
|||
|
||||
multipart/form-data is the standard way to upload files over HTTP"""
|
||||
|
||||
__all__ = ['gen_boundary', 'encode_and_quote', 'MultipartParam',
|
||||
'encode_string', 'encode_file_header', 'get_body_size', 'get_headers',
|
||||
'multipart_encode']
|
||||
import mimetypes
|
||||
import os
|
||||
import re
|
||||
from email.header import Header
|
||||
|
||||
from cloudinary.compat import (PY3, advance_iterator, quote_plus, to_bytearray,
|
||||
to_bytes, to_string)
|
||||
|
||||
__all__ = [
|
||||
'gen_boundary', 'encode_and_quote', 'MultipartParam', 'encode_string',
|
||||
'encode_file_header', 'get_body_size', 'get_headers', 'multipart_encode']
|
||||
|
||||
try:
|
||||
from io import UnsupportedOperation
|
||||
|
@ -17,25 +25,19 @@ except ImportError:
|
|||
|
||||
try:
|
||||
import uuid
|
||||
|
||||
def gen_boundary():
|
||||
"""Returns a random string to use as the boundary for a message"""
|
||||
return uuid.uuid4().hex
|
||||
except ImportError:
|
||||
import random, sha
|
||||
import random
|
||||
import sha
|
||||
|
||||
def gen_boundary():
|
||||
"""Returns a random string to use as the boundary for a message"""
|
||||
bits = random.getrandbits(160)
|
||||
return sha.new(str(bits)).hexdigest()
|
||||
|
||||
import re, os, mimetypes
|
||||
from cloudinary.compat import (PY3, string_types, to_bytes, to_string,
|
||||
to_bytearray, quote_plus, advance_iterator)
|
||||
try:
|
||||
from email.header import Header
|
||||
except ImportError:
|
||||
# Python 2.4
|
||||
from email.Header import Header
|
||||
|
||||
if PY3:
|
||||
def encode_and_quote(data):
|
||||
if data is None:
|
||||
|
@ -47,7 +49,7 @@ else:
|
|||
"""If ``data`` is unicode, return quote_plus(data.encode("utf-8")) otherwise return quote_plus(data)"""
|
||||
if data is None:
|
||||
return None
|
||||
|
||||
|
||||
if isinstance(data, unicode):
|
||||
data = data.encode("utf-8")
|
||||
return quote_plus(data)
|
||||
|
@ -65,13 +67,15 @@ if PY3:
|
|||
return to_bytes(str(s))
|
||||
else:
|
||||
def _strify(s):
|
||||
"""If s is a unicode string, encode it to UTF-8 and return the results, otherwise return str(s), or None if s is None"""
|
||||
"""If s is a unicode string, encode it to UTF-8 and return the results,
|
||||
otherwise return str(s), or None if s is None"""
|
||||
if s is None:
|
||||
return None
|
||||
if isinstance(s, unicode):
|
||||
return s.encode("utf-8")
|
||||
return str(s)
|
||||
|
||||
|
||||
class MultipartParam(object):
|
||||
"""Represents a single parameter in a multipart/form-data request
|
||||
|
||||
|
@ -105,7 +109,7 @@ class MultipartParam(object):
|
|||
transferred, and the total size.
|
||||
"""
|
||||
def __init__(self, name, value=None, filename=None, filetype=None,
|
||||
filesize=None, fileobj=None, cb=None):
|
||||
filesize=None, fileobj=None, cb=None):
|
||||
self.name = Header(name).encode()
|
||||
self.value = _strify(value)
|
||||
if filename is None:
|
||||
|
@ -141,7 +145,7 @@ class MultipartParam(object):
|
|||
fileobj.seek(0, 2)
|
||||
self.filesize = fileobj.tell()
|
||||
fileobj.seek(0)
|
||||
except:
|
||||
except Exception:
|
||||
raise ValueError("Could not determine filesize")
|
||||
|
||||
def __cmp__(self, other):
|
||||
|
@ -169,9 +173,9 @@ class MultipartParam(object):
|
|||
"""
|
||||
|
||||
return cls(paramname, filename=os.path.basename(filename),
|
||||
filetype=mimetypes.guess_type(filename)[0],
|
||||
filesize=os.path.getsize(filename),
|
||||
fileobj=open(filename, "rb"))
|
||||
filetype=mimetypes.guess_type(filename)[0],
|
||||
filesize=os.path.getsize(filename),
|
||||
fileobj=open(filename, "rb"))
|
||||
|
||||
@classmethod
|
||||
def from_params(cls, params):
|
||||
|
@ -204,7 +208,7 @@ class MultipartParam(object):
|
|||
filetype = None
|
||||
|
||||
retval.append(cls(name=name, filename=filename,
|
||||
filetype=filetype, fileobj=value))
|
||||
filetype=filetype, fileobj=value))
|
||||
else:
|
||||
retval.append(cls(name, value))
|
||||
return retval
|
||||
|
@ -216,8 +220,8 @@ class MultipartParam(object):
|
|||
headers = ["--%s" % boundary]
|
||||
|
||||
if self.filename:
|
||||
disposition = 'form-data; name="%s"; filename="%s"' % (self.name,
|
||||
to_string(self.filename))
|
||||
disposition = 'form-data; name="%s"; filename="%s"' % (
|
||||
self.name, to_string(self.filename))
|
||||
else:
|
||||
disposition = 'form-data; name="%s"' % self.name
|
||||
|
||||
|
@ -267,8 +271,8 @@ class MultipartParam(object):
|
|||
self.cb(self, current, total)
|
||||
last_block = to_bytearray("")
|
||||
encoded_boundary = "--%s" % encode_and_quote(boundary)
|
||||
boundary_exp = re.compile(to_bytes("^%s$" % re.escape(encoded_boundary)),
|
||||
re.M)
|
||||
boundary_exp = re.compile(
|
||||
to_bytes("^%s$" % re.escape(encoded_boundary)), re.M)
|
||||
while True:
|
||||
block = self.fileobj.read(blocksize)
|
||||
if not block:
|
||||
|
@ -296,6 +300,7 @@ class MultipartParam(object):
|
|||
|
||||
return len(self.encode_hdr(boundary)) + 2 + valuesize
|
||||
|
||||
|
||||
def encode_string(boundary, name, value):
|
||||
"""Returns ``name`` and ``value`` encoded as a multipart/form-data
|
||||
variable. ``boundary`` is the boundary string used throughout
|
||||
|
@ -303,8 +308,8 @@ def encode_string(boundary, name, value):
|
|||
|
||||
return MultipartParam(name, value).encode(boundary)
|
||||
|
||||
def encode_file_header(boundary, paramname, filesize, filename=None,
|
||||
filetype=None):
|
||||
|
||||
def encode_file_header(boundary, paramname, filesize, filename=None, filetype=None):
|
||||
"""Returns the leading data for a multipart/form-data field that contains
|
||||
file data.
|
||||
|
||||
|
@ -324,7 +329,8 @@ def encode_file_header(boundary, paramname, filesize, filename=None,
|
|||
"""
|
||||
|
||||
return MultipartParam(paramname, filesize=filesize, filename=filename,
|
||||
filetype=filetype).encode_hdr(boundary)
|
||||
filetype=filetype).encode_hdr(boundary)
|
||||
|
||||
|
||||
def get_body_size(params, boundary):
|
||||
"""Returns the number of bytes that the multipart/form-data encoding
|
||||
|
@ -332,6 +338,7 @@ def get_body_size(params, boundary):
|
|||
size = sum(p.get_size(boundary) for p in MultipartParam.from_params(params))
|
||||
return size + len(boundary) + 6
|
||||
|
||||
|
||||
def get_headers(params, boundary):
|
||||
"""Returns a dictionary with Content-Type and Content-Length headers
|
||||
for the multipart/form-data encoding of ``params``."""
|
||||
|
@ -341,6 +348,7 @@ def get_headers(params, boundary):
|
|||
headers['Content-Length'] = str(get_body_size(params, boundary))
|
||||
return headers
|
||||
|
||||
|
||||
class multipart_yielder:
|
||||
def __init__(self, params, boundary, cb):
|
||||
self.params = params
|
||||
|
@ -396,6 +404,7 @@ class multipart_yielder:
|
|||
for param in self.params:
|
||||
param.reset()
|
||||
|
||||
|
||||
def multipart_encode(params, boundary=None, cb=None):
|
||||
"""Encode ``params`` as multipart/form-data.
|
||||
|
||||
|
|
|
@ -27,15 +27,18 @@ Example usage:
|
|||
... {'Content-Length': str(len(s))})
|
||||
"""
|
||||
|
||||
import sys, socket
|
||||
from cloudinary.compat import httplib, urllib2, NotConnected
|
||||
import socket
|
||||
import sys
|
||||
|
||||
from cloudinary.compat import NotConnected, httplib, urllib2
|
||||
|
||||
__all__ = ['StreamingHTTPConnection', 'StreamingHTTPRedirectHandler',
|
||||
'StreamingHTTPHandler', 'register_openers']
|
||||
'StreamingHTTPHandler', 'register_openers']
|
||||
|
||||
if hasattr(httplib, 'HTTPS'):
|
||||
__all__.extend(['StreamingHTTPSHandler', 'StreamingHTTPSConnection'])
|
||||
|
||||
|
||||
class _StreamingHTTPMixin:
|
||||
"""Mixin class for HTTP and HTTPS connections that implements a streaming
|
||||
send method."""
|
||||
|
@ -62,7 +65,7 @@ class _StreamingHTTPMixin:
|
|||
print("send:", repr(value))
|
||||
try:
|
||||
blocksize = 8192
|
||||
if hasattr(value, 'read') :
|
||||
if hasattr(value, 'read'):
|
||||
if hasattr(value, 'seek'):
|
||||
value.seek(0)
|
||||
if self.debuglevel > 0:
|
||||
|
@ -86,10 +89,12 @@ class _StreamingHTTPMixin:
|
|||
self.close()
|
||||
raise
|
||||
|
||||
|
||||
class StreamingHTTPConnection(_StreamingHTTPMixin, httplib.HTTPConnection):
|
||||
"""Subclass of `httplib.HTTPConnection` that overrides the `send()` method
|
||||
to support iterable body objects"""
|
||||
|
||||
|
||||
class StreamingHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
|
||||
"""Subclass of `urllib2.HTTPRedirectHandler` that overrides the
|
||||
`redirect_request` method to properly handle redirected POST requests
|
||||
|
@ -114,7 +119,7 @@ class StreamingHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
|
|||
"""
|
||||
m = req.get_method()
|
||||
if (code in (301, 302, 303, 307) and m in ("GET", "HEAD")
|
||||
or code in (301, 302, 303) and m == "POST"):
|
||||
or code in (301, 302, 303) and m == "POST"):
|
||||
# Strictly (according to RFC 2616), 301 or 302 in response
|
||||
# to a POST MUST NOT cause a redirection without confirmation
|
||||
# from the user (of urllib2, in this case). In practice,
|
||||
|
@ -125,14 +130,16 @@ class StreamingHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
|
|||
newheaders = dict((k, v) for k, v in req.headers.items()
|
||||
if k.lower() not in (
|
||||
"content-length", "content-type")
|
||||
)
|
||||
return urllib2.Request(newurl,
|
||||
headers=newheaders,
|
||||
origin_req_host=req.get_origin_req_host(),
|
||||
unverifiable=True)
|
||||
)
|
||||
return urllib2.Request(
|
||||
newurl,
|
||||
headers=newheaders,
|
||||
origin_req_host=req.get_origin_req_host(),
|
||||
unverifiable=True)
|
||||
else:
|
||||
raise urllib2.HTTPError(req.get_full_url(), code, msg, headers, fp)
|
||||
|
||||
|
||||
class StreamingHTTPHandler(urllib2.HTTPHandler):
|
||||
"""Subclass of `urllib2.HTTPHandler` that uses
|
||||
StreamingHTTPConnection as its http connection class."""
|
||||
|
@ -156,9 +163,9 @@ class StreamingHTTPHandler(urllib2.HTTPHandler):
|
|||
"No Content-Length specified for iterable body")
|
||||
return urllib2.HTTPHandler.do_request_(self, req)
|
||||
|
||||
|
||||
if hasattr(httplib, 'HTTPS'):
|
||||
class StreamingHTTPSConnection(_StreamingHTTPMixin,
|
||||
httplib.HTTPSConnection):
|
||||
class StreamingHTTPSConnection(_StreamingHTTPMixin, httplib.HTTPSConnection):
|
||||
"""Subclass of `httplib.HTTSConnection` that overrides the `send()`
|
||||
method to support iterable body objects"""
|
||||
|
||||
|
@ -179,7 +186,7 @@ if hasattr(httplib, 'HTTPS'):
|
|||
if hasattr(data, 'read') or hasattr(data, 'next'):
|
||||
if not req.has_header('Content-length'):
|
||||
raise ValueError(
|
||||
"No Content-Length specified for iterable body")
|
||||
"No Content-Length specified for iterable body")
|
||||
return urllib2.HTTPSHandler.do_request_(self, req)
|
||||
|
||||
|
||||
|
@ -188,7 +195,8 @@ def get_handlers():
|
|||
if hasattr(httplib, "HTTPS"):
|
||||
handlers.append(StreamingHTTPSHandler)
|
||||
return handlers
|
||||
|
||||
|
||||
|
||||
def register_openers():
|
||||
"""Register the streaming http handlers in the global urllib2 default
|
||||
opener object.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue