Skip to content

Instantly share code, notes, and snippets.

@Slater-Victoroff
Last active August 29, 2015 14:01
Show Gist options
  • Save Slater-Victoroff/ea6f3ddea1034913018a to your computer and use it in GitHub Desktop.
Save Slater-Victoroff/ea6f3ddea1034913018a to your computer and use it in GitHub Desktop.
Boto Plugin
import json, os
from boto.s3.connection import S3Connection, OrdinaryCallingFormat
from boto.s3.key import Key
CREDENTIALS = ['AWSAccessKeyId', 'AWSSecretKey']
class MissingCredentialsException(Exception):
def __init__(self, credentials_dict):
self.data = credentials_dict
def value_check(self, test_key):
"""
Checks that the indicated key is present within the dict, the key has a non-false value, and is a string
"""
return (test_key in self.data and bool(self.data[test_key]) and isinstance(self.data[test_key], str))
def __str__(self):
validity_list = [self.value_check(credential) for credential in CREDENTIALS]
missing_credential_list = filter(None, [a*b for a, b in zip(validity_list, CREDENTIALS)])
return "Missing Expected Credentials: %s" % missing_credential_list.__repr__()
class MissingKeyException(Exception):
"""
If we can't figure out what the key is of an item being saved, we just say so.
Should probably make a better error message that says what we can figure out and what they can do about it.
"""
def __init__(self, data_structure):
self.ds = data_structure
def __str__(self):
return "Could not determine key for: %s" % self.ds.__repr__()
def credentials(filename=None):
"""
Generally made for standard AWS export format. Turns conf file into python dict
If no filename is given, will attempt to read environment variables instead
"""
credential_dict = {}
if filename:
var_list = filter(None, open(filename).read().split('\n'))
credential_dict = dict([var.split('=') for var in var_list])
elif set(CREDENTIALS).issubset(set(os.environ.keys())):
credential_dict = {var: os.environ.get[var] for var in CREDENTIALS}
elif set(CREDENTIALS).issubset(set(globals().keys())):
credential_dict = {var: globals()[var] for var in CREDENTIALS}
if not set(CREDENTIALS) == set(credential_dict.keys()):
raise MissingCredentialsException(credential_dict)
return credential_dict
def find_key(data_atom):
"""
Tries to find an appropriate S3 key from an arbitrary data structure
"""
if isinstance(data_atom, dict):
if len(data_atom.keys()) == 1:
current_key = data_atom.keys()[0]
else:
current_key = data_atom.get('key', False) or data_atom.get('title', False) or data_atom.get('name', False)
elif isinstance(data_atom, list) or isinstance(data_atom, tuple):
current_key = data_atom[0]
else:
raise MissingKeyException
return current_key
class BotoSave(object):
def __init__(self, bucket, explicit_key=None, filename=None, validate=True, serialization_callback=json.dumps):
"""
serialization_callback should be a function that returns a string
"""
credential_dict = credentials(filename)
conn = S3Connection(
credential_dict['AWSAccessKeyId'],
credential_dict['AWSSecretKey'],
calling_format=OrdinaryCallingFormat()
)
self.save_bucket = conn.get_bucket(bucket, validate=validate)
self.explicit_key = explicit_key
self.serialization_callback = serialization_callback
def __call__(self, f):
def data_output(*args, **kwargs):
data_atom = f(*args, **kwargs)
new_key = Key(self.save_bucket)
new_key.key = self.explicit_key or find_key(data_atom)
new_key.set_contents_from_string(self.serialization_callback(data_atom))
return data_output
@BotoSave('Test', filename='s3.conf')
def this_is_a_test():
return {'ThisIsTheKey': "Something else should probably be here"}
this_is_a_test()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment