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