17423c01aSMichael Walsh#!/usr/bin/env python 27423c01aSMichael Walsh 37423c01aSMichael Walshr""" 4018e25fbSMichael WalshThis module provides validation functions like valid_value(), valid_integer(), 5018e25fbSMichael Walshetc. 67423c01aSMichael Walsh""" 77423c01aSMichael Walsh 878bdfdd6SMichael Walshimport os 97423c01aSMichael Walshimport gen_print as gp 10be3a8150SMichael Walshimport gen_cmd as gc 11018e25fbSMichael Walshimport func_args as fa 127423c01aSMichael Walsh 13e23b5ad3SMichael Walshexit_on_error = False 14e23b5ad3SMichael Walsh 15e23b5ad3SMichael Walsh 16e23b5ad3SMichael Walshdef set_exit_on_error(value): 17e23b5ad3SMichael Walsh r""" 18e23b5ad3SMichael Walsh Set the exit_on_error value to either True or False. 19e23b5ad3SMichael Walsh 20018e25fbSMichael Walsh If exit_on_error is set, validation functions like valid_value() will exit 21e23b5ad3SMichael Walsh the program on error instead of returning False. 22e23b5ad3SMichael Walsh 23e23b5ad3SMichael Walsh Description of argument(s): 24e23b5ad3SMichael Walsh value Value to set global exit_on_error to. 25e23b5ad3SMichael Walsh """ 26e23b5ad3SMichael Walsh 27e23b5ad3SMichael Walsh global exit_on_error 28e23b5ad3SMichael Walsh exit_on_error = value 29e23b5ad3SMichael Walsh 30e23b5ad3SMichael Walsh 31*89eff544SMichael Walshdef get_var_name(var_name): 32e23b5ad3SMichael Walsh r""" 33*89eff544SMichael Walsh If var_name is not None, simply return its value. Otherwise, get the 34*89eff544SMichael Walsh variable name of the first argument used to call the validation function 35*89eff544SMichael Walsh (e.g. valid, valid_integer, etc.) and return it. 36e23b5ad3SMichael Walsh 37e23b5ad3SMichael Walsh This function is designed solely for use by other functions in this file. 38e23b5ad3SMichael Walsh 39e23b5ad3SMichael Walsh Example: 40e23b5ad3SMichael Walsh 41e23b5ad3SMichael Walsh A programmer codes this: 42e23b5ad3SMichael Walsh 43e23b5ad3SMichael Walsh valid_value(last_name) 44e23b5ad3SMichael Walsh 45e23b5ad3SMichael Walsh Which results in the following call stack: 46e23b5ad3SMichael Walsh 47e23b5ad3SMichael Walsh valid_value(last_name) 48e23b5ad3SMichael Walsh -> get_var_name(var_name) 49e23b5ad3SMichael Walsh 50e23b5ad3SMichael Walsh In this example, this function will return "last_name". 51e23b5ad3SMichael Walsh 52e23b5ad3SMichael Walsh Example: 53e23b5ad3SMichael Walsh 54018e25fbSMichael Walsh err_msg = valid_value(last_name, var_name="some_other_name") 55e23b5ad3SMichael Walsh 56e23b5ad3SMichael Walsh Which results in the following call stack: 57e23b5ad3SMichael Walsh 58018e25fbSMichael Walsh valid_value(var_value, var_name="some_other_name") 59e23b5ad3SMichael Walsh -> get_var_name(var_name) 60e23b5ad3SMichael Walsh 61e23b5ad3SMichael Walsh In this example, this function will return "some_other_name". 62e23b5ad3SMichael Walsh 63e23b5ad3SMichael Walsh Description of argument(s): 64e23b5ad3SMichael Walsh var_name The name of the variable. 65e23b5ad3SMichael Walsh """ 66e23b5ad3SMichael Walsh 67*89eff544SMichael Walsh return var_name or gp.get_arg_name(0, 1, stack_frame_ix=3) 68e23b5ad3SMichael Walsh 69e23b5ad3SMichael Walsh 70e23b5ad3SMichael Walshdef process_error_message(error_message): 71e23b5ad3SMichael Walsh r""" 72018e25fbSMichael Walsh Process the error_message in the manner described below. 73e23b5ad3SMichael Walsh 74018e25fbSMichael Walsh This function is designed solely for use by other functions in this file. 75018e25fbSMichael Walsh 76018e25fbSMichael Walsh NOTE: A blank error_message means that there is no error. 77018e25fbSMichael Walsh 78018e25fbSMichael Walsh For the following explanations, assume the caller of this function is a 79018e25fbSMichael Walsh function with the following definition: 80*89eff544SMichael Walsh valid_value(var_value, valid_values=[], invalid_values=[], var_name=None): 81018e25fbSMichael Walsh 82018e25fbSMichael Walsh If the user of valid_value() is assigning the valid_value() return value 83018e25fbSMichael Walsh to a variable, process_error_message() will simply return the 84018e25fbSMichael Walsh error_message. This mode of usage is illustrated by the following example: 85018e25fbSMichael Walsh 86018e25fbSMichael Walsh error_message = valid_value(var1) 87018e25fbSMichael Walsh 88018e25fbSMichael Walsh This mode is useful for callers who wish to validate a variable and then 89018e25fbSMichael Walsh decide for themselves what to do with the error_message (e.g. 90018e25fbSMichael Walsh raise(error_message), BuiltIn().fail(error_message), etc.). 91018e25fbSMichael Walsh 92018e25fbSMichael Walsh If the user of valid_value() is NOT assigning the valid_value() return 93018e25fbSMichael Walsh value to a variable, process_error_message() will behave as follows. 94018e25fbSMichael Walsh 95018e25fbSMichael Walsh First, if error_message is non-blank, it will be printed to stderr via a 96018e25fbSMichael Walsh call to gp.print_error_report(error_message). 97018e25fbSMichael Walsh 98018e25fbSMichael Walsh If exit_on_error is set: 99018e25fbSMichael Walsh - If the error_message is blank, simply return. 100018e25fbSMichael Walsh - If the error_message is non-blank, exit the program with a return code 101018e25fbSMichael Walsh of 1. 102018e25fbSMichael Walsh 103018e25fbSMichael Walsh If exit_on_error is NOT set: 104018e25fbSMichael Walsh - If the error_message is blank, return True. 105018e25fbSMichael Walsh - If the error_message is non-blank, return False. 106e23b5ad3SMichael Walsh 107e23b5ad3SMichael Walsh Description of argument(s): 108e23b5ad3SMichael Walsh error_message An error message. 109e23b5ad3SMichael Walsh """ 110e23b5ad3SMichael Walsh 111018e25fbSMichael Walsh # Determine whether the caller's caller is assigning the result to a 112018e25fbSMichael Walsh # variable. 113018e25fbSMichael Walsh l_value = gp.get_arg_name(None, -1, stack_frame_ix=3) 114018e25fbSMichael Walsh if l_value: 115018e25fbSMichael Walsh return error_message 116018e25fbSMichael Walsh 117e23b5ad3SMichael Walsh if error_message == "": 118018e25fbSMichael Walsh if exit_on_error: 119018e25fbSMichael Walsh return 120e23b5ad3SMichael Walsh return True 121e23b5ad3SMichael Walsh 122018e25fbSMichael Walsh gp.print_error_report(error_message, stack_frame_ix=4) 123e23b5ad3SMichael Walsh if exit_on_error: 12410a4d98bSMichael Walsh exit(1) 125e23b5ad3SMichael Walsh return False 126e23b5ad3SMichael Walsh 1277423c01aSMichael Walsh 128018e25fbSMichael Walsh# Note to programmers: All of the validation functions in this module should 129018e25fbSMichael Walsh# follow the same basic template: 130*89eff544SMichael Walsh# def valid_value(var_value, var1, var2, varn, var_name=None): 131018e25fbSMichael Walsh# 132018e25fbSMichael Walsh# error_message = "" 133018e25fbSMichael Walsh# if not valid: 134*89eff544SMichael Walsh# var_name = get_var_name(var_name) 135018e25fbSMichael Walsh# error_message += "The following variable is invalid because...:\n" 136018e25fbSMichael Walsh# error_message += gp.sprint_varx(var_name, var_value, gp.blank()) 137018e25fbSMichael Walsh# 138018e25fbSMichael Walsh# return process_error_message(error_message) 1397423c01aSMichael Walsh 140018e25fbSMichael Walsh 141018e25fbSMichael Walsh# The docstring header and footer will be added to each validation function's 142018e25fbSMichael Walsh# existing docstring. 143018e25fbSMichael Walshdocstring_header = \ 144018e25fbSMichael Walsh r""" 145018e25fbSMichael Walsh Determine whether var_value is valid, construct an error_message and call 146018e25fbSMichael Walsh process_error_message(error_message). 147018e25fbSMichael Walsh 148018e25fbSMichael Walsh See the process_error_message() function defined in this module for a 149018e25fbSMichael Walsh description of how error messages are processed. 1507423c01aSMichael Walsh """ 1517423c01aSMichael Walsh 152018e25fbSMichael Walshadditional_args_docstring_footer = \ 153018e25fbSMichael Walsh r""" 154018e25fbSMichael Walsh var_name The name of the variable whose value is 155018e25fbSMichael Walsh passed in var_value. For the general 156018e25fbSMichael Walsh case, this argument is unnecessary as this 157018e25fbSMichael Walsh function can figure out the var_name. 158018e25fbSMichael Walsh This is provided for Robot callers in 159018e25fbSMichael Walsh which case, this function lacks the 160018e25fbSMichael Walsh ability to determine the variable name. 161018e25fbSMichael Walsh """ 162018e25fbSMichael Walsh 163018e25fbSMichael Walsh 164*89eff544SMichael Walshdef valid_type(var_value, required_type, var_name=None): 165018e25fbSMichael Walsh r""" 166018e25fbSMichael Walsh The variable value is valid if it is of the required type. 167018e25fbSMichael Walsh 168018e25fbSMichael Walsh Examples: 169018e25fbSMichael Walsh 170018e25fbSMichael Walsh valid_type(var1, int) 171018e25fbSMichael Walsh 172018e25fbSMichael Walsh valid_type(var1, (list, dict)) 173018e25fbSMichael Walsh 174018e25fbSMichael Walsh Description of argument(s): 175018e25fbSMichael Walsh var_value The value being validated. 176018e25fbSMichael Walsh required_type A type or a tuple of types (e.g. str, int, 177018e25fbSMichael Walsh etc.). 178018e25fbSMichael Walsh """ 179018e25fbSMichael Walsh 180018e25fbSMichael Walsh error_message = "" 181018e25fbSMichael Walsh if type(required_type) is tuple: 182018e25fbSMichael Walsh if type(var_value) in required_type: 183018e25fbSMichael Walsh return process_error_message(error_message) 184018e25fbSMichael Walsh else: 185018e25fbSMichael Walsh if type(var_value) is required_type: 186018e25fbSMichael Walsh return process_error_message(error_message) 187018e25fbSMichael Walsh 188018e25fbSMichael Walsh # If we get to this point, the validation has failed. 189*89eff544SMichael Walsh var_name = get_var_name(var_name) 190018e25fbSMichael Walsh error_message += "Invalid variable type:\n" 191018e25fbSMichael Walsh error_message += gp.sprint_varx(var_name, var_value, 192018e25fbSMichael Walsh gp.blank() | gp.show_type()) 193018e25fbSMichael Walsh error_message += "\n" 194018e25fbSMichael Walsh error_message += gp.sprint_var(required_type) 195018e25fbSMichael Walsh 196018e25fbSMichael Walsh return process_error_message(error_message) 197018e25fbSMichael Walsh 198018e25fbSMichael Walsh 199*89eff544SMichael Walshdef valid_value(var_value, valid_values=[], invalid_values=[], var_name=None): 200018e25fbSMichael Walsh 201018e25fbSMichael Walsh r""" 202018e25fbSMichael Walsh The variable value is valid if it is either contained in the valid_values 203018e25fbSMichael Walsh list or if it is NOT contained in the invalid_values list. If the caller 204018e25fbSMichael Walsh specifies nothing for either of these 2 arguments, invalid_values will be 205018e25fbSMichael Walsh initialized to ['', None]. This is a good way to fail on variables which 206018e25fbSMichael Walsh contain blank values. 207018e25fbSMichael Walsh 208018e25fbSMichael Walsh It is illegal to specify both valid_values and invalid values. 209018e25fbSMichael Walsh 210018e25fbSMichael Walsh Example: 211018e25fbSMichael Walsh 212018e25fbSMichael Walsh var1 = '' 213018e25fbSMichael Walsh valid_value(var1) 214018e25fbSMichael Walsh 215018e25fbSMichael Walsh This code would fail because var1 is blank and the default value for 216018e25fbSMichael Walsh invalid_values is ['', None]. 217018e25fbSMichael Walsh 218018e25fbSMichael Walsh Example: 219018e25fbSMichael Walsh var1 = 'yes' 220018e25fbSMichael Walsh valid_value(var1, valid_values=['yes', 'true']) 221018e25fbSMichael Walsh 222018e25fbSMichael Walsh This code would pass. 223018e25fbSMichael Walsh 224018e25fbSMichael Walsh Description of argument(s): 225018e25fbSMichael Walsh var_value The value being validated. 226018e25fbSMichael Walsh valid_values A list of valid values. The variable 227018e25fbSMichael Walsh value must be equal to one of these values 228018e25fbSMichael Walsh to be considered valid. 229018e25fbSMichael Walsh invalid_values A list of invalid values. If the variable 230018e25fbSMichael Walsh value is equal to any of these, it is 231018e25fbSMichael Walsh considered invalid. 232018e25fbSMichael Walsh """ 233018e25fbSMichael Walsh 234bec416ddSMichael Walsh error_message = "" 235bec416ddSMichael Walsh 236e23b5ad3SMichael Walsh # Validate this function's arguments. 2377423c01aSMichael Walsh len_valid_values = len(valid_values) 2387423c01aSMichael Walsh len_invalid_values = len(invalid_values) 2397423c01aSMichael Walsh if len_valid_values > 0 and len_invalid_values > 0: 240018e25fbSMichael Walsh error_message += "Programmer error - You must provide either an" 241018e25fbSMichael Walsh error_message += " invalid_values list or a valid_values" 242018e25fbSMichael Walsh error_message += " list but NOT both:\n" 243018e25fbSMichael Walsh error_message += gp.sprint_var(invalid_values) 244018e25fbSMichael Walsh error_message += gp.sprint_var(valid_values) 245018e25fbSMichael Walsh return process_error_message(error_message) 2467423c01aSMichael Walsh 2477423c01aSMichael Walsh if len_valid_values > 0: 2487423c01aSMichael Walsh # Processing the valid_values list. 2497423c01aSMichael Walsh if var_value in valid_values: 250018e25fbSMichael Walsh return process_error_message(error_message) 251*89eff544SMichael Walsh var_name = get_var_name(var_name) 252018e25fbSMichael Walsh error_message += "Invalid variable value:\n" 253018e25fbSMichael Walsh error_message += gp.sprint_varx(var_name, var_value, 254018e25fbSMichael Walsh gp.blank() | gp.verbose() 255018e25fbSMichael Walsh | gp.show_type()) 256018e25fbSMichael Walsh error_message += "\n" 257018e25fbSMichael Walsh error_message += "It must be one of the following values:\n" 258018e25fbSMichael Walsh error_message += "\n" 259018e25fbSMichael Walsh error_message += gp.sprint_var(valid_values, 260018e25fbSMichael Walsh gp.blank() | gp.show_type()) 261018e25fbSMichael Walsh return process_error_message(error_message) 2627423c01aSMichael Walsh 2637423c01aSMichael Walsh if len_invalid_values == 0: 264bec416ddSMichael Walsh # Assign default value. 265018e25fbSMichael Walsh invalid_values = ["", None] 2667423c01aSMichael Walsh 2677423c01aSMichael Walsh # Assertion: We have an invalid_values list. Processing it now. 2687423c01aSMichael Walsh if var_value not in invalid_values: 269018e25fbSMichael Walsh return process_error_message(error_message) 270bec416ddSMichael Walsh 271*89eff544SMichael Walsh var_name = get_var_name(var_name) 272018e25fbSMichael Walsh error_message += "Invalid variable value:\n" 273018e25fbSMichael Walsh error_message += gp.sprint_varx(var_name, var_value, 274018e25fbSMichael Walsh gp.blank() | gp.verbose() 275018e25fbSMichael Walsh | gp.show_type()) 276018e25fbSMichael Walsh error_message += "\n" 277018e25fbSMichael Walsh error_message += "It must NOT be one of the following values:\n" 278018e25fbSMichael Walsh error_message += "\n" 279018e25fbSMichael Walsh error_message += gp.sprint_var(invalid_values, 280018e25fbSMichael Walsh gp.blank() | gp.show_type()) 281e23b5ad3SMichael Walsh return process_error_message(error_message) 2827423c01aSMichael Walsh 283bec416ddSMichael Walsh 284*89eff544SMichael Walshdef valid_range(var_value, lower=None, upper=None, var_name=None): 285bec416ddSMichael Walsh r""" 286018e25fbSMichael Walsh The variable value is valid if it is within the specified range. 287bec416ddSMichael Walsh 288018e25fbSMichael Walsh This function can be used with any type of operands where they can have a 289018e25fbSMichael Walsh greater than/less than relationship to each other (e.g. int, float, str). 290018e25fbSMichael Walsh 291018e25fbSMichael Walsh Description of argument(s): 292bec416ddSMichael Walsh var_value The value being validated. 293018e25fbSMichael Walsh lower The lower end of the range. If not None, 294018e25fbSMichael Walsh the var_value must be greater than or 295018e25fbSMichael Walsh equal to lower. 296018e25fbSMichael Walsh upper The upper end of the range. If not None, 297018e25fbSMichael Walsh the var_value must be less than or equal 298018e25fbSMichael Walsh to upper. 299bec416ddSMichael Walsh """ 300bec416ddSMichael Walsh 301bec416ddSMichael Walsh error_message = "" 302b9d8dfd2SMichael Walsh if lower is None and upper is None: 303018e25fbSMichael Walsh return process_error_message(error_message) 304b9d8dfd2SMichael Walsh if lower is None and var_value <= upper: 305018e25fbSMichael Walsh return process_error_message(error_message) 306b9d8dfd2SMichael Walsh if upper is None and var_value >= lower: 307018e25fbSMichael Walsh return process_error_message(error_message) 308018e25fbSMichael Walsh if lower and upper: 309018e25fbSMichael Walsh if lower > upper: 310*89eff544SMichael Walsh var_name = get_var_name(var_name) 311018e25fbSMichael Walsh error_message += "Programmer error - the lower value is greater" 312018e25fbSMichael Walsh error_message += " than the upper value:\n" 313018e25fbSMichael Walsh error_message += gp.sprint_vars(lower, upper, fmt=gp.show_type()) 314018e25fbSMichael Walsh return process_error_message(error_message) 315018e25fbSMichael Walsh if lower <= var_value <= upper: 316018e25fbSMichael Walsh return process_error_message(error_message) 317bec416ddSMichael Walsh 318*89eff544SMichael Walsh var_name = get_var_name(var_name) 319018e25fbSMichael Walsh error_message += "The following variable is not within the expected" 320018e25fbSMichael Walsh error_message += " range:\n" 321018e25fbSMichael Walsh error_message += gp.sprint_varx(var_name, var_value, gp.show_type()) 322018e25fbSMichael Walsh error_message += "\n" 323018e25fbSMichael Walsh error_message += "range:\n" 324018e25fbSMichael Walsh error_message += gp.sprint_vars(lower, upper, fmt=gp.show_type(), indent=2) 325e23b5ad3SMichael Walsh return process_error_message(error_message) 3267423c01aSMichael Walsh 32778bdfdd6SMichael Walsh 328*89eff544SMichael Walshdef valid_integer(var_value, lower=None, upper=None, var_name=None): 32978bdfdd6SMichael Walsh r""" 330018e25fbSMichael Walsh The variable value is valid if it is an integer or can be interpreted as 331018e25fbSMichael Walsh an integer (e.g. 7, "7", etc.). 33278bdfdd6SMichael Walsh 333018e25fbSMichael Walsh This function also calls valid_range to make sure the integer value is 334018e25fbSMichael Walsh within the specified range (if any). 335018e25fbSMichael Walsh 336018e25fbSMichael Walsh Description of argument(s): 33778bdfdd6SMichael Walsh var_value The value being validated. 338018e25fbSMichael Walsh lower The lower end of the range. If not None, 339018e25fbSMichael Walsh the var_value must be greater than or 340018e25fbSMichael Walsh equal to lower. 341018e25fbSMichael Walsh upper The upper end of the range. If not None, 342018e25fbSMichael Walsh the var_value must be less than or equal 343018e25fbSMichael Walsh to upper. 344018e25fbSMichael Walsh """ 345018e25fbSMichael Walsh 346018e25fbSMichael Walsh error_message = "" 347*89eff544SMichael Walsh var_name = get_var_name(var_name) 348018e25fbSMichael Walsh try: 349018e25fbSMichael Walsh var_value = int(str(var_value), 0) 350018e25fbSMichael Walsh except ValueError: 351018e25fbSMichael Walsh error_message += "Invalid integer value:\n" 352018e25fbSMichael Walsh error_message += gp.sprint_varx(var_name, var_value, 353018e25fbSMichael Walsh gp.blank() | gp.show_type()) 354018e25fbSMichael Walsh return process_error_message(error_message) 355018e25fbSMichael Walsh 356018e25fbSMichael Walsh # Check the range (if any). 357018e25fbSMichael Walsh if lower: 358018e25fbSMichael Walsh lower = int(str(lower), 0) 359018e25fbSMichael Walsh if upper: 360018e25fbSMichael Walsh upper = int(str(upper), 0) 361018e25fbSMichael Walsh error_message = valid_range(var_value, lower, upper, var_name=var_name) 362018e25fbSMichael Walsh 363018e25fbSMichael Walsh return process_error_message(error_message) 364018e25fbSMichael Walsh 365018e25fbSMichael Walsh 366*89eff544SMichael Walshdef valid_dir_path(var_value, var_name=None): 367018e25fbSMichael Walsh r""" 368018e25fbSMichael Walsh The variable value is valid if it contains the path of an existing 369018e25fbSMichael Walsh directory. 370018e25fbSMichael Walsh 371018e25fbSMichael Walsh Description of argument(s): 372018e25fbSMichael Walsh var_value The value being validated. 37378bdfdd6SMichael Walsh """ 37478bdfdd6SMichael Walsh 37578bdfdd6SMichael Walsh error_message = "" 37678bdfdd6SMichael Walsh if not os.path.isdir(str(var_value)): 377*89eff544SMichael Walsh var_name = get_var_name(var_name) 378018e25fbSMichael Walsh error_message += "The following directory does not exist:\n" 37900244345SMichael Walsh error_message += gp.sprint_varx(var_name, var_value, gp.blank()) 38078bdfdd6SMichael Walsh 381e23b5ad3SMichael Walsh return process_error_message(error_message) 38278bdfdd6SMichael Walsh 38378bdfdd6SMichael Walsh 384*89eff544SMichael Walshdef valid_file_path(var_value, var_name=None): 38578bdfdd6SMichael Walsh r""" 386018e25fbSMichael Walsh The variable value is valid if it contains the path of an existing file. 38778bdfdd6SMichael Walsh 388018e25fbSMichael Walsh Description of argument(s): 38978bdfdd6SMichael Walsh var_value The value being validated. 39078bdfdd6SMichael Walsh """ 39178bdfdd6SMichael Walsh 39278bdfdd6SMichael Walsh error_message = "" 39378bdfdd6SMichael Walsh if not os.path.isfile(str(var_value)): 394*89eff544SMichael Walsh var_name = get_var_name(var_name) 395018e25fbSMichael Walsh error_message += "The following file does not exist:\n" 39600244345SMichael Walsh error_message += gp.sprint_varx(var_name, var_value, gp.blank()) 39778bdfdd6SMichael Walsh 398e23b5ad3SMichael Walsh return process_error_message(error_message) 39978bdfdd6SMichael Walsh 40078bdfdd6SMichael Walsh 401*89eff544SMichael Walshdef valid_path(var_value, var_name=None): 402e23b5ad3SMichael Walsh r""" 403018e25fbSMichael Walsh The variable value is valid if it contains the path of an existing file or 404018e25fbSMichael Walsh directory. 405e23b5ad3SMichael Walsh 406018e25fbSMichael Walsh Description of argument(s): 407e23b5ad3SMichael Walsh var_value The value being validated. 408e23b5ad3SMichael Walsh """ 409e23b5ad3SMichael Walsh 410e23b5ad3SMichael Walsh error_message = "" 411e23b5ad3SMichael Walsh if not (os.path.isfile(str(var_value)) or os.path.isdir(str(var_value))): 412*89eff544SMichael Walsh var_name = get_var_name(var_name) 413018e25fbSMichael Walsh error_message += "Invalid path (file or directory does not exist):\n" 41400244345SMichael Walsh error_message += gp.sprint_varx(var_name, var_value, gp.blank()) 415e23b5ad3SMichael Walsh 416e23b5ad3SMichael Walsh return process_error_message(error_message) 4172c687e98SMichael Walsh 4182c687e98SMichael Walsh 41935026be5SMichael Walshdef valid_list(var_value, valid_values=[], invalid_values=[], 420*89eff544SMichael Walsh required_values=[], fail_on_empty=False, var_name=None): 4212c687e98SMichael Walsh r""" 422018e25fbSMichael Walsh The variable value is valid if it is a list where each entry can be found 42335026be5SMichael Walsh in the valid_values list or if none of its values can be found in the 42435026be5SMichael Walsh invalid_values list or if all of the values in the required_values list 42535026be5SMichael Walsh can be found in var_value. 42635026be5SMichael Walsh 42735026be5SMichael Walsh The caller may only specify one of these 3 arguments: valid_values, 42835026be5SMichael Walsh invalid_values, required_values. 4292c687e98SMichael Walsh 430018e25fbSMichael Walsh Description of argument(s): 431018e25fbSMichael Walsh var_value The value being validated. 432ca193993SMichael Walsh valid_values A list of valid values. Each element in 433ca193993SMichael Walsh the var_value list must be equal to one of 434ca193993SMichael Walsh these values to be considered valid. 43535026be5SMichael Walsh invalid_values A list of invalid values. If any element 43635026be5SMichael Walsh in var_value is equal to any of the values 43735026be5SMichael Walsh in this argument, var_value is considered 43835026be5SMichael Walsh invalid. 43935026be5SMichael Walsh required_values Every value in required_values must be 44035026be5SMichael Walsh found in var_value. Otherwise, var_value 44135026be5SMichael Walsh is considered invalid. 442018e25fbSMichael Walsh fail_on_empty Indicates that an empty list for the 443018e25fbSMichael Walsh variable value should be considered an 444018e25fbSMichael Walsh error. 445ca193993SMichael Walsh """ 446ca193993SMichael Walsh 447ca193993SMichael Walsh error_message = "" 448018e25fbSMichael Walsh 44935026be5SMichael Walsh # Validate this function's arguments. 45035026be5SMichael Walsh len_valid_values = len(valid_values) 45135026be5SMichael Walsh len_invalid_values = len(invalid_values) 45235026be5SMichael Walsh len_required_values = len(required_values) 45335026be5SMichael Walsh if (len_valid_values + len_invalid_values + len_required_values) > 1: 45435026be5SMichael Walsh error_message += "Programmer error - You must provide only one of the" 45535026be5SMichael Walsh error_message += " following: valid_values, invalid_values," 45635026be5SMichael Walsh error_message += " required_values.\n" 45735026be5SMichael Walsh error_message += gp.sprint_var(invalid_values) 45835026be5SMichael Walsh error_message += gp.sprint_var(valid_values) 45935026be5SMichael Walsh error_message += gp.sprint_var(required_values) 46035026be5SMichael Walsh return process_error_message(error_message) 46135026be5SMichael Walsh 462018e25fbSMichael Walsh if type(var_value) is not list: 463*89eff544SMichael Walsh var_name = get_var_name(var_name) 464018e25fbSMichael Walsh error_message = valid_type(var_value, list, var_name=var_name) 465018e25fbSMichael Walsh if error_message: 466018e25fbSMichael Walsh return process_error_message(error_message) 467018e25fbSMichael Walsh 468018e25fbSMichael Walsh if fail_on_empty and len(var_value) == 0: 469*89eff544SMichael Walsh var_name = get_var_name(var_name) 470018e25fbSMichael Walsh error_message += "Invalid empty list:\n" 471018e25fbSMichael Walsh error_message += gp.sprint_varx(var_name, var_value, gp.show_type()) 472018e25fbSMichael Walsh return process_error_message(error_message) 473ca193993SMichael Walsh 47435026be5SMichael Walsh if len(required_values): 47535026be5SMichael Walsh found_error = 0 47635026be5SMichael Walsh display_required_values = list(required_values) 47735026be5SMichael Walsh for ix in range(0, len(required_values)): 47835026be5SMichael Walsh if required_values[ix] not in var_value: 47935026be5SMichael Walsh found_error = 1 48035026be5SMichael Walsh display_required_values[ix] = \ 48135026be5SMichael Walsh str(display_required_values[ix]) + "*" 48235026be5SMichael Walsh if found_error: 483*89eff544SMichael Walsh var_name = get_var_name(var_name) 48435026be5SMichael Walsh error_message += "The following list is invalid:\n" 48535026be5SMichael Walsh error_message += gp.sprint_varx(var_name, var_value, 48635026be5SMichael Walsh gp.blank() | gp.show_type()) 48735026be5SMichael Walsh error_message += "\n" 48835026be5SMichael Walsh error_message += "Because some of the values in the " 48935026be5SMichael Walsh error_message += "required_values list are not present (see" 49035026be5SMichael Walsh error_message += " entries marked with \"*\"):\n" 49135026be5SMichael Walsh error_message += "\n" 49235026be5SMichael Walsh error_message += gp.sprint_varx('required_values', 49335026be5SMichael Walsh display_required_values, 49435026be5SMichael Walsh gp.blank() | gp.show_type()) 49535026be5SMichael Walsh error_message += "\n" 49635026be5SMichael Walsh 49735026be5SMichael Walsh return process_error_message(error_message) 49835026be5SMichael Walsh 49935026be5SMichael Walsh if len(invalid_values): 50035026be5SMichael Walsh found_error = 0 50135026be5SMichael Walsh display_var_value = list(var_value) 50235026be5SMichael Walsh for ix in range(0, len(var_value)): 50335026be5SMichael Walsh if var_value[ix] in invalid_values: 50435026be5SMichael Walsh found_error = 1 50535026be5SMichael Walsh display_var_value[ix] = str(var_value[ix]) + "*" 50635026be5SMichael Walsh 50735026be5SMichael Walsh if found_error: 508*89eff544SMichael Walsh var_name = get_var_name(var_name) 50935026be5SMichael Walsh error_message += "The following list is invalid (see entries" 51035026be5SMichael Walsh error_message += " marked with \"*\"):\n" 51135026be5SMichael Walsh error_message += gp.sprint_varx(var_name, display_var_value, 51235026be5SMichael Walsh gp.blank() | gp.show_type()) 51335026be5SMichael Walsh error_message += "\n" 51435026be5SMichael Walsh error_message += gp.sprint_var(invalid_values, gp.show_type()) 51535026be5SMichael Walsh return process_error_message(error_message) 51635026be5SMichael Walsh 517ca193993SMichael Walsh found_error = 0 518ca193993SMichael Walsh display_var_value = list(var_value) 519ca193993SMichael Walsh for ix in range(0, len(var_value)): 520ca193993SMichael Walsh if var_value[ix] not in valid_values: 521ca193993SMichael Walsh found_error = 1 52235026be5SMichael Walsh display_var_value[ix] = str(var_value[ix]) + "*" 523ca193993SMichael Walsh 524ca193993SMichael Walsh if found_error: 525*89eff544SMichael Walsh var_name = get_var_name(var_name) 526018e25fbSMichael Walsh error_message += "The following list is invalid (see entries marked" 527018e25fbSMichael Walsh error_message += " with \"*\"):\n" 528018e25fbSMichael Walsh error_message += gp.sprint_varx(var_name, display_var_value, 529018e25fbSMichael Walsh gp.blank() | gp.show_type()) 530018e25fbSMichael Walsh error_message += "\n" 53135026be5SMichael Walsh error_message += gp.sprint_var(valid_values, gp.show_type()) 532018e25fbSMichael Walsh return process_error_message(error_message) 533ca193993SMichael Walsh 534ca193993SMichael Walsh return process_error_message(error_message) 5357ac5fd81SMichael Walsh 5367ac5fd81SMichael Walsh 537*89eff544SMichael Walshdef valid_dict(var_value, required_keys=[], var_name=None): 5387ac5fd81SMichael Walsh r""" 539018e25fbSMichael Walsh The variable value is valid if it is a dictionary containing all of the 540018e25fbSMichael Walsh required keys. 5417ac5fd81SMichael Walsh 542018e25fbSMichael Walsh Description of argument(s): 543018e25fbSMichael Walsh var_value The value being validated. 5447ac5fd81SMichael Walsh required_keys A list of keys which must be found in the 5457ac5fd81SMichael Walsh dictionary for it to be considered valid. 5467ac5fd81SMichael Walsh """ 5477ac5fd81SMichael Walsh 5487ac5fd81SMichael Walsh error_message = "" 549018e25fbSMichael Walsh missing_keys = list(set(required_keys) - set(var_value.keys())) 550018e25fbSMichael Walsh if len(missing_keys) > 0: 551*89eff544SMichael Walsh var_name = get_var_name(var_name) 552018e25fbSMichael Walsh error_message += "The following dictionary is invalid because it is" 553018e25fbSMichael Walsh error_message += " missing required keys:\n" 554018e25fbSMichael Walsh error_message += gp.sprint_varx(var_name, var_value, 555018e25fbSMichael Walsh gp.blank() | gp.show_type()) 556018e25fbSMichael Walsh error_message += "\n" 55735026be5SMichael Walsh error_message += gp.sprint_var(missing_keys, gp.show_type()) 5587ac5fd81SMichael Walsh return process_error_message(error_message) 559018e25fbSMichael Walsh 560018e25fbSMichael Walsh 561*89eff544SMichael Walshdef valid_program(var_value, var_name=None): 562be3a8150SMichael Walsh r""" 563be3a8150SMichael Walsh The variable value is valid if it contains the name of a program which can 564be3a8150SMichael Walsh be located using the "which" command. 565be3a8150SMichael Walsh 566be3a8150SMichael Walsh Description of argument(s): 567be3a8150SMichael Walsh var_value The value being validated. 568be3a8150SMichael Walsh """ 569be3a8150SMichael Walsh 570be3a8150SMichael Walsh error_message = "" 571be3a8150SMichael Walsh rc, out_buf = gc.shell_cmd("which " + var_value, quiet=1, show_err=0, 572be3a8150SMichael Walsh ignore_err=1) 573be3a8150SMichael Walsh if rc: 574*89eff544SMichael Walsh var_name = get_var_name(var_name) 575be3a8150SMichael Walsh error_message += "The following required program could not be found" 576be3a8150SMichael Walsh error_message += " using the $PATH environment variable:\n" 57700244345SMichael Walsh error_message += gp.sprint_varx(var_name, var_value, gp.blank()) 578be3a8150SMichael Walsh PATH = os.environ.get("PATH", "").split(":") 579be3a8150SMichael Walsh error_message += "\n" 580be3a8150SMichael Walsh error_message += gp.sprint_var(PATH) 581be3a8150SMichael Walsh return process_error_message(error_message) 582be3a8150SMichael Walsh 583be3a8150SMichael Walsh 584*89eff544SMichael Walshdef valid_length(var_value, min_length=None, max_length=None, var_name=None): 585b9d8dfd2SMichael Walsh r""" 586b9d8dfd2SMichael Walsh The variable value is valid if it is an object (e.g. list, dictionary) 587b9d8dfd2SMichael Walsh whose length is within the specified range. 588b9d8dfd2SMichael Walsh 589b9d8dfd2SMichael Walsh Description of argument(s): 590b9d8dfd2SMichael Walsh var_value The value being validated. 591b9d8dfd2SMichael Walsh min_length The minimum length of the object. If not 592b9d8dfd2SMichael Walsh None, the length of var_value must be 593b9d8dfd2SMichael Walsh greater than or equal to min_length. 594b9d8dfd2SMichael Walsh max_length The maximum length of the object. If not 595b9d8dfd2SMichael Walsh None, the length of var_value must be less 596b9d8dfd2SMichael Walsh than or equal to min_length. 597b9d8dfd2SMichael Walsh """ 598b9d8dfd2SMichael Walsh 599b9d8dfd2SMichael Walsh error_message = "" 600b9d8dfd2SMichael Walsh length = len(var_value) 601b9d8dfd2SMichael Walsh error_message = valid_range(length, min_length, max_length) 602b9d8dfd2SMichael Walsh if error_message: 603*89eff544SMichael Walsh var_name = get_var_name(var_name) 604b9d8dfd2SMichael Walsh error_message = "The length of the following object is not within the" 605b9d8dfd2SMichael Walsh error_message += " expected range:\n" 606b9d8dfd2SMichael Walsh error_message += gp.sprint_var(length) 607b9d8dfd2SMichael Walsh error_message += gp.sprint_varx(var_name, var_value, gp.blank()) 608b9d8dfd2SMichael Walsh error_message += "\n" 609b9d8dfd2SMichael Walsh error_message += gp.sprint_vars(min_length, max_length) 610b9d8dfd2SMichael Walsh return process_error_message(error_message) 611b9d8dfd2SMichael Walsh 612b9d8dfd2SMichael Walsh return process_error_message(error_message) 613b9d8dfd2SMichael Walsh 614b9d8dfd2SMichael Walsh 615018e25fbSMichael Walsh# Modify selected function docstrings by adding headers/footers. 616018e25fbSMichael Walsh 617018e25fbSMichael Walshfunc_names = [ 618018e25fbSMichael Walsh "valid_type", "valid_value", "valid_range", "valid_integer", 619018e25fbSMichael Walsh "valid_dir_path", "valid_file_path", "valid_path", "valid_list", 620*89eff544SMichael Walsh "valid_dict", "valid_program", "valid_length" 621018e25fbSMichael Walsh] 622018e25fbSMichael Walsh 623018e25fbSMichael Walshraw_doc_strings = {} 624018e25fbSMichael Walsh 625018e25fbSMichael Walshfor func_name in func_names: 626018e25fbSMichael Walsh cmd_buf = "raw_doc_strings['" + func_name + "'] = " + func_name 627018e25fbSMichael Walsh cmd_buf += ".__doc__" 628018e25fbSMichael Walsh exec(cmd_buf) 629018e25fbSMichael Walsh cmd_buf = func_name + ".__doc__ = docstring_header + " + func_name 630018e25fbSMichael Walsh cmd_buf += ".__doc__.rstrip(\" \\n\") + additional_args_docstring_footer" 631018e25fbSMichael Walsh exec(cmd_buf) 632