bgneal@697: """s3.py bgneal@697: bgneal@700: This module provides Amazon S3 convenience wrappers. bgneal@697: bgneal@697: """ bgneal@1157: from boto.s3 import connect_to_region bgneal@1157: from boto.s3.connection import OrdinaryCallingFormat bgneal@697: from boto.s3.key import Key bgneal@697: bgneal@697: bgneal@697: class S3Bucket(object): bgneal@697: """This class abstracts an Amazon S3 bucket. bgneal@697: bgneal@697: """ bgneal@1157: def __init__(self, access_key, secret_key, base_url, bucket_name, bgneal@1157: region_name='us-west-1'): bgneal@1157: self.region_name = region_name bgneal@1157: self.conn = self._get_connection(access_key, secret_key) bgneal@697: self.bucket = self.conn.get_bucket(bucket_name, validate=False) bgneal@700: self.base_url = base_url bgneal@700: if not base_url.endswith('/'): bgneal@700: self.base_url += '/' bgneal@700: self.name = bucket_name bgneal@700: bgneal@1157: def _get_connection(self, access_key, secret_key): bgneal@1157: conn = connect_to_region( bgneal@1157: self.region_name, bgneal@1157: aws_access_key_id=access_key, bgneal@1157: aws_secret_access_key=secret_key, bgneal@1157: calling_format=OrdinaryCallingFormat()) bgneal@1157: return conn bgneal@1157: bgneal@700: def upload_from_file(self, key_name, fp, metadata=None, public=True): bgneal@700: """Uploads data from the file object fp to a new key named bgneal@700: key_name. metadata, if not None, must be a dict of metadata key / value bgneal@700: pairs which will be added to the key. bgneal@700: bgneal@700: If public is True, the key will be made public after the upload. bgneal@700: bgneal@700: Returns the URL to the uploaded file. bgneal@700: bgneal@700: """ bgneal@700: key = self._make_key(key_name, metadata) bgneal@700: key.set_contents_from_file(fp) bgneal@700: if public: bgneal@700: key.make_public() bgneal@700: return '{}{}/{}'.format(self.base_url, self.name, key_name) bgneal@697: bgneal@697: def upload_from_filename(self, key_name, filename, metadata=None, bgneal@697: public=True): bgneal@697: """Uploads data from the file named by filename to a new key named bgneal@697: key_name. metadata, if not None, must be a dict of metadata key / value bgneal@697: pairs which will be added to the key. bgneal@697: bgneal@697: If public is True, the key will be made public after the upload. bgneal@697: bgneal@700: Returns the URL to the uploaded file. bgneal@700: bgneal@697: """ bgneal@697: key = self._make_key(key_name, metadata) bgneal@697: key.set_contents_from_filename(filename) bgneal@697: if public: bgneal@697: key.make_public() bgneal@700: return '{}{}/{}'.format(self.base_url, self.name, key_name) bgneal@697: bgneal@697: def upload_from_string(self, key_name, content, metadata=None, bgneal@697: public=True): bgneal@697: """Creates a new key with the given key_name, and uploads the string bgneal@697: content to it. metadata, if not None, must be a dict of metadata key / bgneal@697: value pairs which will be added to the key. bgneal@697: bgneal@697: If public is True, the key will be made public after the upload. bgneal@697: bgneal@700: Returns the URL to the uploaded file. bgneal@700: bgneal@697: """ bgneal@697: key = self._make_key(key_name, metadata) bgneal@697: key.set_contents_from_string(content) bgneal@697: if public: bgneal@697: key.make_public() bgneal@700: return '{}{}/{}'.format(self.base_url, self.name, key_name) bgneal@697: bgneal@718: def delete_keys(self, key_urls): bgneal@718: """Deletes a set of keys, specified as a list of URLs. The URLs could bgneal@718: have been returned by one or more of the upload_* methods. bgneal@718: bgneal@718: Returns the number of keys that were successfully deleted. bgneal@718: bgneal@718: """ bgneal@718: if len(key_urls) == 0: bgneal@718: return 0 bgneal@718: bgneal@718: prefix = '{}{}/'.format(self.base_url, self.name) bgneal@718: prefix_len = len(prefix) bgneal@718: bgneal@718: keys = [] bgneal@718: for url in key_urls: bgneal@718: if url.startswith(prefix): bgneal@718: key = url[prefix_len:] bgneal@718: keys.append(key) bgneal@718: bgneal@718: response = self.bucket.delete_keys(keys, quiet=True) bgneal@718: return len(key_urls) - len(response.errors) bgneal@718: bgneal@697: def _make_key(self, key_name, metadata): bgneal@697: """Private method to create a key and optionally apply metadata to bgneal@697: it. bgneal@697: bgneal@697: """ bgneal@697: key = Key(self.bucket) bgneal@697: key.key = key_name bgneal@697: if metadata: bgneal@697: for k, v in metadata.iteritems(): bgneal@697: key.set_metadata(k, v) bgneal@697: return key