summaryrefslogtreecommitdiffstats
path: root/src/nbblib/progutils.py
blob: c4c632c34cb028c0f8bb49f7910903ceaf08366f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
56
57
58
59
60
61
62
63
"""\
Utility functions for running external programs
"""


import os
import subprocess


__all__ = ['prog_stdout', 'prog_retstd', 'ProgramRunError', 'prog_run']


def prog_stdout(call_list):
    """Run program and return stdout (similar to shell backticks)"""
    proc = subprocess.Popen(call_list,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    stdout, stderr = proc.communicate(input=None)
    return stdout.strip()


def prog_retstd(call_list):
    """Run program and return stdout (similar to shell backticks)"""
    proc = subprocess.Popen(call_list,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    stdout, stderr = proc.communicate(input=None)
    return (proc.returncode, stdout.strip(), stderr.strip())


class ProgramRunError(Exception):
    """A program run returns a retcode != 0"""
    def __init__(self, call_list, retcode, cwd=None):
        super(ProgramRunError, self).__init__()
        self.call_list = call_list
        self.retcode = retcode
        if cwd:
            self.cwd = cwd
        else:
            self.cwd = os.getcwd()
    def __str__(self):
        return ("Error running program (%s, retcode=%d, cwd=%s)"
                % (repr(self.call_list),
                   self.retcode,
                   repr(self.cwd)))


def prog_run(call_list, context=None, env=None, env_update=None):
    """Run program showing its output. Raise exception if retcode != 0."""
    print "RUN:", call_list
    print "  in", os.getcwd()
    if context and context.dry_run:
        return None
    if not env:
        env = os.environ.copy()
    if env_update:
        env.update(env_update)
    proc = subprocess.Popen(call_list, env=env)
    stdout, stderr = proc.communicate(input=None)
    if proc.returncode != 0:
        raise ProgramRunError(call_list, proc.returncode, os.getcwd())
    return proc.returncode