valid_list support invalid_values/required_values

Added support to valid_list function for 2 new arguments:

- invalid_values
- required_values

Also, corrected a few small errors.

Change-Id: Iec161b32ab2fce30cd42aa77168a9814dc099ed0
Signed-off-by: Michael Walsh <micwalsh@us.ibm.com>
diff --git a/lib/gen_valid.py b/lib/gen_valid.py
index d1601ec..6ead645 100755
--- a/lib/gen_valid.py
+++ b/lib/gen_valid.py
@@ -426,17 +426,29 @@
     return process_error_message(error_message)
 
 
-def valid_list(var_value, valid_values=[], fail_on_empty=False, *args,
-               **kwargs):
+def valid_list(var_value, valid_values=[], invalid_values=[],
+               required_values=[], fail_on_empty=False, *args, **kwargs):
     r"""
     The variable value is valid if it is a list where each entry can be found
-    in the valid_values list.
+    in the valid_values list or if none of its values can be found in the
+    invalid_values list or if all of the values in the required_values list
+    can be found in var_value.
+
+    The caller may only specify one of these 3 arguments: valid_values,
+    invalid_values, required_values.
 
     Description of argument(s):
     var_value                       The value being validated.
     valid_values                    A list of valid values.  Each element in
                                     the var_value list must be equal to one of
                                     these values to be considered valid.
+    invalid_values                  A list of invalid values.  If any element
+                                    in var_value is equal to any of the values
+                                    in this argument, var_value is considered
+                                    invalid.
+    required_values                 Every value in required_values must be
+                                    found in var_value.  Otherwise, var_value
+                                    is considered invalid.
     fail_on_empty                   Indicates that an empty list for the
                                     variable value should be considered an
                                     error.
@@ -444,6 +456,19 @@
 
     error_message = ""
 
+    # Validate this function's arguments.
+    len_valid_values = len(valid_values)
+    len_invalid_values = len(invalid_values)
+    len_required_values = len(required_values)
+    if (len_valid_values + len_invalid_values + len_required_values) > 1:
+        error_message += "Programmer error - You must provide only one of the"
+        error_message += " following: valid_values, invalid_values,"
+        error_message += " required_values.\n"
+        error_message += gp.sprint_var(invalid_values)
+        error_message += gp.sprint_var(valid_values)
+        error_message += gp.sprint_var(required_values)
+        return process_error_message(error_message)
+
     if type(var_value) is not list:
         var_name = get_var_name(*args, **kwargs)
         error_message = valid_type(var_value, list, var_name=var_name)
@@ -456,12 +481,55 @@
         error_message += gp.sprint_varx(var_name, var_value, gp.show_type())
         return process_error_message(error_message)
 
+    if len(required_values):
+        found_error = 0
+        display_required_values = list(required_values)
+        for ix in range(0, len(required_values)):
+            if required_values[ix] not in var_value:
+                found_error = 1
+                display_required_values[ix] = \
+                    str(display_required_values[ix]) + "*"
+        if found_error:
+            var_name = get_var_name(*args, **kwargs)
+            error_message += "The following list is invalid:\n"
+            error_message += gp.sprint_varx(var_name, var_value,
+                                            gp.blank() | gp.show_type())
+            error_message += "\n"
+            error_message += "Because some of the values in the "
+            error_message += "required_values list are not present (see"
+            error_message += " entries marked with \"*\"):\n"
+            error_message += "\n"
+            error_message += gp.sprint_varx('required_values',
+                                            display_required_values,
+                                            gp.blank() | gp.show_type())
+            error_message += "\n"
+
+        return process_error_message(error_message)
+
+    if len(invalid_values):
+        found_error = 0
+        display_var_value = list(var_value)
+        for ix in range(0, len(var_value)):
+            if var_value[ix] in invalid_values:
+                found_error = 1
+                display_var_value[ix] = str(var_value[ix]) + "*"
+
+        if found_error:
+            var_name = get_var_name(*args, **kwargs)
+            error_message += "The following list is invalid (see entries"
+            error_message += " marked with \"*\"):\n"
+            error_message += gp.sprint_varx(var_name, display_var_value,
+                                            gp.blank() | gp.show_type())
+            error_message += "\n"
+            error_message += gp.sprint_var(invalid_values, gp.show_type())
+        return process_error_message(error_message)
+
     found_error = 0
     display_var_value = list(var_value)
     for ix in range(0, len(var_value)):
         if var_value[ix] not in valid_values:
             found_error = 1
-            display_var_value[ix] = var_value[ix] + "*"
+            display_var_value[ix] = str(var_value[ix]) + "*"
 
     if found_error:
         var_name = get_var_name(*args, **kwargs)
@@ -470,7 +538,7 @@
         error_message += gp.sprint_varx(var_name, display_var_value,
                                         gp.blank() | gp.show_type())
         error_message += "\n"
-        error_message += gp.sprint_var(valid_values | gp.show_type())
+        error_message += gp.sprint_var(valid_values, gp.show_type())
         return process_error_message(error_message)
 
     return process_error_message(error_message)
@@ -496,7 +564,7 @@
         error_message += gp.sprint_varx(var_name, var_value,
                                         gp.blank() | gp.show_type())
         error_message += "\n"
-        error_message += gp.sprint_var(missing_keys | gp.show_type())
+        error_message += gp.sprint_var(missing_keys, gp.show_type())
     return process_error_message(error_message)