Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:boutiques/boutiques into release…
Browse files Browse the repository at this point in the history
…0.5.15
  • Loading branch information
glatard committed Nov 15, 2018
2 parents 5f14287 + 56bd8ec commit 2f4a9b9
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 9 deletions.
12 changes: 12 additions & 0 deletions README.md
Expand Up @@ -75,6 +75,18 @@ There are additional custom arguments which can be supplied to this script, such
no interpretation of output files is attempted by this tool, so your descriptor could certainly be enhanced by addind these and other
features available through Boutiques, such as tests, tags, error codes, groups, and container images.

Once you've created your descriptor this way you can translate your arguments to a Boutiques-style invocation using the following
code block on runtime:

args = myparser.parse_args()
invoc = newDescriptor.createInvocation(args)

# Then, if you want to save them to a file...
import json
with open('my-inputs.json', 'w') as fhandle:
fhandle.write(json.dumps(invoc, indent=4))


### Validation

You just created a Boutiques descriptor (compliant with the [schema](./tools/python/boutiques/schema/descriptor.schema.json), of course)
Expand Down
16 changes: 13 additions & 3 deletions tools/python/boutiques/creator.py
Expand Up @@ -29,7 +29,7 @@ def __init__(self, parser=None, **kwargs):
kwargs.get('docker_image'),
kwargs.get('use_singularity'))

self.count = 0
self.sp_count = 0
if parser is not None:
self.parser = parser
self.descriptor["inputs"] = []
Expand All @@ -47,6 +47,11 @@ def save(self, filename):
with open(filename, "w") as f:
f.write(json.dumps(self.descriptor, indent=4, sort_keys=True))

def createInvocation(self, arguments):
argdict = vars(arguments)
argdict = {k: v for k, v in argdict.items() if v is not None}
return argdict

def parse_docker(self, descriptor, docker_image_name, use_singularity):
cont_image = {}

Expand Down Expand Up @@ -177,8 +182,13 @@ def parseAction(self, action, **kwargs):
print("{0}: Adding".format(actstring))
actdict = vars(action)
if action.dest == "==SUPPRESS==":
adest = "subparser_{0}".format(self.count)
self.count += 1
adest = "subparser_{0}".format(self.sp_count)
if kwargs.get("verbose"):
print("WARNING: Subparser has no destination set, "
"invocation parsing may not work as expected. This "
"can be fixed by adding \"dest='mysubparser'\" to "
"subparser creation.")
self.sp_count += 1
else:
adest = action.dest

Expand Down
1 change: 1 addition & 0 deletions tools/python/boutiques/invocationSchemaHandler.py
Expand Up @@ -171,6 +171,7 @@ def validateSchema(s, d=None, **kwargs):
try:
jsonschema.validate(d, s)
except ValidationError as e:
raise e
raise InvocationValidationError(e)
if kwargs.get("verbose"):
print("Invocation Schema validation OK")
Expand Down
5 changes: 4 additions & 1 deletion tools/python/boutiques/localExec.py
Expand Up @@ -804,7 +804,10 @@ def escape_string(s):
s = str(x)
if escape:
s = escape_string(str(x))
s_val += s + " "
if val.index(x) == len(val)-1:
s_val += s
else:
s_val += s + " "
val = s_val
else:
val = str(val)
Expand Down
11 changes: 10 additions & 1 deletion tools/python/boutiques/schema/examples/no_spaces.json
@@ -1,12 +1,21 @@
{
"command-line": "there[INPUT]shouldnotbeanyspace[INPUT]inhereaftersubstitution",
"command-line": "there[INPUT]shouldnotbeanyspace[INPUT_LIST]inhereaftersubstitution",
"description": "A command-line with no space",
"inputs": [
{
"id": "param",
"name": "param",
"type": "String",
"value-key": "[INPUT]"
},
{
"id": "param2",
"name": "param2",
"type": "String",
"list": true,
"min-list-entries": 1,
"max-list-entries": 1,
"value-key": "[INPUT_LIST]"
}
],
"name": "nospace",
Expand Down
16 changes: 15 additions & 1 deletion tools/python/boutiques/tests/test_creator.py
Expand Up @@ -7,6 +7,7 @@
import boutiques.creator as bc
import subprocess
import os.path as op
import json
import os
import pytest

Expand Down Expand Up @@ -50,7 +51,8 @@ def test_success_argparser(self):
help="my help 2", type=int)
parser.add_argument("--myarg3", "-m", action="store",
help="my help 3")
subparser = parser.add_subparsers(help="the choices you will make")
subparser = parser.add_subparsers(help="the choices you will make",
dest="mysubparser")
sb1 = subparser.add_parser("option1", help="the first value")
sb1.add_argument("suboption1", help="the first sub option option")
sb1.add_argument("suboption2", help="the first sub option option",
Expand All @@ -69,6 +71,18 @@ def test_success_argparser(self):
verbose=True,
tags={"purpose": "testing-creator",
"foo": "bar"})

fil = './test-created-argparse-descriptor.json'
creatorObj.save(fil)

invof = './test-created-argparse-inputs.json'
args = parser.parse_args([['val1', 'val2'], '2', 'option2',
'subval1', 'subval3',
'--suboptionflag1', 't1',
'--suboptionflag2'])
invo = creatorObj.createInvocation(args)
with open(invof, 'w') as fhandle:
fhandle.write(json.dumps(invo, indent=4))

assert bosh(['validate', fil]) is None
assert bosh(['invocation', fil, '-i', invof]) is None
6 changes: 3 additions & 3 deletions tools/python/cleanup_tests.sh
Expand Up @@ -6,9 +6,9 @@
#

rm -r temp-*.sh log*.txt config*.txt file.txt creator_output.json \
test-created-argparse-descriptor.json .pytest_cache/ bar.dat \
baz.txt cwl_inv_out.json cwl_out.json example.conf foo.txt \
goodbye.txt hello.js hello.tar stdout.txt
test-created-argparse-descriptor.json test-created-argparse-inputs.json \
.pytest_cache/ bar.dat baz.txt cwl_inv_out.json cwl_out.json \
example.conf foo.txt goodbye.txt hello.js hello.tar stdout.txt
git checkout boutiques/schema/examples/good.json
git checkout boutiques/schema/examples/example1/example1_docker.json
git checkout boutiques/schema/examples/example1/example1_sing.json
Expand Down

0 comments on commit 2f4a9b9

Please sign in to comment.