# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not use this file except in compliance with the License. A copy of # the License is located at # # http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. import copy import datetime import six import sys import inspect if six.PY3: from six.moves import http_client class HTTPHeaders(http_client.HTTPMessage): pass from urllib.parse import quote from urllib.parse import urlencode from urllib.parse import unquote from urllib.parse import unquote_plus from urllib.parse import urlsplit from urllib.parse import urlunsplit from urllib.parse import urljoin from urllib.parse import parse_qsl from urllib.parse import parse_qs from http.client import HTTPResponse from io import IOBase as _IOBase from base64 import encodebytes from email.utils import formatdate file_type = _IOBase zip = zip # In python3, unquote takes a str() object, url decodes it, # then takes the bytestring and decodes it to utf-8. # Python2 we'll have to do this ourself (see below). unquote_str = unquote_plus def set_socket_timeout(http_response, timeout): """Set the timeout of the socket from an HTTPResponse. :param http_response: An instance of ``httplib.HTTPResponse`` """ http_response._fp.fp.raw._sock.settimeout(timeout) def accepts_kwargs(func): # In python3.4.1, there's backwards incompatible # changes when using getargspec with functools.partials. return inspect.getfullargspec(func)[2] else: from urllib import quote from urllib import urlencode from urllib import unquote from urllib import unquote_plus from urlparse import urlsplit from urlparse import urlunsplit from urlparse import urljoin from urlparse import parse_qsl from urlparse import parse_qs from email.message import Message from email.Utils import formatdate file_type = file from itertools import izip as zip from httplib import HTTPResponse from base64 import encodestring as encodebytes class HTTPHeaders(Message): # The __iter__ method is not available in python2.x, so we have # to port the py3 version. def __iter__(self): for field, value in self._headers: yield field def unquote_str(value, encoding='utf-8'): # In python2, unquote() gives us a string back that has the urldecoded # bits, but not the unicode parts. We need to decode this manually. # unquote has special logic in which if it receives a unicode object it # will decode it to latin1. This is hard coded. To avoid this, we'll # encode the string with the passed in encoding before trying to # unquote it. byte_string = value.encode(encoding) return unquote_plus(byte_string).decode(encoding) def set_socket_timeout(http_response, timeout): """Set the timeout of the socket from an HTTPResponse. :param http_response: An instance of ``httplib.HTTPResponse`` """ http_response._fp.fp._sock.settimeout(timeout) def accepts_kwargs(func): return inspect.getargspec(func)[2] try: from collections import OrderedDict except ImportError: # Python2.6 we use the 3rd party back port. from ordereddict import OrderedDict if sys.version_info[:2] == (2, 6): import simplejson as json # In py26, invalid xml parsed by element tree # will raise a plain old SyntaxError instead of # a real exception, so we need to abstract this change. XMLParseError = SyntaxError else: import xml.etree.cElementTree XMLParseError = xml.etree.cElementTree.ParseError import json @classmethod def from_dict(cls, d): new_instance = cls() for key, value in d.items(): new_instance[key] = value return new_instance @classmethod def from_pairs(cls, pairs): new_instance = cls() for key, value in pairs: new_instance[key] = value return new_instance HTTPHeaders.from_dict = from_dict HTTPHeaders.from_pairs = from_pairs def copy_kwargs(kwargs): """ There is a bug in Python versions < 2.6.5 that prevents you from passing unicode keyword args (#4978). This function takes a dictionary of kwargs and returns a copy. If you are using Python < 2.6.5, it also encodes the keys to avoid this bug. Oh, and version_info wasn't a namedtuple back then, either! """ vi = sys.version_info if vi[0] == 2 and vi[1] <= 6 and vi[3] < 5: copy_kwargs = {} for key in kwargs: copy_kwargs[key.encode('utf-8')] = kwargs[key] else: copy_kwargs = copy.copy(kwargs) return copy_kwargs def total_seconds(delta): """ Returns the total seconds in a ``datetime.timedelta``. Python 2.6 does not have ``timedelta.total_seconds()``, so we have to calculate this ourselves. On 2.7 or better, we'll take advantage of the built-in method. The math was pulled from the ``datetime`` docs (http://docs.python.org/2.7/library/datetime.html#datetime.timedelta.total_seconds). :param delta: The timedelta object :type delta: ``datetime.timedelta`` """ if sys.version_info[:2] != (2, 6): return delta.total_seconds() day_in_seconds = delta.days * 24 * 3600.0 micro_in_seconds = delta.microseconds / 10.0**6 return day_in_seconds + delta.seconds + micro_in_seconds