-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from ArcanaFramework/multiple-commands
Added support for multiple commands
- Loading branch information
Showing
6 changed files
with
193 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
from pathlib import Path | ||
import random | ||
from copy import deepcopy | ||
import pytest | ||
from conftest import ( | ||
TEST_XNAT_DATASET_BLUEPRINTS, | ||
|
@@ -7,6 +9,7 @@ | |
FileBP, | ||
access_dataset, | ||
) | ||
from frametree.xnat import Xnat | ||
from pipeline2app.xnat.image import XnatApp | ||
from pipeline2app.xnat.command import XnatCommand | ||
from pipeline2app.xnat.deploy import ( | ||
|
@@ -47,7 +50,7 @@ def run_spec( | |
"package": "1.0", | ||
}, | ||
"title": "A pipeline to test Pipeline2app's deployment tool", | ||
"command": command_spec, | ||
"commands": {"concatenate-test": command_spec}, | ||
"authors": [{"name": "Some One", "email": "[email protected]"}], | ||
"docs": { | ||
"info_url": "http://concatenate.readthefakedocs.io", | ||
|
@@ -108,7 +111,7 @@ def run_spec( | |
"pipeline2app-xnat", | ||
], | ||
}, | ||
"command": bids_command_spec, | ||
"commands": {"bids-test-command": bids_command_spec}, | ||
"authors": [ | ||
{"name": "Some One Else", "email": "[email protected]"} | ||
], | ||
|
@@ -212,7 +215,9 @@ def test_xnat_cs_pipeline(xnat_repository, run_spec, run_prefix, work_dir): | |
# the fact that the container service test XNAT instance shares the | ||
# outer Docker socket. Since we build the pipeline image with the same | ||
# socket there is no need to pull it. | ||
xnat_command = image_spec.command.make_json() | ||
|
||
cmd = image_spec.command() | ||
xnat_command = cmd.make_json() | ||
|
||
launch_inputs = {} | ||
|
||
|
@@ -222,11 +227,11 @@ def test_xnat_cs_pipeline(xnat_repository, run_spec, run_prefix, work_dir): | |
for pname, pval in params.items(): | ||
launch_inputs[pname] = pval | ||
|
||
if image_spec.command.internal_upload: | ||
if cmd.internal_upload: | ||
# If using internal upload, the output names are fixed | ||
output_values = {o: o for o in image_spec.command.output_names} | ||
output_values = {o: o for o in cmd.output_names} | ||
else: | ||
output_values = {o: o + "_sink" for o in image_spec.command.output_names} | ||
output_values = {o: o + "_sink" for o in cmd.output_names} | ||
launch_inputs.update(output_values) | ||
|
||
with xnat_repository.connection: | ||
|
@@ -245,7 +250,7 @@ def test_xnat_cs_pipeline(xnat_repository, run_spec, run_prefix, work_dir): | |
|
||
assert status == "Complete", f"Workflow {workflow_id} failed.\n{out_str}" | ||
|
||
access_type = "direct" if image_spec.command.internal_upload else "api" | ||
access_type = "direct" if cmd.internal_upload else "api" | ||
|
||
assert f"via {access_type} access" in out_str.lower() | ||
|
||
|
@@ -259,10 +264,146 @@ def test_xnat_cs_pipeline(xnat_repository, run_spec, run_prefix, work_dir): | |
Path(f).name.lstrip("sub-DEFAULT_") | ||
for f in test_xsession.resources[sinked_name].files | ||
) | ||
if image_spec.command.internal_upload: | ||
if cmd.internal_upload: | ||
reference = sorted( | ||
d.rstrip("_sink.txt") + ".txt" for d in deriv.filenames | ||
) | ||
else: | ||
reference = sorted(deriv.filenames) | ||
assert uploaded_files == reference | ||
|
||
|
||
def test_multi_command(xnat_repository: Xnat, tmp_path: Path, run_prefix) -> None: | ||
|
||
bp = TestXnatDatasetBlueprint( | ||
dim_lengths=[1, 1, 1], | ||
scans=[ | ||
ScanBP( | ||
name="scan1", | ||
resources=[FileBP(path="TEXT", datatype=Text, filenames=["file1.txt"])], | ||
), | ||
ScanBP( | ||
name="scan2", | ||
resources=[FileBP(path="TEXT", datatype=Text, filenames=["file2.txt"])], | ||
), | ||
], | ||
) | ||
|
||
project_id = run_prefix + "multi_command" + str(hex(random.getrandbits(16)))[2:] | ||
|
||
dataset = bp.make_dataset( | ||
dataset_id=project_id, | ||
store=xnat_repository, | ||
name="", | ||
) | ||
|
||
two_dup_spec = dict( | ||
name="concatenate", | ||
task="pipeline2app.testing.tasks:concatenate", | ||
row_frequency=Clinical.session.tostr(), | ||
inputs=[ | ||
{ | ||
"name": "first_file", | ||
"datatype": "text/text-file", | ||
"field": "in_file1", | ||
"help": "dummy", | ||
}, | ||
{ | ||
"name": "second_file", | ||
"datatype": "text/text-file", | ||
"field": "in_file2", | ||
"help": "dummy", | ||
}, | ||
], | ||
outputs=[ | ||
{ | ||
"name": "concatenated", | ||
"datatype": "text/text-file", | ||
"field": "out_file", | ||
"help": "dummy", | ||
} | ||
], | ||
parameters={ | ||
"duplicates": { | ||
"datatype": "field/integer", | ||
"default": 2, | ||
"help": "dummy", | ||
} | ||
}, | ||
) | ||
|
||
three_dup_spec = deepcopy(two_dup_spec) | ||
three_dup_spec["parameters"]["duplicates"]["default"] = 3 | ||
|
||
test_spec = { | ||
"name": "test_multi_commands", | ||
"title": "a test image for multi-image commands", | ||
"commands": { | ||
"two_duplicates": two_dup_spec, | ||
"three_duplicates": three_dup_spec, | ||
}, | ||
"version": {"package": "1.0", "build": "1"}, | ||
"packages": { | ||
"system": ["vim"], # just to test it out | ||
"pip": { | ||
"fileformats": None, | ||
"pipeline2app": None, | ||
"frametree": None, | ||
}, | ||
}, | ||
"authors": [{"name": "Some One", "email": "[email protected]"}], | ||
"docs": { | ||
"info_url": "http://concatenate.readthefakedocs.io", | ||
}, | ||
} | ||
|
||
app = XnatApp.load(test_spec) | ||
|
||
app.make( | ||
build_dir=tmp_path / "build-dir", | ||
pipeline2app_install_extras=["test"], | ||
use_local_packages=True, | ||
for_localhost=True, | ||
) | ||
|
||
fnames = ["file1.txt", "file2.txt"] | ||
|
||
base_launch_inputs = { | ||
"first_file": "scan1", | ||
"second_file": "scan2", | ||
} | ||
|
||
command_names = ["two_duplicates", "three_duplicates"] | ||
|
||
with xnat_repository.connection as xlogin: | ||
|
||
test_xsession = next(iter(xlogin.projects[dataset.id].experiments.values())) | ||
for command_name in command_names: | ||
|
||
launch_inputs = deepcopy(base_launch_inputs) | ||
launch_inputs["concatenated"] = command_name | ||
|
||
workflow_id, status, out_str = install_and_launch_xnat_cs_command( | ||
command_json=app.command(command_name).make_json(), | ||
project_id=project_id, | ||
session_id=test_xsession.id, | ||
inputs=launch_inputs, | ||
xlogin=xlogin, | ||
) | ||
|
||
assert status == "Complete", f"Workflow {workflow_id} failed.\n{out_str}" | ||
|
||
assert sorted(r.label for r in test_xsession.resources.values()) == sorted( | ||
command_names | ||
) | ||
|
||
# Add source column to saved dataset | ||
reloaded = dataset.reload() | ||
for command_name in command_names: | ||
sink = reloaded[command_name] | ||
duplicates = 2 if command_name == "two_duplicates" else 3 | ||
expected_contents = "\n".join(fnames * duplicates) | ||
for item in sink: | ||
with open(item) as f: | ||
contents = f.read() | ||
assert contents == expected_contents |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters