88logger = logging .getLogger ("investing_algorithm_framework" )
99
1010
11+ def _fix_permissions (target_directory : str ):
12+ """
13+ Fix permissions on downloaded files to make them writable.
14+
15+ Args:
16+ target_directory (str): Directory to fix permissions for
17+ """
18+ try :
19+ # Fix the target directory itself
20+ os .chmod (target_directory , 0o755 )
21+
22+ # Recursively fix all subdirectories and files
23+ for root , dirs , files in os .walk (target_directory ):
24+ # Fix current directory permissions
25+ os .chmod (root , 0o755 )
26+
27+ # Fix all subdirectories
28+ for dir_name in dirs :
29+ dir_path = os .path .join (root , dir_name )
30+ os .chmod (dir_path , 0o755 )
31+
32+ # Fix all files - make them readable and writable
33+ for file_name in files :
34+ file_path = os .path .join (root , file_name )
35+ os .chmod (file_path , 0o644 )
36+
37+ logger .info (f"Update permissions for { target_directory } " )
38+ except Exception as e :
39+ logger .warning (f"Error fixing permissions: { e } " )
40+
41+
1142class AWSS3StorageStateHandler (StateHandler ):
1243 """
1344 A state handler for AWS S3 storage.
@@ -28,40 +59,13 @@ def initialize(self):
2859
2960 if not self .bucket_name :
3061 raise OperationalException (
31- "AWS S3 state handler requires a bucket name or the "
32- "AWS_S3_BUCKET_NAME environment variable to be set."
62+ "AWS S3 state handler requires a bucket_name para or the "
63+ "AWS_S3_BUCKET_NAME environment variable needs to be set "
64+ "in the environment."
3365 )
3466
3567 self .s3_client = boto3 .client ("s3" )
3668
37- def _fix_permissions (self , target_directory : str ):
38- """
39- Fix permissions on downloaded files to make them writable.
40-
41- Args:
42- target_directory (str): Directory to fix permissions for
43- """
44- try :
45- # Fix directory permissions
46- os .chmod (target_directory , 0o755 )
47-
48- # Recursively fix all files and subdirectories
49- for root , dirs , files in os .walk (target_directory ):
50- # Fix subdirectories
51- for dir_name in dirs :
52- dir_path = os .path .join (root , dir_name )
53- os .chmod (dir_path , 0o755 )
54-
55- # Fix files - make them readable and writable
56- for file_name in files :
57- file_path = os .path .join (root , file_name )
58- # Set to 0o644 (rw-r--r--)
59- os .chmod (file_path , 0o644 )
60-
61- logger .info (f"Permissions fixed for { target_directory } " )
62- except Exception as e :
63- logger .warning (f"Error fixing permissions: { e } " )
64-
6569 def save (self , source_directory : str ):
6670 """
6771 Save the state to AWS S3.
@@ -85,9 +89,11 @@ def save(self, source_directory: str):
8589 s3_key = os .path .relpath (file_path , source_directory ) \
8690 .replace ("\\ " , "/" )
8791
88- # Upload the file
8992 self .s3_client .upload_file (
90- file_path , self .bucket_name , s3_key
93+ file_path ,
94+ self .bucket_name ,
95+ s3_key ,
96+ ExtraArgs = {'ACL' : 'private' }
9197 )
9298
9399 except (NoCredentialsError , PartialCredentialsError ) as ex :
@@ -102,37 +108,44 @@ def save(self, source_directory: str):
102108 def load (self , target_directory : str ):
103109 """
104110 Load the state from AWS S3.
105-
106- Args:
107- target_directory (str): Directory to load the state
108-
109- Returns:
110- None
111111 """
112112 logger .info ("Loading state from AWS S3 ..." )
113113
114114 try :
115- # Ensure the local directory exists
116115 if not os .path .exists (target_directory ):
117- os .makedirs (target_directory )
116+ os .makedirs (target_directory , mode = 0o755 )
117+
118+ os .chmod (target_directory , 0o755 )
118119
119- # List and download objects
120120 response = self .s3_client .list_objects_v2 (Bucket = self .bucket_name )
121+
121122 if "Contents" in response :
122123 for obj in response ["Contents" ]:
123124 s3_key = obj ["Key" ]
124125 file_path = os .path .join (target_directory , s3_key )
125126
126- # Create subdirectories locally if needed
127- os . makedirs ( os . path . dirname ( file_path ), exist_ok = True )
127+ os . makedirs ( os . path . dirname ( file_path ), exist_ok = True ,
128+ mode = 0o755 )
128129
129- # Download object to file
130130 self .s3_client .download_file (
131131 self .bucket_name , s3_key , file_path
132132 )
133133
134- # Fix permissions on all downloaded files
135- self ._fix_permissions (target_directory )
134+ if os .path .isfile (file_path ):
135+ os .chmod (file_path , 0o644 )
136+ else :
137+ os .chmod (file_path , 0o755 )
138+
139+ # Final recursive fix
140+ _fix_permissions (target_directory )
141+
142+ # Add write permission to file (0o666 = rw-rw-rw-, then masked by umask)
143+ db_file = os .path .join (target_directory ,
144+ 'databases/prod-database.sqlite3' )
145+ if os .path .exists (db_file ):
146+ os .chmod (db_file , 0o666 )
147+ logger .info (
148+ f"Database file permissions after fix: { oct (os .stat (db_file ).st_mode )} " )
136149
137150 except (NoCredentialsError , PartialCredentialsError ) as ex :
138151 logger .error (f"Error loading state from AWS S3: { ex } " )
0 commit comments