Source code for openS3.utils
from base64 import b64encode
from datetime import datetime
import hashlib
import hmac
import re
from urllib import parse
from .constants import ENCODING, AWS_DATETIME_FORMAT
[docs]def b64_string(byte_string):
"""
Return an base64 encoded byte string as an ENCODING decoded string
"""
return b64encode(byte_string).decode(ENCODING)
[docs]def get_valid_filename(string_to_clean):
"""
Returns the given string converted to a string that can be used for a clean
filename. Specifically, leading and trailing spaces are removed; other
spaces are converted to underscores; and anything that is not a unicode
alphanumeric, dash, underscore, or dot, is removed.
>>> get_valid_filename("john's portrait in 2004.jpg")
'johns_portrait_in_2004.jpg'
"""
string_to_clean = string_to_clean.strip().replace(' ', '_')
return re.sub(r'(?u)[^-\w.]', '', string_to_clean)
[docs]def validate_values(validation_func, dic):
"""
Validate each value in ``dic`` by passing it through ``func``.
Raise a ``ValueError`` if ``validation_func`` does not return ``True``.
"""
for value_name, value in dic.items():
if not validation_func(value):
raise ValueError('{} can not be {}'.format(value_name, value))
[docs]def strpawstime(timestamp):
"""
Return datetime from parsed AWS header timestamp string.
AWS Datetime Format: Wed, 28 Oct 2009 22:32:00 GMT
"""
return datetime.strptime(timestamp, AWS_DATETIME_FORMAT)
def get_canonical_query_string(query_string_dict):
query_pairs = sorted(query_string_dict.items())
query_strings = [uri_encode(p) + '=' + uri_encode(v) for p, v in query_pairs]
return '&'.join(query_strings)
def get_canonical_headers_string(header_dict):
header_pairs = sorted(header_dict.items())
header_strings = [h.lower() + ':' + v.strip() for h, v in header_pairs]
return '\n'.join(header_strings)
def uri_encode(string):
return parse.quote(string)
# Source for function:
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def hmac_sha256(key, msg, digest=True):
m = hmac.new(key, msg.encode("utf-8"), hashlib.sha256)
if digest:
return m.digest()
return m
# Source for function:
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def get_signing_key(secret_key, date_stamp, region_name, service_name):
k_date = hmac_sha256(("AWS4" + secret_key).encode("utf-8"), date_stamp)
k_region = hmac_sha256(k_date, region_name)
k_service = hmac_sha256(k_region, service_name)
k_signing = hmac_sha256(k_service, "aws4_request")
return k_signing
[docs]def get_dirs_and_files(key_list, prefix):
"""
Return a 2-tuple of sets. The first set in the 2-tuple
contains directory names and the second set contains files names.
Example with an object_key of /static/. The leading slash from /
get_dirs_and_files('/static/', ['static/css/ads.css', 'static/js/main.js', 'static/robots.txt'])
{'css', 'js'} {'robots.txt'}
"""
dirs = set()
files = set()
prefix = prefix.lstrip('/')
prefix_len = len(prefix)
for key in key_list:
if key.startswith(prefix):
key = key[prefix_len:]
if '/' in key:
dirs.add(key.split('/')[0])
else:
files.add(key)
return dirs, files
[docs]class S3IOError(IOError):
"""
Generic exception class for S3 communication errors.
"""
class S3FileDoesNotExistError(S3IOError):
def __init__(self, name=None, msg=None):
total_msg = 'File does not exist: {}'.format(name)
if msg:
total_msg += ' {}'.format(msg)
super().__init__(total_msg)