def valid_value(var_value, invalid_values=[""], valid_values=[]): r""" Return True if var_value is a valid value. Otherwise, return False and print an error message to stderr. Description of arguments: var_value The value being validated. invalid_values A list of invalid values. If var_value is equal to any of these, it is invalid. Note that if you specify anything for invalid_values (below), the valid_values list is not even processed. valid_values A list of invalid values. var_value must be equal to one of these values to be considered valid. """ len_valid_values = len(valid_values) len_invalid_values = len(invalid_values) if len_valid_values > 0 and len_invalid_values > 0: gp.print_error_report("Programmer error - You must provide either an" + " invalid_values list or a valid_values" + " list but NOT both.") return False if len_valid_values > 0: # Processing the valid_values list. if var_value in valid_values: return True var_name = gp.get_arg_name(0, 1, 2) gp.print_error_report("The following variable has an invalid" + " value:\n" + gp.sprint_varx(var_name, var_value) + "\nIt must be one of the following values:\n" + gp.sprint_varx("valid_values", valid_values)) return False if len_invalid_values == 0: gp.print_error_report("Programmer error - You must provide either an" + " invalid_values list or a valid_values" + " list. Both are empty.") return False # Assertion: We have an invalid_values list. Processing it now. if var_value not in invalid_values: return True var_name = gp.get_arg_name(0, 1, 2) gp.print_error_report("The following variable has an invalid value:\n" + gp.sprint_varx(var_name, var_value) + "\nIt must" + " NOT be one of the following values:\n" + gp.sprint_varx("invalid_values", invalid_values)) return False
def restore_plug_in_value(*args, **kwargs): r""" Return a value from a plug-in save file. The args/kwargs are interpreted differently depending on how this function is called. Mode 1 - The output of this function is assigned to a variable: Example: my_var1 = restore_plug_in_value(2) In this mode, the lvalue ("my_var1" in this example) will serve as the name of the value to be restored. Mode 2 - The output of this function is NOT assigned to a variable: Example: if restore_plug_in_value('my_var1', 2): do_something() In this mode, the caller must explicitly provide the name of the value being restored. The args/kwargs are interpreted as follows: Description of argument(s): var_name The name of the value to be restored. Only relevant in mode 1 (see example above). default The default value to be returned if there is no plug-in save file for the value in question. plug_in_package_name See compose_plug_in_save_dir_path for details. """ # Process args. lvalue = gp.get_arg_name(0, -1, stack_frame_ix=2) if lvalue: var_name = lvalue else: var_name, args, kwargs = fa.pop_arg("", *args, **kwargs) default, args, kwargs = fa.pop_arg("", *args, **kwargs) plug_in_package_name, args, kwargs = fa.pop_arg(None, *args, **kwargs) if args or kwargs: error_message = "Programmer error - Too many arguments passed for this function." raise ValueError(error_message) plug_in_save_dir_path = create_plug_in_save_dir(plug_in_package_name) save_file_path = plug_in_save_dir_path + var_name if os.path.isfile(save_file_path): gp.qprint_timen("Restoring " + var_name + " value from " + save_file_path + ".") var_value = gm.file_to_list(save_file_path, newlines=0, comments=0, trim=1)[0] if type(default) is bool: # Convert from string to bool. var_value = (var_value == 'True') if type(default) is int: # Convert from string to int. var_value = int(var_value) else: var_value = default gp.qprint_timen("Save file " + save_file_path + " does not exist so returning default value.") gp.qprint_varx(var_name, var_value) return var_value
def set_pgm_arg(var_value, var_name=None): r""" Set the value of the arg_obj.__dict__ entry named in var_name with the var_value provided. Also, set corresponding global variable. Description of arguments: var_value The value to set in the variable. var_name The name of the variable to set. This defaults to the name of the variable used for var_value when calling this function. """ if var_name is None: var_name = gp.get_arg_name(None, 1, 2) arg_obj.__dict__[var_name] = var_value module = sys.modules['__main__'] setattr(module, var_name, var_value) if var_name == "quiet": __builtin__.quiet = var_value elif var_name == "debug": __builtin__.debug = var_value elif var_name == "test_mode": __builtin__.test_mode = var_value
def restore_plug_in_value(default=""): r""" Return a value from a plug-in save file. The name of the value to be restored will be determined by this function based on the lvalue being assigned. Consider the following example: my_var1 = restore_plug_in_value(2) In this example, this function would look for the "my_var1" file in the plug-in save directory, read its value and return it. If no such file exists, the default value of 2 would be returned. Description of argument(s): default The default value to be returned if there is no plug-in save file for the value in question. """ # Get the lvalue from the caller's invocation of this function. lvalue = gp.get_arg_name(0, -1, stack_frame_ix=2) plug_in_save_dir_path = create_plug_in_save_dir() save_file_path = plug_in_save_dir_path + lvalue if os.path.isfile(save_file_path): gp.qprint_timen("Restoring " + lvalue + " value from " + save_file_path + ".") return gm.file_to_list(save_file_path, newlines=0, comments=0, trim=1)[0] else: gp.qprint_timen("Save file " + save_file_path + " does not exist so returning default value.") return default
def save_plug_in_value(value): r""" Save a value in a plug-in save file. The value may be retrieved later via a call to the restore_plug_in_value function. This function will figure out the variable name of the value passed and use that name in creating the plug-in save file. Example call: my_var1 = 5 save_plug_in_value(my_var1) In this example, the value "5" would be saved to the "my_var1" file in the plug-in save directory. Description of argument(s): value The value to be saved. """ # Get the name of the variable used as argument one to this function. var_name = gp.get_arg_name(0, 1, stack_frame_ix=2) plug_in_save_dir_path = create_plug_in_save_dir() save_file_path = plug_in_save_dir_path + var_name gp.qprint_timen("Saving \"" + var_name + "\" value.") gc.shell_cmd("echo '" + str(value) + "' > " + save_file_path)
def svalid_file_path(var_value, var_name=""): r""" Return an empty string if var_value is a valid file path. Otherwise, return an error string. Description of arguments: var_value The value being validated. var_name The name of the variable whose value is passed in var_value. This parameter is normally unnecessary as this function can figure out the var_name. This is provided for Robot callers. In this scenario, we are unable to get the variable name ourselves. """ error_message = "" if not os.path.isfile(str(var_value)): if var_name is "": stack_index = 3 var_name = gp.get_arg_name(0, 1, stack_index) error_message += "Invalid file (does not exist):\n" +\ gp.sprint_varx(var_name, var_value) return error_message
def svalid_integer(var_value, var_name=""): r""" Return an empty string if var_value is a valid integer. Otherwise, return an error string. Description of arguments: var_value The value being validated. var_name The name of the variable whose value is passed in var_value. This parameter is normally unnecessary as this function can figure out the var_name. This is provided for Robot callers. In this scenario, we are unable to get the variable name ourselves. """ success_message = "" error_message = "" try: if type(int(str(var_value), 0)) is int: return success_message except ValueError: pass # If we get to this point, the validation has failed. if var_name is "": stack_index = 3 var_name = gp.get_arg_name(0, 1, stack_index) show_blanks = 1 error_message += "Invalid integer value:\n" +\ gp.sprint_varx(var_name, var_value, show_blanks) return error_message
def push(self, var_value, var_name=""): r""" push the var_name/var_value pair onto the stack. Description of argument(s): var_value The value being pushed. var_name The name of the variable containing the value to be pushed. This parameter is normally unnecessary as this function can figure out the var_name. This is provided for Robot callers. In this scenario, we are unable to get the variable name ourselves. """ if var_name == "": # The caller has not passed a var_name so we will try to figure # it out. stack_frame_ix = 2 var_name = gp.get_arg_name(0, 1, stack_frame_ix) if var_name in self.__stack_dict: self.__stack_dict[var_name].append(var_value) else: self.__stack_dict[var_name] = [var_value]
def save_plug_in_value(value, plug_in_package_name=None): r""" Save a value in a plug-in save file. The value may be retrieved later via a call to the restore_plug_in_value function. This function will figure out the variable name of the value passed and use that name in creating the plug-in save file. Example call: my_var1 = 5 save_plug_in_value(my_var1) In this example, the value "5" would be saved to the "my_var1" file in the plug-in save directory. Description of argument(s): value The value to be saved. plug_in_package_name See compose_plug_in_save_dir_path for details. """ # Get the name of the variable used as argument one to this function. var_name = gp.get_arg_name(0, 1, stack_frame_ix=2) plug_in_save_dir_path = create_plug_in_save_dir(plug_in_package_name) save_file_path = plug_in_save_dir_path + var_name gp.qprint_timen("Saving \"" + var_name + "\" value.") gc.shell_cmd("echo '" + str(value) + "' > " + save_file_path)
def set_mod_global(var_value, mod_name="__main__", var_name=None): r""" Set a global variable for a given module. Description of arguments: var_value The value to set in the variable. mod_name The name of the module whose variable is to be set. var_name The name of the variable to set. This defaults to the name of the variable used for var_value when calling this function. """ try: module = sys.modules[mod_name] except KeyError: gp.print_error_report("Programmer error - The mod_name passed to" + " this function is invalid:\n" + gp.sprint_var(mod_name)) raise ValueError('Programmer error.') if var_name is None: var_name = gp.get_arg_name(None, 1, 2) setattr(module, var_name, var_value)
def valid_integer(var_value): r""" Return True if var_value is a valid integer. Otherwise, return False and print an error message to stderr. Description of arguments: var_value The value being validated. """ # This currently allows floats which is not good. try: if type(int(var_value)) is int: return True except ValueError: pass # If we get to this point, the validation has failed. var_name = gp.get_arg_name(0, 1, 2) gp.print_varx("var_name", var_name) gp.print_error_report("Invalid integer value:\n" + gp.sprint_varx(var_name, var_value)) return False
def re_order_kwargs(stack_frame_ix, **kwargs): r""" Re-order the kwargs to match the order in which they were specified on a function invocation and return as an ordered dictionary. Note that this re_order_kwargs function should not be necessary in python versions 3.6 and beyond. Example: The caller calls func1 like this: func1('mike', arg1='one', arg2='two', arg3='three') And func1 is defined as follows: def func1(first_arg, **kwargs): kwargs = re_order_kwargs(first_arg_num=2, stack_frame_ix=3, **kwargs) The kwargs dictionary before calling re_order_kwargs (where order is not guaranteed): kwargs: kwargs[arg3]: three kwargs[arg2]: two kwargs[arg1]: one The kwargs dictionary after calling re_order_kwargs: kwargs: kwargs[arg1]: one kwargs[arg2]: two kwargs[arg3]: three Note that the re-ordered kwargs match the order specified on the call to func1. Description of argument(s): stack_frame_ix The stack frame of the function whose kwargs values must be re-ordered. 0 is the stack frame of re_order_kwargs, 1 is the stack from of its caller and so on. kwargs The keyword argument dictionary which is to be re-ordered. """ new_kwargs = collections.OrderedDict() # Get position number of first keyword on the calling line of code. (args, varargs, keywords, locals) =\ inspect.getargvalues(inspect.stack()[stack_frame_ix][0]) first_kwarg_pos = 1 + len(args) if varargs is not None: first_kwarg_pos += len(locals[varargs]) for arg_num in range(first_kwarg_pos, first_kwarg_pos + len(kwargs)): # This will result in an arg_name value such as "arg1='one'". arg_name = gp.get_arg_name(None, arg_num, stack_frame_ix + 2) # Continuing with the prior example, the following line will result # in key being set to 'arg1'. key = arg_name.split('=')[0] new_kwargs[key] = kwargs[key] return new_kwargs
def process_error_message(error_message): r""" Process the error_message in the manner described below. This function is designed solely for use by other functions in this file. NOTE: A blank error_message means that there is no error. For the following explanations, assume the caller of this function is a function with the following definition: valid_value(var_value, valid_values=[], invalid_values=[], *args, **kwargs): If the user of valid_value() is assigning the valid_value() return value to a variable, process_error_message() will simply return the error_message. This mode of usage is illustrated by the following example: error_message = valid_value(var1) This mode is useful for callers who wish to validate a variable and then decide for themselves what to do with the error_message (e.g. raise(error_message), BuiltIn().fail(error_message), etc.). If the user of valid_value() is NOT assigning the valid_value() return value to a variable, process_error_message() will behave as follows. First, if error_message is non-blank, it will be printed to stderr via a call to gp.print_error_report(error_message). If exit_on_error is set: - If the error_message is blank, simply return. - If the error_message is non-blank, exit the program with a return code of 1. If exit_on_error is NOT set: - If the error_message is blank, return True. - If the error_message is non-blank, return False. Description of argument(s): error_message An error message. """ # Determine whether the caller's caller is assigning the result to a # variable. l_value = gp.get_arg_name(None, -1, stack_frame_ix=3) if l_value: return error_message if error_message == "": if exit_on_error: return return True gp.print_error_report(error_message, stack_frame_ix=4) if exit_on_error: exit(1) return False
def pop_arg(pop_arg_default=None, *args, **kwargs): r""" Pop a named argument from the args/kwargs and return a tuple consisting of the argument value, the modified args and the modified kwargs. The name of the argument is determined automatically by this function by examining the source code which calls it (see examples below). If no suitable argument can be found, the default value passed to this function will be returned as the argument value. This function is useful for wrapper functions that wish to process arguments in some way before calling subordinate function. Examples: Given this code: def func1(*args, **kwargs): last_name, args, kwargs = pop_arg('Doe', *args, **kwargs) some_function(last_name.capitalize(), *args, **kwargs) Consider this call to func1: func1('Johnson', ssn='111-11-1111') The pop_arg in func1 would return the following: 'Johnson', [], {'ssn': "111-11-1111"} Notice that the 'args' value returned is an empty list. Since last_name was assumed to be the first positional argument, it was popped from args. Now consider this call to func1: func1(last_name='Johnson', ssn='111-11-1111') The pop_arg in func1 would return the same last_name value as in the previous example. The only difference being that the last_name value was popped from kwargs rather than from args. Description of argument(s): pop_arg_default The value to return if the named argument is not present in args/kwargs. args The positional arguments passed to the calling function. kwargs The keyword arguments passed to the calling function. """ # Retrieve the argument name by examining the source code. arg_name = gp.get_arg_name(None, arg_num=-3, stack_frame_ix=2) if arg_name in kwargs: arg_value = kwargs.pop(arg_name) else: # Convert args from a tuple to a list. args = list(args) if args: arg_value = args.pop(0) else: arg_value = pop_arg_default return arg_value, args, kwargs
def get_var_name(var_name): r""" If var_name has a value, simply return it. Otherwise, get the variable name of the first arguement used to call the validation function (e.g. valid_value, valid_integer, etc.) and return it. This function is designed solely for use by other functions in this file. Example: A programmer codes this: valid_value(last_name) Which results in the following call stack: valid_value(last_name) -> svalid_value(var_value...) -> get_var_name(var_name) In this example, this function will return "last_name". Example: err_msg = svalid_value(last_name, var_name="some_other_name") Which results in the following call stack: svalid_value(var_value, var_name="some_other_name") -> get_var_name(var_name) In this example, this function will return "some_other_name". Description of argument(s): var_name The name of the variable. """ if var_name != "": return var_name # Calculate stack_frame_ix. The validation functions in this file come # in pairs. There is an "s" version of each validation function (e.g. # svalid_value) whose job is to return an error message string. Then # there is a wrapper function (e.g. valid_value) that will call the "s" # version and print the result if there is an error. See examples 1 and 2 # above for illustration. This function must be cognizant of both # scenarios to accurately determine the name of the variable being # validated. Where the "s" function is being called directly, the # stack_frame_ix should be set to 3. Where the wrapper function is being # called, the stack_frame_ix should be incremented to 4. stack_frame_ix = 3 parent_func_name = gp.sprint_func_name(2) grandparent_func_name = gp.sprint_func_name(3) if parent_func_name == "s" + grandparent_func_name: stack_frame_ix += 1 var_name = gp.get_arg_name(0, 1, stack_frame_ix) return var_name
def create_robot_cmd_string(robot_file_path, *parms): r""" Create a robot command string and return it. On failure, return an empty string. Description of arguments: robot_file_path The path to the robot file to be run. parms The list of parms to be included in the command string. The name of each variable in this list must be the same as the name of the corresponding parm. This function figures out that name. This function is also able to distinguish robot parms (e.g. --outputdir) from robot program parms (all other parms which will be passed as "-v PARM_NAME:parm_value").. Example: The following call to this function... cmd_buf = create_robot_cmd_string("tools/start_sol_console.robot", OPENBMC_HOST, quiet, test_mode, debug, outputdir, output, log, report) Would return a string something like this. robot -v OPENBMC_HOST:beye6 -v quiet:0 -v test_mode:1 -v debug:1 --outputdir=/gsa/ausgsa/projects/a/autoipl/status --output=beye6.OS_Console.output.xml --log=beye6.OS_Console.log.html --report=beye6.OS_Console.report.html tools/start_sol_console.robot """ robot_file_path = init_robot_file_path(robot_file_path) robot_parm_names = get_robot_parm_names() robot_parm_list = [] stack_frame = 2 ix = 2 for arg in parms: parm = arg parm = gm.quote_bash_parm(gm.escape_bash_quotes(str(parm))) var_name = gp.get_arg_name(None, ix, stack_frame) if var_name in robot_parm_names: p_string = "--" + var_name + "=" + str(parm) robot_parm_list.append(p_string) else: p_string = "-v " + var_name + ":" + str(parm) robot_parm_list.append(p_string) ix += 1 robot_cmd_buf = "robot " + ' '.join(robot_parm_list) + " " +\ robot_file_path return robot_cmd_buf
def restore_plug_in_value(default="", plug_in_package_name=None): r""" Return a value from a plug-in save file. The name of the value to be restored will be determined by this function based on the lvalue being assigned. Consider the following example: my_var1 = restore_plug_in_value(2) In this example, this function would look for the "my_var1" file in the plug-in save directory, read its value and return it. If no such file exists, the default value of 2 would be returned. Description of argument(s): default The default value to be returned if there is no plug-in save file for the value in question. plug_in_package_name See compose_plug_in_save_dir_path for details. """ # Get the lvalue from the caller's invocation of this function. lvalue = gp.get_arg_name(0, -1, stack_frame_ix=2) plug_in_save_dir_path = create_plug_in_save_dir(plug_in_package_name) save_file_path = plug_in_save_dir_path + lvalue if os.path.isfile(save_file_path): gp.qprint_timen("Restoring " + lvalue + " value from " + save_file_path + ".") value = gm.file_to_list(save_file_path, newlines=0, comments=0, trim=1)[0] if type(default) is bool: # Convert from string to bool. value = (value == 'True') if type(default) is int: # Convert from string to int. value = int(value) gp.qprint_varx(lvalue, value) return value else: gp.qprint_timen("Save file " + save_file_path + " does not exist so returning default value.") gp.qprint_var(default) return default
def save_plug_in_value(var_value=None, plug_in_package_name=None, **kwargs): r""" Save a value in a plug-in save file. The value may be retrieved later via a call to the restore_plug_in_value function. This function will figure out the variable name corresponding to the value passed and use that name in creating the plug-in save file. The caller may pass the value as a simple variable or as a keyword=value (see examples below). Example 1: my_var1 = 5 save_plug_in_value(my_var1) In this example, the value "5" would be saved to the "my_var1" file in the plug-in save directory. Example 2: save_plug_in_value(my_var1=5) In this example, the value "5" would be saved to the "my_var1" file in the plug-in save directory. Description of argument(s): var_value The value to be saved. plug_in_package_name See compose_plug_in_save_dir_path for details. kwargs The first entry may contain a var_name/var_value. Other entries are ignored. """ if var_value is None: var_name = next(iter(kwargs)) var_value = kwargs[var_name] else: # Get the name of the variable used as argument one to this function. var_name = gp.get_arg_name(0, 1, stack_frame_ix=2) plug_in_save_dir_path = create_plug_in_save_dir(plug_in_package_name) save_file_path = plug_in_save_dir_path + var_name gp.qprint_timen("Saving \"" + var_name + "\" value.") gp.qprint_varx(var_name, var_value) gc.shell_cmd("echo '" + str(var_value) + "' > " + save_file_path)
def global_default(var_value, default=0): r""" If var_value is not None, return it. Otherwise, return the global variable of the same name, if it exists. If not, return default. This is meant for use by functions needing help assigning dynamic default values to their parms. Example: def func1(parm1=None): parm1 = global_default(parm1, 0) Description of arguments: var_value The value being evaluated. default The value to be returned if var_value is None AND the global variable of the same name does not exist. """ var_name = gp.get_arg_name(0, 1, stack_frame_ix=2) return dft(var_value, get_mod_global(var_name, 0))
def get_var_name(*args, **kwargs): r""" If args/kwargs contain a var_name, simply return its value. Otherwise, get the variable name of the first argument used to call the validation function (e.g. valid, valid_integer, etc.) and return it. This function is designed solely for use by other functions in this file. Example: A programmer codes this: valid_value(last_name) Which results in the following call stack: valid_value(last_name) -> get_var_name(var_name) In this example, this function will return "last_name". Example: err_msg = valid_value(last_name, var_name="some_other_name") Which results in the following call stack: valid_value(var_value, var_name="some_other_name") -> get_var_name(var_name) In this example, this function will return "some_other_name". Description of argument(s): var_name The name of the variable. """ var_name, args, kwargs = fa.pop_arg(*args, **kwargs) if var_name: return var_name return gp.get_arg_name(0, 1, stack_frame_ix=3)
def process_host(host, host_var_name=""): r""" Process a host by getting the associated host name and IP address and setting them in global variables. If the caller does not pass the host_var_name, this function will try to figure out the name of the variable used by the caller for the host parm. Callers are advised to explicitly specify the host_var_name when calling with an exec command. In such cases, the get_arg_name cannot figure out the host variable name. This function will then create similar global variable names by removing "_host" and appending "_host_name" or "_ip" to the host variable name. Example: If a call is made like this: process_host(openbmc_host) Global variables openbmc_host_name and openbmc_ip will be set. Description of argument(s): host A host name or IP. The name of the variable used should have a suffix of "_host". host_var_name The name of the variable being used as the host parm. """ if host_var_name == "": host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2) host_name_var_name = re.sub("host", "host_name", host_var_name) ip_var_name = re.sub("host", "ip", host_var_name) cmd_buf = "global " + host_name_var_name + ", " + ip_var_name + " ; " +\ host_name_var_name + ", " + ip_var_name + " = gm.get_host_name_ip('" +\ host + "')" exec(cmd_buf)
def create_var_dict(*args): r""" Create a dictionary whose keys/values are the arg names/arg values passed to it and return it to the caller. Note: The resulting dictionary will be ordered. Description of argument(s): *args An unlimited number of arguments to be processed. Example use: first_name = 'Steve' last_name = 'Smith' var_dict = create_var_dict(first_name, last_name) gp.print_var(var_dict) The print-out of the resulting var dictionary is: var_dict: var_dict[first_name]: Steve var_dict[last_name]: Smith """ try: result_dict = collections.OrderedDict() except AttributeError: result_dict = DotDict() arg_num = 1 for arg in args: arg_name = gp.get_arg_name(None, arg_num, stack_frame_ix=2) result_dict[arg_name] = arg arg_num += 1 return result_dict
def svalid_value(var_value, invalid_values=[], valid_values=[], var_name=""): r""" Return an empty string if var_value is a valid value. Otherwise, return an error string. Description of arguments: var_value The value being validated. invalid_values A list of invalid values. If var_value is equal to any of these, it is invalid. Note that if you specify anything for invalid_values (below), the valid_values list is not even processed. valid_values A list of invalid values. var_value must be equal to one of these values to be considered valid. var_name The name of the variable whose value is passed in var_value. This parameter is normally unnecessary as this function can figure out the var_name. This is provided for Robot callers. In this scenario, we are unable to get the variable name ourselves. """ success_message = "" error_message = "" stack_frame_ix = 3 len_valid_values = len(valid_values) len_invalid_values = len(invalid_values) if len_valid_values > 0 and len_invalid_values > 0: error_message += "Programmer error - You must provide either an" +\ " invalid_values list or a valid_values" +\ " list but NOT both.\n" +\ gp.sprint_var(invalid_values) +\ gp.sprint_var(valid_values) return error_message show_blanks = 1 if len_valid_values > 0: # Processing the valid_values list. if var_value in valid_values: return success_message if var_name == "": var_name = gp.get_arg_name(0, 1, stack_frame_ix) error_message += "The following variable has an invalid" +\ " value:\n" +\ gp.sprint_varx(var_name, var_value, show_blanks) +\ "\nIt must be one of the following values:\n" +\ gp.sprint_varx("valid_values", valid_values, show_blanks) return error_message if len_invalid_values == 0: # Assign default value. invalid_values = [""] # Assertion: We have an invalid_values list. Processing it now. if var_value not in invalid_values: return success_message if var_name == "": var_name = gp.get_arg_name(0, 1, stack_frame_ix) error_message += "The following variable has an invalid value:\n" +\ gp.sprint_varx(var_name, var_value, show_blanks) +\ "\nIt must NOT be one of the following values:\n" +\ gp.sprint_varx("invalid_values", invalid_values, show_blanks) return error_message