summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boto/cloudformation/connection.py40
-rw-r--r--boto/cloudfront/__init__.py52
-rw-r--r--boto/connection.py580
-rw-r--r--boto/dynamodb/layer1.py17
-rw-r--r--boto/ecs/__init__.py8
-rw-r--r--boto/fps/connection.py70
-rw-r--r--boto/gs/bucket.py12
-rwxr-xr-xboto/gs/connection.py10
-rw-r--r--boto/gs/resumable_upload_handler.py2
-rw-r--r--boto/iam/connection.py8
-rw-r--r--boto/mturk/connection.py4
-rw-r--r--boto/roboto/awsqueryrequest.py10
-rw-r--r--boto/route53/connection.py42
-rw-r--r--boto/s3/bucket.py255
-rw-r--r--boto/s3/connection.py22
-rw-r--r--boto/s3/key.py113
-rw-r--r--boto/s3/multipart.py4
-rw-r--r--boto/s3/resumable_download_handler.py2
-rw-r--r--boto/sdb/connection.py8
-rw-r--r--boto/ses/connection.py8
-rw-r--r--boto/sns/connection.py104
-rw-r--r--boto/utils.py2
-rw-r--r--tests/s3/test_bucket.py12
23 files changed, 563 insertions, 822 deletions
diff --git a/boto/cloudformation/connection.py b/boto/cloudformation/connection.py
index 6243dc6c..cd07d6b5 100644
--- a/boto/cloudformation/connection.py
+++ b/boto/cloudformation/connection.py
@@ -133,14 +133,14 @@ class CloudFormationConnection(AWSQueryConnection):
params['TimeoutInMinutes'] = int(timeout_in_minutes)
response = self.make_request('CreateStack', params, '/', 'POST')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
body = json.loads(body)
return body['CreateStackResponse']['CreateStackResult']['StackId']
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def update_stack(self, stack_name, template_body=None, template_url=None,
parameters=[], notification_arns=[], disable_rollback=False,
@@ -200,26 +200,26 @@ class CloudFormationConnection(AWSQueryConnection):
params['TimeoutInMinutes'] = int(timeout_in_minutes)
response = self.make_request('UpdateStack', params, '/', 'POST')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
body = json.loads(body)
return body['UpdateStackResponse']['UpdateStackResult']['StackId']
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def delete_stack(self, stack_name_or_id):
params = {'ContentType': "JSON", 'StackName': stack_name_or_id}
# TODO: change this to get_status ?
response = self.make_request('DeleteStack', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def describe_stack_events(self, stack_name_or_id=None, next_token=None):
params = {}
@@ -235,13 +235,13 @@ class CloudFormationConnection(AWSQueryConnection):
'LogicalResourceId': logical_resource_id}
response = self.make_request('DescribeStackResource', params,
'/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def describe_stack_resources(self, stack_name_or_id=None,
logical_resource_id=None,
@@ -265,13 +265,13 @@ class CloudFormationConnection(AWSQueryConnection):
def get_template(self, stack_name_or_id):
params = {'ContentType': "JSON", 'StackName': stack_name_or_id}
response = self.make_request('GetTemplate', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def list_stack_resources(self, stack_name_or_id, next_token=None):
params = {'StackName': stack_name_or_id}
diff --git a/boto/cloudfront/__init__.py b/boto/cloudfront/__init__.py
index 7f98b70b..250958e6 100644
--- a/boto/cloudfront/__init__.py
+++ b/boto/cloudfront/__init__.py
@@ -47,7 +47,7 @@ class CloudFrontConnection(AWSAuthConnection):
True, port, proxy, proxy_port, debug=debug)
def get_etag(self, response):
- response_headers = response.msg
+ response_headers = response.headers
for key in response_headers.keys():
if key.lower() == 'etag':
return response_headers[key]
@@ -62,10 +62,10 @@ class CloudFrontConnection(AWSAuthConnection):
if not tags:
tags=[('DistributionSummary', DistributionSummary)]
response = self.make_request('GET', '/%s/%s' % (self.Version, resource))
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status >= 300:
- raise CloudFrontServerError(response.status, response.reason, body)
+ if response.status_code >= 300:
+ raise CloudFrontServerError(response.status_code, response.reason, body)
rs = ResultSet(tags)
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
@@ -74,12 +74,12 @@ class CloudFrontConnection(AWSAuthConnection):
def _get_info(self, id, resource, dist_class):
uri = '/%s/%s/%s' % (self.Version, resource, id)
response = self.make_request('GET', uri)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status >= 300:
- raise CloudFrontServerError(response.status, response.reason, body)
+ if response.status_code >= 300:
+ raise CloudFrontServerError(response.status_code, response.reason, body)
d = dist_class(connection=self)
- response_headers = response.msg
+ response_headers = response.headers
for key in response_headers.keys():
if key.lower() == 'etag':
d.etag = response_headers[key]
@@ -90,10 +90,10 @@ class CloudFrontConnection(AWSAuthConnection):
def _get_config(self, id, resource, config_class):
uri = '/%s/%s/%s/config' % (self.Version, resource, id)
response = self.make_request('GET', uri)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status >= 300:
- raise CloudFrontServerError(response.status, response.reason, body)
+ if response.status_code >= 300:
+ raise CloudFrontServerError(response.status_code, response.reason, body)
d = config_class(connection=self)
d.etag = self.get_etag(response)
h = handler.XmlHandler(d, self)
@@ -108,33 +108,33 @@ class CloudFrontConnection(AWSAuthConnection):
uri = '/%s/%s/%s/config' % (self.Version, resource, distribution_id)
headers = {'If-Match' : etag, 'Content-Type' : 'text/xml'}
response = self.make_request('PUT', uri, headers, config.to_xml())
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status != 200:
- raise CloudFrontServerError(response.status, response.reason, body)
+ if response.status_code != 200:
+ raise CloudFrontServerError(response.status_code, response.reason, body)
return self.get_etag(response)
def _create_object(self, config, resource, dist_class):
response = self.make_request('POST', '/%s/%s' % (self.Version, resource),
{'Content-Type' : 'text/xml'}, data=config.to_xml())
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status == 201:
+ if response.status_code == 201:
d = dist_class(connection=self)
h = handler.XmlHandler(d, self)
xml.sax.parseString(body, h)
d.etag = self.get_etag(response)
return d
else:
- raise CloudFrontServerError(response.status, response.reason, body)
+ raise CloudFrontServerError(response.status_code, response.reason, body)
def _delete_object(self, id, etag, resource):
uri = '/%s/%s/%s' % (self.Version, resource, id)
response = self.make_request('DELETE', uri, {'If-Match' : etag})
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status != 204:
- raise CloudFrontServerError(response.status, response.reason, body)
+ if response.status_code != 204:
+ raise CloudFrontServerError(response.status_code, response.reason, body)
# Distributions
@@ -241,24 +241,24 @@ class CloudFrontConnection(AWSAuthConnection):
response = self.make_request('POST', uri,
{'Content-Type' : 'text/xml'},
data=paths.to_xml())
- body = response.read()
- if response.status == 201:
+ body = response.content
+ if response.status_code == 201:
h = handler.XmlHandler(paths, self)
xml.sax.parseString(body, h)
return paths
else:
- raise CloudFrontServerError(response.status, response.reason, body)
+ raise CloudFrontServerError(response.status_code, response.reason, body)
def invalidation_request_status (self, distribution_id, request_id, caller_reference=None):
uri = '/%s/distribution/%s/invalidation/%s' % (self.Version, distribution_id, request_id )
response = self.make_request('GET', uri, {'Content-Type' : 'text/xml'})
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
paths = InvalidationBatch([])
h = handler.XmlHandler(paths, self)
xml.sax.parseString(body, h)
return paths
else:
- raise CloudFrontServerError(response.status, response.reason, body)
+ raise CloudFrontServerError(response.status_code, response.reason, body)
diff --git a/boto/connection.py b/boto/connection.py
index e170d0b3..b8c3221b 100644
--- a/boto/connection.py
+++ b/boto/connection.py
@@ -43,7 +43,6 @@ Handles basic connections to AWS
"""
from __future__ import with_statement
-import base64
import errno
import httplib
import os
@@ -53,9 +52,11 @@ import re
import socket
import sys
import time
-import urllib, urlparse
+import urlparse
import xml.sax
+import requests
+
import auth
import auth_handler
import boto
@@ -78,10 +79,51 @@ try:
except ImportError:
pass
-try:
- import threading
-except ImportError:
- import dummy_threading as threading
+# This is an ugly hack to bring over the sillyness that is HTTPResponse.reason.
+# TODO: Try to get this from somewhere else? Can we pluck straight from
+# httplib? Didn't have time to source dive.
+HTTP_REASON_CODES = {
+ "100": "Continue",
+ "101": "Switching Protocols",
+ "200": "OK",
+ "201": "Created",
+ "202": "Accepted",
+ "203": "Non-Authoritative Information",
+ "204": "No Content",
+ "205": "Reset Content",
+ "206": "Partial Content",
+ "300": "Multiple Choices",
+ "301": "Moved Permanently",
+ "302": "Found",
+ "303": "See Other",
+ "304": "Not Modified",
+ "305": "Use Proxy",
+ "307": "Temporary Redirect",
+ "400": "Bad Request",
+ "401": "Unauthorized",
+ "402": "Payment Required",
+ "403": "Forbidden",
+ "404": "Not Found",
+ "405": "Method Not Allowed",
+ "406": "Not Acceptable",
+ "407": "Proxy Authentication Required",
+ "408": "Request Time-out",
+ "409": "Conflict",
+ "410": "Gone",
+ "411": "Length Required",
+ "412": "Precondition Failed",
+ "413": "Request Entity Too Large",
+ "414": "Request-URI Too Large",
+ "415": "Unsupported Media Type",
+ "416": "Requested range not satisfiable",
+ "417": "Expectation Failed",
+ "500": "Internal Server Error",
+ "501": "Not Implemented",
+ "502": "Bad Gateway",
+ "503": "Service Unavailable",
+ "504": "Gateway Time-out",
+ "505": "HTTP Version not supported",
+}
ON_APP_ENGINE = all(key in os.environ for key in (
'USER_IS_ADMIN', 'CURRENT_VERSION_ID', 'APPLICATION_ID'))
@@ -91,201 +133,12 @@ PORTS_BY_SECURITY = { True: 443, False: 80 }
DEFAULT_CA_CERTS_FILE = os.path.join(
os.path.dirname(os.path.abspath(boto.cacerts.__file__ )), "cacerts.txt")
-class HostConnectionPool(object):
-
- """
- A pool of connections for one remote (host,is_secure).
-
- When connections are added to the pool, they are put into a
- pending queue. The _mexe method returns connections to the pool
- before the response body has been read, so they connections aren't
- ready to send another request yet. They stay in the pending queue
- until they are ready for another request, at which point they are
- returned to the pool of ready connections.
-
- The pool of ready connections is an ordered list of
- (connection,time) pairs, where the time is the time the connection
- was returned from _mexe. After a certain period of time,
- connections are considered stale, and discarded rather than being
- reused. This saves having to wait for the connection to time out
- if AWS has decided to close it on the other end because of
- inactivity.
-
- Thread Safety:
-
- This class is used only fram ConnectionPool while it's mutex
- is held.
- """
-
- def __init__(self):
- self.queue = []
-
- def size(self):
- """
- Returns the number of connections in the pool for this host.
- Some of the connections may still be in use, and may not be
- ready to be returned by get().
- """
- return len(self.queue)
-
- def put(self, conn):
- """
- Adds a connection to the pool, along with the time it was
- added.
- """
- self.queue.append((conn, time.time()))
-
- def get(self):
- """
- Returns the next connection in this pool that is ready to be
- reused. Returns None of there aren't any.
- """
- # Discard ready connections that are too old.
- self.clean()
-
- # Return the first connection that is ready, and remove it
- # from the queue. Connections that aren't ready are returned
- # to the end of the queue with an updated time, on the
- # assumption that somebody is actively reading the response.
- for _ in range(len(self.queue)):
- (conn, _) = self.queue.pop(0)
- if self._conn_ready(conn):
- return conn
- else:
- self.put(conn)
- return None
-
- def _conn_ready(self, conn):
- """
- There is a nice state diagram at the top of httplib.py. It
- indicates that once the response headers have been read (which
- _mexe does before adding the connection to the pool), a
- response is attached to the connection, and it stays there
- until it's done reading. This isn't entirely true: even after
- the client is done reading, the response may be closed, but
- not removed from the connection yet.
-
- This is ugly, reading a private instance variable, but the
- state we care about isn't available in any public methods.
- """
- if ON_APP_ENGINE:
- # Google App Engine implementation of HTTPConnection doesn't contain
- # _HTTPConnection__response attribute. Moreover, it's not possible
- # to determine if given connection is ready. Reusing connections
- # simply doesn't make sense with App Engine urlfetch service.
- return False
- else:
- response = getattr(conn, '_HTTPConnection__response', None)
- return (response is None) or response.isclosed()
-
- def clean(self):
- """
- Get rid of stale connections.
- """
- # Note that we do not close the connection here -- somebody
- # may still be reading from it.
- while len(self.queue) > 0 and self._pair_stale(self.queue[0]):
- self.queue.pop(0)
-
- def _pair_stale(self, pair):
- """
- Returns true of the (connection,time) pair is too old to be
- used.
- """
- (_conn, return_time) = pair
- now = time.time()
- return return_time + ConnectionPool.STALE_DURATION < now
-
-class ConnectionPool(object):
-
+class HTTPRequest(object):
"""
- A connection pool that expires connections after a fixed period of
- time. This saves time spent waiting for a connection that AWS has
- timed out on the other end.
-
- This class is thread-safe.
+ A data encapsulation class used for passing values to our HTTP client.
+ This is currently the 'requests' library.
"""
- #
- # The amout of time between calls to clean.
- #
-
- CLEAN_INTERVAL = 5.0
-
- #
- # How long before a connection becomes "stale" and won't be reused
- # again. The intention is that this time is less that the timeout
- # period that AWS uses, so we'll never try to reuse a connection
- # and find that AWS is timing it out.
- #
- # Experimentation in July 2011 shows that AWS starts timing things
- # out after three minutes. The 60 seconds here is conservative so
- # we should never hit that 3-minute timout.
- #
-
- STALE_DURATION = 60.0
-
- def __init__(self):
- # Mapping from (host,is_secure) to HostConnectionPool.
- # If a pool becomes empty, it is removed.
- self.host_to_pool = {}
- # The last time the pool was cleaned.
- self.last_clean_time = 0.0
- self.mutex = threading.Lock()
-
- def size(self):
- """
- Returns the number of connections in the pool.
- """
- return sum(pool.size() for pool in self.host_to_pool.values())
-
- def get_http_connection(self, host, is_secure):
- """
- Gets a connection from the pool for the named host. Returns
- None if there is no connection that can be reused. It's the caller's
- responsibility to call close() on the connection when it's no longer
- needed.
- """
- self.clean()
- with self.mutex:
- key = (host, is_secure)
- if key not in self.host_to_pool:
- return None
- return self.host_to_pool[key].get()
-
- def put_http_connection(self, host, is_secure, conn):
- """
- Adds a connection to the pool of connections that can be
- reused for the named host.
- """
- with self.mutex:
- key = (host, is_secure)
- if key not in self.host_to_pool:
- self.host_to_pool[key] = HostConnectionPool()
- self.host_to_pool[key].put(conn)
-
- def clean(self):
- """
- Clean up the stale connections in all of the pools, and then
- get rid of empty pools. Pools clean themselves every time a
- connection is fetched; this cleaning takes care of pools that
- aren't being used any more, so nothing is being gotten from
- them.
- """
- with self.mutex:
- now = time.time()
- if self.last_clean_time + self.CLEAN_INTERVAL < now:
- to_remove = []
- for (host, pool) in self.host_to_pool.items():
- pool.clean()
- if pool.size() == 0:
- to_remove.append(host)
- for host in to_remove:
- del self.host_to_pool[host]
- self.last_clean_time = now
-
-class HTTPRequest(object):
-
def __init__(self, method, protocol, host, port, path, auth_path,
params, headers, body):
"""Represents an HTTP request.
@@ -327,32 +180,26 @@ class HTTPRequest(object):
self.host = host
self.port = port
self.path = path
- if auth_path is None:
- auth_path = path
- self.auth_path = auth_path
+ self.auth_path = auth_path or path
self.params = params
+ self.body = body
+
# chunked Transfer-Encoding should act only on PUT request.
if headers and 'Transfer-Encoding' in headers and \
- headers['Transfer-Encoding'] == 'chunked' and \
- self.method != 'PUT':
+ headers['Transfer-Encoding'] == 'chunked' and \
+ self.method != 'PUT':
self.headers = headers.copy()
del self.headers['Transfer-Encoding']
else:
self.headers = headers
- self.body = body
def __str__(self):
return (('method:(%s) protocol:(%s) host(%s) port(%s) path(%s) '
- 'params(%s) headers(%s) body(%s)') % (self.method,
- self.protocol, self.host, self.port, self.path, self.params,
- self.headers, self.body))
+ 'params(%s) headers(%s) body(%s)') % (
+ self.method, self.protocol, self.host, self.port, self.path,
+ self.params, self.headers, self.body))
def authorize(self, connection, **kwargs):
- for key in self.headers:
- val = self.headers[key]
- if isinstance(val, unicode):
- self.headers[key] = urllib.quote_plus(val.encode('utf-8'))
-
connection._auth_handler.add_auth(self, **kwargs)
self.headers['User-Agent'] = UserAgent
@@ -427,15 +274,18 @@ class AWSAuthConnection(object):
"2.6 or later.")
self.ca_certificates_file = config.get_value(
'Boto', 'ca_certificates_file', DEFAULT_CA_CERTS_FILE)
- self.handle_proxy(proxy, proxy_port, proxy_user, proxy_pass)
# define exceptions from httplib that we want to catch and retry
- self.http_exceptions = (httplib.HTTPException, socket.error,
- socket.gaierror)
+ # TODO: Update for requests.
+ self.http_exceptions = (
+ httplib.HTTPException,
+ socket.error,
+ socket.gaierror
+ )
# define subclasses of the above that are not retryable.
self.http_unretryable_exceptions = []
if HAVE_HTTPS_CONNECTION:
self.http_unretryable_exceptions.append(
- https_connection.InvalidCertificateException)
+ requests.exceptions.SSLError)
# define values in socket exceptions we don't want to catch
self.socket_exception_values = (errno.EINTR,)
@@ -444,7 +294,7 @@ class AWSAuthConnection(object):
self.http_exceptions += https_connection_factory[1]
else:
self.https_connection_factory = None
- if (is_secure):
+ if is_secure:
self.protocol = 'https'
else:
self.protocol = 'http'
@@ -459,16 +309,10 @@ class AWSAuthConnection(object):
else:
self.port = PORTS_BY_SECURITY[is_secure]
- # Timeout used to tell httplib how long to wait for socket timeouts.
- # Default is to leave timeout unchanged, which will in turn result in
- # the socket's default global timeout being used. To specify a
- # timeout, set http_socket_timeout in Boto config. Regardless,
- # timeouts will only be applied if Python is 2.6 or greater.
- self.http_connection_kwargs = {}
- if (sys.version_info[0], sys.version_info[1]) >= (2, 6):
- if config.has_option('Boto', 'http_socket_timeout'):
- timeout = config.getint('Boto', 'http_socket_timeout')
- self.http_connection_kwargs['timeout'] = timeout
+ if config.has_option('Boto', 'http_socket_timeout'):
+ self.timeout = config.getint('Boto', 'http_socket_timeout')
+ else:
+ self.timeout = None
self.provider = Provider(provider,
aws_access_key_id,
@@ -479,7 +323,6 @@ class AWSAuthConnection(object):
if self.provider.host:
self.host = self.provider.host
- self._pool = ConnectionPool()
self._connection = (self.server_name(), self.is_secure)
self._last_rs = None
self._auth_handler = auth.get_auth_handler(
@@ -491,10 +334,6 @@ class AWSAuthConnection(object):
def _required_auth_capability(self):
return []
- def connection(self):
- return self.get_http_connection(*self._connection)
- connection = property(connection)
-
def aws_access_key_id(self):
return self.provider.access_key
aws_access_key_id = property(aws_access_key_id)
@@ -554,148 +393,6 @@ class AWSAuthConnection(object):
signature_host = '%s:%d' % (self.host, port)
return signature_host
- def handle_proxy(self, proxy, proxy_port, proxy_user, proxy_pass):
- self.proxy = proxy
- self.proxy_port = proxy_port
- self.proxy_user = proxy_user
- self.proxy_pass = proxy_pass
- if os.environ.has_key('http_proxy') and not self.proxy:
- pattern = re.compile(
- '(?:http://)?' \
- '(?:(?P<user>\w+):(?P<pass>.*)@)?' \
- '(?P<host>[\w\-\.]+)' \
- '(?::(?P<port>\d+))?'
- )
- match = pattern.match(os.environ['http_proxy'])
- if match:
- self.proxy = match.group('host')
- self.proxy_port = match.group('port')
- self.proxy_user = match.group('user')
- self.proxy_pass = match.group('pass')
- else:
- if not self.proxy:
- self.proxy = config.get_value('Boto', 'proxy', None)
- if not self.proxy_port:
- self.proxy_port = config.get_value('Boto', 'proxy_port', None)
- if not self.proxy_user:
- self.proxy_user = config.get_value('Boto', 'proxy_user', None)
- if not self.proxy_pass:
- self.proxy_pass = config.get_value('Boto', 'proxy_pass', None)
-
- if not self.proxy_port and self.proxy:
- print "http_proxy environment variable does not specify " \
- "a port, using default"
- self.proxy_port = self.port
- self.use_proxy = (self.proxy != None)
-
- def get_http_connection(self, host, is_secure):
- conn = self._pool.get_http_connection(host, is_secure)
- if conn is not None:
- return conn
- else:
- return self.new_http_connection(host, is_secure)
-
- def new_http_connection(self, host, is_secure):
- if self.use_proxy:
- host = '%s:%d' % (self.proxy, int(self.proxy_port))
- if host is None:
- host = self.server_name()
- if is_secure:
- boto.log.debug(
- 'establishing HTTPS connection: host=%s, kwargs=%s',
- host, self.http_connection_kwargs)
- if self.use_proxy:
- connection = self.proxy_ssl()
- elif self.https_connection_factory:
- connection = self.https_connection_factory(host)
- elif self.https_validate_certificates and HAVE_HTTPS_CONNECTION:
- connection = https_connection.CertValidatingHTTPSConnection(
- host, ca_certs=self.ca_certificates_file,
- **self.http_connection_kwargs)
- else:
- connection = httplib.HTTPSConnection(host,
- **self.http_connection_kwargs)
- else:
- boto.log.debug('establishing HTTP connection: kwargs=%s' %
- self.http_connection_kwargs)
- connection = httplib.HTTPConnection(host,
- **self.http_connection_kwargs)
- if self.debug > 1:
- connection.set_debuglevel(self.debug)
- # self.connection must be maintained for backwards-compatibility
- # however, it must be dynamically pulled from the connection pool
- # set a private variable which will enable that
- if host.split(':')[0] == self.host and is_secure == self.is_secure:
- self._connection = (host, is_secure)
- return connection
-
- def put_http_connection(self, host, is_secure, connection):
- self._pool.put_http_connection(host, is_secure, connection)
-
- def proxy_ssl(self):
- host = '%s:%d' % (self.host, self.port)
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- try:
- sock.connect((self.proxy, int(self.proxy_port)))
- except:
- raise
- boto.log.debug("Proxy connection: CONNECT %s HTTP/1.0\r\n", host)
- sock.sendall("CONNECT %s HTTP/1.0\r\n" % host)
- sock.sendall("User-Agent: %s\r\n" % UserAgent)
- if self.proxy_user and self.proxy_pass:
- for k, v in self.get_proxy_auth_header().items():
- sock.sendall("%s: %s\r\n" % (k, v))
- sock.sendall("\r\n")
- resp = httplib.HTTPResponse(sock, strict=True, debuglevel=self.debug)
- resp.begin()
-
- if resp.status != 200:
- # Fake a socket error, use a code that make it obvious it hasn't
- # been generated by the socket library
- raise socket.error(-71,
- "Error talking to HTTP proxy %s:%s: %s (%s)" %
- (self.proxy, self.proxy_port, resp.status, resp.reason))
-
- # We can safely close the response, it duped the original socket
- resp.close()
-
- h = httplib.HTTPConnection(host)
-
- if self.https_validate_certificates and HAVE_HTTPS_CONNECTION:
- boto.log.debug("wrapping ssl socket for proxied connection; "
- "CA certificate file=%s",
- self.ca_certificates_file)
- key_file = self.http_connection_kwargs.get('key_file', None)
- cert_file = self.http_connection_kwargs.get('cert_file', None)
- sslSock = ssl.wrap_socket(sock, keyfile=key_file,
- certfile=cert_file,
- cert_reqs=ssl.CERT_REQUIRED,
- ca_certs=self.ca_certificates_file)
- cert = sslSock.getpeercert()
- hostname = self.host.split(':', 0)[0]
- if not https_connection.ValidateCertificateHostname(cert, hostname):
- raise https_connection.InvalidCertificateException(
- hostname, cert, 'hostname mismatch')
- else:
- # Fallback for old Python without ssl.wrap_socket
- if hasattr(httplib, 'ssl'):
- sslSock = httplib.ssl.SSLSocket(sock)
- else:
- sslSock = socket.ssl(sock, None, None)
- sslSock = httplib.FakeSocket(sock, sslSock)
-
- # This is a bit unclean
- h.sock = sslSock
- return h
-
- def prefix_proxy_to_path(self, path, host=None):
- path = self.protocol + '://' + (host or self.server_name()) + path
- return path
-
- def get_proxy_auth_header(self):
- auth = base64.encodestring(self.proxy_user + ':' + self.proxy_pass)
- return {'Proxy-Authorization': 'Basic %s' % auth}
-
def _mexe(self, request, sender=None, override_num_retries=None,
retry_handler=None):
"""
@@ -707,11 +404,12 @@ class AWSAuthConnection(object):
Google group by Larry Bates. Thanks!
"""
+ boto.log.debug('')
+ boto.log.debug('>>>>>> Request Details >>>>>>')
boto.log.debug('Method: %s' % request.method)
boto.log.debug('Path: %s' % request.path)
- boto.log.debug('Data: %s' % request.body)
- boto.log.debug('Headers: %s' % request.headers)
boto.log.debug('Host: %s' % request.host)
+
response = None
body = None
e = None
@@ -720,28 +418,62 @@ class AWSAuthConnection(object):
else:
num_retries = override_num_retries
i = 0
- connection = self.get_http_connection(request.host, self.is_secure)
+
while i <= num_retries:
- # Use binary exponential backoff to desynchronize client requests
+ # Use binary exponential backoff to de-synchronize client requests
next_sleep = random.random() * (2 ** i)
try:
# we now re-sign each request before it is retried
boto.log.debug('Token: %s' % self.provider.security_token)
request.authorize(connection=self)
- if callable(sender):
- response = sender(connection, request.method, request.path,
- request.body, request.headers)
+
+ url = '%s://%s%s' % (
+ request.protocol,
+ request.host,
+ request.path
+ )
+
+ # This is really, really explicit, but meh.
+ if request.method == 'GET':
+ request_method = requests.get
+ elif request.method == 'POST':
+ request_method = requests.post
+ elif request.method == 'HEAD':
+ request_method = requests.head
+ elif request.method == 'PUT':
+ request_method = requests.put
+ elif request.method == 'DELETE':
+ request_method = requests.delete
else:
- connection.request(request.method, request.path,
- request.body, request.headers)
- response = connection.getresponse()
- location = response.getheader('location')
- # -- gross hack --
- # httplib gets confused with chunked responses to HEAD requests
- # so I have to fake it out
- if request.method == 'HEAD' and getattr(response,
- 'chunked', False):
- response.chunked = 0
+ raise BotoClientError(
+ "Unrecognized HTTP method: %s" % request.method
+ )
+
+ response = request_method(
+ url,
+ data=request.body,
+ headers=request.headers,
+ verify=self.https_validate_certificates,
+ timeout=self.timeout,
+ #config={'verbose': sys.stderr},
+ )
+ boto.log.debug('Headers: %s' % response.request.headers)
+ boto.log.debug('Params: %s' % response.request.params)
+ boto.log.debug('Data: %s' % request.body)
+
+ status_reason = HTTP_REASON_CODES.get(response.status_code, 'Unknown')
+ setattr(response, 'reason', status_reason)
+
+ boto.log.debug('')
+ boto.log.debug('<<<<<< Response Details <<<<<<')
+ boto.log.debug('Status: %s' % response.status_code)
+ boto.log.debug('Headers: %s' % response.headers)
+ boto.log.debug('Content: %s' % response.content)
+ boto.log.debug('<' * 30)
+ boto.log.debug('')
+
+ location = response.headers['location']
+
if callable(retry_handler):
status = retry_handler(response, i, next_sleep)
if status:
@@ -750,17 +482,19 @@ class AWSAuthConnection(object):
boto.log.debug(msg)
time.sleep(next_sleep)
continue
- if response.status == 500 or response.status == 503:
- msg = 'Received %d response. ' % response.status
+ if response.status_code == 500 or response.status_code == 503:
+ msg = 'Received %d response. ' % response.status_code
msg += 'Retrying in %3.1f seconds' % next_sleep
boto.log.debug(msg)
- body = response.read()
- elif response.status < 300 or response.status >= 400 or \
- not location:
- self.put_http_connection(request.host, self.is_secure,
- connection)
+ body = response.text
+ elif response.status_code < 300 or \
+ response.status_code >= 400 or \
+ not location:
+ # Success.
return response
else:
+ # Not sure what happened, appears to be a redir. Grab
+ # the components out of the 'location' header value.
scheme, request.host, request.path, \
params, query, fragment = urlparse.urlparse(location)
if query:
@@ -768,8 +502,7 @@ class AWSAuthConnection(object):
msg = 'Redirecting: %s' % scheme + '://'
msg += request.host + request.path
boto.log.debug(msg)
- connection = self.get_http_connection(request.host,
- scheme == 'https')
+ # Fall through to another re-try with the modified values.
continue
except self.http_exceptions, e:
for unretryable in self.http_unretryable_exceptions:
@@ -780,8 +513,6 @@ class AWSAuthConnection(object):
raise e
boto.log.debug('encountered %s exception, reconnecting' % \
e.__class__.__name__)
- connection = self.new_http_connection(request.host,
- self.is_secure)
time.sleep(next_sleep)
i += 1
# If we made it here, it's because we have exhausted our retries
@@ -789,7 +520,7 @@ class AWSAuthConnection(object):
# use it to raise an exception.
# Otherwise, raise the exception that must have already h#appened.
if response:
- raise BotoServerError(response.status, response.reason, body)
+ raise BotoServerError(response.status_code, status.reason, body)
elif e:
raise e
else:
@@ -801,23 +532,16 @@ class AWSAuthConnection(object):
path = self.get_path(path)
if auth_path is not None:
auth_path = self.get_path(auth_path)
- if params == None:
+ if params is None:
params = {}
else:
params = params.copy()
- if headers == None:
+ if headers is None:
headers = {}
else:
headers = headers.copy()
host = host or self.host
- if self.use_proxy:
- if not auth_path:
- auth_path = path
- path = self.prefix_proxy_to_path(path, host)
- if self.proxy_user and self.proxy_pass and not self.is_secure:
- # If is_secure, we don't have to set the proxy authentication
- # header here, we did that in the CONNECT to the proxy.
- headers.update(self.get_proxy_auth_header())
+
return HTTPRequest(method, self.protocol, host, self.port,
path, auth_path, params, headers, data)
@@ -880,56 +604,56 @@ class AWSQueryConnection(AWSAuthConnection):
if not parent:
parent = self
response = self.make_request(action, params, path, verb)
- body = response.read()
+ body = response.content
boto.log.debug(body)
if not body:
boto.log.error('Null body %s' % body)
- raise self.ResponseError(response.status, response.reason, body)
- elif response.status == 200:
+ raise self.ResponseError(response.status_code, response.reason, body)
+ elif response.status_code == 200:
rs = ResultSet(markers)
h = boto.handler.XmlHandler(rs, parent)
xml.sax.parseString(body, h)
return rs
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def get_object(self, action, params, cls, path='/',
parent=None, verb='GET'):
if not parent:
parent = self
response = self.make_request(action, params, path, verb)
- body = response.read()
+ body = response.content
boto.log.debug(body)
if not body:
boto.log.error('Null body %s' % body)
- raise self.ResponseError(response.status, response.reason, body)
- elif response.status == 200:
+ raise self.ResponseError(response.status_code, response.reason, body)
+ elif response.status_code == 200:
obj = cls(parent)
h = boto.handler.XmlHandler(obj, parent)
xml.sax.parseString(body, h)
return obj
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def get_status(self, action, params, path='/', parent=None, verb='GET'):
if not parent:
parent = self
response = self.make_request(action, params, path, verb)
- body = response.read()
+ body = response.content
boto.log.debug(body)
if not body:
boto.log.error('Null body %s' % body)
- raise self.ResponseError(response.status, response.reason, body)
- elif response.status == 200:
+ raise self.ResponseError(response.status_code, response.reason, body)
+ elif response.status_code == 200:
rs = ResultSet()
h = boto.handler.XmlHandler(rs, parent)
xml.sax.parseString(body, h)
return rs.status
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
diff --git a/boto/dynamodb/layer1.py b/boto/dynamodb/layer1.py
index d7b27f41..2ff77ce4 100644
--- a/boto/dynamodb/layer1.py
+++ b/boto/dynamodb/layer1.py
@@ -110,23 +110,24 @@ class Layer1(AWSAuthConnection):
"""
:raises: ``DynamoDBExpiredTokenError`` if the security token expires.
"""
- headers = {'X-Amz-Target' : '%s_%s.%s' % (self.ServiceName,
- self.Version, action),
- 'Content-Type' : 'application/x-amz-json-1.0',
- 'Content-Length' : str(len(body))}
+ headers = {
+ 'X-Amz-Target' : '%s_%s.%s' % (self.ServiceName, self.Version, action),
+ 'Content-Type' : 'application/x-amz-json-1.0',
+ 'Content-Length' : str(len(body)),
+ }
http_request = self.build_base_http_request('POST', '/', '/',
{}, headers, body, None)
response = self._mexe(http_request, sender=None,
override_num_retries=10,
retry_handler=self._retry_handler)
- response_body = response.read()
+ response_body = response.content
boto.log.debug(response_body)
return json.loads(response_body, object_hook=object_hook)
def _retry_handler(self, response, i, next_sleep):
status = None
- if response.status == 400:
- response_body = response.read()
+ if response.status_code == 400:
+ response_body = response.content
boto.log.debug(response_body)
json_response = json.loads(response_body)
if self.ThruputError in json_response.get('__type'):
@@ -144,7 +145,7 @@ class Layer1(AWSAuthConnection):
self._update_provider()
status = (msg, i+self.num_retries-1, next_sleep)
else:
- raise self.ResponseError(response.status, response.reason,
+ raise self.ResponseError(response.status_code, response.reason,
json_response)
return status
diff --git a/boto/ecs/__init__.py b/boto/ecs/__init__.py
index cbaf478a..abf298ad 100644
--- a/boto/ecs/__init__.py
+++ b/boto/ecs/__init__.py
@@ -58,13 +58,13 @@ class ECSConnection(AWSQueryConnection):
if page:
params['ItemPage'] = page
response = self.make_request(None, params, "/onca/xml")
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status != 200:
- boto.log.error('%s %s' % (response.status, response.reason))
+ if response.status_code != 200:
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
if itemSet == None:
rs = ItemSet(self, action, params, page)
diff --git a/boto/fps/connection.py b/boto/fps/connection.py
index 24b04d91..6094e003 100644
--- a/boto/fps/connection.py
+++ b/boto/fps/connection.py
@@ -83,8 +83,8 @@ class FPSConnection(AWSQueryConnection):
response = self.install_payment_instruction("MyRole=='Caller';",
token_type=token_type,
transaction_id=transaction_id)
- body = response.read()
- if(response.status == 200):
+ body = response.content
+ if response.status_code == 200:
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
@@ -92,12 +92,12 @@ class FPSConnection(AWSQueryConnection):
try:
boto.config.save_system_option("FPS", "caller_token",
caller_token)
- except(IOError):
+ except IOError:
boto.config.save_user_option("FPS", "caller_token",
caller_token)
return caller_token
else:
- raise FPSResponseError(response.status, response.reason, body)
+ raise FPSResponseError(response.status_code, response.reason, body)
def install_recipient_instruction(self, token_type="Unrestricted",
transaction_id=None):
@@ -109,8 +109,8 @@ class FPSConnection(AWSQueryConnection):
response = self.install_payment_instruction("MyRole=='Recipient';",
token_type=token_type,
transaction_id=transaction_id)
- body = response.read()
- if(response.status == 200):
+ body = response.content
+ if response.status_code == 200:
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
@@ -118,13 +118,13 @@ class FPSConnection(AWSQueryConnection):
try:
boto.config.save_system_option("FPS", "recipient_token",
recipient_token)
- except(IOError):
+ except IOError:
boto.config.save_user_option("FPS", "recipient_token",
recipient_token)
return recipient_token
else:
- raise FPSResponseError(response.status, response.reason, body)
+ raise FPSResponseError(response.status_code, response.reason, body)
def make_marketplace_registration_url(self, returnURL, pipelineName,
maxFixedFee=0.0, maxVariableFee=0.0,
@@ -266,14 +266,14 @@ class FPSConnection(AWSQueryConnection):
response = self.make_request("Reserve", params)
else:
response = self.make_request("Pay", params)
- body = response.read()
- if(response.status == 200):
+ body = response.content
+ if(response.status_code == 200):
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs
else:
- raise FPSResponseError(response.status, response.reason, body)
+ raise FPSResponseError(response.status_code, response.reason, body)
def get_transaction_status(self, transactionId):
"""
@@ -283,14 +283,14 @@ class FPSConnection(AWSQueryConnection):
params['TransactionId'] = transactionId
response = self.make_request("GetTransactionStatus", params)
- body = response.read()
- if(response.status == 200):
+ body = response.content
+ if(response.status_code == 200):
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs
else:
- raise FPSResponseError(response.status, response.reason, body)
+ raise FPSResponseError(response.status_code, response.reason, body)
def cancel(self, transactionId, description=None):
"""
@@ -302,14 +302,14 @@ class FPSConnection(AWSQueryConnection):
params['description'] = description
response = self.make_request("Cancel", params)
- body = response.read()
- if(response.status == 200):
+ body = response.content
+ if(response.status_code == 200):
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs
else:
- raise FPSResponseError(response.status, response.reason, body)
+ raise FPSResponseError(response.status_code, response.reason, body)
def settle(self, reserveTransactionId, transactionAmount=None):
"""
@@ -321,14 +321,14 @@ class FPSConnection(AWSQueryConnection):
params['TransactionAmount'] = transactionAmount
response = self.make_request("Settle", params)
- body = response.read()
- if(response.status == 200):
+ body = response.content
+ if(response.status_code == 200):
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs
else:
- raise FPSResponseError(response.status, response.reason, body)
+ raise FPSResponseError(response.status_code, response.reason, body)
def refund(self, callerReference, transactionId, refundAmount=None,
callerDescription=None):
@@ -345,14 +345,14 @@ class FPSConnection(AWSQueryConnection):
params['CallerDescription'] = callerDescription
response = self.make_request("Refund", params)
- body = response.read()
- if(response.status == 200):
+ body = response.content
+ if(response.status_code == 200):
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs
else:
- raise FPSResponseError(response.status, response.reason, body)
+ raise FPSResponseError(response.status_code, response.reason, body)
def get_recipient_verification_status(self, recipientTokenId):
"""
@@ -362,14 +362,14 @@ class FPSConnection(AWSQueryConnection):
params['RecipientTokenId'] = recipientTokenId
response = self.make_request("GetRecipientVerificationStatus", params)
- body = response.read()
- if(response.status == 200):
+ body = response.content
+ if(response.status_code == 200):
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs
else:
- raise FPSResponseError(response.status, response.reason, body)
+ raise FPSResponseError(response.status_code, response.reason, body)
def get_token_by_caller_reference(self, callerReference):
"""
@@ -379,14 +379,14 @@ class FPSConnection(AWSQueryConnection):
params['CallerReference'] = callerReference
response = self.make_request("GetTokenByCaller", params)
- body = response.read()
- if(response.status == 200):
+ body = response.content
+ if(response.status_code == 200):
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs
else:
- raise FPSResponseError(response.status, response.reason, body)
+ raise FPSResponseError(response.status_code, response.reason, body)
def get_token_by_caller_token(self, tokenId):
"""
@@ -396,14 +396,14 @@ class FPSConnection(AWSQueryConnection):
params['TokenId'] = tokenId
response = self.make_request("GetTokenByCaller", params)
- body = response.read()
- if(response.status == 200):
+ body = response.content
+ if(response.status_code == 200):
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs
else:
- raise FPSResponseError(response.status, response.reason, body)
+ raise FPSResponseError(response.status_code, response.reason, body)
def verify_signature(self, end_point_url, http_parameters):
params = dict(
@@ -411,9 +411,9 @@ class FPSConnection(AWSQueryConnection):
HttpParameters = http_parameters,
)
response = self.make_request("VerifySignature", params)
- body = response.read()
- if(response.status != 200):
- raise FPSResponseError(response.status, response.reason, body)
+ body = response.content
+ if(response.status_code != 200):
+ raise FPSResponseError(response.status_code, response.reason, body)
rs = ResultSet()
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
diff --git a/boto/gs/bucket.py b/boto/gs/bucket.py
index aa2d4c23..869a42c4 100644
--- a/boto/gs/bucket.py
+++ b/boto/gs/bucket.py
@@ -64,15 +64,15 @@ class Bucket(S3Bucket):
response = self.connection.make_request('GET', self.name, key_name,
query_args=query_args,
headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
acl = ACL(self)
h = handler.XmlHandler(acl, self)
xml.sax.parseString(body, h)
return acl
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def get_acl(self, key_name='', headers=None, version_id=None):
"""returns a bucket's acl. We include a version_id argument
@@ -97,10 +97,10 @@ class Bucket(S3Bucket):
response = self.connection.make_request('PUT', self.name, key_name,
headers=headers, query_args=query_args)
- body = response.read()
- if response.status != 200:
+ body = response.content
+ if response.status_code != 200:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def set_canned_acl(self, acl_str, key_name='', headers=None,
version_id=None):
diff --git a/boto/gs/connection.py b/boto/gs/connection.py
index 20b02203..59a6f8ae 100755
--- a/boto/gs/connection.py
+++ b/boto/gs/connection.py
@@ -82,13 +82,13 @@ class GSConnection(S3Connection):
'</CreateBucketConfiguration>' % location)
response = self.make_request('PUT', bucket_name, headers=headers,
data=data)
- body = response.read()
- if response.status == 409:
+ body = response.content
+ if response.status_code == 409:
raise self.provider.storage_create_error(
- response.status, response.reason, body)
- if response.status == 200:
+ response.status_code, response.reason, body)
+ if response.status_code == 200:
return self.bucket_class(self, bucket_name)
else:
raise self.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
diff --git a/boto/gs/resumable_upload_handler.py b/boto/gs/resumable_upload_handler.py
index 3959565a..93185a92 100644
--- a/boto/gs/resumable_upload_handler.py
+++ b/boto/gs/resumable_upload_handler.py
@@ -234,7 +234,7 @@ class ResumableUploadHandler(object):
if not got_valid_response:
raise ResumableUploadException(
'Couldn\'t parse upload server state query response (%s)' %
- str(resp.getheaders()), ResumableTransferDisposition.START_OVER)
+ str(resp.headers), ResumableTransferDisposition.START_OVER)
if conn.debug >= 1:
print 'Server has: Range: %d - %d.' % (server_start, server_end)
return (server_start, server_end)
diff --git a/boto/iam/connection.py b/boto/iam/connection.py
index ae68f337..5d8c3c55 100644
--- a/boto/iam/connection.py
+++ b/boto/iam/connection.py
@@ -54,18 +54,18 @@ class IAMConnection(AWSQueryConnection):
if not parent:
parent = self
response = self.make_request(action, params, path, verb)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status == 200:
+ if response.status_code == 200:
e = boto.jsonresponse.Element(list_marker=list_marker,
pythonize_name=True)
h = boto.jsonresponse.XmlHandler(e, parent)
h.parse(body)
return e
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
#
# Group methods
diff --git a/boto/mturk/connection.py b/boto/mturk/connection.py
index ecd3318e..65e01073 100644
--- a/boto/mturk/connection.py
+++ b/boto/mturk/connection.py
@@ -735,7 +735,7 @@ class MTurkConnection(AWSQueryConnection):
"""
Helper to process the xml response from AWS
"""
- body = response.read()
+ body = response.content
#print body
if '<Errors>' not in body:
rs = ResultSet(marker_elems)
@@ -743,7 +743,7 @@ class MTurkConnection(AWSQueryConnection):
xml.sax.parseString(body, h)
return rs
else:
- raise MTurkRequestError(response.status, response.reason, body)
+ raise MTurkRequestError(response.status_code, response.reason, body)
@staticmethod
def get_keywords_as_string(keywords):
diff --git a/boto/roboto/awsqueryrequest.py b/boto/roboto/awsqueryrequest.py
index 9e05ac63..03d95d44 100644
--- a/boto/roboto/awsqueryrequest.py
+++ b/boto/roboto/awsqueryrequest.py
@@ -201,7 +201,7 @@ class AWSQueryRequest(object):
def status(self):
retval = None
if self.http_response is not None:
- retval = self.http_response.status
+ retval = self.http_response.status_code
return retval
@property
@@ -298,19 +298,19 @@ class AWSQueryRequest(object):
self.http_response = conn.make_request(self.name(),
self.request_params,
verb=verb)
- self.body = self.http_response.read()
+ self.body = self.http_response.response
boto.log.debug(self.body)
- if self.http_response.status == 200:
+ if self.http_response.status_code == 200:
self.aws_response = boto.jsonresponse.Element(list_marker=self.list_markers,
item_marker=self.item_markers)
h = boto.jsonresponse.XmlHandler(self.aws_response, self)
h.parse(self.body)
return self.aws_response
else:
- boto.log.error('%s %s' % (self.http_response.status,
+ boto.log.error('%s %s' % (self.http_response.status_code,
self.http_response.reason))
boto.log.error('%s' % self.body)
- raise conn.ResponseError(self.http_response.status,
+ raise conn.ResponseError(self.http_response.status_code,
self.http_response.reason,
self.body)
diff --git a/boto/route53/connection.py b/boto/route53/connection.py
index 7c3f1b88..64ecd420 100644
--- a/boto/route53/connection.py
+++ b/boto/route53/connection.py
@@ -89,10 +89,10 @@ class Route53Connection(AWSAuthConnection):
params = {'marker': start_marker}
response = self.make_request('GET', '/%s/hostedzone' % self.Version,
params=params)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status >= 300:
- raise exception.DNSServerError(response.status,
+ if response.status_code >= 300:
+ raise exception.DNSServerError(response.status_code,
response.reason,
body)
e = boto.jsonresponse.Element(list_marker='HostedZones',
@@ -117,10 +117,10 @@ class Route53Connection(AWSAuthConnection):
"""
uri = '/%s/hostedzone/%s' % (self.Version, hosted_zone_id)
response = self.make_request('GET', uri)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status >= 300:
- raise exception.DNSServerError(response.status,
+ if response.status_code >= 300:
+ raise exception.DNSServerError(response.status_code,
response.reason,
body)
e = boto.jsonresponse.Element(list_marker='NameServers',
@@ -167,26 +167,26 @@ class Route53Connection(AWSAuthConnection):
uri = '/%s/hostedzone' % self.Version
response = self.make_request('POST', uri,
{'Content-Type' : 'text/xml'}, xml)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status == 201:
+ if response.status_code == 201:
e = boto.jsonresponse.Element(list_marker='NameServers',
item_marker=('NameServer',))
h = boto.jsonresponse.XmlHandler(e, None)
h.parse(body)
return e
else:
- raise exception.DNSServerError(response.status,
+ raise exception.DNSServerError(response.status_code,
response.reason,
body)
def delete_hosted_zone(self, hosted_zone_id):
uri = '/%s/hostedzone/%s' % (self.Version, hosted_zone_id)
response = self.make_request('DELETE', uri)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status not in (200, 204):
- raise exception.DNSServerError(response.status,
+ if response.status_code not in (200, 204):
+ raise exception.DNSServerError(response.status_code,
response.reason,
body)
e = boto.jsonresponse.Element()
@@ -253,10 +253,10 @@ class Route53Connection(AWSAuthConnection):
'Identifier': identifier, 'maxitems': maxitems}
uri = '/%s/hostedzone/%s/rrset' % (self.Version, hosted_zone_id)
response = self.make_request('GET', uri, params=params)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status >= 300:
- raise exception.DNSServerError(response.status,
+ if response.status_code >= 300:
+ raise exception.DNSServerError(response.status_code,
response.reason,
body)
rs = ResourceRecordSets(connection=self, hosted_zone_id=hosted_zone_id)
@@ -283,10 +283,10 @@ class Route53Connection(AWSAuthConnection):
response = self.make_request('POST', uri,
{'Content-Type' : 'text/xml'},
xml_body)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status >= 300:
- raise exception.DNSServerError(response.status,
+ if response.status_code >= 300:
+ raise exception.DNSServerError(response.status_code,
response.reason,
body)
e = boto.jsonresponse.Element()
@@ -308,10 +308,10 @@ class Route53Connection(AWSAuthConnection):
"""
uri = '/%s/change/%s' % (self.Version, change_id)
response = self.make_request('GET', uri)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status >= 300:
- raise exception.DNSServerError(response.status,
+ if response.status_code >= 300:
+ raise exception.DNSServerError(response.status_code,
response.reason,
body)
e = boto.jsonresponse.Element()
diff --git a/boto/s3/bucket.py b/boto/s3/bucket.py
index a1f0730a..25325a07 100644
--- a/boto/s3/bucket.py
+++ b/boto/s3/bucket.py
@@ -44,7 +44,6 @@ import xml.sax.saxutils
import StringIO
import urllib
import re
-import base64
from collections import defaultdict
# as per http://goo.gl/BDuud (02/19/2011)
@@ -59,8 +58,8 @@ class S3WebsiteEndpointTranslate:
trans_region['ap-southeast-1'] = 's3-website-ap-southeast-1'
@classmethod
- def translate_region(self, reg):
- return self.trans_region[reg]
+ def translate_region(cls, reg):
+ return cls.trans_region[reg]
S3Permissions = ['READ', 'WRITE', 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL']
@@ -169,41 +168,43 @@ class Bucket(object):
query_args = 'versionId=%s' % version_id
else:
query_args = None
- response = self.connection.make_request('HEAD', self.name, key_name,
+ response = self.connection.make_request('HEAD',
+ bucket=self.name,
+ key=key_name,
headers=headers,
query_args=query_args)
# Allow any success status (2xx) - for example this lets us
# support Range gets, which return status 206:
- if response.status/100 == 2:
- response.read()
+ if response.status_code / 100 == 2:
+ response.content
k = self.key_class(self)
provider = self.connection.provider
- k.metadata = boto.utils.get_aws_metadata(response.msg, provider)
- k.etag = response.getheader('etag')
- k.content_type = response.getheader('content-type')
- k.content_encoding = response.getheader('content-encoding')
- k.last_modified = response.getheader('last-modified')
+ k.metadata = boto.utils.get_aws_metadata(response.headers, provider)
+ k.etag = response.headers.get('etag')
+ k.content_type = response.headers.get('content-type')
+ k.content_encoding = response.headers.get('content-encoding')
+ k.last_modified = response.headers.get('last-modified')
# the following machinations are a workaround to the fact that
# apache/fastcgi omits the content-length header on HEAD
# requests when the content-length is zero.
# See http://goo.gl/0Tdax for more details.
- clen = response.getheader('content-length')
+ clen = response.headers.get('content-length')
if clen:
- k.size = int(response.getheader('content-length'))
+ k.size = int(response.headers.get('content-length'))
else:
k.size = 0
- k.cache_control = response.getheader('cache-control')
+ k.cache_control = response.headers.get('cache-control')
k.name = key_name
k.handle_version_headers(response)
k.handle_encryption_headers(response)
return k
else:
- if response.status == 404:
- response.read()
+ if response.status_code == 404:
+ response.content
return None
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, '')
+ response.status_code, response.reason, '')
def list(self, prefix='', delimiter='', marker='', headers=None):
"""
@@ -267,8 +268,8 @@ class Bucket(object):
http://docs.amazonwebservices.com/AmazonS3/2006-03-01/
for more details.
- :type marker: string
- :param marker: The "marker" of where you are in the result set
+ :type key_marker: string
+ :param key_marker: The "marker" of where you are in the result set
:rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet`
:return: an instance of a BucketListResultSet that handles paging, etc
@@ -285,8 +286,8 @@ class Bucket(object):
handles all of the result paging, etc. from S3. You just need
to keep iterating until there are no more results.
- :type marker: string
- :param marker: The "marker" of where you are in the result set
+ :type key_marker: string
+ :param key_marker: The "marker" of where you are in the result set
:rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet`
:return: an instance of a BucketListResultSet that handles paging, etc
@@ -313,16 +314,16 @@ class Bucket(object):
response = self.connection.make_request('GET', self.name,
headers=headers,
query_args=s)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status == 200:
+ if response.status_code == 200:
rs = ResultSet(element_map)
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def get_all_keys(self, headers=None, **params):
"""
@@ -543,13 +544,13 @@ class Bucket(object):
headers=hdrs,
query_args=query_args,
data=data)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
h = handler.XmlHandler(result, self)
xml.sax.parseString(body, h)
return count >= 1000 # more?
else:
- raise provider.storage_response_error(response.status,
+ raise provider.storage_response_error(response.status_code,
response.reason,
body)
while delete_keys2(headers):
@@ -588,9 +589,9 @@ class Bucket(object):
response = self.connection.make_request('DELETE', self.name, key_name,
headers=headers,
query_args=query_args)
- body = response.read()
- if response.status != 204:
- raise provider.storage_response_error(response.status,
+ body = response.content
+ if response.status_code != 204:
+ raise provider.storage_response_error(response.status_code,
response.reason, body)
def copy_key(self, new_key_name, src_bucket_name,
@@ -683,8 +684,8 @@ class Bucket(object):
response = self.connection.make_request('PUT', self.name, new_key_name,
headers=headers,
query_args=query_args)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
key = self.new_key(new_key_name)
h = handler.XmlHandler(key, self)
xml.sax.parseString(body, h)
@@ -695,7 +696,7 @@ class Bucket(object):
self.set_xml_acl(acl, new_key_name)
return key
else:
- raise provider.storage_response_error(response.status,
+ raise provider.storage_response_error(response.status_code,
response.reason, body)
def set_canned_acl(self, acl_str, key_name='', headers=None,
@@ -712,10 +713,10 @@ class Bucket(object):
query_args += '&versionId=%s' % version_id
response = self.connection.make_request('PUT', self.name, key_name,
headers=headers, query_args=query_args)
- body = response.read()
- if response.status != 200:
+ body = response.content
+ if response.status_code != 200:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def get_xml_acl(self, key_name='', headers=None, version_id=None):
query_args = 'acl'
@@ -724,24 +725,26 @@ class Bucket(object):
response = self.connection.make_request('GET', self.name, key_name,
query_args=query_args,
headers=headers)
- body = response.read()
- if response.status != 200:
+ body = response.content
+ if response.status_code != 200:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
return body
def set_xml_acl(self, acl_str, key_name='', headers=None, version_id=None,
query_args='acl'):
if version_id:
query_args += '&versionId=%s' % version_id
+ headers = headers or {}
+ headers['Content-Type'] = 'text/xml'
response = self.connection.make_request('PUT', self.name, key_name,
data=acl_str.encode('ISO-8859-1'),
query_args=query_args,
headers=headers)
- body = response.read()
- if response.status != 200:
+ body = response.content
+ if response.status_code != 200:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def set_acl(self, acl_or_str, key_name='', headers=None, version_id=None):
if isinstance(acl_or_str, Policy):
@@ -758,15 +761,15 @@ class Bucket(object):
response = self.connection.make_request('GET', self.name, key_name,
query_args=query_args,
headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
policy = Policy(self)
h = handler.XmlHandler(policy, self)
xml.sax.parseString(body, h)
return policy
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def set_subresource(self, subresource, value, key_name = '', headers=None,
version_id=None):
@@ -786,8 +789,8 @@ class Bucket(object):
:type headers: dict
:param headers: Additional HTTP headers to include in the request.
- :type src_version_id: string
- :param src_version_id: Optional. The version id of the key to operate
+ :type version_id: string
+ :param version_id: Optional. The version id of the key to operate
on. If not specified, operate on the newest
version.
"""
@@ -796,14 +799,16 @@ class Bucket(object):
query_args = subresource
if version_id:
query_args += '&versionId=%s' % version_id
+ headers = headers or {}
+ headers['Content-Type'] = 'text/xml'
response = self.connection.make_request('PUT', self.name, key_name,
data=value.encode('UTF-8'),
query_args=query_args,
headers=headers)
- body = response.read()
- if response.status != 200:
+ body = response.content
+ if response.status_code != 200:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def get_subresource(self, subresource, key_name='', headers=None,
version_id=None):
@@ -820,8 +825,8 @@ class Bucket(object):
:type headers: dict
:param headers: Additional HTTP headers to include in the request.
- :type src_version_id: string
- :param src_version_id: Optional. The version id of the key to operate
+ :type version_id: string
+ :param version_id: Optional. The version id of the key to operate
on. If not specified, operate on the newest
version.
@@ -836,10 +841,10 @@ class Bucket(object):
response = self.connection.make_request('GET', self.name, key_name,
query_args=query_args,
headers=headers)
- body = response.read()
- if response.status != 200:
+ body = response.content
+ if response.status_code != 200:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
return body
def make_public(self, recursive=False, headers=None):
@@ -939,49 +944,53 @@ class Bucket(object):
"""
response = self.connection.make_request('GET', self.name,
query_args='location')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
rs = ResultSet(self)
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
return rs.LocationConstraint
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def enable_logging(self, target_bucket, target_prefix='', headers=None):
if isinstance(target_bucket, Bucket):
target_bucket = target_bucket.name
body = self.BucketLoggingBody % (target_bucket, target_prefix)
+ headers = headers or {}
+ headers['Content-Type'] = 'text/xml'
response = self.connection.make_request('PUT', self.name, data=body,
query_args='logging', headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return True
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def disable_logging(self, headers=None):
body = self.EmptyBucketLoggingBody
+ headers = headers or {}
+ headers['Content-Type'] = 'text/xml'
response = self.connection.make_request('PUT', self.name, data=body,
query_args='logging', headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return True
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def get_logging_status(self, headers=None):
response = self.connection.make_request('GET', self.name,
query_args='logging', headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return body
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def set_as_logging_target(self, headers=None):
policy = self.get_acl(headers=headers)
@@ -994,23 +1003,25 @@ class Bucket(object):
def get_request_payment(self, headers=None):
response = self.connection.make_request('GET', self.name,
query_args='requestPayment', headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return body
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def set_request_payment(self, payer='BucketOwner', headers=None):
body = self.BucketPaymentBody % payer
+ headers = headers or {}
+ headers['Content-Type'] = 'text/xml'
response = self.connection.make_request('PUT', self.name, data=body,
query_args='requestPayment', headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return True
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def configure_versioning(self, versioning, mfa_delete=False,
mfa_token=None, headers=None):
@@ -1053,14 +1064,16 @@ class Bucket(object):
headers = {}
provider = self.connection.provider
headers[provider.mfa_header] = ' '.join(mfa_token)
+ headers = headers or {}
+ headers['Content-Type'] = 'text/xml'
response = self.connection.make_request('PUT', self.name, data=body,
query_args='versioning', headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return True
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def get_versioning_status(self, headers=None):
"""
@@ -1076,9 +1089,9 @@ class Bucket(object):
"""
response = self.connection.make_request('GET', self.name,
query_args='versioning', headers=headers)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status == 200:
+ if response.status_code == 200:
d = {}
ver = re.search(self.VersionRE, body)
if ver:
@@ -1089,7 +1102,7 @@ class Bucket(object):
return d
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def configure_lifecycle(self, lifecycle_config, headers=None):
"""
@@ -1109,12 +1122,12 @@ class Bucket(object):
data=fp.getvalue(),
query_args='lifecycle',
headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return True
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def get_lifecycle_config(self, headers=None):
"""
@@ -1126,16 +1139,16 @@ class Bucket(object):
"""
response = self.connection.make_request('GET', self.name,
query_args='lifecycle', headers=headers)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status == 200:
+ if response.status_code == 200:
lifecycle = Lifecycle(self)
h = handler.XmlHandler(lifecycle, self)
xml.sax.parseString(body, h)
return lifecycle
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def delete_lifecycle_configuration(self, headers=None):
"""
@@ -1144,13 +1157,13 @@ class Bucket(object):
response = self.connection.make_request('DELETE', self.name,
query_args='lifecycle',
headers=headers)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status == 204:
+ if response.status_code == 204:
return True
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def configure_website(self, suffix, error_key='', headers=None):
"""
@@ -1175,15 +1188,17 @@ class Bucket(object):
else:
error_frag = ''
body = self.WebsiteBody % (suffix, error_frag)
+ headers = headers or {}
+ headers['Content-Type'] = 'text/xml'
response = self.connection.make_request('PUT', self.name, data=body,
query_args='website',
headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return True
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def get_website_configuration(self, headers=None):
"""
@@ -1205,16 +1220,16 @@ class Bucket(object):
"""
response = self.connection.make_request('GET', self.name,
query_args='website', headers=headers)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status == 200:
+ if response.status_code == 200:
e = boto.jsonresponse.Element()
h = boto.jsonresponse.XmlHandler(e, None)
h.parse(body)
return e
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def delete_website_configuration(self, headers=None):
"""
@@ -1222,13 +1237,13 @@ class Bucket(object):
"""
response = self.connection.make_request('DELETE', self.name,
query_args='website', headers=headers)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status == 204:
+ if response.status_code == 204:
return True
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def get_website_endpoint(self):
"""
@@ -1236,9 +1251,11 @@ class Bucket(object):
bucket as a website. This doesn't validate whether the bucket has
been correctly configured as a website or not.
"""
- l = [self.name]
- l.append(S3WebsiteEndpointTranslate.translate_region(self.get_location()))
- l.append('.'.join(self.connection.host.split('.')[-2:]))
+ l = [
+ self.name,
+ S3WebsiteEndpointTranslate.translate_region(self.get_location()),
+ '.'.join(self.connection.host.split('.')[-2:]),
+ ]
return '.'.join(l)
def get_policy(self, headers=None):
@@ -1248,12 +1265,12 @@ class Bucket(object):
"""
response = self.connection.make_request('GET', self.name,
query_args='policy', headers=headers)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return body
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def set_policy(self, policy, headers=None):
"""
@@ -1262,28 +1279,30 @@ class Bucket(object):
:type policy: str
:param policy: The JSON policy as a string.
"""
+ headers = headers or {}
+ headers['Content-Type'] = 'text/json'
response = self.connection.make_request('PUT', self.name,
data=policy,
query_args='policy',
headers=headers)
- body = response.read()
- if response.status >= 200 and response.status <= 204:
+ body = response.content
+ if response.status_code >= 200 and response.status_code <= 204:
return True
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def delete_policy(self, headers=None):
response = self.connection.make_request('DELETE', self.name,
data='/?policy',
query_args='policy',
headers=headers)
- body = response.read()
- if response.status >= 200 and response.status <= 204:
+ body = response.content
+ if response.status_code >= 200 and response.status_code <= 204:
return True
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def initiate_multipart_upload(self, key_name, headers=None,
@@ -1340,16 +1359,16 @@ class Bucket(object):
response = self.connection.make_request('POST', self.name, key_name,
query_args=query_args,
headers=headers)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status == 200:
+ if response.status_code == 200:
resp = MultiPartUpload(self)
h = handler.XmlHandler(resp, self)
xml.sax.parseString(body, h)
return resp
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def complete_multipart_upload(self, key_name, upload_id,
xml_body, headers=None):
@@ -1364,32 +1383,32 @@ class Bucket(object):
query_args=query_args,
headers=headers, data=xml_body)
contains_error = False
- body = response.read()
+ body = response.content
# Some errors will be reported in the body of the response
# even though the HTTP response code is 200. This check
# does a quick and dirty peek in the body for an error element.
if body.find('<Error>') > 0:
contains_error = True
boto.log.debug(body)
- if response.status == 200 and not contains_error:
+ if response.status_code == 200 and not contains_error:
resp = CompleteMultiPartUpload(self)
h = handler.XmlHandler(resp, self)
xml.sax.parseString(body, h)
return resp
else:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def cancel_multipart_upload(self, key_name, upload_id, headers=None):
query_args = 'uploadId=%s' % upload_id
response = self.connection.make_request('DELETE', self.name, key_name,
query_args=query_args,
headers=headers)
- body = response.read()
+ body = response.content
boto.log.debug(body)
- if response.status != 204:
+ if response.status_code != 204:
raise self.connection.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def delete(self, headers=None):
return self.connection.delete_bucket(self.name, headers=headers)
diff --git a/boto/s3/connection.py b/boto/s3/connection.py
index c757c137..dd878d13 100644
--- a/boto/s3/connection.py
+++ b/boto/s3/connection.py
@@ -339,10 +339,10 @@ class S3Connection(AWSAuthConnection):
def get_all_buckets(self, headers=None):
response = self.make_request('GET', headers=headers)
- body = response.read()
- if response.status > 300:
+ body = response.content
+ if response.status_code > 300:
raise self.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
rs = ResultSet([('Bucket', self.bucket_class)])
h = handler.XmlHandler(rs, self)
xml.sax.parseString(body, h)
@@ -411,22 +411,22 @@ class S3Connection(AWSAuthConnection):
location + '</LocationConstraint></CreateBucketConstraint>'
response = self.make_request('PUT', bucket_name, headers=headers,
data=data)
- body = response.read()
- if response.status == 409:
+ body = response.content
+ if response.status_code == 409:
raise self.provider.storage_create_error(
- response.status, response.reason, body)
- if response.status == 200:
+ response.status_code, response.reason, body)
+ if response.status_code == 200:
return self.bucket_class(self, bucket_name)
else:
raise self.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def delete_bucket(self, bucket, headers=None):
response = self.make_request('DELETE', bucket, headers=headers)
- body = response.read()
- if response.status != 204:
+ body = response.content
+ if response.status_code != 204:
raise self.provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
def make_request(self, method, bucket='', key='', headers=None, data='',
query_args=None, sender=None, override_num_retries=None):
diff --git a/boto/s3/key.py b/boto/s3/key.py
index 206bcb6e..15e32281 100644
--- a/boto/s3/key.py
+++ b/boto/s3/key.py
@@ -109,12 +109,12 @@ class Key(object):
base64md5 = base64.encodestring(digest)
if base64md5[-1] == '\n':
base64md5 = base64md5[0:-1]
- return (md5_hexdigest, base64md5)
+ return md5_hexdigest, base64md5
def handle_encryption_headers(self, resp):
provider = self.bucket.connection.provider
if provider.server_side_encryption_header:
- self.encrypted = resp.getheader(provider.server_side_encryption_header, None)
+ self.encrypted = resp.headers.get(provider.server_side_encryption_header, None)
else:
self.encrypted = None
@@ -126,10 +126,10 @@ class Key(object):
# version of the Key. In that case, we don't really want to
# overwrite the version_id in this Key object. Comprende?
if self.version_id is None or force:
- self.version_id = resp.getheader(provider.version_id, None)
- self.source_version_id = resp.getheader(provider.copy_source_version_id,
+ self.version_id = resp.headers.get(provider.version_id, None)
+ self.source_version_id = resp.headers.get(provider.copy_source_version_id,
None)
- if resp.getheader(provider.delete_marker, 'false') == 'true':
+ if resp.headers.get(provider.delete_marker, 'false') == 'true':
self.delete_marker = True
else:
self.delete_marker = False
@@ -155,7 +155,7 @@ class Key(object):
the stored object in the response.
See http://goo.gl/EWOPb for details.
"""
- if self.resp == None:
+ if self.resp is None:
self.mode = 'r'
provider = self.bucket.connection.provider
@@ -163,14 +163,15 @@ class Key(object):
'GET', self.bucket.name, self.name, headers,
query_args=query_args,
override_num_retries=override_num_retries)
- if self.resp.status < 199 or self.resp.status > 299:
- body = self.resp.read()
- raise provider.storage_response_error(self.resp.status,
+
+ if self.resp.status_code < 199 or self.resp.status_code > 299:
+ body = self.resp.content
+ raise provider.storage_response_error(self.resp.status_code,
self.resp.reason, body)
- response_headers = self.resp.msg
+ response_headers = self.resp.headers
self.metadata = boto.utils.get_aws_metadata(response_headers,
provider)
- for name,value in response_headers.items():
+ for name, value in response_headers.items():
# To get correct size for Range GETs, use Content-Range
# header if one was returned. If not, use Content-Length
# header.
@@ -222,8 +223,7 @@ class Key(object):
closed = False
def close(self):
- if self.resp:
- self.resp.read()
+ # TODO: This may not be necessary anymore with requests integrated.
self.resp = None
self.mode = None
self.closed = True
@@ -239,18 +239,29 @@ class Key(object):
All of the HTTP connection stuff is handled for you.
"""
self.open_read()
- data = self.resp.read(self.BufferSize)
+ data = self.resp.iter_content(chunk_size=self.BufferSize)
if not data:
self.close()
raise StopIteration
return data
def read(self, size=0):
+ """
+ Reads either the entire contents of the key at once (by default),
+ or returns an iterator with the given chunk size.
+
+ :keyword int size: Chunk size for the iterator, if non-zero.
+
+ :rtype: bytes or iterator of bytes
+ :returns: If no ``size`` is specified, returns the entire contents
+ of the key. If ``size`` is specified, returns an iterator with
+ the given chunk size.
+ """
self.open_read()
- if size == 0:
- data = self.resp.read()
+ if size is 0:
+ data = self.resp.content
else:
- data = self.resp.read(size)
+ data = self.resp.iter_content(chunk_size=size)
if not data:
self.close()
return data
@@ -501,6 +512,7 @@ class Key(object):
spos = None
self.read_from_stream = False
+ # TODO: Replace this with requests implementation, once it exists.
def sender(http_conn, method, path, data, headers):
# This function is called repeatedly for temporary retries
# so we must be sure the file pointer is pointing at the
@@ -601,22 +613,22 @@ class Key(object):
cb(data_len, cb_size)
response = http_conn.getresponse()
- body = response.read()
+ body = response.content
http_conn.set_debuglevel(save_debug)
self.bucket.connection.debug = save_debug
- if ((response.status == 500 or response.status == 503 or
- response.getheader('location')) and not chunked_transfer):
+ if ((response.status_code == 500 or response.status_code == 503 or
+ response.headers.get('location')) and not chunked_transfer):
# we'll try again.
return response
- elif response.status >= 200 and response.status <= 299:
- self.etag = response.getheader('etag')
+ elif response.status_code >= 200 and response.status_code <= 299:
+ self.etag = response.headers.get('etag')
if self.etag != '"%s"' % self.md5:
raise provider.storage_data_error(
'ETag from S3 did not match computed MD5')
return response
else:
raise provider.storage_response_error(
- response.status, response.reason, body)
+ response.status_code, response.reason, body)
if not headers:
headers = {}
@@ -639,7 +651,7 @@ class Key(object):
del headers['Content-Type']
elif self.path:
self.content_type = mimetypes.guess_type(self.path)[0]
- if self.content_type == None:
+ if self.content_type is None:
self.content_type = self.DefaultContentType
headers['Content-Type'] = self.content_type
else:
@@ -768,7 +780,7 @@ class Key(object):
if provider.storage_class_header:
headers[provider.storage_class_header] = self.storage_class
- if self.bucket != None:
+ if self.bucket is not None:
if not replace:
if self.bucket.lookup(self.name):
return
@@ -1046,7 +1058,7 @@ class Key(object):
:type fp: file
:param fp: File pointer to put the data into
- :type headers: string
+ :type headers: dict
:param: headers to send when retrieving the files
:type cb: function
@@ -1077,6 +1089,16 @@ class Key(object):
the stored object in the response.
See http://goo.gl/EWOPb for details.
"""
+ if cb:
+ if num_cb > 2:
+ cb_count = self.size / self.BufferSize / (num_cb - 2)
+ elif num_cb < 0:
+ cb_count = -1
+ else:
+ cb_count = 0
+ i = total_bytes = 0
+ cb(total_bytes, self.size)
+
save_debug = self.bucket.connection.debug
if self.bucket.connection.debug == 1:
self.bucket.connection.debug = 0
@@ -1093,33 +1115,17 @@ class Key(object):
if version_id is None:
version_id = self.version_id
if version_id:
+ # TODO: Do we need to be assembling strings anymore with requests?
query_args.append('versionId=%s' % version_id)
if response_headers:
+ # TODO: Is this necessary with requests?
for key in response_headers:
query_args.append('%s=%s' % (key, urllib.quote(response_headers[key])))
query_args = '&'.join(query_args)
self.open('r', headers, query_args=query_args,
override_num_retries=override_num_retries)
- data_len = 0
- if cb:
- if self.size is None:
- cb_size = 0
- else:
- cb_size = self.size
- if self.size is None and num_cb != -1:
- # If size is not available due to chunked transfer for example,
- # we'll call the cb for every 1MB of data transferred.
- cb_count = (1024 * 1024)/self.BufferSize
- elif num_cb > 1:
- cb_count = int(math.ceil(cb_size/self.BufferSize/(num_cb-1.0)))
- elif num_cb < 0:
- cb_count = -1
- else:
- cb_count = 0
- i = 0
- cb(data_len, cb_size)
- for bytes in self:
+ for bytes in self.read(size=self.BufferSize):
fp.write(bytes)
data_len += len(bytes)
if m:
@@ -1205,7 +1211,7 @@ class Key(object):
:param torrent: If True, returns the contents of a torrent
file as a string.
- :type res_upload_handler: ResumableDownloadHandler
+ :type res_download_handler: ResumableDownloadHandler
:param res_download_handler: If provided, this handler will
perform the download.
@@ -1215,7 +1221,7 @@ class Key(object):
the stored object in the response.
See http://goo.gl/EWOPb for details.
"""
- if self.bucket != None:
+ if self.bucket is not None:
if res_download_handler:
res_download_handler.get_file(self, fp, headers, cb, num_cb,
torrent=torrent,
@@ -1262,7 +1268,7 @@ class Key(object):
:param torrent: If True, returns the contents of a torrent file
as a string.
- :type res_upload_handler: ResumableDownloadHandler
+ :type res_download_handler: ResumableDownloadHandler
:param res_download_handler: If provided, this handler will
perform the download.
@@ -1279,7 +1285,7 @@ class Key(object):
response_headers=response_headers)
fp.close()
# if last_modified date was sent from s3, try to set file's timestamp
- if self.last_modified != None:
+ if self.last_modified is not None:
try:
modified_tuple = rfc822.parsedate_tz(self.last_modified)
modified_stamp = int(rfc822.mktime_tz(modified_tuple))
@@ -1348,15 +1354,6 @@ class Key(object):
:type email_address: string
:param email_address: The email address associated with the AWS
account your are granting the permission to.
-
- :type recursive: boolean
- :param recursive: A boolean value to controls whether the command
- will apply the grant to all keys within the bucket
- or not. The default value is False. By passing a
- True value, the call will iterate through all keys
- in the bucket and apply the same grant to each key.
- CAUTION: If you have a lot of keys, this could take
- a long time!
"""
policy = self.get_acl(headers=headers)
policy.acl.add_email_grant(permission, email_address)
diff --git a/boto/s3/multipart.py b/boto/s3/multipart.py
index 4eddc397..dde83464 100644
--- a/boto/s3/multipart.py
+++ b/boto/s3/multipart.py
@@ -204,8 +204,8 @@ class MultiPartUpload(object):
response = self.bucket.connection.make_request('GET', self.bucket.name,
self.key_name,
query_args=query_args)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
h = handler.XmlHandler(self, self)
xml.sax.parseString(body, h)
return self._parts
diff --git a/boto/s3/resumable_download_handler.py b/boto/s3/resumable_download_handler.py
index ffa20957..9efb0f28 100644
--- a/boto/s3/resumable_download_handler.py
+++ b/boto/s3/resumable_download_handler.py
@@ -222,7 +222,7 @@ class ResumableDownloadHandler(object):
:type fp: file
:param fp: File pointer into which data should be downloaded
- :type headers: string
+ :type headers: dict
:param: headers to send when retrieving the files
:type cb: function
diff --git a/boto/sdb/connection.py b/boto/sdb/connection.py
index f0431932..44299a2e 100644
--- a/boto/sdb/connection.py
+++ b/boto/sdb/connection.py
@@ -491,15 +491,15 @@ class SDBConnection(AWSQueryConnection):
attribute_names = [attribute_names]
self.build_list_params(params, attribute_names, 'AttributeName')
response = self.make_request('GetAttributes', params)
- body = response.read()
- if response.status == 200:
- if item == None:
+ body = response.content
+ if response.status_code == 200:
+ if item is None:
item = self.item_cls(domain, item_name)
h = handler.XmlHandler(item, self)
xml.sax.parseString(body, h)
return item
else:
- raise SDBResponseError(response.status, response.reason, body)
+ raise SDBResponseError(response.status_code, response.reason, body)
def delete_attributes(self, domain_or_name, item_name, attr_names=None,
expected_value=None):
diff --git a/boto/ses/connection.py b/boto/ses/connection.py
index c9ae41d4..6d479c45 100644
--- a/boto/ses/connection.py
+++ b/boto/ses/connection.py
@@ -97,8 +97,8 @@ class SESConnection(AWSAuthConnection):
headers=headers,
data=urllib.urlencode(params)
)
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
list_markers = ('VerifiedEmailAddresses', 'SendDataPoints')
e = boto.jsonresponse.Element(list_marker=list_markers)
h = boto.jsonresponse.XmlHandler(e, None)
@@ -115,7 +115,7 @@ class SESConnection(AWSAuthConnection):
errors share the same HTTP response code, meaning we have to get really
kludgey and do string searches to figure out what went wrong.
"""
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
if "Address blacklisted." in body:
@@ -149,7 +149,7 @@ class SESConnection(AWSAuthConnection):
ExceptionToRaise = self.ResponseError
exc_reason = response.reason
- raise ExceptionToRaise(response.status, exc_reason, body)
+ raise ExceptionToRaise(response.status_code, exc_reason, body)
def send_email(self, source, subject, body, to_addresses, cc_addresses=None,
bcc_addresses=None, format='text', reply_addresses=None,
diff --git a/boto/sns/connection.py b/boto/sns/connection.py
index 6ce4ff19..2bc1ad0b 100644
--- a/boto/sns/connection.py
+++ b/boto/sns/connection.py
@@ -66,13 +66,13 @@ class SNSConnection(AWSQueryConnection):
if next_token:
params['NextToken'] = next_token
response = self.make_request('ListTopics', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def get_topic_attributes(self, topic):
"""
@@ -85,13 +85,13 @@ class SNSConnection(AWSQueryConnection):
params = {'ContentType' : 'JSON',
'TopicArn' : topic}
response = self.make_request('GetTopicAttributes', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def set_topic_attributes(self, topic, attr_name, attr_value):
"""
@@ -114,13 +114,13 @@ class SNSConnection(AWSQueryConnection):
'AttributeName' : attr_name,
'AttributeValue' : attr_value}
response = self.make_request('SetTopicAttributes', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def add_permission(self, topic, label, account_ids, actions):
"""
@@ -148,13 +148,13 @@ class SNSConnection(AWSQueryConnection):
self.build_list_params(params, account_ids, 'AWSAccountId')
self.build_list_params(params, actions, 'ActionName')
response = self.make_request('AddPermission', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def remove_permission(self, topic, label):
"""
@@ -172,13 +172,13 @@ class SNSConnection(AWSQueryConnection):
'TopicArn' : topic,
'Label' : label}
response = self.make_request('RemovePermission', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def create_topic(self, topic):
"""
@@ -191,13 +191,13 @@ class SNSConnection(AWSQueryConnection):
params = {'ContentType' : 'JSON',
'Name' : topic}
response = self.make_request('CreateTopic', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def delete_topic(self, topic):
"""
@@ -210,13 +210,13 @@ class SNSConnection(AWSQueryConnection):
params = {'ContentType' : 'JSON',
'TopicArn' : topic}
response = self.make_request('DeleteTopic', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
@@ -243,13 +243,13 @@ class SNSConnection(AWSQueryConnection):
if subject:
params['Subject'] = subject
response = self.make_request('Publish', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def subscribe(self, topic, protocol, endpoint):
"""
@@ -278,13 +278,13 @@ class SNSConnection(AWSQueryConnection):
'Protocol' : protocol,
'Endpoint' : endpoint}
response = self.make_request('Subscribe', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def subscribe_sqs_queue(self, topic, queue):
"""
@@ -353,13 +353,13 @@ class SNSConnection(AWSQueryConnection):
if authenticate_on_unsubscribe:
params['AuthenticateOnUnsubscribe'] = 'true'
response = self.make_request('ConfirmSubscription', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def unsubscribe(self, subscription):
"""
@@ -373,13 +373,13 @@ class SNSConnection(AWSQueryConnection):
params = {'ContentType' : 'JSON',
'SubscriptionArn' : subscription}
response = self.make_request('Unsubscribe', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def get_all_subscriptions(self, next_token=None):
"""
@@ -394,13 +394,13 @@ class SNSConnection(AWSQueryConnection):
if next_token:
params['NextToken'] = next_token
response = self.make_request('ListSubscriptions', params, '/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
def get_all_subscriptions_by_topic(self, topic, next_token=None):
"""
@@ -421,11 +421,11 @@ class SNSConnection(AWSQueryConnection):
params['NextToken'] = next_token
response = self.make_request('ListSubscriptionsByTopic', params,
'/', 'GET')
- body = response.read()
- if response.status == 200:
+ body = response.content
+ if response.status_code == 200:
return json.loads(body)
else:
- boto.log.error('%s %s' % (response.status, response.reason))
+ boto.log.error('%s %s' % (response.status_code, response.reason))
boto.log.error('%s' % body)
- raise self.ResponseError(response.status, response.reason, body)
+ raise self.ResponseError(response.status_code, response.reason, body)
diff --git a/boto/utils.py b/boto/utils.py
index 2eeb3d32..4817dd33 100644
--- a/boto/utils.py
+++ b/boto/utils.py
@@ -161,8 +161,10 @@ def get_aws_metadata(headers, provider=None):
metadata = {}
for hkey in headers.keys():
if hkey.lower().startswith(metadata_prefix):
+ # TODO: Is this necessary anymore with requests?
val = urllib.unquote_plus(headers[hkey])
try:
+ # TODO: Is this necessary anymore with requests?
metadata[hkey[len(metadata_prefix):]] = unicode(val, 'utf-8')
except UnicodeDecodeError:
metadata[hkey[len(metadata_prefix):]] = val
diff --git a/tests/s3/test_bucket.py b/tests/s3/test_bucket.py
index ad2e6cac..71a093d5 100644
--- a/tests/s3/test_bucket.py
+++ b/tests/s3/test_bucket.py
@@ -51,9 +51,8 @@ class S3BucketTest (unittest.TestCase):
# last element will be "b" so no issue.
rs = self.bucket.get_all_keys(max_keys=2)
for element in rs:
- pass
- self.assertEqual(element.name, "b")
- self.assertEqual(rs.next_marker, None)
+ self.assertEqual(element.name, "b")
+ self.assertEqual(rs.next_marker, None)
# list using delimiter of first 2 keys will have
# a NextMarker set (when truncated). As prefixes
@@ -61,13 +60,12 @@ class S3BucketTest (unittest.TestCase):
# last element, but luckily we have next_marker.
rs = self.bucket.get_all_keys(max_keys=2, delimiter="/")
for element in rs:
- pass
- self.assertEqual(element.name, "a/")
- self.assertEqual(rs.next_marker, "b")
+ self.assertEqual(element.name, "a/")
+ self.assertEqual(rs.next_marker, "b")
# ensure bucket.list() still works by just
# popping elements off the front of expected.
rs = self.bucket.list()
for element in rs:
self.assertEqual(element.name, expected.pop(0))
- self.assertEqual(expected, [])
+ self.assertEqual(expected, [])