1#!/usr/bin/env python3 2 3r""" 4This module provides validation functions like valid_value(), valid_integer(), etc. for robot programs. 5""" 6 7import re 8 9import func_args as fa 10import gen_print as gp 11import gen_valid as gv 12from robot.libraries.BuiltIn import BuiltIn 13 14 15def valid_var_name(var_name): 16 r""" 17 Validate the robot variable name and return its value. 18 19 If the variable is undefined, this function will print an error message and call BuiltIn().fail(). 20 21 Description of arguments(): 22 var_name The name of the robot variable (e.g. "var1"). Do not include "${}" (e.g. 23 "${var1}". Just provide the simple name of the variable. 24 """ 25 26 # Note: get_variable_value() seems to have no trouble with local variables. 27 var_value = BuiltIn().get_variable_value("${" + var_name + "}") 28 if var_value is None: 29 var_value = "<undefined>" 30 error_message = gv.valid_value( 31 var_value, invalid_values=[var_value], var_name=var_name 32 ) 33 BuiltIn().fail(error_message) 34 35 return var_value 36 37 38def valid_init(var_name, *args, **kwargs): 39 r""" 40 Do initialization for variable validation and return var_name, args and kwargs. 41 42 This function is to be called by all of the various validation functions in this module. 43 44 This function is designed solely for use by other functions in this file. 45 46 Description of argument(s): 47 var_name The name of the variable to be validated. 48 args The positional arguments to be passed to a validation function. 49 kwargs The keyword arguments to be passed to a validation function. 50 """ 51 52 var_value = valid_var_name(var_name) 53 # Convert python string object definitions to objects (useful for robot callers). 54 args = fa.args_to_objects(args) 55 kwargs = fa.args_to_objects(kwargs) 56 return var_value, args, kwargs 57 58 59def process_error_message(error_message): 60 r""" 61 Process an error message. 62 63 If error_message is non-blank, fail. Otherwise, do nothing. 64 65 This function is designed solely for use by other functions in this file. 66 67 Description of argument(s): 68 error_message The error message to be processed. 69 """ 70 71 if error_message: 72 error_message = gp.sprint_error_report(error_message) 73 BuiltIn().fail(error_message) 74 75 76# The docstring header will be prepended to each validation function's existing docstring. 77docstring_header = r""" 78 Fail if the variable named by var_name is invalid. 79 """ 80 81 82def customize_doc_string(doc_string): 83 r""" 84 Customize a gen_valid function docstring and return the result. 85 86 This function is designed solely for use by other functions in this file. 87 88 The caller should pass a docstring from a gen_valid.py validation function. This docstring will be 89 changed to make a suitable docstring for this module's corresponding validation function. 90 91 For example: 92 93 Let's suppose that gen_valid.py has a function called "valid_value()". This module could make the 94 following call to essentially copy gen_valid's "valid_value()" function, modify it and then assign it to 95 the local version of the valid_value() function. 96 97 valid.__doc__ = customize_doc_string(gv.valid.__doc__) 98 99 Description of argument(s): 100 doc_string The docstring to be customized. 101 """ 102 103 doc_string = docstring_header + doc_string 104 doc_string = doc_string.split("\n") 105 106 start_ix = 0 107 # Find the "var_value" line. 108 start_ix = next( 109 ( 110 index 111 for index, value in enumerate(doc_string[start_ix:], start_ix) 112 if re.match("[ ]+var_value ", value) 113 ), 114 None, 115 ) 116 # Replace the "var_value" line with our "var_name" line. 117 doc_string[start_ix] = ( 118 " var_name " 119 + "The name of the variable to be validated." 120 ) 121 122 return "\n".join(doc_string) 123 124 125# All of the following functions are robot wrappers for the equivalent functions defined in gen_valid.py. 126# Note that the only difference between any two of these locally defined functions is the function name and 127# the gv.<function name> which they call. Also, note that the docstring for each is created by modifying the 128# docstring from the supporting gen_valid.py function. 129 130 131def valid_type(var_name, *args, **kwargs): 132 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 133 error_message = gv.valid_type( 134 var_value, *args, var_name=var_name, **kwargs 135 ) 136 process_error_message(error_message) 137 138 139def valid_value(var_name, *args, **kwargs): 140 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 141 error_message = gv.valid_value( 142 var_value, *args, var_name=var_name, **kwargs 143 ) 144 process_error_message(error_message) 145 146 147def valid_range(var_name, *args, **kwargs): 148 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 149 error_message = gv.valid_range( 150 var_value, *args, var_name=var_name, **kwargs 151 ) 152 process_error_message(error_message) 153 154 155def valid_integer(var_name, *args, **kwargs): 156 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 157 error_message = gv.valid_integer( 158 var_value, *args, var_name=var_name, **kwargs 159 ) 160 process_error_message(error_message) 161 162 163def valid_float(var_name, *args, **kwargs): 164 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 165 error_message = gv.valid_float( 166 var_value, *args, var_name=var_name, **kwargs 167 ) 168 process_error_message(error_message) 169 170 171def valid_date_time(var_name, *args, **kwargs): 172 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 173 error_message = gv.valid_date_time( 174 var_value, *args, var_name=var_name, **kwargs 175 ) 176 process_error_message(error_message) 177 178 179def valid_dir_path(var_name, *args, **kwargs): 180 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 181 error_message = gv.valid_dir_path( 182 var_value, *args, var_name=var_name, **kwargs 183 ) 184 process_error_message(error_message) 185 186 187def valid_file_path(var_name, *args, **kwargs): 188 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 189 error_message = gv.valid_file_path( 190 var_value, *args, var_name=var_name, **kwargs 191 ) 192 process_error_message(error_message) 193 194 195def valid_path(var_name, *args, **kwargs): 196 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 197 error_message = gv.valid_path( 198 var_value, *args, var_name=var_name, **kwargs 199 ) 200 process_error_message(error_message) 201 202 203def valid_list(var_name, *args, **kwargs): 204 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 205 error_message = gv.valid_list( 206 var_value, *args, var_name=var_name, **kwargs 207 ) 208 process_error_message(error_message) 209 210 211def valid_dict(var_name, *args, **kwargs): 212 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 213 error_message = gv.valid_dict( 214 var_value, *args, var_name=var_name, **kwargs 215 ) 216 process_error_message(error_message) 217 218 219def valid_program(var_name, *args, **kwargs): 220 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 221 error_message = gv.valid_program( 222 var_value, *args, var_name=var_name, **kwargs 223 ) 224 process_error_message(error_message) 225 226 227def valid_length(var_name, *args, **kwargs): 228 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 229 error_message = gv.valid_length( 230 var_value, *args, var_name=var_name, **kwargs 231 ) 232 process_error_message(error_message) 233 234 235# Modify the validation function docstrings by calling customize_doc_string for each function in the 236# func_names list. 237func_names = [ 238 "valid_type", 239 "valid_value", 240 "valid_range", 241 "valid_integer", 242 "valid_dir_path", 243 "valid_file_path", 244 "valid_path", 245 "valid_list", 246 "valid_dict", 247 "valid_program", 248 "valid_length", 249 "valid_float", 250 "valid_date_time", 251] 252 253for func_name in func_names: 254 cmd_buf = ( 255 func_name 256 + ".__doc__ = customize_doc_string(gv.raw_doc_strings['" 257 + func_name 258 + "'])" 259 ) 260 exec(cmd_buf) 261