run.py 2.25 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python
#
# run.py - Functions for running shell commands
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides some functions for running shell commands.

.. autosummary::
   :nosignatures:

   run
   runfsl
   fslsub
"""


import               logging
19
import               contextlib
20
21
22
import subprocess as sp
import os.path    as op

23
24
import               six

25
26
27
28
29
30
from fsl.utils.platform import platform as fslplatform


log = logging.getLogger(__name__)


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
DRY_RUN = False
"""If ``True``, the :func:`run` function will only log commands, but will not
execute them.
"""


@contextlib.contextmanager
def dryrun(*args):
    """Context manager which causes all calls to :func:`run` to be logged but
    not executed. See the :data:`DRY_RUN` flag.
    """
    global DRY_RUN

    oldval  = DRY_RUN
    DRY_RUN = True

    try:
        yield
    finally:
        DRY_RUN = oldval


def _prepareArgs(args):
    """Used by the :func:`run` function. Ensures that the given arguments is a
    list of strings.
56
57
58
59
    """

    if len(args) == 1:

60
61
62
        # Argument was a command string
        if isinstance(args[0], six.string_types):
            args = args[0].split()
63

64
65
66
        # Argument was an unpacked sequence
        else:
            args = args[0]
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
    return list(args)


def run(*args):
    """Call a command and return its output. You can pass the command and
    arguments as a single string, or as a regular or unpacked sequence.
    """

    args = _prepareArgs(args)

    if DRY_RUN:
        log.debug('dryrun: {}'.format(' '.join(args)))
    else:
        log.debug('run: {}'.format(' '.join(args)))

    if DRY_RUN:
        result = '<dryrun>'
    else:
        result = sp.check_output(args).decode('utf-8').strip()
87
88
89
90
91
92
93
94

    log.debug('result: {}'.format(result))

    return result


def runfsl(*args):
    """Call a FSL command and return its output. This function simply prepends
95
    ``$FSLDIR/bin/`` to the command before passing it to :func:`run`.
96
97
98
99
100
    """

    if fslplatform.fsldir is None:
        raise RuntimeError('$FSLDIR is not set - FSL cannot be found!')

101
    args    = _prepareArgs(args)
102
103
104
105
106
107
108
109
    args[0] = op.join(fslplatform.fsldir, 'bin', args[0])

    return run(*args)


def fslsub(*args):
    """Not implemented yet. """
    raise NotImplementedError('')