1010from aiida .common .datastructures import CalcInfo , CodeInfo , FileCopyOperation
1111from aiida .common .folders import Folder
1212from aiida .engine import CalcJob , CalcJobProcessSpec
13- from aiida .orm import Data , Dict , FolderData , List , RemoteData , SinglefileData , to_aiida_type
13+ from aiida .orm import Computer , Data , Dict , FolderData , List , RemoteData , SinglefileData , to_aiida_type
1414from aiida .parsers import Parser
1515
1616from aiida_shell .data import EntryPointData , PickledData
@@ -281,9 +281,11 @@ def prepare_for_submission(self, folder: Folder) -> CalcInfo:
281281 inputs = {}
282282
283283 nodes = inputs .get ('nodes' , {})
284+ computer = inputs ['code' ].computer
284285 filenames = (inputs .get ('filenames' , None ) or Dict ()).get_dict ()
285286 arguments = (inputs .get ('arguments' , None ) or List ()).get_list ()
286287 outputs = (inputs .get ('outputs' , None ) or List ()).get_list ()
288+ use_symlinks = inputs ['metadata' ]['options' ]['use_symlinks' ]
287289 filename_stdin = inputs ['metadata' ]['options' ].get ('filename_stdin' , None )
288290 filename_stdout = inputs ['metadata' ]['options' ].get ('output_filename' , None )
289291 default_retrieved_temporary = list (self .DEFAULT_RETRIEVED_TEMPORARY )
@@ -300,7 +302,10 @@ def prepare_for_submission(self, folder: Folder) -> CalcInfo:
300302 if filename_stdin and filename_stdin in processed_arguments :
301303 processed_arguments .remove (filename_stdin )
302304
303- remote_copy_list , remote_symlink_list = self .handle_remote_data_nodes (inputs )
305+ remote_data_nodes = {key : node for key , node in nodes .items () if isinstance (node , RemoteData )}
306+ remote_copy_list , remote_symlink_list = self .handle_remote_data_nodes (
307+ remote_data_nodes , filenames , computer , use_symlinks
308+ )
304309
305310 code_info = CodeInfo ()
306311 code_info .code_uuid = inputs ['code' ].uuid
@@ -329,16 +334,22 @@ def prepare_for_submission(self, folder: Folder) -> CalcInfo:
329334 return calc_info
330335
331336 @staticmethod
332- def handle_remote_data_nodes (inputs : dict [str , Data ]) -> tuple [list [t .Any ], list [t .Any ]]:
333- """Handle a ``RemoteData`` that was passed in the ``nodes`` input.
337+ def handle_remote_data_nodes (
338+ remote_data_nodes : dict [str , RemoteData ], filenames : dict [str , str ], computer : Computer , use_symlinks : bool
339+ ) -> tuple [list [t .Any ], list [t .Any ]]:
340+ """Handle all ``RemoteData`` nodes that were passed in the ``nodes`` input.
334341
335- :param inputs: The inputs dictionary.
342+ :param remote_data_nodes: The ``RemoteData`` input nodes.
343+ :param filenames: A dictionary of explicit filenames to use for the ``nodes`` to be written to ``dirpath``.
336344 :returns: A tuple of two lists, the ``remote_copy_list`` and the ``remote_symlink_list``.
337345 """
338- use_symlinks : bool = inputs ['metadata' ]['options' ]['use_symlinks' ] # type: ignore[index]
339- computer_uuid = inputs ['code' ].computer .uuid # type: ignore[union-attr]
340- remote_nodes = [node for node in inputs .get ('nodes' , {}).values () if isinstance (node , RemoteData )]
341- instructions = [(computer_uuid , f'{ node .get_remote_path ()} /*' , '.' ) for node in remote_nodes ]
346+ instructions = []
347+
348+ for key , node in remote_data_nodes .items ():
349+ if key in filenames :
350+ instructions .append ((computer .uuid , node .get_remote_path (), filenames [key ]))
351+ else :
352+ instructions .append ((computer .uuid , f'{ node .get_remote_path ()} /*' , '.' ))
342353
343354 if use_symlinks :
344355 return [], instructions
@@ -407,7 +418,10 @@ def process_arguments_and_nodes(
407418 self .write_folder_data (node , dirpath , filename )
408419 argument_interpolated = argument .format (** {placeholder : filename or placeholder })
409420 elif isinstance (node , RemoteData ):
410- self .handle_remote_data (node )
421+ # Only the placeholder needs to be formatted. The content of the remote data itself is handled by the
422+ # engine through the instructions created in ``handle_remote_data_nodes``.
423+ filename = prepared_filenames [placeholder ]
424+ argument_interpolated = argument .format (** {placeholder : filename or placeholder })
411425 else :
412426 argument_interpolated = argument .format (** {placeholder : str (node .value )})
413427
@@ -465,6 +479,8 @@ def prepare_filenames(self, nodes: dict[str, SinglefileData], filenames: dict[st
465479 raise RuntimeError (
466480 f'node `{ key } ` contains the file `{ f } ` which overlaps with a reserved output filename.'
467481 )
482+ elif isinstance (node , RemoteData ):
483+ filename = filenames .get (key , None )
468484 else :
469485 continue
470486
0 commit comments