Source code for simstack.methods.upload_helpers
import zipfile
import tarfile
import os
from pathlib import Path
from simstack.core.context import context
from simstack.core.node import node
from simstack.models import FileListModel
from simstack.models.files import FileStack
[docs]
@node
async def archive_upload(file_upload: FileStack, **kwargs):
"""
Asynchronously processes a file upload, extracts files from supported archive formats
(.zip, .tar, .tar.gz), and returns a list of extracted files wrapped in FileStack
instances. If the file is not an archive, it is added as-is to the output.
Args:
file_upload (FileStack): The uploaded file to be processed.
**kwargs: Additional keyword arguments.
node_runner: An optional object for logging or processing context. If supplied,
it will log file paths and extraction details using its `info` method.
Returns:
FileListModel: A model containing a list of FileStack instances representing
the extracted files or the original file if it is not an archive.
"""
node_runner = kwargs.get('node_runner', None)
local_file = file_upload.get()
local_file_path = Path(local_file)
node_runner.info(f"Local file path: {local_file_path}")
extract_dir = local_file_path.parent
output_file_list = FileListModel(field_name="extracted_files")
if local_file_path.suffix == '.zip':
with zipfile.ZipFile(local_file_path, 'r') as zip_ref:
node_runner.info(f"Extracting files from {local_file_path} to {extract_dir}")
zip_ref.extractall(extract_dir)
for root, dirs, files in os.walk(extract_dir):
for file in files:
file_path = Path(root) / file
if file_path != local_file_path:
node_runner.info(f"Storing extracted file: {file_path}")
file_stack = FileStack.from_local_file(file_path, in_memory=True, is_hashable=True, secure_source=True)
output_file_list.append(file_stack)
elif local_file_path.suffix == '.tar' or local_file_path.name.endswith('.tar.gz'):
with tarfile.open(local_file_path, 'r:*') as tar_ref:
node_runner.info(f"Extracting files from {local_file_path} to {extract_dir}")
tar_ref.extractall(extract_dir)
for root, dirs, files in os.walk(extract_dir):
for file in files:
file_path = Path(root) / file
if file_path != local_file_path:
node_runner.info(f"Storing extracted file: {file_path}")
file_stack = FileStack.from_local_file(file_path, in_memory=True, is_hashable=True, secure_source=True)
output_file_list.append(file_stack)
else:
output_file_list.append(file_upload)
return output_file_list
[docs]
@node
async def file_list_upload_test(file_list: FileListModel,**kwargs):
node_runner = kwargs.get('node_runner', None)
# Ensure cache is loaded before iterating synchronously
for file_stack in file_list:
local_file = file_stack.get()
node_runner.info(f"Local file path: {local_file}")
return True
[docs]
@node
async def file_list_upload_all(file_stack: FileStack,**kwargs):
file_list = await archive_upload(file_stack, **kwargs)
unpacked = await file_list_upload_test(file_list, **kwargs)
return unpacked