blob: f41c9cd82eb6b5676104478c2cb87349e894c9e7 [file] [log] [blame]
Michael Walsh7423c012016-10-04 10:27:21 -05001#!/usr/bin/env python
2
3r"""
4This module provides valuable argument processing functions like
5gen_get_options and sprint_args.
6"""
7
Michael Walsh78bdfdd2017-01-10 11:27:30 -06008import os
Michael Walsh7423c012016-10-04 10:27:21 -05009import gen_print as gp
10
Michael Walshe23b5ad2018-06-01 14:54:35 -050011exit_on_error = False
12
13
14def set_exit_on_error(value):
15 r"""
16 Set the exit_on_error value to either True or False.
17
18 If exit_on_error is set, validation functions like valid_value will exit
19 the program on error instead of returning False.
20
21 Description of argument(s):
22 value Value to set global exit_on_error to.
23 """
24
25 global exit_on_error
26 exit_on_error = value
27
28
29def get_var_name(var_name):
30 r"""
31 If var_name has a value, simply return it. Otherwise, get the variable
32 name of the first arguement used to call the validation function (e.g.
33 valid_value, valid_integer, etc.) and return it.
34
35 This function is designed solely for use by other functions in this file.
36
37 Example:
38
39 A programmer codes this:
40
41 valid_value(last_name)
42
43 Which results in the following call stack:
44
45 valid_value(last_name)
46 -> svalid_value(var_value...)
47 -> get_var_name(var_name)
48
49 In this example, this function will return "last_name".
50
51 Example:
52
53 err_msg = svalid_value(last_name, var_name="some_other_name")
54
55 Which results in the following call stack:
56
57 svalid_value(var_value, var_name="some_other_name")
58 -> get_var_name(var_name)
59
60 In this example, this function will return "some_other_name".
61
62 Description of argument(s):
63 var_name The name of the variable.
64 """
65
66 if var_name != "":
67 return var_name
68 # Calculate stack_frame_ix. The validation functions in this file come
69 # in pairs. There is an "s" version of each validation function (e.g.
70 # svalid_value) whose job is to return an error message string. Then
71 # there is a wrapper function (e.g. valid_value) that will call the "s"
72 # version and print the result if there is an error. See examples 1 and 2
73 # above for illustration. This function must be cognizant of both
74 # scenarios to accurately determine the name of the variable being
75 # validated. Where the "s" function is being called directly, the
76 # stack_frame_ix should be set to 3. Where the wrapper function is being
77 # called, the stack_frame_ix should be incremented to 4.
78 stack_frame_ix = 3
79 parent_func_name = gp.sprint_func_name(2)
80 grandparent_func_name = gp.sprint_func_name(3)
81 if parent_func_name == "s" + grandparent_func_name:
82 stack_frame_ix += 1
83 var_name = gp.get_arg_name(0, 1, stack_frame_ix)
84 return var_name
85
86
87def process_error_message(error_message):
88 r"""
89 Process the error_message as follows:
90 - If the error_message is blank, return True.
91 - If the error_message contains a value:
92 - Print the error_message as part of a full error report.
93 - If global exit_on_error is set, then exit the program with a return
94 code of 1.
95 - If exit_on_error is not set, return False.
96
97 This function is designed solely for use by wrapper functions in this file
98 (e.g. "valid_value").
99
100 Description of argument(s):
101 error_message An error message.
102 """
103
104 if error_message == "":
105 return True
106
107 gp.print_error_report(error_message)
108 if exit_on_error:
109 exit(0)
110 return False
111
Michael Walsh7423c012016-10-04 10:27:21 -0500112
Michael Walshbec416d2016-11-10 08:54:52 -0600113def svalid_value(var_value,
114 invalid_values=[],
115 valid_values=[],
116 var_name=""):
Michael Walsh7423c012016-10-04 10:27:21 -0500117 r"""
Michael Walshbec416d2016-11-10 08:54:52 -0600118 Return an empty string if var_value is a valid value. Otherwise, return
119 an error string.
Michael Walsh7423c012016-10-04 10:27:21 -0500120
121 Description of arguments:
122 var_value The value being validated.
123 invalid_values A list of invalid values. If var_value is
124 equal to any of these, it is invalid.
125 Note that if you specify anything for
126 invalid_values (below), the valid_values
Michael Walshe23b5ad2018-06-01 14:54:35 -0500127 list is not even processed. If you
128 specify nothing for both invalid_values
129 and valid_values, invalid_values will be
130 set to a default value of [""].
Michael Walsh7423c012016-10-04 10:27:21 -0500131 valid_values A list of invalid values. var_value must
132 be equal to one of these values to be
133 considered valid.
Michael Walshbec416d2016-11-10 08:54:52 -0600134 var_name The name of the variable whose value is
135 passed in var_value. This parameter is
136 normally unnecessary as this function can
137 figure out the var_name. This is provided
138 for Robot callers. In this scenario, we
139 are unable to get the variable name
140 ourselves.
Michael Walsh7423c012016-10-04 10:27:21 -0500141 """
142
Michael Walshbec416d2016-11-10 08:54:52 -0600143 success_message = ""
144 error_message = ""
Michael Walshbec416d2016-11-10 08:54:52 -0600145
Michael Walshe23b5ad2018-06-01 14:54:35 -0500146 # Validate this function's arguments.
Michael Walsh7423c012016-10-04 10:27:21 -0500147 len_valid_values = len(valid_values)
148 len_invalid_values = len(invalid_values)
149 if len_valid_values > 0 and len_invalid_values > 0:
Michael Walshbec416d2016-11-10 08:54:52 -0600150 error_message += "Programmer error - You must provide either an" +\
151 " invalid_values list or a valid_values" +\
152 " list but NOT both.\n" +\
153 gp.sprint_var(invalid_values) +\
154 gp.sprint_var(valid_values)
155 return error_message
Michael Walsh7423c012016-10-04 10:27:21 -0500156
Michael Walshbec416d2016-11-10 08:54:52 -0600157 show_blanks = 1
Michael Walsh7423c012016-10-04 10:27:21 -0500158 if len_valid_values > 0:
159 # Processing the valid_values list.
160 if var_value in valid_values:
Michael Walshbec416d2016-11-10 08:54:52 -0600161 return success_message
Michael Walshbec416d2016-11-10 08:54:52 -0600162 error_message += "The following variable has an invalid" +\
163 " value:\n" +\
Michael Walshe23b5ad2018-06-01 14:54:35 -0500164 gp.sprint_varx(get_var_name(var_name), var_value,
165 show_blanks) +\
Michael Walshbec416d2016-11-10 08:54:52 -0600166 "\nIt must be one of the following values:\n" +\
167 gp.sprint_varx("valid_values", valid_values,
168 show_blanks)
169 return error_message
Michael Walsh7423c012016-10-04 10:27:21 -0500170
171 if len_invalid_values == 0:
Michael Walshbec416d2016-11-10 08:54:52 -0600172 # Assign default value.
173 invalid_values = [""]
Michael Walsh7423c012016-10-04 10:27:21 -0500174
175 # Assertion: We have an invalid_values list. Processing it now.
176 if var_value not in invalid_values:
Michael Walshbec416d2016-11-10 08:54:52 -0600177 return success_message
Michael Walsh7423c012016-10-04 10:27:21 -0500178
Michael Walshbec416d2016-11-10 08:54:52 -0600179 error_message += "The following variable has an invalid value:\n" +\
Michael Walshe23b5ad2018-06-01 14:54:35 -0500180 gp.sprint_varx(get_var_name(var_name), var_value,
181 show_blanks) +\
Michael Walshbec416d2016-11-10 08:54:52 -0600182 "\nIt must NOT be one of the following values:\n" +\
183 gp.sprint_varx("invalid_values", invalid_values,
184 show_blanks)
185 return error_message
Michael Walsh7423c012016-10-04 10:27:21 -0500186
Michael Walsh7423c012016-10-04 10:27:21 -0500187
Michael Walshbec416d2016-11-10 08:54:52 -0600188def valid_value(var_value,
189 invalid_values=[],
190 valid_values=[],
191 var_name=""):
Michael Walshbec416d2016-11-10 08:54:52 -0600192 r"""
Michael Walshe23b5ad2018-06-01 14:54:35 -0500193 Return True if var_value is valid. Otherwise, print an error message and
194 either return False or exit(1) depending on the value of exit_on_error.
Michael Walshbec416d2016-11-10 08:54:52 -0600195
196 Description of arguments:
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600197 (See description of arguments for svalid_value (above)).
Michael Walshbec416d2016-11-10 08:54:52 -0600198 """
199
200 error_message = svalid_value(var_value, invalid_values, valid_values,
201 var_name)
Michael Walshe23b5ad2018-06-01 14:54:35 -0500202 return process_error_message(error_message)
Michael Walshbec416d2016-11-10 08:54:52 -0600203
Michael Walshbec416d2016-11-10 08:54:52 -0600204
Michael Walshbec416d2016-11-10 08:54:52 -0600205def svalid_integer(var_value,
206 var_name=""):
Michael Walshbec416d2016-11-10 08:54:52 -0600207 r"""
208 Return an empty string if var_value is a valid integer. Otherwise, return
209 an error string.
210
211 Description of arguments:
212 var_value The value being validated.
213 var_name The name of the variable whose value is
214 passed in var_value. This parameter is
215 normally unnecessary as this function can
216 figure out the var_name. This is provided
217 for Robot callers. In this scenario, we
218 are unable to get the variable name
219 ourselves.
220 """
221
Michael Walshbec416d2016-11-10 08:54:52 -0600222 success_message = ""
223 error_message = ""
224 try:
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500225 if isinstance(int(str(var_value), 0), int):
Michael Walshbec416d2016-11-10 08:54:52 -0600226 return success_message
227 except ValueError:
228 pass
229
230 # If we get to this point, the validation has failed.
Michael Walshbec416d2016-11-10 08:54:52 -0600231 show_blanks = 1
Michael Walshe23b5ad2018-06-01 14:54:35 -0500232 error_message +=\
233 "Invalid integer value:\n" +\
234 gp.sprint_varx(get_var_name(var_name), var_value, show_blanks)
Michael Walshbec416d2016-11-10 08:54:52 -0600235
236 return error_message
237
Michael Walshbec416d2016-11-10 08:54:52 -0600238
Michael Walshbec416d2016-11-10 08:54:52 -0600239def valid_integer(var_value,
240 var_name=""):
Michael Walsh7423c012016-10-04 10:27:21 -0500241 r"""
Michael Walshe23b5ad2018-06-01 14:54:35 -0500242 Return True if var_value is a valid integer. Otherwise, print an error
243 message and either return False or exit(1) depending on the value of
244 exit_on_error.
Michael Walsh7423c012016-10-04 10:27:21 -0500245
246 Description of arguments:
Michael Walshe23b5ad2018-06-01 14:54:35 -0500247 (See description of arguments for svalid_integer (above)).
Michael Walsh7423c012016-10-04 10:27:21 -0500248 """
249
Michael Walshbec416d2016-11-10 08:54:52 -0600250 error_message = svalid_integer(var_value, var_name)
Michael Walshe23b5ad2018-06-01 14:54:35 -0500251 return process_error_message(error_message)
Michael Walsh7423c012016-10-04 10:27:21 -0500252
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600253
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600254def svalid_dir_path(var_value,
255 var_name=""):
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600256 r"""
257 Return an empty string if var_value is a valid directory path. Otherwise,
258 return an error string.
259
260 Description of arguments:
261 var_value The value being validated.
262 var_name The name of the variable whose value is
263 passed in var_value. This parameter is
264 normally unnecessary as this function can
265 figure out the var_name. This is provided
266 for Robot callers. In this scenario, we
267 are unable to get the variable name
268 ourselves.
269 """
270
271 error_message = ""
272 if not os.path.isdir(str(var_value)):
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600273 error_message += "The following directory does not exist:\n" +\
Michael Walshe23b5ad2018-06-01 14:54:35 -0500274 gp.sprint_varx(get_var_name(var_name), var_value)
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600275
276 return error_message
277
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600278
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600279def valid_dir_path(var_value,
280 var_name=""):
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600281 r"""
Michael Walshe23b5ad2018-06-01 14:54:35 -0500282 Return True if var_value is a valid directory path. Otherwise, print an
283 error message and either return False or exit(1) depending on the value of
284 exit_on_error.
285
286 Valid means that the directory path exists.
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600287
288 Description of arguments:
Michael Walshe23b5ad2018-06-01 14:54:35 -0500289 (See description of arguments for svalid_dir_path (above)).
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600290 """
291
292 error_message = svalid_dir_path(var_value, var_name)
Michael Walshe23b5ad2018-06-01 14:54:35 -0500293 return process_error_message(error_message)
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600294
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600295
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600296def svalid_file_path(var_value,
297 var_name=""):
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600298 r"""
299 Return an empty string if var_value is a valid file path. Otherwise,
300 return an error string.
301
302 Description of arguments:
303 var_value The value being validated.
304 var_name The name of the variable whose value is
305 passed in var_value. This parameter is
306 normally unnecessary as this function can
307 figure out the var_name. This is provided
308 for Robot callers. In this scenario, we
309 are unable to get the variable name
310 ourselves.
311 """
312
313 error_message = ""
314 if not os.path.isfile(str(var_value)):
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600315 error_message += "Invalid file (does not exist):\n" +\
Michael Walshe23b5ad2018-06-01 14:54:35 -0500316 gp.sprint_varx(get_var_name(var_name), var_value)
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600317
318 return error_message
319
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600320
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600321def valid_file_path(var_value,
322 var_name=""):
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600323 r"""
Michael Walshe23b5ad2018-06-01 14:54:35 -0500324 Return True if var_value is a valid file path. Otherwise, print an error
325 message and either return False or exit(1) depending on the value of
326 exit_on_error.
327
328 Valid means that the file exists.
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600329
330 Description of arguments:
Michael Walshe23b5ad2018-06-01 14:54:35 -0500331 (See description of arguments for svalid_file_path (above)).
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600332 """
333
334 error_message = svalid_file_path(var_value, var_name)
Michael Walshe23b5ad2018-06-01 14:54:35 -0500335 return process_error_message(error_message)
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600336
Michael Walsh78bdfdd2017-01-10 11:27:30 -0600337
Michael Walshe23b5ad2018-06-01 14:54:35 -0500338def svalid_path(var_value,
339 var_name=""):
340 r"""
341 Return an empty string if var_value is either a valid file path or
342 directory path. Otherwise, return an error string.
343
344 Description of arguments:
345 var_value The value being validated.
346 var_name The name of the variable whose value is
347 passed in var_value. This parameter is
348 normally unnecessary as this function can
349 figure out the var_name. This is provided
350 for Robot callers. In this scenario, we
351 are unable to get the variable name
352 ourselves.
353 """
354
355 error_message = ""
356 if not (os.path.isfile(str(var_value)) or os.path.isdir(str(var_value))):
357 error_message = "Invalid path (file or directory does not exist):\n" +\
358 gp.sprint_varx(get_var_name(var_name), var_value)
359
360 return error_message
361
362
363def valid_path(var_value,
364 var_name=""):
365 r"""
366 Return True if var_value is a valid file path. Otherwise, print an error
367 message and either return False or exit(1) depending on the value of
368 exit_on_error.
369
370 Valid means that the file exists.
371
372 Description of arguments:
373 (See description of arguments for svalid_path (above)).
374 """
375
376 error_message = svalid_path(var_value, var_name)
377 return process_error_message(error_message)
Michael Walsh2c687e92018-05-09 11:47:56 -0500378
379
380def svalid_range(var_value,
Michael Walshe23b5ad2018-06-01 14:54:35 -0500381 valid_range=[],
Michael Walsh2c687e92018-05-09 11:47:56 -0500382 var_name=""):
383 r"""
384 Return an empty string if var_value is within the range. Otherwise,
385 return an error string.
386
387 Description of arguments:
388 var_value The value being validated. This value
389 must be an integer.
Michael Walshe23b5ad2018-06-01 14:54:35 -0500390 valid_range A list comprised of one or two elements
Michael Walsh2c687e92018-05-09 11:47:56 -0500391 which are the lower and upper ends of a
392 range. These values must be integers
393 except where noted. Valid specifications
394 may be of the following forms: [lower,
395 upper], [lower] or [None, upper].
396 var_name The name of the variable whose value is
397 passed in var_value. This parameter is
398 normally unnecessary as this function can
399 figure out the var_name. This is provided
400 for Robot callers. In this scenario, we
401 are unable to get the variable name
402 ourselves.
403 """
404
405 error_message = ""
Michael Walsh2c687e92018-05-09 11:47:56 -0500406
407 # Validate this function's parms:
408 # First, ensure that the value is an integer.
409 error_message = svalid_integer(var_value, var_name)
410 if not error_message == "":
411 return error_message
412 var_value = int(var_value)
413
Michael Walshe23b5ad2018-06-01 14:54:35 -0500414 len_valid_range = len(valid_range)
415 if len_valid_range == 0 or len_valid_range > 2:
416 error_message += "Programmer error - For the valid_range parameter," +\
417 " you must provide a list consisting of one or two" +\
Michael Walsh2c687e92018-05-09 11:47:56 -0500418 " elements.\n" +\
Michael Walshe23b5ad2018-06-01 14:54:35 -0500419 gp.sprint_var(valid_range)
Michael Walsh2c687e92018-05-09 11:47:56 -0500420 return error_message
421
Michael Walshe23b5ad2018-06-01 14:54:35 -0500422 if len_valid_range == 1 or valid_range[0] is not None:
423 # Make sure lower valid_range value is an integer.
424 error_message = svalid_integer(valid_range[0], "valid_range[0]")
Michael Walsh2c687e92018-05-09 11:47:56 -0500425 if not error_message == "":
426 error_message = "Programmer error:\n" + error_message
427 return error_message
Michael Walshe23b5ad2018-06-01 14:54:35 -0500428 if valid_range[0] is not None:
429 valid_range[0] = int(valid_range[0])
430 if len_valid_range == 2:
431 # Make sure upper valid_range value is an integer.
432 error_message = svalid_integer(valid_range[1], "valid_range[1]")
Michael Walsh2c687e92018-05-09 11:47:56 -0500433 if not error_message == "":
434 error_message = "Programmer error:\n" + error_message
435 return error_message
Michael Walshe23b5ad2018-06-01 14:54:35 -0500436 valid_range[1] = int(valid_range[1])
437 if valid_range[0] is not None and valid_range[0] > valid_range[1]:
438 error_message = "Programmer error - In the following range, the" +\
439 " lower limit is greater than the upper" +\
440 " limit:\n" + gp.sprint_varx("valid_range",
441 valid_range)
Michael Walsh2c687e92018-05-09 11:47:56 -0500442 return error_message
443
Michael Walshe23b5ad2018-06-01 14:54:35 -0500444 if len_valid_range == 1:
445 if var_value < valid_range[0]:
Michael Walsh2c687e92018-05-09 11:47:56 -0500446 error_message += "The following variable is not within the" +\
447 " expected range:\n" +\
Michael Walshe23b5ad2018-06-01 14:54:35 -0500448 gp.sprint_varx(get_var_name(var_name),
449 var_value) +\
Michael Walsh2c687e92018-05-09 11:47:56 -0500450 gp.sprint_varx("valid_range",
Michael Walshe23b5ad2018-06-01 14:54:35 -0500451 str(valid_range[0]) + "..")
452 return error_message
453 return error_message
454
455 if valid_range[0] is None:
456 if var_value > valid_range[1]:
457 error_message += "The following variable is not within the" +\
458 " expected range:\n" +\
459 gp.sprint_varx(get_var_name(var_name),
460 var_value) +\
461 gp.sprint_varx("valid_range",
462 ".." + str(valid_range[1]))
Michael Walsh2c687e92018-05-09 11:47:56 -0500463 return error_message
464
Michael Walshe23b5ad2018-06-01 14:54:35 -0500465 if var_value < valid_range[0] or var_value > valid_range[1]:
Michael Walsh2c687e92018-05-09 11:47:56 -0500466 error_message += "The following variable is not within the expected" +\
467 " range:\n" +\
Michael Walshe23b5ad2018-06-01 14:54:35 -0500468 gp.sprint_varx(get_var_name(var_name), var_value) +\
Michael Walsh2c687e92018-05-09 11:47:56 -0500469 gp.sprint_varx("valid_range",
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500470 str(valid_range[0]) + ".."
471 + str(valid_range[1]))
Michael Walsh2c687e92018-05-09 11:47:56 -0500472 return error_message
473
474 return error_message
475
476
477def valid_range(var_value,
Michael Walshe23b5ad2018-06-01 14:54:35 -0500478 valid_range=[],
Michael Walsh2c687e92018-05-09 11:47:56 -0500479 var_name=""):
480 r"""
Michael Walshe23b5ad2018-06-01 14:54:35 -0500481 Return True if var_value is within range. Otherwise, print an error
482 message and either return False or exit(1) depending on the value of
483 exit_on_error.
Michael Walsh2c687e92018-05-09 11:47:56 -0500484
485 Description of arguments:
486 (See description of arguments for svalid_range (above)).
487 """
488
Michael Walshe23b5ad2018-06-01 14:54:35 -0500489 error_message = svalid_range(var_value, valid_range, var_name)
490 return process_error_message(error_message)