#!/usr/bin/env python r""" This module provides valuable argument processing functions like gen_get_options and sprint_args. """ import sys try: import __builtin__ except ImportError: import builtins as __builtin__ import atexit import signal import argparse import gen_print as gp import gen_valid as gv default_string = ' The default value is "%(default)s".' def gen_get_options(parser, stock_list=[]): r""" Parse the command line arguments using the parser object passed and return True/False (i.e. pass/fail). However, if gv.exit_on_error is set, simply exit the program on failure. Also set the following built in values: __builtin__.quiet This value is used by the qprint functions. __builtin__.test_mode This value is used by command processing functions. __builtin__.debug This value is used by the dprint functions. __builtin__.arg_obj This value is used by print_program_header, etc. __builtin__.parser This value is used by print_program_header, etc. Description of arguments: parser A parser object. See argparse module documentation for details. stock_list The caller can use this parameter to request certain stock parameters offered by this function. For example, this function will define a "quiet" option upon request. This includes stop help text and parm checking. The stock_list is a list of tuples each of which consists of an arg_name and a default value. Example: stock_list = [("test_mode", 0), ("quiet", 1), ("debug", 0)] """ # This is a list of stock parms that we support. master_stock_list = ["quiet", "test_mode", "debug", "loglevel"] # Process stock_list. for ix in range(0, len(stock_list)): if len(stock_list[ix]) < 1: error_message = "Programmer error - stock_list[" + str(ix) +\ "] is supposed to be a tuple containing at" +\ " least one element which is the name of" +\ " the desired stock parameter:\n" +\ gp.sprint_var(stock_list) return gv.process_error_message(error_message) if isinstance(stock_list[ix], tuple): arg_name = stock_list[ix][0] default = stock_list[ix][1] else: arg_name = stock_list[ix] default = None if arg_name not in master_stock_list: error_message = "Programmer error - arg_name \"" + arg_name +\ "\" not found found in stock list:\n" +\ gp.sprint_var(master_stock_list) return gv.process_error_message(error_message) if arg_name == "quiet": if default is None: default = 0 parser.add_argument( '--quiet', default=default, type=int, choices=[1, 0], help='If this parameter is set to "1", %(prog)s' + ' will print only essential information, i.e. it will' + ' not echo parameters, echo commands, print the total' + ' run time, etc.' + default_string) elif arg_name == "test_mode": if default is None: default = 0 parser.add_argument( '--test_mode', default=default, type=int, choices=[1, 0], help='This means that %(prog)s should go through all the' + ' motions but not actually do anything substantial.' + ' This is mainly to be used by the developer of' + ' %(prog)s.' + default_string) elif arg_name == "debug": if default is None: default = 0 parser.add_argument( '--debug', default=default, type=int, choices=[1, 0], help='If this parameter is set to "1", %(prog)s will print' + ' additional debug information. This is mainly to be' + ' used by the developer of %(prog)s.' + default_string) elif arg_name == "loglevel": if default is None: default = "info" parser.add_argument( '--loglevel', default=default, type=str, choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL', 'debug', 'info', 'warning', 'error', 'critical'], help='If this parameter is set to "1", %(prog)s will print' + ' additional debug information. This is mainly to be' + ' used by the developer of %(prog)s.' + default_string) arg_obj = parser.parse_args() __builtin__.quiet = 0 __builtin__.test_mode = 0 __builtin__.debug = 0 __builtin__.loglevel = 'WARNING' for ix in range(0, len(stock_list)): if isinstance(stock_list[ix], tuple): arg_name = stock_list[ix][0] default = stock_list[ix][1] else: arg_name = stock_list[ix] default = None if arg_name == "quiet": __builtin__.quiet = arg_obj.quiet elif arg_name == "test_mode": __builtin__.test_mode = arg_obj.test_mode elif arg_name == "debug": __builtin__.debug = arg_obj.debug elif arg_name == "loglevel": __builtin__.loglevel = arg_obj.loglevel __builtin__.arg_obj = arg_obj __builtin__.parser = parser # For each command line parameter, create a corresponding global variable and assign it the appropriate # value. For example, if the command line contained "--last_name='Smith', we'll create a global variable # named "last_name" with the value "Smith". module = sys.modules['__main__'] for key in arg_obj.__dict__: setattr(module, key, getattr(__builtin__.arg_obj, key)) return True def set_pgm_arg(var_value, var_name=None): r""" Set the value of the arg_obj.__dict__ entry named in var_name with the var_value provided. Also, set corresponding global variable. Description of arguments: var_value The value to set in the variable. var_name The name of the variable to set. This defaults to the name of the variable used for var_value when calling this function. """ if var_name is None: var_name = gp.get_arg_name(None, 1, 2) arg_obj.__dict__[var_name] = var_value module = sys.modules['__main__'] setattr(module, var_name, var_value) if var_name == "quiet": __builtin__.quiet = var_value elif var_name == "debug": __builtin__.debug = var_value elif var_name == "test_mode": __builtin__.test_mode = var_value def sprint_args(arg_obj, indent=0): r""" sprint_var all of the arguments found in arg_obj and return the result as a string. Description of arguments: arg_obj An argument object such as is returned by the argparse parse_args() method. indent The number of spaces to indent each line of output. """ col1_width = gp.dft_col1_width + indent buffer = "" for key in arg_obj.__dict__: buffer += gp.sprint_varx(key, getattr(arg_obj, key), 0, indent, col1_width) return buffer module = sys.modules["__main__"] def gen_exit_function(signal_number=0, frame=None): r""" Execute whenever the program ends normally or with the signals that we catch (i.e. TERM, INT). """ gp.dprint_executing() gp.dprint_var(signal_number) # ignore_err influences the way shell_cmd processes errors. Since we're doing exit processing, we don't # want to stop the program due to a shell_cmd failure. ignore_err = 1 # Call the main module's exit_function if it is defined. exit_function = getattr(module, "exit_function", None) if exit_function: exit_function(signal_number, frame) gp.qprint_pgm_footer() def gen_signal_handler(signal_number, frame): r""" Handle signals. Without a function to catch a SIGTERM or SIGINT, the program would terminate immediately with return code 143 and without calling the exit_function. """ # The convention is to set up exit_function with atexit.register() so there is no need to explicitly # call exit_function from here. gp.dprint_executing() # Calling exit prevents control from returning to the code that was running when the signal was received. exit(0) def gen_post_validation(exit_function=None, signal_handler=None): r""" Do generic post-validation processing. By "post", we mean that this is to be called from a validation function after the caller has done any validation desired. If the calling program passes exit_function and signal_handler parms, this function will register them. In other words, it will make the signal_handler functions get called for SIGINT and SIGTERM and will make the exit_function function run prior to the termination of the program. Description of arguments: exit_function A function object pointing to the caller's exit function. This defaults to this module's gen_exit_function. signal_handler A function object pointing to the caller's signal_handler function. This defaults to this module's gen_signal_handler. """ # Get defaults. exit_function = exit_function or gen_exit_function signal_handler = signal_handler or gen_signal_handler atexit.register(exit_function) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) def gen_setup(): r""" Do general setup for a program. """ # Set exit_on_error for gen_valid functions. gv.set_exit_on_error(True) # Get main module variable values. parser = getattr(module, "parser") stock_list = getattr(module, "stock_list") validate_parms = getattr(module, "validate_parms", None) gen_get_options(parser, stock_list) if validate_parms: validate_parms() gen_post_validation() gp.qprint_pgm_header()