blob: 88048f18bc7a83b10103f46f64eaccfc362bb34c [file] [log] [blame]
Michael Walsh18176322016-11-15 15:11:21 -06001#!/usr/bin/env python
2
3r"""
Michael Walsh84230c22019-08-01 12:23:07 -05004This module provides validation functions like valid_value(), valid_integer(),
5etc. for robot programs.
Michael Walsh18176322016-11-15 15:11:21 -06006"""
7
Michael Walsh84230c22019-08-01 12:23:07 -05008import re
Michael Walshc108e422019-03-28 12:27:18 -05009import gen_print as gp
Michael Walsh18176322016-11-15 15:11:21 -060010import gen_valid as gv
Michael Walsh84230c22019-08-01 12:23:07 -050011import func_args as fa
Michael Walsh18176322016-11-15 15:11:21 -060012
13from robot.libraries.BuiltIn import BuiltIn
Michael Walsh18176322016-11-15 15:11:21 -060014
15
Michael Walsh84230c22019-08-01 12:23:07 -050016def valid_var_name(var_name):
Michael Walsh18176322016-11-15 15:11:21 -060017 r"""
Michael Walsh84230c22019-08-01 12:23:07 -050018 Validate the robot variable name and return its value.
Michael Walsh3e26e102017-01-10 11:29:28 -060019
Michael Walsh84230c22019-08-01 12:23:07 -050020 If the variable is undefined, this function will print an error message
21 and call BuiltIn().fail().
Michael Walsh18176322016-11-15 15:11:21 -060022
Michael Walsh84230c22019-08-01 12:23:07 -050023 Description of arguments():
24 var_name The name of the robot variable (e.g.
25 "var1"). Do not include "${}" (e.g.
26 "${var1}". Just provide the simple name
27 of the variable.
Michael Walsh18176322016-11-15 15:11:21 -060028 """
29
30 # Note: get_variable_value() seems to have no trouble with local variables.
31 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
Michael Walsh18176322016-11-15 15:11:21 -060032 if var_value is None:
Michael Walsh84230c22019-08-01 12:23:07 -050033 var_value = "<undefined>"
34 error_message = gv.valid_value(var_value, invalid_values=[var_value],
35 var_name=var_name)
Michael Walsh18176322016-11-15 15:11:21 -060036 BuiltIn().fail(error_message)
37
Michael Walsh84230c22019-08-01 12:23:07 -050038 return var_value
Michael Walsh18176322016-11-15 15:11:21 -060039
Michael Walsh84230c22019-08-01 12:23:07 -050040
41def valid_init(var_name, *args, **kwargs):
Michael Walsh18176322016-11-15 15:11:21 -060042 r"""
Michael Walsh84230c22019-08-01 12:23:07 -050043 Do initialization for variable validation and return var_name, args and
44 kwargs.
Michael Walsh3e26e102017-01-10 11:29:28 -060045
Michael Walsh84230c22019-08-01 12:23:07 -050046 This function is to be called by all of the various validation functions
47 in this module.
Michael Walsh18176322016-11-15 15:11:21 -060048
Michael Walsh84230c22019-08-01 12:23:07 -050049 This function is designed solely for use by other functions in this file.
Michael Walsh18176322016-11-15 15:11:21 -060050
Michael Walsh84230c22019-08-01 12:23:07 -050051 Description of argument(s):
52 var_name The name of the variable to be validated.
53 args The positional arguments to be passed to a
54 validation function.
55 kwargs The keyword arguments to be passed to a
56 validation function.
Michael Walsh18176322016-11-15 15:11:21 -060057 """
58
Michael Walsh84230c22019-08-01 12:23:07 -050059 var_value = valid_var_name(var_name)
60 # Convert python string object definitions to objects (useful for robot
61 # callers).
62 args = fa.args_to_objects(args)
63 kwargs = fa.args_to_objects(kwargs)
64 return var_value, args, kwargs
Michael Walsh2c687e92018-05-09 11:47:56 -050065
66
Michael Walsh84230c22019-08-01 12:23:07 -050067def process_error_message(error_message):
Michael Walsh2c687e92018-05-09 11:47:56 -050068 r"""
Michael Walsh84230c22019-08-01 12:23:07 -050069 Process an error message.
Michael Walsh2c687e92018-05-09 11:47:56 -050070
Michael Walsh84230c22019-08-01 12:23:07 -050071 If error_message is non-blank, fail. Otherwise, do nothing.
Michael Walsh2c687e92018-05-09 11:47:56 -050072
Michael Walsh84230c22019-08-01 12:23:07 -050073 This function is designed solely for use by other functions in this file.
Michael Walsh2c687e92018-05-09 11:47:56 -050074
Michael Walsh84230c22019-08-01 12:23:07 -050075 Description of argument(s):
76 error_message The error message to be processed.
Michael Walsh2c687e92018-05-09 11:47:56 -050077 """
78
Michael Walsh84230c22019-08-01 12:23:07 -050079 if error_message:
Michael Walshc108e422019-03-28 12:27:18 -050080 error_message = gp.sprint_error_report(error_message)
Michael Walsh2c687e92018-05-09 11:47:56 -050081 BuiltIn().fail(error_message)
Michael Walsh84230c22019-08-01 12:23:07 -050082
83
84# The docstring header will be pre-pended to each validation function's
85# existing docstring.
86docstring_header = \
87 r"""
88 Fail if the variable named by var_name is invalid.
89 """
90
91
92def customize_doc_string(doc_string):
93 r"""
94 Customize a gen_valid function docstring and return the result.
95
96 This function is designed solely for use by other functions in this file.
97
98 The caller should pass a docstring from a gen_valid.py validation
99 function. This docstring will be changed to make a suitable docstring for
100 this module's corresponding validation function.
101
102 For example:
103
104 Let's suppose that gen_valid.py has a function called "valid_value()".
105 This module could make the following call to essentially copy gen_valid's
106 "valid_value()" function, modify it and then assign it to the local
107 version of the valid_value() function.
108
109 valid.__doc__ = customize_doc_string(gv.valid.__doc__)
110
111 Description of argument(s):
112 doc_string The docstring to be customized.
113 """
114
115 doc_string = docstring_header + doc_string
116 doc_string = doc_string.split("\n")
117
118 start_ix = 0
119 # Find the "var_value" line.
120 start_ix = next((index for index, value in
121 enumerate(doc_string[start_ix:], start_ix)
122 if re.match("[ ]+var_value ", value)), None)
123 # Replace the "var_value" line with our "var_name" line.
124 doc_string[start_ix] = " var_name " \
125 + "The name of the variable to be validated."
126
127 return "\n".join(doc_string)
128
129
130# All of the following functions are robot wrappers for the equivalent
131# functions defined in gen_valid.py. Note that the only difference between
132# any two of these locally defined functions is the function name and the
133# gv.<function name> which they call. Also, note that the docstring for each
134# is created by modifying the docstring from the supporting gen_valid.py
135# function.
136
137def valid_type(var_name, *args, **kwargs):
138
139 var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
140 error_message = \
141 gv.valid_type(var_value, *args, var_name=var_name, **kwargs)
142 process_error_message(error_message)
143
144
145def valid_value(var_name, *args, **kwargs):
146
147 var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
148 error_message = \
149 gv.valid_value(var_value, *args, var_name=var_name, **kwargs)
150 process_error_message(error_message)
151
152
153def valid_range(var_name, *args, **kwargs):
154
155 var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
156 error_message = \
157 gv.valid_range(var_value, *args, var_name=var_name, **kwargs)
158 process_error_message(error_message)
159
160
161def valid_integer(var_name, *args, **kwargs):
162
163 var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
164 error_message = \
165 gv.valid_integer(var_value, *args, var_name=var_name, **kwargs)
166 process_error_message(error_message)
167
168
169def valid_dir_path(var_name, *args, **kwargs):
170
171 var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
172 error_message = \
173 gv.valid_dir_path(var_value, *args, var_name=var_name, **kwargs)
174 process_error_message(error_message)
175
176
177def valid_file_path(var_name, *args, **kwargs):
178
179 var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
180 error_message = \
181 gv.valid_file_path(var_value, *args, var_name=var_name, **kwargs)
182 process_error_message(error_message)
183
184
185def valid_path(var_name, *args, **kwargs):
186
187 var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
188 error_message = \
189 gv.valid_path(var_value, *args, var_name=var_name, **kwargs)
190 process_error_message(error_message)
191
192
193def valid_list(var_name, *args, **kwargs):
194
195 var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
196 error_message = \
197 gv.valid_list(var_value, *args, var_name=var_name, **kwargs)
198 process_error_message(error_message)
199
200
201def valid_dict(var_name, *args, **kwargs):
202
203 var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
204 error_message = \
205 gv.valid_dict(var_value, *args, var_name=var_name, **kwargs)
206 process_error_message(error_message)
207
208
209# Modify the validation function docstrings by calling customize_doc_string
210# for each function in the func_names list.
211func_names = [
212 "valid_type", "valid_value", "valid_range", "valid_integer",
213 "valid_dir_path", "valid_file_path", "valid_path", "valid_list",
214 "valid_dict"
215]
216
217for func_name in func_names:
218 cmd_buf = func_name \
219 + ".__doc__ = customize_doc_string(gv.raw_doc_strings['" \
220 + func_name + "'])"
221 exec(cmd_buf)
222
223# Define aliases for backward compatibility.
224rvalid_value = valid_value