Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2446)

Unified Diff: boto/s3/key.py

Issue 8386013: Merging in latest boto. (Closed) Base URL: svn://svn.chromium.org/boto
Patch Set: Redoing vendor drop by deleting and then merging. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « boto/s3/connection.py ('k') | boto/s3/multipart.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: boto/s3/key.py
diff --git a/boto/s3/key.py b/boto/s3/key.py
index c7e77f4c6dd6b55e525f7ae48f4f6a91f072598d..18829c2b91e094eb4c94f302fc67f5f4e9755cd6 100644
--- a/boto/s3/key.py
+++ b/boto/s3/key.py
@@ -1,4 +1,5 @@
# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/
+# Copyright (c) 2011, Nexenta Systems Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
@@ -14,13 +15,14 @@
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
import mimetypes
import os
+import re
import rfc822
import StringIO
import base64
@@ -62,6 +64,7 @@ class Key(object):
self.version_id = None
self.source_version_id = None
self.delete_marker = False
+ self.encrypted = None
def __repr__(self):
if self.bucket:
@@ -91,7 +94,7 @@ class Key(object):
if self.bucket.connection:
provider = self.bucket.connection.provider
return provider
-
+
def get_md5_from_hexdigest(self, md5_hexdigest):
"""
A utility function to create the 2-tuple (md5hexdigest, base64md5)
@@ -103,7 +106,14 @@ class Key(object):
if base64md5[-1] == '\n':
base64md5 = base64md5[0:-1]
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)
+ else:
+ self.encrypted = None
+
def handle_version_headers(self, resp, force=False):
provider = self.bucket.connection.provider
# If the Key object already has a version_id attribute value, it
@@ -113,7 +123,8 @@ class Key(object):
# 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, None)
+ self.source_version_id = resp.getheader(provider.copy_source_version_id,
+ None)
if resp.getheader(provider.delete_marker, 'false') == 'true':
self.delete_marker = True
else:
@@ -123,13 +134,13 @@ class Key(object):
override_num_retries=None, response_headers=None):
"""
Open this key for reading
-
+
:type headers: dict
:param headers: Headers to pass in the web request
-
+
:type query_args: string
:param query_args: Arguments to pass in the query string (ie, 'torrent')
-
+
:type override_num_retries: int
:param override_num_retries: If not None will override configured
num_retries parameter for underlying GET.
@@ -142,7 +153,7 @@ class Key(object):
"""
if self.resp == None:
self.mode = 'r'
-
+
provider = self.bucket.connection.provider
self.resp = self.bucket.connection.make_request(
'GET', self.bucket.name, self.name, headers,
@@ -156,8 +167,15 @@ class Key(object):
self.metadata = boto.utils.get_aws_metadata(response_headers,
provider)
for name,value in response_headers.items():
- if name.lower() == 'content-length':
+ # To get correct size for Range GETs, use Content-Range
+ # header if one was returned. If not, use Content-Length
+ # header.
+ if (name.lower() == 'content-length' and
+ 'Content-Range' not in response_headers):
self.size = int(value)
+ elif name.lower() == 'content-range':
+ end_range = re.sub('.*/(.*)', '\\1', value)
+ self.size = int(end_range)
elif name.lower() == 'etag':
self.etag = value
elif name.lower() == 'content-type':
@@ -169,12 +187,13 @@ class Key(object):
elif name.lower() == 'cache-control':
self.cache_control = value
self.handle_version_headers(self.resp)
+ self.handle_encryption_headers(self.resp)
def open_write(self, headers=None, override_num_retries=None):
"""
- Open this key for writing.
+ Open this key for writing.
Not yet implemented
-
+
:type headers: dict
:param headers: Headers to pass in the write request
@@ -204,7 +223,7 @@ class Key(object):
self.resp = None
self.mode = None
self.closed = True
-
+
def next(self):
"""
By providing a next method, the key object supports use as an iterator.
@@ -223,10 +242,11 @@ class Key(object):
return data
def read(self, size=0):
- if size == 0:
- size = self.BufferSize
self.open_read()
- data = self.resp.read(size)
+ if size == 0:
+ data = self.resp.read()
+ else:
+ data = self.resp.read(size)
if not data:
self.close()
return data
@@ -250,7 +270,7 @@ class Key(object):
:param dst_bucket: The name of a destination bucket. If not
provided the current bucket of the key
will be used.
-
+
"""
if new_storage_class == 'STANDARD':
return self.copy(self.bucket.name, self.name,
@@ -263,7 +283,8 @@ class Key(object):
new_storage_class)
def copy(self, dst_bucket, dst_key, metadata=None,
- reduced_redundancy=False, preserve_acl=False):
+ reduced_redundancy=False, preserve_acl=False,
+ encrypt_key=False):
"""
Copy this Key to another bucket.
@@ -272,7 +293,7 @@ class Key(object):
:type dst_key: string
:param dst_key: The name of the destination key
-
+
:type metadata: dict
:param metadata: Metadata to be associated with new key.
If metadata is supplied, it will replace the
@@ -303,6 +324,12 @@ class Key(object):
of False will be significantly more
efficient.
+ :type encrypt_key: bool
+ :param encrypt_key: If True, the new copy of the object will
+ be encrypted on the server-side by S3 and
+ will be stored in an encrypted form while
+ at rest in S3.
+
:rtype: :class:`boto.s3.key.Key` or subclass
:returns: An instance of the newly created key object
"""
@@ -314,7 +341,8 @@ class Key(object):
return dst_bucket.copy_key(dst_key, self.bucket.name,
self.name, metadata,
storage_class=storage_class,
- preserve_acl=preserve_acl)
+ preserve_acl=preserve_acl,
+ encrypt_key=encrypt_key)
def startElement(self, name, attrs, connection):
if name == 'Owner':
@@ -344,7 +372,7 @@ class Key(object):
def exists(self):
"""
Returns True if the key exists
-
+
:rtype: bool
:return: Whether the key exists on S3
"""
@@ -364,7 +392,7 @@ class Key(object):
def update_metadata(self, d):
self.metadata.update(d)
-
+
# convenience methods for setting/getting ACL
def set_acl(self, acl_str, headers=None):
if self.bucket != None:
@@ -384,51 +412,56 @@ class Key(object):
def set_canned_acl(self, acl_str, headers=None):
return self.bucket.set_canned_acl(acl_str, self.name, headers)
-
+
def make_public(self, headers=None):
return self.bucket.set_canned_acl('public-read', self.name, headers)
def generate_url(self, expires_in, method='GET', headers=None,
- query_auth=True, force_http=False):
+ query_auth=True, force_http=False, response_headers=None):
"""
Generate a URL to access this key.
-
+
:type expires_in: int
:param expires_in: How long the url is valid for, in seconds
-
+
:type method: string
- :param method: The method to use for retrieving the file (default is GET)
-
+ :param method: The method to use for retrieving the file
+ (default is GET)
+
:type headers: dict
:param headers: Any headers to pass along in the request
-
+
:type query_auth: bool
- :param query_auth:
-
+ :param query_auth:
+
:rtype: string
:return: The URL to access the key
"""
return self.bucket.connection.generate_url(expires_in, method,
self.bucket.name, self.name,
- headers, query_auth, force_http)
+ headers, query_auth,
+ force_http,
+ response_headers)
- def send_file(self, fp, headers=None, cb=None, num_cb=10, query_args=None):
+ def send_file(self, fp, headers=None, cb=None, num_cb=10,
+ query_args=None, chunked_transfer=False):
"""
Upload a file to a key into a bucket on S3.
-
+
:type fp: file
:param fp: The file pointer to upload
-
+
:type headers: dict
:param headers: The headers to pass along with the PUT request
-
+
:type cb: function
:param cb: a callback function that will be called to report
- progress on the upload. The callback should accept two integer
- parameters, the first representing the number of bytes that have
- been successfully transmitted to S3 and the second representing
- the total number of bytes that need to be transmitted.
-
+ progress on the upload. The callback should accept
+ two integer parameters, the first representing the
+ number of bytes that have been successfully
+ transmitted to S3 and the second representing the
+ size of the to be transmitted object.
+
:type num_cb: int
:param num_cb: (optional) If a callback is specified with the cb
parameter this parameter determines the granularity
@@ -436,7 +469,7 @@ class Key(object):
times the callback will be called during the file
transfer. Providing a negative integer will cause
your callback to be called with each buffer read.
-
+
"""
provider = self.bucket.connection.provider
@@ -445,12 +478,28 @@ class Key(object):
for key in headers:
http_conn.putheader(key, headers[key])
http_conn.endheaders()
- fp.seek(0)
+ if chunked_transfer:
+ # MD5 for the stream has to be calculated on the fly, as
+ # we don't know the size of the stream before hand.
+ m = md5()
+ else:
+ fp.seek(0)
+
save_debug = self.bucket.connection.debug
self.bucket.connection.debug = 0
- http_conn.set_debuglevel(0)
+ # If the debuglevel < 3 we don't want to show connection
+ # payload, so turn off HTTP connection-level debug output (to
+ # be restored below).
+ # Use the getattr approach to allow this to work in AppEngine.
+ if getattr(http_conn, 'debuglevel', 0) < 3:
+ http_conn.set_debuglevel(0)
if cb:
- if num_cb > 2:
+ if chunked_transfer:
+ # For chunked Transfer, we call the cb for every 1MB
+ # of data transferred.
+ cb_count = (1024 * 1024)/self.BufferSize
+ self.size = 0
+ elif num_cb > 2:
cb_count = self.size / self.BufferSize / (num_cb-2)
elif num_cb < 0:
cb_count = -1
@@ -460,24 +509,39 @@ class Key(object):
cb(total_bytes, self.size)
l = fp.read(self.BufferSize)
while len(l) > 0:
- http_conn.send(l)
+ if chunked_transfer:
+ http_conn.send('%x;\r\n' % len(l))
+ http_conn.send(l)
+ http_conn.send('\r\n')
+ else:
+ http_conn.send(l)
if cb:
total_bytes += len(l)
i += 1
if i == cb_count or cb_count == -1:
cb(total_bytes, self.size)
i = 0
+ if chunked_transfer:
+ m.update(l)
l = fp.read(self.BufferSize)
+ if chunked_transfer:
+ http_conn.send('0\r\n')
+ http_conn.send('\r\n')
+ if cb:
+ self.size = total_bytes
+ # Get the md5 which is calculated on the fly.
+ self.md5 = m.hexdigest()
+ else:
+ fp.seek(0)
if cb:
cb(total_bytes, self.size)
response = http_conn.getresponse()
body = response.read()
- fp.seek(0)
http_conn.set_debuglevel(save_debug)
self.bucket.connection.debug = save_debug
- if response.status == 500 or response.status == 503 or \
- response.getheader('location'):
- # we'll try again
+ if ((response.status == 500 or response.status == 503 or
+ response.getheader('location')) and not chunked_transfer):
+ # we'll try again.
return response
elif response.status >= 200 and response.status <= 299:
self.etag = response.getheader('etag')
@@ -494,7 +558,8 @@ class Key(object):
else:
headers = headers.copy()
headers['User-Agent'] = UserAgent
- headers['Content-MD5'] = self.base64md5
+ if self.base64md5:
+ headers['Content-MD5'] = self.base64md5
if self.storage_class != 'STANDARD':
headers[provider.storage_class_header] = self.storage_class
if headers.has_key('Content-Encoding'):
@@ -508,7 +573,8 @@ class Key(object):
headers['Content-Type'] = self.content_type
else:
headers['Content-Type'] = self.content_type
- headers['Content-Length'] = str(self.size)
+ if not chunked_transfer:
+ headers['Content-Length'] = str(self.size)
headers['Expect'] = '100-Continue'
headers = boto.utils.merge_meta(headers, self.metadata, provider)
resp = self.bucket.connection.make_request('PUT', self.bucket.name,
@@ -520,9 +586,10 @@ class Key(object):
def compute_md5(self, fp):
"""
:type fp: file
- :param fp: File pointer to the file to MD5 hash. The file pointer will be
- reset to the beginning of the file before the method returns.
-
+ :param fp: File pointer to the file to MD5 hash. The file pointer
+ will be reset to the beginning of the file before the
+ method returns.
+
:rtype: tuple
:return: A tuple containing the hex digest version of the MD5 hash
as the first element and the base64 encoded version of the
@@ -542,19 +609,102 @@ class Key(object):
fp.seek(0)
return (hex_md5, base64md5)
+ def set_contents_from_stream(self, fp, headers=None, replace=True,
+ cb=None, num_cb=10, policy=None,
+ reduced_redundancy=False, query_args=None):
+ """
+ Store an object using the name of the Key object as the key in
+ cloud and the contents of the data stream pointed to by 'fp' as
+ the contents.
+ The stream object is not seekable and total size is not known.
+ This has the implication that we can't specify the Content-Size and
+ Content-MD5 in the header. So for huge uploads, the delay in calculating
+ MD5 is avoided but with a penalty of inability to verify the integrity
+ of the uploaded data.
+
+ :type fp: file
+ :param fp: the file whose contents are to be uploaded
+
+ :type headers: dict
+ :param headers: additional HTTP headers to be sent with the PUT request.
+
+ :type replace: bool
+ :param replace: If this parameter is False, the method will first check
+ to see if an object exists in the bucket with the same key. If it
+ does, it won't overwrite it. The default value is True which will
+ overwrite the object.
+
+ :type cb: function
+ :param cb: a callback function that will be called to report
+ progress on the upload. The callback should accept two integer
+ parameters, the first representing the number of bytes that have
+ been successfully transmitted to GS and the second representing the
+ total number of bytes that need to be transmitted.
+
+ :type num_cb: int
+ :param num_cb: (optional) If a callback is specified with the cb
+ parameter, this parameter determines the granularity of the callback
+ by defining the maximum number of times the callback will be called
+ during the file transfer.
+
+ :type policy: :class:`boto.gs.acl.CannedACLStrings`
+ :param policy: A canned ACL policy that will be applied to the new key
+ in GS.
+
+ :type reduced_redundancy: bool
+ :param reduced_redundancy: If True, this will set the storage
+ class of the new Key to be
+ REDUCED_REDUNDANCY. The Reduced Redundancy
+ Storage (RRS) feature of S3, provides lower
+ redundancy at lower storage cost.
+ """
+
+ provider = self.bucket.connection.provider
+ if not provider.supports_chunked_transfer():
+ raise BotoClientError('%s does not support chunked transfer'
+ % provider.get_provider_name())
+
+ # Name of the Object should be specified explicitly for Streams.
+ if not self.name or self.name == '':
+ raise BotoClientError('Cannot determine the destination '
+ 'object name for the given stream')
+
+ if headers is None:
+ headers = {}
+ if policy:
+ headers[provider.acl_header] = policy
+
+ # Set the Transfer Encoding for Streams.
+ headers['Transfer-Encoding'] = 'chunked'
+
+ if reduced_redundancy:
+ self.storage_class = 'REDUCED_REDUNDANCY'
+ if provider.storage_class_header:
+ headers[provider.storage_class_header] = self.storage_class
+
+ if self.bucket != None:
+ if not replace:
+ k = self.bucket.lookup(self.name)
+ if k:
+ return
+ self.send_file(fp, headers, cb, num_cb, query_args,
+ chunked_transfer=True)
+
def set_contents_from_file(self, fp, headers=None, replace=True,
cb=None, num_cb=10, policy=None, md5=None,
- reduced_redundancy=False, query_args=None):
+ reduced_redundancy=False, query_args=None,
+ encrypt_key=False):
"""
Store an object in S3 using the name of the Key object as the
key in S3 and the contents of the file pointed to by 'fp' as the
contents.
-
+
:type fp: file
:param fp: the file whose contents to upload
-
+
:type headers: dict
- :param headers: additional HTTP headers that will be sent with the PUT request.
+ :param headers: Additional HTTP headers that will be sent with
+ the PUT request.
:type replace: bool
:param replace: If this parameter is False, the method
@@ -562,29 +712,36 @@ class Key(object):
bucket with the same key. If it does, it won't
overwrite it. The default value is True which will
overwrite the object.
-
+
:type cb: function
:param cb: a callback function that will be called to report
- progress on the upload. The callback should accept two integer
- parameters, the first representing the number of bytes that have
- been successfully transmitted to S3 and the second representing
- the total number of bytes that need to be transmitted.
-
+ progress on the upload. The callback should accept
+ two integer parameters, the first representing the
+ number of bytes that have been successfully
+ transmitted to S3 and the second representing the
+ size of the to be transmitted object.
+
:type cb: int
- :param num_cb: (optional) If a callback is specified with the cb parameter
- this parameter determines the granularity of the callback by defining
- the maximum number of times the callback will be called during the file transfer.
+ :param num_cb: (optional) If a callback is specified with the cb
+ parameter this parameter determines the granularity
+ of the callback by defining the maximum number of
+ times the callback will be called during the
+ file transfer.
:type policy: :class:`boto.s3.acl.CannedACLStrings`
- :param policy: A canned ACL policy that will be applied to the new key in S3.
-
- :type md5: A tuple containing the hexdigest version of the MD5 checksum of the
- file as the first element and the Base64-encoded version of the plain
- checksum as the second element. This is the same format returned by
+ :param policy: A canned ACL policy that will be applied to the
+ new key in S3.
+
+ :type md5: A tuple containing the hexdigest version of the MD5
+ checksum of the file as the first element and the
+ Base64-encoded version of the plain checksum as the
+ second element. This is the same format returned by
the compute_md5 method.
- :param md5: If you need to compute the MD5 for any reason prior to upload,
- it's silly to have to do it twice so this param, if present, will be
- used as the MD5 values of the file. Otherwise, the checksum will be computed.
+ :param md5: If you need to compute the MD5 for any reason prior
+ to upload, it's silly to have to do it twice so this
+ param, if present, will be used as the MD5 values of
+ the file. Otherwise, the checksum will be computed.
+
:type reduced_redundancy: bool
:param reduced_redundancy: If True, this will set the storage
class of the new Key to be
@@ -592,17 +749,25 @@ class Key(object):
Storage (RRS) feature of S3, provides lower
redundancy at lower storage cost.
+ :type encrypt_key: bool
+ :param encrypt_key: If True, the new copy of the object will
+ be encrypted on the server-side by S3 and
+ will be stored in an encrypted form while
+ at rest in S3.
"""
provider = self.bucket.connection.provider
if headers is None:
headers = {}
if policy:
headers[provider.acl_header] = policy
+ if encrypt_key:
+ headers[provider.server_side_encryption_header] = 'AES256'
+
if reduced_redundancy:
self.storage_class = 'REDUCED_REDUNDANCY'
if provider.storage_class_header:
headers[provider.storage_class_header] = self.storage_class
- # TODO - What if the provider doesn't support reduced reduncancy?
+ # TODO - What if provider doesn't support reduced reduncancy?
# What if different providers provide different classes?
if hasattr(fp, 'name'):
self.path = fp.name
@@ -626,105 +791,137 @@ class Key(object):
def set_contents_from_filename(self, filename, headers=None, replace=True,
cb=None, num_cb=10, policy=None, md5=None,
- reduced_redundancy=False):
+ reduced_redundancy=False,
+ encrypt_key=False):
"""
Store an object in S3 using the name of the Key object as the
key in S3 and the contents of the file named by 'filename'.
See set_contents_from_file method for details about the
parameters.
-
+
:type filename: string
:param filename: The name of the file that you want to put onto S3
-
+
:type headers: dict
- :param headers: Additional headers to pass along with the request to AWS.
-
+ :param headers: Additional headers to pass along with the
+ request to AWS.
+
:type replace: bool
- :param replace: If True, replaces the contents of the file if it already exists.
-
+ :param replace: If True, replaces the contents of the file
+ if it already exists.
+
:type cb: function
- :param cb: (optional) a callback function that will be called to report
- progress on the download. The callback should accept two integer
- parameters, the first representing the number of bytes that have
- been successfully transmitted from S3 and the second representing
- the total number of bytes that need to be transmitted.
-
+ :param cb: a callback function that will be called to report
+ progress on the upload. The callback should accept
+ two integer parameters, the first representing the
+ number of bytes that have been successfully
+ transmitted to S3 and the second representing the
+ size of the to be transmitted object.
+
:type cb: int
- :param num_cb: (optional) If a callback is specified with the cb parameter
- this parameter determines the granularity of the callback by defining
- the maximum number of times the callback will be called during the file transfer.
-
+ :param num_cb: (optional) If a callback is specified with
+ the cb parameter this parameter determines the
+ granularity of the callback by defining
+ the maximum number of times the callback will
+ be called during the file transfer.
+
:type policy: :class:`boto.s3.acl.CannedACLStrings`
- :param policy: A canned ACL policy that will be applied to the new key in S3.
-
- :type md5: A tuple containing the hexdigest version of the MD5 checksum of the
- file as the first element and the Base64-encoded version of the plain
- checksum as the second element. This is the same format returned by
+ :param policy: A canned ACL policy that will be applied to the
+ new key in S3.
+
+ :type md5: A tuple containing the hexdigest version of the MD5
+ checksum of the file as the first element and the
+ Base64-encoded version of the plain checksum as the
+ second element. This is the same format returned by
the compute_md5 method.
- :param md5: If you need to compute the MD5 for any reason prior to upload,
- it's silly to have to do it twice so this param, if present, will be
- used as the MD5 values of the file. Otherwise, the checksum will be computed.
-
+ :param md5: If you need to compute the MD5 for any reason prior
+ to upload, it's silly to have to do it twice so this
+ param, if present, will be used as the MD5 values
+ of the file. Otherwise, the checksum will be computed.
+
:type reduced_redundancy: bool
:param reduced_redundancy: If True, this will set the storage
class of the new Key to be
REDUCED_REDUNDANCY. The Reduced Redundancy
Storage (RRS) feature of S3, provides lower
redundancy at lower storage cost.
+ :type encrypt_key: bool
+ :param encrypt_key: If True, the new copy of the object will
+ be encrypted on the server-side by S3 and
+ will be stored in an encrypted form while
+ at rest in S3.
"""
fp = open(filename, 'rb')
self.set_contents_from_file(fp, headers, replace, cb, num_cb,
- policy, md5, reduced_redundancy)
+ policy, md5, reduced_redundancy,
+ encrypt_key=encrypt_key)
fp.close()
def set_contents_from_string(self, s, headers=None, replace=True,
cb=None, num_cb=10, policy=None, md5=None,
- reduced_redundancy=False):
+ reduced_redundancy=False,
+ encrypt_key=False):
"""
Store an object in S3 using the name of the Key object as the
key in S3 and the string 's' as the contents.
See set_contents_from_file method for details about the
parameters.
-
+
:type headers: dict
- :param headers: Additional headers to pass along with the request to AWS.
-
+ :param headers: Additional headers to pass along with the
+ request to AWS.
+
:type replace: bool
- :param replace: If True, replaces the contents of the file if it already exists.
-
+ :param replace: If True, replaces the contents of the file if
+ it already exists.
+
:type cb: function
- :param cb: (optional) a callback function that will be called to report
- progress on the download. The callback should accept two integer
- parameters, the first representing the number of bytes that have
- been successfully transmitted from S3 and the second representing
- the total number of bytes that need to be transmitted.
-
+ :param cb: a callback function that will be called to report
+ progress on the upload. The callback should accept
+ two integer parameters, the first representing the
+ number of bytes that have been successfully
+ transmitted to S3 and the second representing the
+ size of the to be transmitted object.
+
:type cb: int
- :param num_cb: (optional) If a callback is specified with the cb parameter
- this parameter determines the granularity of the callback by defining
- the maximum number of times the callback will be called during the file transfer.
-
+ :param num_cb: (optional) If a callback is specified with
+ the cb parameter this parameter determines the
+ granularity of the callback by defining
+ the maximum number of times the callback will
+ be called during the file transfer.
+
:type policy: :class:`boto.s3.acl.CannedACLStrings`
- :param policy: A canned ACL policy that will be applied to the new key in S3.
-
- :type md5: A tuple containing the hexdigest version of the MD5 checksum of the
- file as the first element and the Base64-encoded version of the plain
- checksum as the second element. This is the same format returned by
+ :param policy: A canned ACL policy that will be applied to the
+ new key in S3.
+
+ :type md5: A tuple containing the hexdigest version of the MD5
+ checksum of the file as the first element and the
+ Base64-encoded version of the plain checksum as the
+ second element. This is the same format returned by
the compute_md5 method.
- :param md5: If you need to compute the MD5 for any reason prior to upload,
- it's silly to have to do it twice so this param, if present, will be
- used as the MD5 values of the file. Otherwise, the checksum will be computed.
-
+ :param md5: If you need to compute the MD5 for any reason prior
+ to upload, it's silly to have to do it twice so this
+ param, if present, will be used as the MD5 values
+ of the file. Otherwise, the checksum will be computed.
+
:type reduced_redundancy: bool
:param reduced_redundancy: If True, this will set the storage
class of the new Key to be
REDUCED_REDUNDANCY. The Reduced Redundancy
Storage (RRS) feature of S3, provides lower
redundancy at lower storage cost.
+ :type encrypt_key: bool
+ :param encrypt_key: If True, the new copy of the object will
+ be encrypted on the server-side by S3 and
+ will be stored in an encrypted form while
+ at rest in S3.
"""
+ if isinstance(s, unicode):
+ s = s.encode("utf-8")
fp = StringIO.StringIO(s)
r = self.set_contents_from_file(fp, headers, replace, cb, num_cb,
- policy, md5, reduced_redundancy)
+ policy, md5, reduced_redundancy,
+ encrypt_key=encrypt_key)
fp.close()
return r
@@ -733,26 +930,28 @@ class Key(object):
response_headers=None):
"""
Retrieves a file from an S3 Key
-
+
:type fp: file
:param fp: File pointer to put the data into
-
+
:type headers: string
:param: headers to send when retrieving the files
-
+
:type cb: function
- :param cb: (optional) a callback function that will be called to report
- progress on the download. The callback should accept two integer
- parameters, the first representing the number of bytes that have
- been successfully transmitted from S3 and the second representing
- the total number of bytes that need to be transmitted.
-
-
+ :param cb: a callback function that will be called to report
+ progress on the upload. The callback should accept
+ two integer parameters, the first representing the
+ number of bytes that have been successfully
+ transmitted to S3 and the second representing the
+ size of the to be transmitted object.
+
:type cb: int
- :param num_cb: (optional) If a callback is specified with the cb parameter
- this parameter determines the granularity of the callback by defining
- the maximum number of times the callback will be called during the file transfer.
-
+ :param num_cb: (optional) If a callback is specified with
+ the cb parameter this parameter determines the
+ granularity of the callback by defining
+ the maximum number of times the callback will
+ be called during the file transfer.
+
:type torrent: bool
:param torrent: Flag for whether to get a torrent for the file
@@ -778,7 +977,7 @@ class Key(object):
save_debug = self.bucket.connection.debug
if self.bucket.connection.debug == 1:
self.bucket.connection.debug = 0
-
+
query_args = []
if torrent:
query_args.append('torrent')
@@ -811,31 +1010,31 @@ class Key(object):
def get_torrent_file(self, fp, headers=None, cb=None, num_cb=10):
"""
Get a torrent file (see to get_file)
-
+
:type fp: file
:param fp: The file pointer of where to put the torrent
-
+
:type headers: dict
:param headers: Headers to be passed
-
+
:type cb: function
- :param cb: (optional) a callback function that will be called to
- report progress on the download. The callback should
- accept two integer parameters, the first representing
- the number of bytes that have been successfully
- transmitted from S3 and the second representing the
- total number of bytes that need to be transmitted.
+ :param cb: a callback function that will be called to report
+ progress on the upload. The callback should accept
+ two integer parameters, the first representing the
+ number of bytes that have been successfully
+ transmitted to S3 and the second representing the
+ size of the to be transmitted object.
+
+ :type cb: int
+ :param num_cb: (optional) If a callback is specified with
+ the cb parameter this parameter determines the
+ granularity of the callback by defining
+ the maximum number of times the callback will
+ be called during the file transfer.
- :type num_cb: int
- :param num_cb: (optional) If a callback is specified with the
- cb parameter this parameter determines the
- granularity of the callback by defining the
- maximum number of times the callback will be
- called during the file transfer.
-
"""
return self.get_file(fp, headers, cb, num_cb, torrent=True)
-
+
def get_contents_to_file(self, fp, headers=None,
cb=None, num_cb=10,
torrent=False,
@@ -846,29 +1045,29 @@ class Key(object):
Retrieve an object from S3 using the name of the Key object as the
key in S3. Write the contents of the object to the file pointed
to by 'fp'.
-
+
:type fp: File -like object
:param fp:
-
+
:type headers: dict
:param headers: additional HTTP headers that will be sent with
the GET request.
-
+
:type cb: function
- :param cb: (optional) a callback function that will be called to
- report progress on the download. The callback should
- accept two integer parameters, the first representing
- the number of bytes that have been successfully
- transmitted from S3 and the second representing the
- total number of bytes that need to be transmitted.
+ :param cb: a callback function that will be called to report
+ progress on the upload. The callback should accept
+ two integer parameters, the first representing the
+ number of bytes that have been successfully
+ transmitted to S3 and the second representing the
+ size of the to be transmitted object.
+
+ :type cb: int
+ :param num_cb: (optional) If a callback is specified with
+ the cb parameter this parameter determines the
+ granularity of the callback by defining
+ the maximum number of times the callback will
+ be called during the file transfer.
- :type num_cb: int
- :param num_cb: (optional) If a callback is specified with the
- cb parameter this parameter determines the
- granularity of the callback by defining the
- maximum number of times the callback will be
- called during the file transfer.
-
:type torrent: bool
:param torrent: If True, returns the contents of a torrent
file as a string.
@@ -904,28 +1103,28 @@ class Key(object):
key in S3. Store contents of the object to a file named by 'filename'.
See get_contents_to_file method for details about the
parameters.
-
+
:type filename: string
:param filename: The filename of where to put the file contents
-
+
:type headers: dict
:param headers: Any additional headers to send in the request
-
+
:type cb: function
- :param cb: (optional) a callback function that will be called to
- report progress on the download. The callback should
- accept two integer parameters, the first representing
- the number of bytes that have been successfully
- transmitted from S3 and the second representing the
- total number of bytes that need to be transmitted.
+ :param cb: a callback function that will be called to report
+ progress on the upload. The callback should accept
+ two integer parameters, the first representing the
+ number of bytes that have been successfully
+ transmitted to S3 and the second representing the
+ size of the to be transmitted object.
+
+ :type cb: int
+ :param num_cb: (optional) If a callback is specified with
+ the cb parameter this parameter determines the
+ granularity of the callback by defining
+ the maximum number of times the callback will
+ be called during the file transfer.
- :type num_cb: int
- :param num_cb: (optional) If a callback is specified with the
- cb parameter this parameter determines the
- granularity of the callback by defining the
- maximum number of times the callback will be
- called during the file transfer.
-
:type torrent: bool
:param torrent: If True, returns the contents of a torrent file
as a string.
@@ -964,35 +1163,35 @@ class Key(object):
key in S3. Return the contents of the object as a string.
See get_contents_to_file method for details about the
parameters.
-
+
:type headers: dict
:param headers: Any additional headers to send in the request
-
+
:type cb: function
- :param cb: (optional) a callback function that will be called to
- report progress on the download. The callback should
- accept two integer parameters, the first representing
- the number of bytes that have been successfully
- transmitted from S3 and the second representing the
- total number of bytes that need to be transmitted.
+ :param cb: a callback function that will be called to report
+ progress on the upload. The callback should accept
+ two integer parameters, the first representing the
+ number of bytes that have been successfully
+ transmitted to S3 and the second representing the
+ size of the to be transmitted object.
+
+ :type cb: int
+ :param num_cb: (optional) If a callback is specified with
+ the cb parameter this parameter determines the
+ granularity of the callback by defining
+ the maximum number of times the callback will
+ be called during the file transfer.
- :type num_cb: int
- :param num_cb: (optional) If a callback is specified with the
- cb parameter this parameter determines the
- granularity of the callback by defining the
- maximum number of times the callback will be
- called during the file transfer.
-
:type torrent: bool
:param torrent: If True, returns the contents of a torrent file
as a string.
-
+
:type response_headers: dict
:param response_headers: A dictionary containing HTTP headers/values
that will override any headers associated with
the stored object in the response.
See http://goo.gl/EWOPb for details.
-
+
:rtype: string
:returns: The contents of the file as a string
"""
@@ -1008,15 +1207,15 @@ class Key(object):
to a key. This method retrieves the current ACL, creates a new
grant based on the parameters passed in, adds that grant to the ACL
and then PUT's the new ACL back to S3.
-
+
:type permission: string
:param permission: The permission being granted. Should be one of:
(READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL).
-
+
: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
@@ -1030,30 +1229,27 @@ class Key(object):
policy.acl.add_email_grant(permission, email_address)
self.set_acl(policy, headers=headers)
- def add_user_grant(self, permission, user_id, headers=None):
+ def add_user_grant(self, permission, user_id, headers=None,
+ display_name=None):
"""
Convenience method that provides a quick way to add a canonical
user grant to a key. This method retrieves the current ACL,
creates a new grant based on the parameters passed in, adds that
grant to the ACL and then PUT's the new ACL back to S3.
-
+
:type permission: string
:param permission: The permission being granted. Should be one of:
(READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL).
-
+
:type user_id: string
:param user_id: The canonical user id 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!
+
+ :type display_name: string
+ :param display_name: An option string containing the user's
+ Display Name. Only required on Walrus.
"""
policy = self.get_acl()
- policy.acl.add_user_grant(permission, user_id)
+ policy.acl.add_user_grant(permission, user_id,
+ display_name=display_name)
self.set_acl(policy, headers=headers)
« no previous file with comments | « boto/s3/connection.py ('k') | boto/s3/multipart.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698