Skip to content

Commit

Permalink
🧪 Additional tests for upload_calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
mbercx committed Jun 3, 2024
1 parent ad15c97 commit fa0e9c5
Show file tree
Hide file tree
Showing 4 changed files with 347 additions and 31 deletions.
26 changes: 20 additions & 6 deletions src/aiida/engine/daemon/execmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,6 @@ def _copy_remote_files(logger, node, computer, transport, remote_copy_list, remo
def _copy_local_files(logger, node, transport, inputs, local_copy_list):
"""Perform the copy instructions of the ``local_copy_list``."""

# The transport class can only copy files directly from the file system, so the files in the source node's repo
# have to first be copied to a temporary directory on disk.
for uuid, filename, target in local_copy_list:
logger.debug(f'[submission of calculation {node.uuid}] copying local file/folder to {target}')

Expand All @@ -347,21 +345,37 @@ def _copy_local_files(logger, node, transport, inputs, local_copy_list):
logger.warning(f'failed to load Node<{uuid}> specified in the `local_copy_list`')
continue

# The transport class can only copy files directly from the file system, so the files in the source node's repo
# have to first be copied to a temporary directory on disk.
with TemporaryDirectory() as tmpdir:
dirpath = pathlib.Path(tmpdir)

# If no explicit source filename is defined, we assume the top-level directory
filename_source = filename or '.'
filename_target = target or ''
filename_target = target or '.'

file_type_source = data_node.base.repository.get_object(filename_source).file_type

# The logic below takes care of an edge case where the source is a file but the target is a directory. In
# this case, the v2.5.1 implementation would raise an `IsADirectoryError` exception, because it would try
# to open the directory in the sandbox folder as a file when writing the contents.
if file_type_source == FileType.FILE and target and transport.isdir(target):
raise IsADirectoryError

# In case the source filename is specified and it is a directory that already exists in the remote, we
# want to avoid nested directories in the target path to replicate the behavior of v2.5.1. This is done by
# setting the target filename to '.', which means the contents of the node will be copied in the top level
# of the temporary directory, whose contents are then copied into the target directory.
if filename and transport.isdir(filename):
filename_target = '.'

# Make the target filepath absolute and create any intermediate directories if they don't yet exist
filepath_target = (dirpath / filename_target).resolve().absolute()
filepath_target.parent.mkdir(parents=True, exist_ok=True)

if data_node.base.repository.get_object(filename_source).file_type == FileType.DIRECTORY:
if file_type_source == FileType.DIRECTORY:
# If the source object is a directory, we copy its entire contents
data_node.base.repository.copy_tree(filepath_target, filename_source)
transport.put(f'{dirpath}/*', target or '.')
transport.put(f'{dirpath}/*', target or '.', overwrite=True)
else:
# Otherwise, simply copy the file
with filepath_target.open('wb') as handle:
Expand Down
2 changes: 1 addition & 1 deletion src/aiida/transports/plugins/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ def puttree(self, localpath, remotepath, *args, **kwargs):

the_destination = os.path.join(self.curdir, remotepath)

shutil.copytree(localpath, the_destination, symlinks=not dereference)
shutil.copytree(localpath, the_destination, symlinks=not dereference, dirs_exist_ok=overwrite)

def rmtree(self, path):
"""Remove tree as rm -r would do
Expand Down
2 changes: 1 addition & 1 deletion src/aiida/transports/plugins/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ def puttree(self, localpath, remotepath, callback=None, dereference=True, overwr
self.mkdir(remotepath) # and make a directory at its place
else: # remotepath exists already: copy the folder inside of it!
remotepath = os.path.join(remotepath, os.path.split(localpath)[1])
self.mkdir(remotepath) # create a nested folder
self.makedirs(remotepath, ignore_existing=overwrite) # create a nested folder

for this_source in os.walk(localpath):
# Get the relative path
Expand Down
Loading

0 comments on commit fa0e9c5

Please sign in to comment.