@@ -244,10 +244,7 @@ ArtifactStorage
244244---------------
245245
246246``` python
247- ArtifactStorage(
248- file_system: AbstractFileSystem,
249- credential_refresher: Callable[[], bool ] | None = None ,
250- )
247+ ArtifactStorage(credential_manager: CredentialManager)
251248```
252249
253250Storage for artifacts with efficient handling of large files and directories.
@@ -256,35 +253,24 @@ Supports:
256253- Content-based deduplication using SHA1 hashing
257254- Batch uploads for directories handled by fsspec
258255
259- Initialize artifact storage with a file system and prefix path .
256+ Initialize artifact storage with credential manager .
260257
261258** Parameters:**
262259
263- * ** ` file_system ` **
264- (` AbstractFileSystem ` )
265- –FSSpec-compatible file system
266- * ** ` credential_refresher ` **
267- (` Callable[[], bool] | None ` , default:
268- ` None `
269- )
270- –Optional function to refresh credentials when it's about to expire
260+ * ** ` credential_manager ` **
261+ (` CredentialManager ` )
262+ –Optional credential manager for S3 operations
271263
272264<Accordion title = " Source code in dreadnode/artifact/storage.py" icon = " code" >
273265``` python
274- def __init__ (
275- self ,
276- file_system : fsspec.AbstractFileSystem,
277- credential_refresher : t.Callable[[], bool ] | None = None ,
278- ):
266+ def __init__ (self , credential_manager : CredentialManager):
279267 """
280- Initialize artifact storage with a file system and prefix path .
268+ Initialize artifact storage with credential manager .
281269
282270 Args:
283- file_system: FSSpec-compatible file system
284- credential_refresher: Optional function to refresh credentials when it's about to expire
271+ credential_manager: Optional credential manager for S3 operations
285272 """
286- self ._file_system = file_system
287- self ._credential_refresher = credential_refresher
273+ self ._credential_manager: CredentialManager = credential_manager
288274```
289275
290276
@@ -330,23 +316,26 @@ def batch_upload_files(self, source_paths: list[str], target_paths: list[str]) -
330316 if not source_paths:
331317 return []
332318
333- logger.debug(" Batch uploading %d files" , len (source_paths))
319+ def batch_upload_operation () -> list[str ]:
320+ filesystem = self ._credential_manager.get_filesystem()
334321
335- srcs = []
336- dsts = []
322+ srcs = []
323+ dsts = []
337324
338- for src, dst in zip (source_paths, target_paths, strict = False ):
339- if not self ._file_system .exists(dst):
340- srcs.append(src)
341- dsts.append(dst)
325+ for src, dst in zip (source_paths, target_paths, strict = False ):
326+ if not filesystem .exists(dst):
327+ srcs.append(src)
328+ dsts.append(dst)
342329
343- if srcs:
344- self ._file_system .put(srcs, dsts)
345- logger.debug (" Batch upload completed for %d files" , len (srcs))
346- else :
347- logger.debug (" All files already exist, skipping upload" )
330+ if srcs:
331+ filesystem .put(srcs, dsts)
332+ logger.info (" Batch upload completed for %d files" , len (srcs))
333+ else :
334+ logger.info (" All files already exist, skipping upload" )
348335
349- return [str (self ._file_system.unstrip_protocol(target)) for target in target_paths]
336+ return [str (filesystem.unstrip_protocol(target)) for target in target_paths]
337+
338+ return self ._credential_manager.execute_with_retry(batch_upload_operation)
350339```
351340
352341
@@ -391,8 +380,9 @@ def compute_file_hash(self, file_path: Path, stream_threshold_mb: int = 10) -> s
391380 Returns:
392381 First 16 chars of SHA1 hash
393382 """
383+
394384 file_size = file_path.stat().st_size
395- stream_threshold = stream_threshold_mb * 1024 * 1024 # Convert MB to bytes
385+ stream_threshold = stream_threshold_mb * 1024 * 1024
396386
397387 sha1 = hashlib.sha1() # noqa: S324 # nosec
398388
@@ -478,7 +468,6 @@ Store a file in the storage system, using multipart upload for large files.
478468
479469<Accordion title = " Source code in dreadnode/artifact/storage.py" icon = " code" >
480470``` python
481- @with_credential_refresh
482471def store_file (self , file_path : Path, target_key : str ) -> str :
483472 """
484473 Store a file in the storage system, using multipart upload for large files.
@@ -490,13 +479,19 @@ def store_file(self, file_path: Path, target_key: str) -> str:
490479 Returns:
491480 Full URI with protocol to the stored file
492481 """
493- if not self ._file_system.exists(target_key):
494- self ._file_system.put(str (file_path), target_key)
495- logger.debug(" Artifact successfully stored at %s " , target_key)
496- else :
497- logger.debug(" Artifact already exists at %s , skipping upload." , target_key)
498482
499- return str (self ._file_system.unstrip_protocol(target_key))
483+ def store_operation () -> str :
484+ filesystem = self ._credential_manager.get_filesystem()
485+
486+ if not filesystem.exists(target_key):
487+ filesystem.put(str (file_path), target_key)
488+ logger.info(" Artifact successfully stored at %s " , target_key)
489+ else :
490+ logger.info(" Artifact already exists at %s , skipping upload." , target_key)
491+
492+ return str (filesystem.unstrip_protocol(target_key))
493+
494+ return self ._credential_manager.execute_with_retry(store_operation)
500495```
501496
502497
0 commit comments