Last active
August 29, 2015 14:01
-
-
Save Slater-Victoroff/ea6f3ddea1034913018a to your computer and use it in GitHub Desktop.
Boto Plugin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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