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 8import gen_print as gp 9import gen_valid as gv 10import func_args as fa 11 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(var_value, invalid_values=[var_value], 31 var_name=var_name) 32 BuiltIn().fail(error_message) 33 34 return var_value 35 36 37def valid_init(var_name, *args, **kwargs): 38 r""" 39 Do initialization for variable validation and return var_name, args and kwargs. 40 41 This function is to be called by all of the various validation functions in this module. 42 43 This function is designed solely for use by other functions in this file. 44 45 Description of argument(s): 46 var_name The name of the variable to be validated. 47 args The positional arguments to be passed to a validation function. 48 kwargs The keyword arguments to be passed to a validation function. 49 """ 50 51 var_value = valid_var_name(var_name) 52 # Convert python string object definitions to objects (useful for robot callers). 53 args = fa.args_to_objects(args) 54 kwargs = fa.args_to_objects(kwargs) 55 return var_value, args, kwargs 56 57 58def process_error_message(error_message): 59 r""" 60 Process an error message. 61 62 If error_message is non-blank, fail. Otherwise, do nothing. 63 64 This function is designed solely for use by other functions in this file. 65 66 Description of argument(s): 67 error_message The error message to be processed. 68 """ 69 70 if error_message: 71 error_message = gp.sprint_error_report(error_message) 72 BuiltIn().fail(error_message) 73 74 75# The docstring header will be pre-pended to each validation function's existing docstring. 76docstring_header = \ 77 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((index for index, value in 109 enumerate(doc_string[start_ix:], start_ix) 110 if re.match("[ ]+var_value ", value)), None) 111 # Replace the "var_value" line with our "var_name" line. 112 doc_string[start_ix] = " var_name " \ 113 + "The name of the variable to be validated." 114 115 return "\n".join(doc_string) 116 117 118# All of the following functions are robot wrappers for the equivalent functions defined in gen_valid.py. 119# Note that the only difference between any two of these locally defined functions is the function name and 120# the gv.<function name> which they call. Also, note that the docstring for each is created by modifying the 121# docstring from the supporting gen_valid.py function. 122 123def valid_type(var_name, *args, **kwargs): 124 125 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 126 error_message = \ 127 gv.valid_type(var_value, *args, var_name=var_name, **kwargs) 128 process_error_message(error_message) 129 130 131def valid_value(var_name, *args, **kwargs): 132 133 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 134 error_message = \ 135 gv.valid_value(var_value, *args, var_name=var_name, **kwargs) 136 process_error_message(error_message) 137 138 139def valid_range(var_name, *args, **kwargs): 140 141 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 142 error_message = \ 143 gv.valid_range(var_value, *args, var_name=var_name, **kwargs) 144 process_error_message(error_message) 145 146 147def valid_integer(var_name, *args, **kwargs): 148 149 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 150 error_message = \ 151 gv.valid_integer(var_value, *args, var_name=var_name, **kwargs) 152 process_error_message(error_message) 153 154 155def valid_float(var_name, *args, **kwargs): 156 157 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 158 error_message = \ 159 gv.valid_float(var_value, *args, var_name=var_name, **kwargs) 160 process_error_message(error_message) 161 162 163def valid_date_time(var_name, *args, **kwargs): 164 165 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 166 error_message = \ 167 gv.valid_date_time(var_value, *args, var_name=var_name, **kwargs) 168 process_error_message(error_message) 169 170 171def valid_dir_path(var_name, *args, **kwargs): 172 173 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 174 error_message = \ 175 gv.valid_dir_path(var_value, *args, var_name=var_name, **kwargs) 176 process_error_message(error_message) 177 178 179def valid_file_path(var_name, *args, **kwargs): 180 181 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 182 error_message = \ 183 gv.valid_file_path(var_value, *args, var_name=var_name, **kwargs) 184 process_error_message(error_message) 185 186 187def valid_path(var_name, *args, **kwargs): 188 189 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 190 error_message = \ 191 gv.valid_path(var_value, *args, var_name=var_name, **kwargs) 192 process_error_message(error_message) 193 194 195def valid_list(var_name, *args, **kwargs): 196 197 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 198 error_message = \ 199 gv.valid_list(var_value, *args, var_name=var_name, **kwargs) 200 process_error_message(error_message) 201 202 203def valid_dict(var_name, *args, **kwargs): 204 205 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 206 error_message = \ 207 gv.valid_dict(var_value, *args, var_name=var_name, **kwargs) 208 process_error_message(error_message) 209 210 211def valid_program(var_name, *args, **kwargs): 212 213 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 214 error_message = \ 215 gv.valid_program(var_value, *args, var_name=var_name, **kwargs) 216 process_error_message(error_message) 217 218 219def valid_length(var_name, *args, **kwargs): 220 221 var_value, args, kwargs = valid_init(var_name, *args, **kwargs) 222 error_message = \ 223 gv.valid_length(var_value, *args, var_name=var_name, **kwargs) 224 process_error_message(error_message) 225 226 227# Modify the validation function docstrings by calling customize_doc_string for each function in the 228# func_names list. 229func_names = [ 230 "valid_type", "valid_value", "valid_range", "valid_integer", 231 "valid_dir_path", "valid_file_path", "valid_path", "valid_list", 232 "valid_dict", "valid_program", "valid_length", "valid_float", 233 "valid_date_time" 234] 235 236for func_name in func_names: 237 cmd_buf = func_name \ 238 + ".__doc__ = customize_doc_string(gv.raw_doc_strings['" \ 239 + func_name + "'])" 240 exec(cmd_buf) 241