if sock:
sock.settimeout(timeout)
- httplib_response = conn.getresponse()
+ try: # Python 2.7+, use buffering of HTTP responses
+ httplib_response = conn.getresponse(buffering=True)
+ except TypeError: # Python 2.6 and older
+ httplib_response = conn.getresponse()
# AppEngine doesn't have a version attr.
http_version = getattr(conn, '_http_vsn_str', 'HTTP/?'),
import codecs
import mimetypes
-try:
- from mimetools import choose_boundary
-except ImportError:
- from .packages.mimetools_choose_boundary import choose_boundary
-
+from uuid import uuid4
from io import BytesIO
from .packages import six
writer = codecs.lookup('utf-8')[3]
+def choose_boundary():
+ """
+ Our embarassingly-simple replacement for mimetools.choose_boundary.
+ """
+ return uuid4().hex
+
+
def get_content_type(filename):
return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
+++ /dev/null
-"""The function mimetools.choose_boundary() from Python 2.7, which seems to
-have disappeared in Python 3 (although email.generator._make_boundary() might
-work as a replacement?).
-
-Tweaked to use lock from threading rather than thread.
-"""
-import os
-from threading import Lock
-_counter_lock = Lock()
-
-_counter = 0
-def _get_next_counter():
- global _counter
- with _counter_lock:
- _counter += 1
- return _counter
-
-_prefix = None
-
-def choose_boundary():
- """Return a string usable as a multipart boundary.
-
- The string chosen is unique within a single program run, and
- incorporates the user id (if available), process id (if available),
- and current time. So it's very unlikely the returned string appears
- in message text, but there's no guarantee.
-
- The boundary contains dots so you have to quote it in the header."""
-
- global _prefix
- import time
- if _prefix is None:
- import socket
- try:
- hostid = socket.gethostbyname(socket.gethostname())
- except socket.gaierror:
- hostid = '127.0.0.1'
- try:
- uid = repr(os.getuid())
- except AttributeError:
- uid = '1'
- try:
- pid = repr(os.getpid())
- except AttributeError:
- pid = '1'
- _prefix = hostid + '.' + uid + '.' + pid
- return "%s.%.3f.%d" % (_prefix, time.time(), _get_next_counter())
return headers
+def split_first(s, delims):
+ """
+ Given a string and an iterable of delimiters, split on the first found
+ delimiter. Return two split parts.
+
+ If not found, then the first part is the full input string.
+
+ Scales linearly with number of delims. Not ideal for large number of delims.
+ """
+ min_idx = None
+ for d in delims:
+ idx = s.find(d)
+ if idx < 0:
+ continue
+
+ if not min_idx:
+ min_idx = idx
+ else:
+ min_idx = min(idx, min_idx)
+
+ if min_idx < 0:
+ return s, ''
+
+ return s[:min_idx], s[min_idx+1:]
+
+
def get_host(url):
"""
Given a url, return its scheme, host and port (None if it's not there).
if '://' in url:
scheme, url = url.split('://', 1)
- if '/' in url:
- url, _path = url.split('/', 1)
+
+ # Find the earliest Authority Terminator
+ # http://tools.ietf.org/html/rfc3986#section-3.2
+ url, _path = split_first(url, ['/', '?', '#'])
+
if '@' in url:
_auth, url = url.split('@', 1)
if ':' in url:
let the platform handle connection recycling transparently for us.
"""
sock = getattr(conn, 'sock', False)
- if not sock: #Platform-specific: AppEngine
+ if not sock: # Platform-specific: AppEngine
return False
if not poll: # Platform-specific
- if not select: #Platform-specific: AppEngine
+ if not select: # Platform-specific: AppEngine
return False
return select([sock], [], [], 0.0)[0]