@@ -11,10 +11,11 @@ class S3Client:
1111 """
1212 Client for fetching and setting an AWS S3 file.
1313
14- Takes as input the name of the S3 bucket and resource to be fetched/set.
14+ Takes as input the name of the S3 bucket. If fetching/setting a cache, also
15+ takes the cached resource.
1516 """
1617
17- def __init__ (self , bucket , resource ):
18+ def __init__ (self , bucket , resource = None ):
1819 self .logger = create_log ('s3_client' )
1920 self .bucket = bucket
2021 self .resource = resource
@@ -23,49 +24,68 @@ def __init__(self, bucket, resource):
2324 self .s3_client = boto3 .client (
2425 's3' , region_name = os .environ .get ('AWS_REGION' , 'us-east-1' ))
2526 except ClientError as e :
26- self .logger .error (
27- 'Could not create S3 client: {err}' .format (err = e ))
28- raise S3ClientError (
29- 'Could not create S3 client: {err}' .format (err = e )) from None
27+ error_msg = f'Could not create S3 client: { e } '
28+ self .logger .error (error_msg )
29+ raise S3ClientError (error_msg ) from None
3030
3131 def close (self ):
3232 self .s3_client .close ()
3333
3434 def fetch_cache (self ):
3535 """Fetches a JSON file from S3 and returns the resulting dictionary"""
36- self .logger .info ('Fetching {file} from S3 bucket {bucket}' . format (
37- file = self .resource , bucket = self .bucket ) )
36+ self .logger .info (
37+ f'Fetching { self .resource } from S3 bucket { self .bucket } ' )
3838 try :
3939 output_stream = BytesIO ()
4040 self .s3_client .download_fileobj (
4141 self .bucket , self .resource , output_stream )
4242 return json .loads (output_stream .getvalue ())
4343 except ClientError as e :
44- self .logger .error (
45- 'Error retrieving {file} from S3 bucket {bucket}: {error}'
46- .format (file = self .resource , bucket = self .bucket , error = e ))
47- raise S3ClientError (
48- 'Error retrieving {file} from S3 bucket {bucket}: {error}'
49- .format (file = self .resource , bucket = self .bucket , error = e )
50- ) from None
44+ error_msg = (
45+ f'Error retrieving { self .resource } from S3 bucket '
46+ f'{ self .bucket } : { e } ' )
47+ self .logger .error (error_msg )
48+ raise S3ClientError (error_msg ) from None
5149
5250 def set_cache (self , state ):
5351 """Writes a dictionary to JSON and uploads the resulting file to S3"""
5452 self .logger .info (
55- 'Setting {file} in S3 bucket {bucket} to {state}' .format (
56- file = self .resource , bucket = self .bucket , state = state ))
53+ f'Setting { self .resource } in S3 bucket { self .bucket } to { state } ' )
5754 try :
5855 input_stream = BytesIO (json .dumps (state ).encode ())
5956 self .s3_client .upload_fileobj (
6057 input_stream , self .bucket , self .resource )
6158 except ClientError as e :
62- self .logger .error (
63- 'Error uploading {file} to S3 bucket {bucket}: {error}'
64- .format (file = self .resource , bucket = self .bucket , error = e ))
65- raise S3ClientError (
66- 'Error uploading {file} to S3 bucket {bucket}: {error}'
67- .format (file = self .resource , bucket = self .bucket , error = e )
68- ) from None
59+ error_msg = (
60+ f'Error uploading { self .resource } to S3 bucket '
61+ f'{ self .s3_bucket } : { e } ' )
62+ self .logger .error (error_msg )
63+ raise S3ClientError (error_msg ) from None
64+
65+ def upload_file (self , content , file_path ):
66+ """
67+ Writes an arbitrary file to S3. Note that this will overwrite any
68+ existing file with the same name.
69+
70+ Parameters
71+ ----------
72+ content: str
73+ The string that should be written to the file. Must be utf-8.
74+ file_path: str
75+ The full path of the file that should be written not including the
76+ bucket. Example: "subdirectory/example_file.csv"
77+ """
78+ self .logger .info (
79+ f'Writing { file_path } in S3 bucket { self .s3_client .name } ' )
80+ try :
81+ input_stream = BytesIO (content .encode ())
82+ self .s3_client .upload_fileobj (input_stream , self .bucket , file_path )
83+ except ClientError as e :
84+ error_msg = (
85+ f'Error uploading { file_path } to S3 bucket '
86+ f'{ self .s3_bucket } : { e } ' )
87+ self .logger .error (error_msg )
88+ raise S3ClientError (error_msg ) from None
6989
7090
7191class S3ClientError (Exception ):
0 commit comments