118176322SMichael Walsh#!/usr/bin/env python 218176322SMichael Walsh 318176322SMichael Walshr""" 4*84230c20SMichael WalshThis module provides validation functions like valid_value(), valid_integer(), 5*84230c20SMichael Walshetc. for robot programs. 618176322SMichael Walsh""" 718176322SMichael Walsh 8*84230c20SMichael Walshimport re 9c108e429SMichael Walshimport gen_print as gp 1018176322SMichael Walshimport gen_valid as gv 11*84230c20SMichael Walshimport func_args as fa 1218176322SMichael Walsh 1318176322SMichael Walshfrom robot.libraries.BuiltIn import BuiltIn 1418176322SMichael Walsh 1518176322SMichael Walsh 16*84230c20SMichael Walshdef valid_var_name(var_name): 1718176322SMichael Walsh r""" 18*84230c20SMichael Walsh Validate the robot variable name and return its value. 193e26e109SMichael Walsh 20*84230c20SMichael Walsh If the variable is undefined, this function will print an error message 21*84230c20SMichael Walsh and call BuiltIn().fail(). 2218176322SMichael Walsh 23*84230c20SMichael Walsh Description of arguments(): 24*84230c20SMichael Walsh var_name The name of the robot variable (e.g. 25*84230c20SMichael Walsh "var1"). Do not include "${}" (e.g. 26*84230c20SMichael Walsh "${var1}". Just provide the simple name 27*84230c20SMichael Walsh of the variable. 2818176322SMichael Walsh """ 2918176322SMichael Walsh 3018176322SMichael Walsh # Note: get_variable_value() seems to have no trouble with local variables. 3118176322SMichael Walsh var_value = BuiltIn().get_variable_value("${" + var_name + "}") 3218176322SMichael Walsh if var_value is None: 33*84230c20SMichael Walsh var_value = "<undefined>" 34*84230c20SMichael Walsh error_message = gv.valid_value(var_value, invalid_values=[var_value], 35*84230c20SMichael Walsh var_name=var_name) 3618176322SMichael Walsh BuiltIn().fail(error_message) 3718176322SMichael Walsh 38*84230c20SMichael Walsh return var_value 3918176322SMichael Walsh 40*84230c20SMichael Walsh 41*84230c20SMichael Walshdef valid_init(var_name, *args, **kwargs): 4218176322SMichael Walsh r""" 43*84230c20SMichael Walsh Do initialization for variable validation and return var_name, args and 44*84230c20SMichael Walsh kwargs. 453e26e109SMichael Walsh 46*84230c20SMichael Walsh This function is to be called by all of the various validation functions 47*84230c20SMichael Walsh in this module. 4818176322SMichael Walsh 49*84230c20SMichael Walsh This function is designed solely for use by other functions in this file. 5018176322SMichael Walsh 51*84230c20SMichael Walsh Description of argument(s): 52*84230c20SMichael Walsh var_name The name of the variable to be validated. 53*84230c20SMichael Walsh args The positional arguments to be passed to a 54*84230c20SMichael Walsh validation function. 55*84230c20SMichael Walsh kwargs The keyword arguments to be passed to a 56*84230c20SMichael Walsh validation function. 5718176322SMichael Walsh """ 5818176322SMichael Walsh 59*84230c20SMichael Walsh var_value = valid_var_name(var_name) 60*84230c20SMichael Walsh # Convert python string object definitions to objects (useful for robot 61*84230c20SMichael Walsh # callers). 62*84230c20SMichael Walsh args = fa.args_to_objects(args) 63*84230c20SMichael Walsh kwargs = fa.args_to_objects(kwargs) 64*84230c20SMichael Walsh return var_value, args, kwargs 652c687e98SMichael Walsh 662c687e98SMichael Walsh 67*84230c20SMichael Walshdef process_error_message(error_message): 682c687e98SMichael Walsh r""" 69*84230c20SMichael Walsh Process an error message. 702c687e98SMichael Walsh 71*84230c20SMichael Walsh If error_message is non-blank, fail. Otherwise, do nothing. 722c687e98SMichael Walsh 73*84230c20SMichael Walsh This function is designed solely for use by other functions in this file. 742c687e98SMichael Walsh 75*84230c20SMichael Walsh Description of argument(s): 76*84230c20SMichael Walsh error_message The error message to be processed. 772c687e98SMichael Walsh """ 782c687e98SMichael Walsh 79*84230c20SMichael Walsh if error_message: 80c108e429SMichael Walsh error_message = gp.sprint_error_report(error_message) 812c687e98SMichael Walsh BuiltIn().fail(error_message) 82*84230c20SMichael Walsh 83*84230c20SMichael Walsh 84*84230c20SMichael Walsh# The docstring header will be pre-pended to each validation function's 85*84230c20SMichael Walsh# existing docstring. 86*84230c20SMichael Walshdocstring_header = \ 87*84230c20SMichael Walsh r""" 88*84230c20SMichael Walsh Fail if the variable named by var_name is invalid. 89*84230c20SMichael Walsh """ 90*84230c20SMichael Walsh 91*84230c20SMichael Walsh 92*84230c20SMichael Walshdef customize_doc_string(doc_string): 93*84230c20SMichael Walsh r""" 94*84230c20SMichael Walsh Customize a gen_valid function docstring and return the result. 95*84230c20SMichael Walsh 96*84230c20SMichael Walsh This function is designed solely for use by other functions in this file. 97*84230c20SMichael Walsh 98*84230c20SMichael Walsh The caller should pass a docstring from a gen_valid.py validation 99*84230c20SMichael Walsh function. This docstring will be changed to make a suitable docstring for 100*84230c20SMichael Walsh this module's corresponding validation function. 101*84230c20SMichael Walsh 102*84230c20SMichael Walsh For example: 103*84230c20SMichael Walsh 104*84230c20SMichael Walsh Let's suppose that gen_valid.py has a function called "valid_value()". 105*84230c20SMichael Walsh This module could make the following call to essentially copy gen_valid's 106*84230c20SMichael Walsh "valid_value()" function, modify it and then assign it to the local 107*84230c20SMichael Walsh version of the valid_value() function. 108*84230c20SMichael Walsh 109*84230c20SMichael Walsh valid.__doc__ = customize_doc_string(gv.valid.__doc__) 110*84230c20SMichael Walsh 111*84230c20SMichael Walsh Description of argument(s): 112*84230c20SMichael Walsh doc_string The docstring to be customized. 113*84230c20SMichael Walsh """ 114*84230c20SMichael Walsh 115*84230c20SMichael Walsh doc_string = docstring_header + doc_string 116*84230c20SMichael Walsh doc_string = doc_string.split("\n") 117*84230c20SMichael Walsh 118*84230c20SMichael Walsh start_ix = 0 119*84230c20SMichael Walsh # Find the "var_value" line. 120*84230c20SMichael Walsh start_ix = next((index for index, value in 121*84230c20SMichael Walsh enumerate(doc_string[start_ix:], start_ix) 122*84230c20SMichael Walsh if re.match("[ ]+var_value ", value)), None) 123*84230c20SMichael Walsh # Replace the "var_value" line with our "var_name" line. 124*84230c20SMichael Walsh doc_string[start_ix] = " var_name " \ 125*84230c20SMichael Walsh + "The name of the variable to be validated." 126*84230c20SMichael Walsh 127*84230c20SMichael Walsh return "\n".join(doc_string) 128*84230c20SMichael Walsh 129*84230c20SMichael Walsh 130*84230c20SMichael Walsh# All of the following functions are robot wrappers for the equivalent 131*84230c20SMichael Walsh# functions defined in gen_valid.py. Note that the only difference between 132*84230c20SMichael Walsh# any two of these locally defined functions is the function name and the 133*84230c20SMichael Walsh# gv.<function name> which they call. Also, note that the docstring for each 134*84230c20SMichael Walsh# is created by modifying the docstring from the supporting gen_valid.py 135*84230c20SMichael Walsh# function. 136*84230c20SMichael Walsh 137*84230c20SMichael Walshdef valid_type(var_name, *args, **kwargs): 138*84230c20SMichael Walsh 139*84230c20SMichael Walsh var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 140*84230c20SMichael Walsh error_message = \ 141*84230c20SMichael Walsh gv.valid_type(var_value, *args, var_name=var_name, **kwargs) 142*84230c20SMichael Walsh process_error_message(error_message) 143*84230c20SMichael Walsh 144*84230c20SMichael Walsh 145*84230c20SMichael Walshdef valid_value(var_name, *args, **kwargs): 146*84230c20SMichael Walsh 147*84230c20SMichael Walsh var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 148*84230c20SMichael Walsh error_message = \ 149*84230c20SMichael Walsh gv.valid_value(var_value, *args, var_name=var_name, **kwargs) 150*84230c20SMichael Walsh process_error_message(error_message) 151*84230c20SMichael Walsh 152*84230c20SMichael Walsh 153*84230c20SMichael Walshdef valid_range(var_name, *args, **kwargs): 154*84230c20SMichael Walsh 155*84230c20SMichael Walsh var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 156*84230c20SMichael Walsh error_message = \ 157*84230c20SMichael Walsh gv.valid_range(var_value, *args, var_name=var_name, **kwargs) 158*84230c20SMichael Walsh process_error_message(error_message) 159*84230c20SMichael Walsh 160*84230c20SMichael Walsh 161*84230c20SMichael Walshdef valid_integer(var_name, *args, **kwargs): 162*84230c20SMichael Walsh 163*84230c20SMichael Walsh var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 164*84230c20SMichael Walsh error_message = \ 165*84230c20SMichael Walsh gv.valid_integer(var_value, *args, var_name=var_name, **kwargs) 166*84230c20SMichael Walsh process_error_message(error_message) 167*84230c20SMichael Walsh 168*84230c20SMichael Walsh 169*84230c20SMichael Walshdef valid_dir_path(var_name, *args, **kwargs): 170*84230c20SMichael Walsh 171*84230c20SMichael Walsh var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 172*84230c20SMichael Walsh error_message = \ 173*84230c20SMichael Walsh gv.valid_dir_path(var_value, *args, var_name=var_name, **kwargs) 174*84230c20SMichael Walsh process_error_message(error_message) 175*84230c20SMichael Walsh 176*84230c20SMichael Walsh 177*84230c20SMichael Walshdef valid_file_path(var_name, *args, **kwargs): 178*84230c20SMichael Walsh 179*84230c20SMichael Walsh var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 180*84230c20SMichael Walsh error_message = \ 181*84230c20SMichael Walsh gv.valid_file_path(var_value, *args, var_name=var_name, **kwargs) 182*84230c20SMichael Walsh process_error_message(error_message) 183*84230c20SMichael Walsh 184*84230c20SMichael Walsh 185*84230c20SMichael Walshdef valid_path(var_name, *args, **kwargs): 186*84230c20SMichael Walsh 187*84230c20SMichael Walsh var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 188*84230c20SMichael Walsh error_message = \ 189*84230c20SMichael Walsh gv.valid_path(var_value, *args, var_name=var_name, **kwargs) 190*84230c20SMichael Walsh process_error_message(error_message) 191*84230c20SMichael Walsh 192*84230c20SMichael Walsh 193*84230c20SMichael Walshdef valid_list(var_name, *args, **kwargs): 194*84230c20SMichael Walsh 195*84230c20SMichael Walsh var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 196*84230c20SMichael Walsh error_message = \ 197*84230c20SMichael Walsh gv.valid_list(var_value, *args, var_name=var_name, **kwargs) 198*84230c20SMichael Walsh process_error_message(error_message) 199*84230c20SMichael Walsh 200*84230c20SMichael Walsh 201*84230c20SMichael Walshdef valid_dict(var_name, *args, **kwargs): 202*84230c20SMichael Walsh 203*84230c20SMichael Walsh var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 204*84230c20SMichael Walsh error_message = \ 205*84230c20SMichael Walsh gv.valid_dict(var_value, *args, var_name=var_name, **kwargs) 206*84230c20SMichael Walsh process_error_message(error_message) 207*84230c20SMichael Walsh 208*84230c20SMichael Walsh 209*84230c20SMichael Walsh# Modify the validation function docstrings by calling customize_doc_string 210*84230c20SMichael Walsh# for each function in the func_names list. 211*84230c20SMichael Walshfunc_names = [ 212*84230c20SMichael Walsh "valid_type", "valid_value", "valid_range", "valid_integer", 213*84230c20SMichael Walsh "valid_dir_path", "valid_file_path", "valid_path", "valid_list", 214*84230c20SMichael Walsh "valid_dict" 215*84230c20SMichael Walsh] 216*84230c20SMichael Walsh 217*84230c20SMichael Walshfor func_name in func_names: 218*84230c20SMichael Walsh cmd_buf = func_name \ 219*84230c20SMichael Walsh + ".__doc__ = customize_doc_string(gv.raw_doc_strings['" \ 220*84230c20SMichael Walsh + func_name + "'])" 221*84230c20SMichael Walsh exec(cmd_buf) 222*84230c20SMichael Walsh 223*84230c20SMichael Walsh# Define aliases for backward compatibility. 224*84230c20SMichael Walshrvalid_value = valid_value 225