| #!/usr/bin/env python3 | 
 |  | 
 | r""" | 
 | See help text for details (--help or -h option).. | 
 |  | 
 | Example properties file content: | 
 | quiet=n | 
 | test_mode=y | 
 | pos=file1 file2 file3 | 
 |  | 
 | Example call: | 
 |  | 
 | prop_call.py --prop_file_name=prop_file my_program | 
 |  | 
 | The result is that the following command will be run: | 
 | my_program --test_mode=y --quiet=n file1 file2 file3 | 
 | """ | 
 |  | 
 | import os | 
 | import sys | 
 |  | 
 | save_path_0 = sys.path[0] | 
 | del sys.path[0] | 
 |  | 
 | from gen_arg import *  # NOQA | 
 | from gen_cmd import *  # NOQA | 
 | from gen_misc import *  # NOQA | 
 | from gen_print import *  # NOQA | 
 | from gen_valid import *  # NOQA | 
 |  | 
 | # Restore sys.path[0]. | 
 | sys.path.insert(0, save_path_0) | 
 |  | 
 |  | 
 | parser = argparse.ArgumentParser( | 
 |     usage="%(prog)s [OPTIONS]", | 
 |     description="%(prog)s will call a program using parameters retrieved" | 
 |     + " from the given properties file.", | 
 |     formatter_class=argparse.ArgumentDefaultsHelpFormatter, | 
 |     prefix_chars="-+", | 
 | ) | 
 |  | 
 | parser.add_argument( | 
 |     "--prop_dir_path", | 
 |     default=os.environ.get("PROP_DIR_PATH", os.getcwd()), | 
 |     help="The path to the directory that contains the properties file." | 
 |     + '  The default value is environment variable "PROP_DIR_PATH", if' | 
 |     + " set.  Otherwise, it is the current working directory.", | 
 | ) | 
 |  | 
 | parser.add_argument( | 
 |     "--prop_file_name", | 
 |     help="The path to a properties file that contains the parameters to" | 
 |     + ' pass to the program.  If the properties file has a ".properties"' | 
 |     + " extension, the caller need not specify the extension.  The format" | 
 |     + " of each line in the properties file should be as follows:" | 
 |     + " <parm_name=parm_value>.  Do not quote the parm value.  To specify" | 
 |     + ' positional parms, use a parm name of "pos".  For example: pos=this' | 
 |     " value", | 
 | ) | 
 |  | 
 | parser.add_argument("program_name", help="The name of the program to be run.") | 
 |  | 
 | # Populate stock_list with options we want. | 
 | stock_list = [("test_mode", 0), ("quiet", 1), ("debug", 0)] | 
 |  | 
 |  | 
 | def 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). | 
 |     """ | 
 |  | 
 |     dprint_executing() | 
 |     dprint_var(signal_number) | 
 |  | 
 |     qprint_pgm_footer() | 
 |  | 
 |  | 
 | def signal_handler(signal_number, frame): | 
 |     r""" | 
 |     Handle signals.  Without a function to catch a SIGTERM or SIGINT, our program would terminate immediately | 
 |     with return code 143 and without calling our exit_function. | 
 |     """ | 
 |  | 
 |     # Our convention is to set up exit_function with atexit.register() so there is no need to explicitly | 
 |     # call exit_function from here. | 
 |  | 
 |     dprint_executing() | 
 |  | 
 |     # Calling exit prevents us from returning to the code that was running when we received the signal. | 
 |     exit(0) | 
 |  | 
 |  | 
 | def validate_parms(): | 
 |     r""" | 
 |     Validate program parameters, etc.  Return True or False (i.e. pass/fail) accordingly. | 
 |     """ | 
 |  | 
 |     global prop_dir_path | 
 |     global prop_file_path | 
 |  | 
 |     if not valid_dir_path(prop_dir_path): | 
 |         return False | 
 |     prop_dir_path = add_trailing_slash(prop_dir_path) | 
 |  | 
 |     if not valid_value(prop_file_name): | 
 |         return False | 
 |  | 
 |     prop_file_path = prop_dir_path + prop_file_name | 
 |  | 
 |     # If properties file is not found, try adding ".properties" extension. | 
 |     if not os.path.isfile(prop_file_path): | 
 |         alt_prop_file_path = prop_file_path + ".properties" | 
 |         if os.path.isfile(alt_prop_file_path): | 
 |             prop_file_path = alt_prop_file_path | 
 |  | 
 |     if not valid_file_path(prop_file_path): | 
 |         return False | 
 |  | 
 |     if not valid_value(program_name): | 
 |         return False | 
 |  | 
 |     gen_post_validation(exit_function, signal_handler) | 
 |  | 
 |     return True | 
 |  | 
 |  | 
 | def main(): | 
 |     if not gen_get_options(parser, stock_list): | 
 |         return False | 
 |  | 
 |     if not validate_parms(): | 
 |         return False | 
 |  | 
 |     qprint_pgm_header() | 
 |  | 
 |     # Get the parameters from the properties file. | 
 |     properties = my_parm_file(prop_file_path) | 
 |     # The parms (including program name) need to go into a list. | 
 |     parms = [program_name] | 
 |     for key, value in properties.items(): | 
 |         if key == "pos": | 
 |             # Process positional parm(s). | 
 |             parms.extend(value.split()) | 
 |         else: | 
 |             parms.append("--" + key + "=" + escape_bash_quotes(value)) | 
 |  | 
 |     # parm_string is only created for display in non-quiet mode. | 
 |     parm_string = " ".join(parms[1:]) | 
 |     cmd_buf = program_name + " " + parm_string | 
 |     qprint_issuing(cmd_buf) | 
 |     if not test_mode: | 
 |         os.execvp(program_name, parms) | 
 |  | 
 |     return True | 
 |  | 
 |  | 
 | # Main | 
 |  | 
 | if not main(): | 
 |     exit(1) |