xref: /openbmc/openbmc-test-automation/lib/gen_robot_valid.py (revision e16f158fb9a0a66dc731acfb9681766f58fbda58)
1 #!/usr/bin/env python3
2 
3 r"""
4 This module provides validation functions like valid_value(), valid_integer(), etc. for robot programs.
5 """
6 
7 import re
8 
9 import func_args as fa
10 import gen_print as gp
11 import gen_valid as gv
12 from robot.libraries.BuiltIn import BuiltIn
13 
14 
15 def 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 
38 def 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 
59 def 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.
77 docstring_header = r"""
78     Fail if the variable named by var_name is invalid.
79     """
80 
81 
82 def 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 
131 def 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 
139 def 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 
147 def 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 
155 def 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 
163 def 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 
171 def 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 
179 def 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 
187 def 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 
195 def 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 
203 def 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 
211 def 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 
219 def 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 
227 def 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.
237 func_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 
253 for 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