Commit 17ffd5f8 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Merge branch 'rel/3.3.2' into 'v3.3'

Rel/3.3.2

See merge request fsl/fslpy!258
parents 3d4a345d 742f56dc
This document contains the ``fslpy`` release history in reverse chronological
order.
3.3.2 (Tuesday 12th October 2020)
---------------------------------
Changed
^^^^^^^
* Most :func:`.wrapper` functions now accept an argument called ``cmdonly``
which, if ``True``, will cause the generated command-line call to be
returned, instead of executed.
3.3.1 (Thursday 8th October 2020)
---------------------------------
......
......@@ -151,6 +151,10 @@ def run(*args, **kwargs):
the :func:`.fslsub.submit` function. May also be a
dictionary containing arguments to that function.
:arg cmdonly: Defaults to ``False``. If ``True``, the command is not
executed, but rather is returned directly, as a list of
arguments.
:arg log: Must be passed as a keyword argument. An optional ``dict``
which may be used to redirect the command's standard output
and error. The following keys are recognised:
......@@ -181,6 +185,7 @@ def run(*args, **kwargs):
returnStderr = kwargs.pop('stderr', False)
returnExitcode = kwargs.pop('exitcode', False)
submit = kwargs.pop('submit', {})
cmdonly = kwargs.pop('cmdonly', False)
log = kwargs.pop('log', None)
args = prepareArgs(args)
......@@ -207,6 +212,9 @@ def run(*args, **kwargs):
raise ValueError('submit must be a mapping containing '
'options for fsl.utils.fslsub.submit')
if cmdonly:
return args
if DRY_RUN:
return _dryrun(
submit, returnStdout, returnStderr, returnExitcode, *args)
......
......@@ -47,7 +47,7 @@ import re
import string
__version__ = '3.3.1'
__version__ = '3.3.2'
"""Current version number, as a string. """
......
......@@ -149,46 +149,73 @@ def _unwrap(func):
return func
def cmdwrapper(func):
"""This decorator can be used on functions which generate a command line.
It will pass the return value of the function to the
:func:`fsl.utils.run.run` function in a standardised manner.
def genxwrapper(func, runner):
"""This function is used by :func:`cmdwrapper` and :func:`fslwrapper`.
It is not intended to be used in any other circumstances.
This function generates a wrapper function which calls ``func`` to
generate a command-line call, and then uses ``runner`` to invoke that
command.
``func`` is assumed to be a wrapper function which generates a command-
line. ``runner`` is assumed to be Either :func:`.run.run` or
:func:`.run.runfsl`.
The generated wrapper function will pass all of its arguments to ``func``,
and will then pass the generated command-line to ``runner``, returning
whatever is returned.
The following keyword arguments will be intercepted by the wrapper
function, and will *not* be passed to ``func``:
- ``stdout``: Passed to ``runner``. Defaults to ``True``.
- ``stderr``: Passed to ``runner``. Defaults to ``True``.
- ``exitcode``: Passed to ``runner``. Defaults to ``False``.
- ``submit``: Passed to ``runner``. Defaults to ``None``.
- ``log``: Passed to ``runner``. Defaults to ``{'tee':True}``.
- ``cmdonly``: Passed to ``runner``. Defaults to ``False``.
:arg func: A function which generates a command line.
:arg runner: Either :func:`.run.run` or :func:`.run.runfsl`.
"""
def wrapper(*args, **kwargs):
stdout = kwargs.pop('stdout', True)
stderr = kwargs.pop('stderr', True)
exitcode = kwargs.pop('exitcode', False)
submit = kwargs.pop('submit', None)
cmdonly = kwargs.pop('cmdonly', False)
log = kwargs.pop('log', {'tee' : True})
cmd = func(*args, **kwargs)
return run.run(cmd,
stderr=stderr,
log=log,
submit=submit,
stdout=stdout,
exitcode=exitcode)
return runner(cmd,
stderr=stderr,
log=log,
submit=submit,
cmdonly=cmdonly,
stdout=stdout,
exitcode=exitcode)
return _update_wrapper(wrapper, func)
def cmdwrapper(func):
"""This decorator can be used on functions which generate a command line.
It will pass the return value of the function to the
:func:`fsl.utils.run.run` function in a standardised manner.
See the :func:`genxwrapper` function for details.
"""
return genxwrapper(func, run.run)
def fslwrapper(func):
"""This decorator can be used on functions which generate a FSL command
line. It will pass the return value of the function to the
:func:`fsl.utils.run.runfsl` function in a standardised manner.
See the :func:`genxwrapper` function for details.
"""
def wrapper(*args, **kwargs):
stdout = kwargs.pop('stdout', True)
stderr = kwargs.pop('stderr', True)
exitcode = kwargs.pop('exitcode', False)
submit = kwargs.pop('submit', None)
log = kwargs.pop('log', {'tee' : True})
cmd = func(*args, **kwargs)
return run.runfsl(cmd,
stderr=stderr,
log=log,
submit=submit,
stdout=stdout,
exitcode=exitcode)
return _update_wrapper(wrapper, func)
return genxwrapper(func, run.runfsl)
SHOW_IF_TRUE = object()
......
......@@ -179,6 +179,13 @@ def test_run_passthrough():
assert run.run('./script.sh', env=env) == expstdout
def test_cmdonly():
assert run.run('script.sh', cmdonly=True) == ['script.sh']
assert run.run('script.sh 1 2 3', cmdonly=True) == ['script.sh', '1', '2', '3']
assert run.run(['script.sh'], cmdonly=True) == ['script.sh']
assert run.run(['script.sh', '1'], cmdonly=True) == ['script.sh', '1']
def test_dryrun():
test_script = textwrap.dedent("""
......
......@@ -753,15 +753,20 @@ def test_cmdwrapper():
with run.dryrun():
assert func(1, 2)[0] == 'func 1 2'
assert func(1, 2, cmdonly=True) == ['func', '1', '2']
def test_fslwrapper():
@wutils.fslwrapper
def func(a, b):
return ['func', str(a), str(b)]
with run.dryrun(), mockFSLDIR(bin=('func',)) as fsldir:
with mockFSLDIR(bin=('func',)) as fsldir:
expected = '{} 1 2'.format(op.join(fsldir, 'bin', 'func'))
assert func(1, 2)[0] == expected
with run.dryrun():
assert func(1, 2)[0] == expected
func(1, 2, cmdonly=True)[0] == list(shlex.split(expected))
_test_script = textwrap.dedent("""
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment