summaryrefslogtreecommitdiff
path: root/test/runner/retry.py
blob: bc1c140a1628654344915f9834920af43c856737 (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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python
# PYTHON_ARGCOMPLETE_OK
"""Automatically retry failed commands."""

from __future__ import absolute_import, print_function

# noinspection PyCompatibility
import argparse
import errno
import os
import sys
import time

from lib.util import (
    display,
    raw_command,
    ApplicationError,
    ApplicationWarning,
    SubprocessError,
)

try:
    import argcomplete
except ImportError:
    argcomplete = None


def main():
    """Main program function."""
    try:
        args = parse_args()
        display.verbosity = args.verbosity
        display.color = args.color

        command = [args.command] + args.args

        for attempt in range(0, args.tries):
            if attempt > 0:
                time.sleep(args.sleep)

            try:
                raw_command(command, env=os.environ)
                return
            except SubprocessError as ex:
                display.error(ex)
    except ApplicationWarning as ex:
        display.warning(str(ex))
        exit(0)
    except ApplicationError as ex:
        display.error(str(ex))
        exit(1)
    except KeyboardInterrupt:
        exit(2)
    except IOError as ex:
        if ex.errno == errno.EPIPE:
            exit(3)
        raise


def parse_args():
    """Parse command line arguments."""
    parser = argparse.ArgumentParser()

    parser.add_argument('-v', '--verbose',
                        dest='verbosity',
                        action='count',
                        default=0,
                        help='display more output')

    parser.add_argument('--color',
                        metavar='COLOR',
                        nargs='?',
                        help='generate color output: %(choices)s',
                        choices=('yes', 'no', 'auto'),
                        const='yes',
                        default='auto')

    parser.add_argument('--tries',
                        metavar='TRIES',
                        type=int,
                        default=3,
                        help='number of tries to execute command (default: %(default)s)')

    parser.add_argument('--sleep',
                        metavar='SECONDS',
                        type=int,
                        default=3,
                        help='seconds to sleep between tries (default: %(default)s)')

    parser.add_argument('command',
                        help='command to execute')

    parser.add_argument('args',
                        metavar='...',
                        nargs=argparse.REMAINDER,
                        help='optional arguments for command')

    if argcomplete:
        argcomplete.autocomplete(parser)

    args = parser.parse_args()

    if args.color == 'yes':
        args.color = True
    elif args.color == 'no':
        args.color = False
    elif 'SHIPPABLE' in os.environ:
        args.color = True
    else:
        args.color = sys.stdout.isatty()

    return args


if __name__ == '__main__':
    main()