@@ -11,24 +11,28 @@ class ArtifactExporter:
11
11
def __init__ (self , config : Dict [str , Any ]):
12
12
self .config = config
13
13
self .config ["output_dir" ] = os .path .abspath (config .get ("output_dir" , "release" ))
14
+ self ._ensure_output_directory ()
14
15
15
- # Ensure directory exists with write permissions
16
- os .makedirs (os .path .join (self .config ["output_dir" ], "latest" ), exist_ok = True )
17
- os .chmod (os .path .join (self .config ["output_dir" ], "latest" ), 0o777 )
16
+ def _ensure_output_directory (self ):
17
+ """Ensure output directory exists with proper permissions"""
18
+ release_dir = os .path .join (self .config ["output_dir" ], "latest" )
19
+ os .makedirs (release_dir , exist_ok = True )
20
+ os .chmod (release_dir , 0o777 )
21
+ return release_dir
18
22
19
23
def export_training_artifacts (
20
24
self , training_results : Dict [str , Any ]
21
25
) -> Dict [str , str ]:
22
26
"""Export all artifacts to release/latest directory"""
23
- try :
24
- release_dir = os . path . join ( self . config [ "output_dir" ], "latest" )
27
+ release_dir = self . _ensure_output_directory ()
28
+ exported_files = {}
25
29
30
+ try :
26
31
# Clear existing contents
27
32
shutil .rmtree (release_dir , ignore_errors = True )
28
33
os .makedirs (release_dir , exist_ok = True )
29
34
os .chmod (release_dir , 0o777 )
30
35
31
- exported_files = {}
32
36
artifacts = training_results ["artifacts" ]
33
37
34
38
# Export model files
@@ -42,29 +46,35 @@ def export_training_artifacts(
42
46
}
43
47
44
48
for filename , src in model_files .items ():
49
+ dest = os .path .join (release_dir , filename )
45
50
if src and os .path .exists (src ):
46
- dest = os .path .join (release_dir , filename )
47
51
shutil .copy2 (src , dest )
48
- os .chmod (dest , 0o666 ) # Ensure writable
52
+ os .chmod (dest , 0o644 )
49
53
exported_files [filename .split ("." )[0 ]] = dest
50
54
elif filename == "metrics.json" :
51
- # Create default metrics if missing
52
55
self ._create_default_metrics (release_dir , training_results )
53
56
exported_files ["metrics" ] = os .path .join (release_dir , filename )
54
57
55
58
# Create supporting files
56
59
self ._create_feature_structure (release_dir , training_results )
57
60
self ._create_package_info (release_dir , exported_files )
58
61
59
- return {k : os .path .abspath (v ) for k , v in exported_files .items ()}
62
+ # Verify all files were created
63
+ for path in exported_files .values ():
64
+ if not os .path .exists (path ):
65
+ raise FileNotFoundError (f"Failed to create artifact at { path } " )
66
+
67
+ return exported_files
60
68
61
69
except Exception as e :
62
- print (f"Artifact export failed: { str (e )} " )
63
- raise
70
+ # Clean up partial exports
71
+ shutil .rmtree (release_dir , ignore_errors = True )
72
+ raise RuntimeError (f"Failed to export artifacts: { str (e )} " )
64
73
65
74
def _create_default_metrics (
66
75
self , release_dir : str , training_results : Dict [str , Any ]
67
76
):
77
+ metrics_path = os .path .join (release_dir , "metrics.json" )
68
78
default_metrics = training_results .get (
69
79
"metrics" ,
70
80
{
@@ -75,31 +85,30 @@ def _create_default_metrics(
75
85
"warning" : "Metrics not properly saved during training" ,
76
86
},
77
87
)
78
- metrics_path = os .path .join (release_dir , "metrics.json" )
79
88
with open (metrics_path , "w" ) as f :
80
89
json .dump (default_metrics , f , indent = 2 )
81
- os .chmod (metrics_path , 0o666 )
90
+ os .chmod (metrics_path , 0o644 )
82
91
83
92
def _create_feature_structure (
84
93
self , release_dir : str , training_results : Dict [str , Any ]
85
94
):
95
+ features_path = os .path .join (release_dir , "feature_structure.json" )
86
96
feature_structure = {
87
97
"feature_names" : training_results .get ("selected_features" , []),
88
98
"required_features" : len (training_results .get ("selected_features" , [])),
89
99
"version" : datetime .now ().strftime ("%Y%m%d_%H%M%S" ),
90
100
}
91
- features_path = os .path .join (release_dir , "feature_structure.json" )
92
101
with open (features_path , "w" ) as f :
93
102
json .dump (feature_structure , f , indent = 2 )
94
- os .chmod (features_path , 0o666 )
103
+ os .chmod (features_path , 0o644 )
95
104
96
105
def _create_package_info (self , release_dir : str , files : Dict [str , str ]):
106
+ info_path = os .path .join (release_dir , "package_info.json" )
97
107
package_info = {
98
108
"created_at" : datetime .now ().isoformat (),
99
109
"contents" : {k : os .path .basename (v ) for k , v in files .items ()},
100
110
"notes" : "Automatically generated by spyware-detector-training pipeline" ,
101
111
}
102
- info_path = os .path .join (release_dir , "package_info.json" )
103
112
with open (info_path , "w" ) as f :
104
113
json .dump (package_info , f , indent = 2 )
105
- os .chmod (info_path , 0o666 )
114
+ os .chmod (info_path , 0o644 )
0 commit comments