1#!/usr/bin/env python
2
3r"""
4This module provides valuable argument processing functions like
5gen_get_options and sprint_args.
6"""
7
8import sys
9import __builtin__
10import atexit
11import signal
12import argparse
13
14import gen_print as gp
15import gen_valid as gv
16
17default_string = '  The default value is "%(default)s".'
18
19
20def gen_get_options(parser,
21                    stock_list=[]):
22    r"""
23    Parse the command line arguments using the parser object passed and return
24    True/False (i.e. pass/fail).  However, if gv.exit_on_error is set, simply
25    exit the program on failure.  Also set the following built in values:
26
27    __builtin__.quiet      This value is used by the qprint functions.
28    __builtin__.test_mode  This value is used by command processing functions.
29    __builtin__.debug      This value is used by the dprint functions.
30    __builtin__.arg_obj    This value is used by print_program_header, etc.
31    __builtin__.parser     This value is used by print_program_header, etc.
32
33    Description of arguments:
34    parser                          A parser object.  See argparse module
35                                    documentation for details.
36    stock_list                      The caller can use this parameter to
37                                    request certain stock parameters offered
38                                    by this function.  For example, this
39                                    function will define a "quiet" option upon
40                                    request.  This includes stop help text and
41                                    parm checking.  The stock_list is a list
42                                    of tuples each of which consists of an
43                                    arg_name and a default value.  Example:
44                                    stock_list = [("test_mode", 0), ("quiet",
45                                    1), ("debug", 0)]
46    """
47
48    # This is a list of stock parms that we support.
49    master_stock_list = ["quiet", "test_mode", "debug", "loglevel"]
50
51    # Process stock_list.
52    for ix in range(0, len(stock_list)):
53        if len(stock_list[ix]) < 1:
54            error_message = "Programmer error - stock_list[" + str(ix) +\
55                            "] is supposed to be a tuple containing at" +\
56                            " least one element which is the name of" +\
57                            " the desired stock parameter:\n" +\
58                            gp.sprint_var(stock_list)
59            return gv.process_error_message(error_message)
60        if isinstance(stock_list[ix], tuple):
61            arg_name = stock_list[ix][0]
62            default = stock_list[ix][1]
63        else:
64            arg_name = stock_list[ix]
65            default = None
66
67        if arg_name not in master_stock_list:
68            error_message = "Programmer error - arg_name \"" + arg_name +\
69                            "\" not found found in stock list:\n" +\
70                            gp.sprint_var(master_stock_list)
71            return gv.process_error_message(error_message)
72
73        if arg_name == "quiet":
74            if default is None:
75                default = 0
76            parser.add_argument(
77                '--quiet',
78                default=default,
79                type=int,
80                choices=[1, 0],
81                help='If this parameter is set to "1", %(prog)s'
82                     + ' will print only essential information, i.e. it will'
83                     + ' not echo parameters, echo commands, print the total'
84                     + ' run time, etc.' + default_string)
85        elif arg_name == "test_mode":
86            if default is None:
87                default = 0
88            parser.add_argument(
89                '--test_mode',
90                default=default,
91                type=int,
92                choices=[1, 0],
93                help='This means that %(prog)s should go through all the'
94                     + ' motions but not actually do anything substantial.'
95                     + '  This is mainly to be used by the developer of'
96                     + ' %(prog)s.' + default_string)
97        elif arg_name == "debug":
98            if default is None:
99                default = 0
100            parser.add_argument(
101                '--debug',
102                default=default,
103                type=int,
104                choices=[1, 0],
105                help='If this parameter is set to "1", %(prog)s will print'
106                     + ' additional debug information.  This is mainly to be'
107                     + ' used by the developer of %(prog)s.' + default_string)
108        elif arg_name == "loglevel":
109            if default is None:
110                default = "info"
111            parser.add_argument(
112                '--loglevel',
113                default=default,
114                type=str,
115                choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL',
116                         'debug', 'info', 'warning', 'error', 'critical'],
117                help='If this parameter is set to "1", %(prog)s will print'
118                     + ' additional debug information.  This is mainly to be'
119                     + ' used by the developer of %(prog)s.' + default_string)
120
121    arg_obj = parser.parse_args()
122
123    __builtin__.quiet = 0
124    __builtin__.test_mode = 0
125    __builtin__.debug = 0
126    __builtin__.loglevel = 'WARNING'
127    for ix in range(0, len(stock_list)):
128        if isinstance(stock_list[ix], tuple):
129            arg_name = stock_list[ix][0]
130            default = stock_list[ix][1]
131        else:
132            arg_name = stock_list[ix]
133            default = None
134        if arg_name == "quiet":
135            __builtin__.quiet = arg_obj.quiet
136        elif arg_name == "test_mode":
137            __builtin__.test_mode = arg_obj.test_mode
138        elif arg_name == "debug":
139            __builtin__.debug = arg_obj.debug
140        elif arg_name == "loglevel":
141            __builtin__.loglevel = arg_obj.loglevel
142
143    __builtin__.arg_obj = arg_obj
144    __builtin__.parser = parser
145
146    # For each command line parameter, create a corresponding global variable
147    # and assign it the appropriate value.  For example, if the command line
148    # contained "--last_name='Smith', we'll create a global variable named
149    # "last_name" with the value "Smith".
150    module = sys.modules['__main__']
151    for key in arg_obj.__dict__:
152        setattr(module, key, getattr(__builtin__.arg_obj, key))
153
154    return True
155
156
157def set_pgm_arg(var_value,
158                var_name=None):
159    r"""
160    Set the value of the arg_obj.__dict__ entry named in var_name with the
161    var_value provided.  Also, set corresponding global variable.
162
163    Description of arguments:
164    var_value                       The value to set in the variable.
165    var_name                        The name of the variable to set.  This
166                                    defaults to the name of the variable used
167                                    for var_value when calling this function.
168    """
169
170    if var_name is None:
171        var_name = gp.get_arg_name(None, 1, 2)
172
173    arg_obj.__dict__[var_name] = var_value
174    module = sys.modules['__main__']
175    setattr(module, var_name, var_value)
176    if var_name == "quiet":
177        __builtin__.quiet = var_value
178    elif var_name == "debug":
179        __builtin__.debug = var_value
180    elif var_name == "test_mode":
181        __builtin__.test_mode = var_value
182
183
184def sprint_args(arg_obj,
185                indent=0):
186    r"""
187    sprint_var all of the arguments found in arg_obj and return the result as
188    a string.
189
190    Description of arguments:
191    arg_obj                         An argument object such as is returned by
192                                    the argparse parse_args() method.
193    indent                          The number of spaces to indent each line
194                                    of output.
195    """
196
197    loc_col1_width = gp.col1_width + indent
198
199    buffer = ""
200
201    for key in arg_obj.__dict__:
202        buffer += gp.sprint_varx(key, getattr(arg_obj, key), 0, indent,
203                                 loc_col1_width)
204
205    return buffer
206
207
208def gen_post_validation(exit_function=None,
209                        signal_handler=None):
210    r"""
211    Do generic post-validation processing.  By "post", we mean that this is to
212    be called from a validation function after the caller has done any
213    validation desired.  If the calling program passes exit_function and
214    signal_handler parms, this function will register them.  In other words,
215    it will make the signal_handler functions get called for SIGINT and
216    SIGTERM and will make the exit_function function run prior to the
217    termination of the program.
218
219    Description of arguments:
220    exit_function                   A function object pointing to the caller's
221                                    exit function.
222    signal_handler                  A function object pointing to the caller's
223                                    signal_handler function.
224    """
225
226    if exit_function is not None:
227        atexit.register(exit_function)
228    if signal_handler is not None:
229        signal.signal(signal.SIGINT, signal_handler)
230        signal.signal(signal.SIGTERM, signal_handler)
231