|  | #!/usr/bin/env python | 
|  |  | 
|  | r""" | 
|  | This module provides valuable argument processing functions like | 
|  | gen_get_options and sprint_args. | 
|  | """ | 
|  |  | 
|  | import os | 
|  | import gen_print as gp | 
|  |  | 
|  | exit_on_error = False | 
|  |  | 
|  |  | 
|  | def set_exit_on_error(value): | 
|  | r""" | 
|  | Set the exit_on_error value to either True or False. | 
|  |  | 
|  | If exit_on_error is set, validation functions like valid_value will exit | 
|  | the program on error instead of returning False. | 
|  |  | 
|  | Description of argument(s): | 
|  | value                           Value to set global exit_on_error to. | 
|  | """ | 
|  |  | 
|  | global exit_on_error | 
|  | exit_on_error = value | 
|  |  | 
|  |  | 
|  | def get_var_name(var_name): | 
|  | r""" | 
|  | If var_name has a value, simply return it.  Otherwise, get the variable | 
|  | name of the first argument used to call the validation function (e.g. | 
|  | valid_value, valid_integer, etc.) and return it. | 
|  |  | 
|  | This function is designed solely for use by other functions in this file. | 
|  |  | 
|  | Example: | 
|  |  | 
|  | A programmer codes this: | 
|  |  | 
|  | valid_value(last_name) | 
|  |  | 
|  | Which results in the following call stack: | 
|  |  | 
|  | valid_value(last_name) | 
|  | -> svalid_value(var_value...) | 
|  | -> get_var_name(var_name) | 
|  |  | 
|  | In this example, this function will return "last_name". | 
|  |  | 
|  | Example: | 
|  |  | 
|  | err_msg = svalid_value(last_name, var_name="some_other_name") | 
|  |  | 
|  | Which results in the following call stack: | 
|  |  | 
|  | svalid_value(var_value, var_name="some_other_name") | 
|  | -> get_var_name(var_name) | 
|  |  | 
|  | In this example, this function will return "some_other_name". | 
|  |  | 
|  | Description of argument(s): | 
|  | var_name                        The name of the variable. | 
|  | """ | 
|  |  | 
|  | if var_name != "": | 
|  | return var_name | 
|  | # Calculate stack_frame_ix.  The validation functions in this file come | 
|  | # in pairs.  There is an "s" version of each validation function (e.g. | 
|  | # svalid_value) whose job is to return an error message string.  Then | 
|  | # there is a wrapper function (e.g. valid_value) that will call the "s" | 
|  | # version and print the result if there is an error.  See examples 1 and 2 | 
|  | # above for illustration.  This function must be cognizant of both | 
|  | # scenarios to accurately determine the name of the variable being | 
|  | # validated.  Where the "s" function is being called directly, the | 
|  | # stack_frame_ix should be set to 3.  Where the wrapper function is being | 
|  | # called, the stack_frame_ix should be incremented to 4. | 
|  | stack_frame_ix = 3 | 
|  | parent_func_name = gp.sprint_func_name(2) | 
|  | grandparent_func_name = gp.sprint_func_name(3) | 
|  | if parent_func_name == "s" + grandparent_func_name: | 
|  | stack_frame_ix += 1 | 
|  | var_name = gp.get_arg_name(0, 1, stack_frame_ix) | 
|  | return var_name | 
|  |  | 
|  |  | 
|  | def process_error_message(error_message): | 
|  | r""" | 
|  | Process the error_message as follows: | 
|  | - If the error_message is blank, return True. | 
|  | - If the error_message contains a value: | 
|  | - Print the error_message as part of a full error report. | 
|  | - If global exit_on_error is set, then exit the program with a return | 
|  | code of 1. | 
|  | - If exit_on_error is not set, return False. | 
|  |  | 
|  | This function is designed solely for use by wrapper functions in this file | 
|  | (e.g. "valid_value"). | 
|  |  | 
|  | Description of argument(s): | 
|  | error_message                   An error message. | 
|  | """ | 
|  |  | 
|  | if error_message == "": | 
|  | return True | 
|  |  | 
|  | gp.print_error_report(error_message) | 
|  | if exit_on_error: | 
|  | exit(1) | 
|  | return False | 
|  |  | 
|  |  | 
|  | def svalid_value(var_value, | 
|  | invalid_values=[], | 
|  | valid_values=[], | 
|  | var_name=""): | 
|  | r""" | 
|  | Return an empty string if var_value is a valid value.  Otherwise, return | 
|  | an error string. | 
|  |  | 
|  | Description of arguments: | 
|  | var_value                       The value being validated. | 
|  | invalid_values                  A list of invalid values.  If var_value is | 
|  | equal to any of these, it is invalid. | 
|  | Note that if you specify anything for | 
|  | invalid_values (below), the valid_values | 
|  | list is not even processed.  If you | 
|  | specify nothing for both invalid_values | 
|  | and valid_values, invalid_values will be | 
|  | set to a default value of [""]. | 
|  | valid_values                    A list of valid values.  var_value must be | 
|  | equal to one of these values to be | 
|  | considered valid. | 
|  | var_name                        The name of the variable whose value is | 
|  | passed in var_value.  This parameter is | 
|  | normally unnecessary as this function can | 
|  | figure out the var_name.  This is provided | 
|  | for Robot callers.  In this scenario, we | 
|  | are unable to get the variable name | 
|  | ourselves. | 
|  | """ | 
|  |  | 
|  | success_message = "" | 
|  | error_message = "" | 
|  |  | 
|  | # Validate this function's arguments. | 
|  | len_valid_values = len(valid_values) | 
|  | len_invalid_values = len(invalid_values) | 
|  | if len_valid_values > 0 and len_invalid_values > 0: | 
|  | error_message += "Programmer error - You must provide either an" +\ | 
|  | " invalid_values list or a valid_values" +\ | 
|  | " list but NOT both.\n" +\ | 
|  | gp.sprint_var(invalid_values) +\ | 
|  | gp.sprint_var(valid_values) | 
|  | return error_message | 
|  |  | 
|  | show_blanks = 1 | 
|  | if len_valid_values > 0: | 
|  | # Processing the valid_values list. | 
|  | if var_value in valid_values: | 
|  | return success_message | 
|  | error_message += "The following variable has an invalid" +\ | 
|  | " value:\n" +\ | 
|  | gp.sprint_varx(get_var_name(var_name), var_value, | 
|  | show_blanks) +\ | 
|  | "\nIt must be one of the following values:\n" +\ | 
|  | gp.sprint_varx("valid_values", valid_values, | 
|  | show_blanks) | 
|  | return error_message | 
|  |  | 
|  | if len_invalid_values == 0: | 
|  | # Assign default value. | 
|  | invalid_values = [""] | 
|  |  | 
|  | # Assertion: We have an invalid_values list.  Processing it now. | 
|  | if var_value not in invalid_values: | 
|  | return success_message | 
|  |  | 
|  | error_message += "The following variable has an invalid value:\n" +\ | 
|  | gp.sprint_varx(get_var_name(var_name), var_value, | 
|  | show_blanks) +\ | 
|  | "\nIt must NOT be one of the following values:\n" +\ | 
|  | gp.sprint_varx("invalid_values", invalid_values, | 
|  | show_blanks) | 
|  | return error_message | 
|  |  | 
|  |  | 
|  | def valid_value(var_value, | 
|  | invalid_values=[], | 
|  | valid_values=[], | 
|  | var_name=""): | 
|  | r""" | 
|  | Return True if var_value is valid.  Otherwise, print an error message and | 
|  | either return False or exit(1) depending on the value of exit_on_error. | 
|  |  | 
|  | Description of arguments: | 
|  | (See description of arguments for svalid_value (above)). | 
|  | """ | 
|  |  | 
|  | error_message = svalid_value(var_value, invalid_values, valid_values, | 
|  | var_name) | 
|  | return process_error_message(error_message) | 
|  |  | 
|  |  | 
|  | def svalid_integer(var_value, | 
|  | var_name=""): | 
|  | r""" | 
|  | Return an empty string if var_value is a valid integer.  Otherwise, return | 
|  | an error string. | 
|  |  | 
|  | Description of arguments: | 
|  | var_value                       The value being validated. | 
|  | var_name                        The name of the variable whose value is | 
|  | passed in var_value.  This parameter is | 
|  | normally unnecessary as this function can | 
|  | figure out the var_name.  This is provided | 
|  | for Robot callers.  In this scenario, we | 
|  | are unable to get the variable name | 
|  | ourselves. | 
|  | """ | 
|  |  | 
|  | success_message = "" | 
|  | error_message = "" | 
|  | try: | 
|  | if isinstance(int(str(var_value), 0), int): | 
|  | return success_message | 
|  | except ValueError: | 
|  | pass | 
|  |  | 
|  | # If we get to this point, the validation has failed. | 
|  | show_blanks = 1 | 
|  | error_message +=\ | 
|  | "Invalid integer value:\n" +\ | 
|  | gp.sprint_varx(get_var_name(var_name), var_value, show_blanks) | 
|  |  | 
|  | return error_message | 
|  |  | 
|  |  | 
|  | def valid_integer(var_value, | 
|  | var_name=""): | 
|  | r""" | 
|  | Return True if var_value is a valid integer.  Otherwise, print an error | 
|  | message and either return False or exit(1) depending on the value of | 
|  | exit_on_error. | 
|  |  | 
|  | Description of arguments: | 
|  | (See description of arguments for svalid_integer (above)). | 
|  | """ | 
|  |  | 
|  | error_message = svalid_integer(var_value, var_name) | 
|  | return process_error_message(error_message) | 
|  |  | 
|  |  | 
|  | def svalid_dir_path(var_value, | 
|  | var_name=""): | 
|  | r""" | 
|  | Return an empty string if var_value is a valid directory path.  Otherwise, | 
|  | return an error string. | 
|  |  | 
|  | Description of arguments: | 
|  | var_value                       The value being validated. | 
|  | var_name                        The name of the variable whose value is | 
|  | passed in var_value.  This parameter is | 
|  | normally unnecessary as this function can | 
|  | figure out the var_name.  This is provided | 
|  | for Robot callers.  In this scenario, we | 
|  | are unable to get the variable name | 
|  | ourselves. | 
|  | """ | 
|  |  | 
|  | error_message = "" | 
|  | if not os.path.isdir(str(var_value)): | 
|  | error_message += "The following directory does not exist:\n" +\ | 
|  | gp.sprint_varx(get_var_name(var_name), var_value) | 
|  |  | 
|  | return error_message | 
|  |  | 
|  |  | 
|  | def valid_dir_path(var_value, | 
|  | var_name=""): | 
|  | r""" | 
|  | Return True if var_value is a valid directory path.  Otherwise, print an | 
|  | error message and either return False or exit(1) depending on the value of | 
|  | exit_on_error. | 
|  |  | 
|  | Valid means that the directory path exists. | 
|  |  | 
|  | Description of arguments: | 
|  | (See description of arguments for svalid_dir_path (above)). | 
|  | """ | 
|  |  | 
|  | error_message = svalid_dir_path(var_value, var_name) | 
|  | return process_error_message(error_message) | 
|  |  | 
|  |  | 
|  | def svalid_file_path(var_value, | 
|  | var_name=""): | 
|  | r""" | 
|  | Return an empty string if var_value is a valid file path.  Otherwise, | 
|  | return an error string. | 
|  |  | 
|  | Description of arguments: | 
|  | var_value                       The value being validated. | 
|  | var_name                        The name of the variable whose value is | 
|  | passed in var_value.  This parameter is | 
|  | normally unnecessary as this function can | 
|  | figure out the var_name.  This is provided | 
|  | for Robot callers.  In this scenario, we | 
|  | are unable to get the variable name | 
|  | ourselves. | 
|  | """ | 
|  |  | 
|  | error_message = "" | 
|  | if not os.path.isfile(str(var_value)): | 
|  | error_message += "Invalid file (does not exist):\n" +\ | 
|  | gp.sprint_varx(get_var_name(var_name), var_value) | 
|  |  | 
|  | return error_message | 
|  |  | 
|  |  | 
|  | def valid_file_path(var_value, | 
|  | var_name=""): | 
|  | r""" | 
|  | Return True if var_value is a valid file path.  Otherwise, print an error | 
|  | message and either return False or exit(1) depending on the value of | 
|  | exit_on_error. | 
|  |  | 
|  | Valid means that the file exists. | 
|  |  | 
|  | Description of arguments: | 
|  | (See description of arguments for svalid_file_path (above)). | 
|  | """ | 
|  |  | 
|  | error_message = svalid_file_path(var_value, var_name) | 
|  | return process_error_message(error_message) | 
|  |  | 
|  |  | 
|  | def svalid_path(var_value, | 
|  | var_name=""): | 
|  | r""" | 
|  | Return an empty string if var_value is either a valid file path or | 
|  | directory path.  Otherwise, return an error string. | 
|  |  | 
|  | Description of arguments: | 
|  | var_value                       The value being validated. | 
|  | var_name                        The name of the variable whose value is | 
|  | passed in var_value.  This parameter is | 
|  | normally unnecessary as this function can | 
|  | figure out the var_name.  This is provided | 
|  | for Robot callers.  In this scenario, we | 
|  | are unable to get the variable name | 
|  | ourselves. | 
|  | """ | 
|  |  | 
|  | error_message = "" | 
|  | if not (os.path.isfile(str(var_value)) or os.path.isdir(str(var_value))): | 
|  | error_message = "Invalid path (file or directory does not exist):\n" +\ | 
|  | gp.sprint_varx(get_var_name(var_name), var_value) | 
|  |  | 
|  | return error_message | 
|  |  | 
|  |  | 
|  | def valid_path(var_value, | 
|  | var_name=""): | 
|  | r""" | 
|  | Return True if var_value is a valid file path.  Otherwise, print an error | 
|  | message and either return False or exit(1) depending on the value of | 
|  | exit_on_error. | 
|  |  | 
|  | Valid means that the file exists. | 
|  |  | 
|  | Description of arguments: | 
|  | (See description of arguments for svalid_path (above)). | 
|  | """ | 
|  |  | 
|  | error_message = svalid_path(var_value, var_name) | 
|  | return process_error_message(error_message) | 
|  |  | 
|  |  | 
|  | def svalid_range(var_value, | 
|  | valid_range=[], | 
|  | var_name=""): | 
|  | r""" | 
|  | Return an empty string if var_value is within the range.  Otherwise, | 
|  | return an error string. | 
|  |  | 
|  | Description of arguments: | 
|  | var_value                       The value being validated.  This value | 
|  | must be an integer. | 
|  | valid_range                     A list comprised of one or two elements | 
|  | which are the lower and upper ends of a | 
|  | range.  These values must be integers | 
|  | except where noted.  Valid specifications | 
|  | may be of the following forms: [lower, | 
|  | upper], [lower] or [None, upper]. | 
|  | var_name                        The name of the variable whose value is | 
|  | passed in var_value.  This parameter is | 
|  | normally unnecessary as this function can | 
|  | figure out the var_name.  This is provided | 
|  | for Robot callers.  In this scenario, we | 
|  | are unable to get the variable name | 
|  | ourselves. | 
|  | """ | 
|  |  | 
|  | error_message = "" | 
|  |  | 
|  | # Validate this function's parms: | 
|  | # First, ensure that the value is an integer. | 
|  | error_message = svalid_integer(var_value, var_name) | 
|  | if not error_message == "": | 
|  | return error_message | 
|  | var_value = int(var_value) | 
|  |  | 
|  | len_valid_range = len(valid_range) | 
|  | if len_valid_range == 0 or len_valid_range > 2: | 
|  | error_message += "Programmer error - For the valid_range parameter," +\ | 
|  | " you must provide a list consisting of one or two" +\ | 
|  | " elements.\n" +\ | 
|  | gp.sprint_var(valid_range) | 
|  | return error_message | 
|  |  | 
|  | if len_valid_range == 1 or valid_range[0] is not None: | 
|  | # Make sure lower valid_range value is an integer. | 
|  | error_message = svalid_integer(valid_range[0], "valid_range[0]") | 
|  | if not error_message == "": | 
|  | error_message = "Programmer error:\n" + error_message | 
|  | return error_message | 
|  | if valid_range[0] is not None: | 
|  | valid_range[0] = int(valid_range[0]) | 
|  | if len_valid_range == 2: | 
|  | # Make sure upper valid_range value is an integer. | 
|  | error_message = svalid_integer(valid_range[1], "valid_range[1]") | 
|  | if not error_message == "": | 
|  | error_message = "Programmer error:\n" + error_message | 
|  | return error_message | 
|  | valid_range[1] = int(valid_range[1]) | 
|  | if valid_range[0] is not None and valid_range[0] > valid_range[1]: | 
|  | error_message = "Programmer error - In the following range, the" +\ | 
|  | " lower limit is greater than the upper" +\ | 
|  | " limit:\n" + gp.sprint_varx("valid_range", | 
|  | valid_range) | 
|  | return error_message | 
|  |  | 
|  | if len_valid_range == 1: | 
|  | if var_value < valid_range[0]: | 
|  | error_message += "The following variable is not within the" +\ | 
|  | " expected range:\n" +\ | 
|  | gp.sprint_varx(get_var_name(var_name), | 
|  | var_value) +\ | 
|  | gp.sprint_varx("valid_range", | 
|  | str(valid_range[0]) + "..") | 
|  | return error_message | 
|  | return error_message | 
|  |  | 
|  | if valid_range[0] is None: | 
|  | if var_value > valid_range[1]: | 
|  | error_message += "The following variable is not within the" +\ | 
|  | " expected range:\n" +\ | 
|  | gp.sprint_varx(get_var_name(var_name), | 
|  | var_value) +\ | 
|  | gp.sprint_varx("valid_range", | 
|  | ".." + str(valid_range[1])) | 
|  | return error_message | 
|  |  | 
|  | if var_value < valid_range[0] or var_value > valid_range[1]: | 
|  | error_message += "The following variable is not within the expected" +\ | 
|  | " range:\n" +\ | 
|  | gp.sprint_varx(get_var_name(var_name), var_value) +\ | 
|  | gp.sprint_varx("valid_range", | 
|  | str(valid_range[0]) + ".." | 
|  | + str(valid_range[1])) | 
|  | return error_message | 
|  |  | 
|  | return error_message | 
|  |  | 
|  |  | 
|  | def valid_range(var_value, | 
|  | valid_range=[], | 
|  | var_name=""): | 
|  | r""" | 
|  | Return True if var_value is within range.  Otherwise, print an error | 
|  | message and either return False or exit(1) depending on the value of | 
|  | exit_on_error. | 
|  |  | 
|  | Description of arguments: | 
|  | (See description of arguments for svalid_range (above)). | 
|  | """ | 
|  |  | 
|  | error_message = svalid_range(var_value, valid_range, var_name) | 
|  | return process_error_message(error_message) | 
|  |  | 
|  |  | 
|  | def svalid_list(var_value, | 
|  | valid_values=[], | 
|  | var_name=""): | 
|  | r""" | 
|  | Return an empty string if var_value is a valid list.  Otherwise, return an | 
|  | error string. | 
|  |  | 
|  | Description of arguments: | 
|  | var_value                       The value (i.e. list) being validated. | 
|  | valid_values                    A list of valid values.  Each element in | 
|  | the var_value list must be equal to one of | 
|  | these values to be considered valid. | 
|  | var_name                        The name of the variable whose value is | 
|  | passed in var_value.  This parameter is | 
|  | normally unnecessary as this function can | 
|  | figure out the var_name.  This is provided | 
|  | for Robot callers.  In this scenario, we | 
|  | are unable to get the variable name | 
|  | ourselves. | 
|  | """ | 
|  |  | 
|  | error_message = "" | 
|  | if len(var_value) == 0: | 
|  | show_blanks = 1 | 
|  | error_message += "The \"" + get_var_name(var_name) | 
|  | error_message += "\" list is empty and is therefore invalid:\n" | 
|  | return error_message | 
|  |  | 
|  | found_error = 0 | 
|  | display_var_value = list(var_value) | 
|  | for ix in range(0, len(var_value)): | 
|  | if var_value[ix] not in valid_values: | 
|  | found_error = 1 | 
|  | display_var_value[ix] = var_value[ix] + "*" | 
|  |  | 
|  | if found_error: | 
|  | show_blanks = 1 | 
|  | error_message += "The list entries marked with \"*\" are not valid:\n" | 
|  | error_message += gp.sprint_varx(get_var_name(var_name), | 
|  | display_var_value, show_blanks) | 
|  | error_message += gp.sprint_var(valid_values) | 
|  | return error_message | 
|  |  | 
|  | return "" | 
|  |  | 
|  |  | 
|  | def valid_list(var_value, | 
|  | valid_values=[], | 
|  | var_name=""): | 
|  | r""" | 
|  | Return True if var_value is a valid list.  Otherwise, print an error | 
|  | message and either return False or exit(1) depending on the value of | 
|  | exit_on_error. | 
|  |  | 
|  | Description of arguments: | 
|  | (See description of arguments for svalid_list (above)). | 
|  | """ | 
|  |  | 
|  | error_message = svalid_list(var_value, valid_values, var_name) | 
|  | return process_error_message(error_message) | 
|  |  | 
|  |  | 
|  | def svalid_dict(var_value, | 
|  | required_keys=[], | 
|  | var_name=""): | 
|  | r""" | 
|  | Return an empty string if var_value is a valid dictionary.  Otherwise, | 
|  | return an error string. | 
|  |  | 
|  | Description of arguments: | 
|  | var_value                       The value (i.e. dictionary) being | 
|  | validated. | 
|  | required_keys                   A list of keys which must be found in the | 
|  | dictionary for it to be considered valid. | 
|  | var_name                        The name of the variable whose value is | 
|  | passed in var_value.  This parameter is | 
|  | normally unnecessary as this function can | 
|  | figure out the var_name.  This is provided | 
|  | for Robot callers.  In this scenario, we | 
|  | are unable to get the variable name | 
|  | ourselves. | 
|  | """ | 
|  |  | 
|  | error_message = "" | 
|  |  | 
|  | keys_missing = list(set(required_keys) - set(var_value.keys())) | 
|  | if len(keys_missing) > 0: | 
|  | show_blanks = 1 | 
|  | var_name = get_var_name(var_name) | 
|  | error_message = "The following key fields are missing from " | 
|  | error_message += var_name + ":\n" | 
|  | error_message += gp.sprint_var(keys_missing) | 
|  | error_message += gp.sprint_varx(var_name, var_value, show_blanks) | 
|  | return error_message | 
|  |  | 
|  | return "" | 
|  |  | 
|  |  | 
|  | def valid_dict(var_value, | 
|  | required_keys=[], | 
|  | var_name=""): | 
|  | r""" | 
|  | Return True if var_value is a valid dictionary.  Otherwise, print an error | 
|  | message and either return False or exit(1) depending on the value of | 
|  | exit_on_error. | 
|  |  | 
|  | Description of arguments: | 
|  | (See description of arguments for svalid_list (above)). | 
|  | """ | 
|  |  | 
|  | error_message = svalid_dict(var_value, required_keys, var_name) | 
|  | return process_error_message(error_message) |