Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CalcJob: make sure local_copy_list files do not end up in node repo #4415

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions aiida/engine/daemon/execmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,15 @@ def find_data_node(inputs, uuid):
# folders that would be empty when considering the `provenance_exclude_list` will *not* be copied to the repo. The
# advantage of this explicit copying instead of deleting the files from `provenance_exclude_list` from the sandbox
# first before moving the entire remaining content to the node's repository, is that in this way we are guaranteed
# not to accidentally move files to the repository that should not go there at all cost.
# not to accidentally move files to the repository that should not go there at all cost. Note that all entries in
# the provenance exclude list are normalized first, just as the paths that are in the sandbox folder, otherwise the
# direct equality test may fail, e.g.: './path/file.txt' != 'path/file.txt' even though they reference the same file
provenance_exclude_list = [os.path.normpath(entry) for entry in provenance_exclude_list]

for root, _, filenames in os.walk(folder.abspath):
for filename in filenames:
filepath = os.path.join(root, filename)
relpath = os.path.relpath(filepath, folder.abspath)
relpath = os.path.normpath(os.path.relpath(filepath, folder.abspath))
if relpath not in provenance_exclude_list:
with open(filepath, 'rb') as handle:
node._repository.put_object_from_filelike(handle, relpath, 'wb', force=True) # pylint: disable=protected-access
Expand Down
36 changes: 36 additions & 0 deletions tests/engine/daemon/test_execmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# For further information please visit http://www.aiida.net #
###########################################################################
"""Tests for the :mod:`aiida.engine.daemon.execmanager` module."""
import io
import os
import pytest

Expand Down Expand Up @@ -54,3 +55,38 @@ def test_retrieve_files_from_list(tmp_path_factory, generate_calculation_node):

with open(str(target / 'file_a.txt'), 'rb') as handle:
assert handle.read() == content_a


@pytest.mark.usefixtures('clear_database_before_test')
def test_upload_local_copy_list(fixture_sandbox, aiida_localhost, aiida_local_code_factory):
"""Test the ``local_copy_list`` functionality in ``upload_calculation``.

Specifically, verify that files in the ``local_copy_list`` do not end up in the repository of the node.
"""
from aiida.common.datastructures import CalcInfo, CodeInfo
from aiida.orm import CalcJobNode, SinglefileData

inputs = {
'file_a': SinglefileData(io.BytesIO(b'content_a')).store(),
'file_b': SinglefileData(io.BytesIO(b'content_b')).store(),
}

node = CalcJobNode(computer=aiida_localhost)
node.store()

code = aiida_local_code_factory('arithmetic.add', '/bin/bash').store()
code_info = CodeInfo()
code_info.code_uuid = code.uuid

calc_info = CalcInfo()
calc_info.uuid = node.uuid
calc_info.codes_info = [code_info]
calc_info.local_copy_list = [
(inputs['file_a'].uuid, inputs['file_a'].filename, './files/file_a'),
(inputs['file_a'].uuid, inputs['file_a'].filename, './files/file_b'),
]

with LocalTransport() as transport:
execmanager.upload_calculation(node, transport, calc_info, fixture_sandbox)

assert node.list_object_names() == []