Changes to run_keyword:

- Allow multiple lib/resource paths separated by ":" for lib_file_path.
- Allow multiple keywords separated by " ; " for keyword_string.
- Add smarts to allow assignments (e.g. ${state}=  Get State).

Change-Id: Idf38edb18b6b0bec0e6cd53ebc0b420439931306
Signed-off-by: Michael Walsh <micwalsh@us.ibm.com>
diff --git a/extended/run_keyword.py b/extended/run_keyword.py
old mode 100755
new mode 100644
index 3f1a10b..38033c7
--- a/extended/run_keyword.py
+++ b/extended/run_keyword.py
@@ -4,11 +4,10 @@
 This module is the python counterpart to run_keyword.robot.
 """
 
-import gen_print as gp
 import gen_robot_print as grp
 import gen_robot_valid as grv
-
 from robot.libraries.BuiltIn import BuiltIn
+import re
 
 
 ###############################################################################
@@ -20,12 +19,34 @@
 
     setup()
 
-    keyword_string = BuiltIn().get_variable_value("${keyword_string}")
-    lib_file_path = BuiltIn().get_variable_value("${lib_file_path}")
+    # NOTE: During code review the following question was raised: Why support
+    # 1) variable assignments 2) multiple keywords?  Couldn't a user simply
+    # call this program twice to get what they need.  If necessary, the user
+    # could take the output of the first call and specify it as a literal on
+    # the second call.
+    #
+    # However, this approach would not work in all cases.  The following case
+    # would be such an example:
+    # Let's say the first keyword string is as follows:
+    # Create Dictionary  foo=bar
+    # You wish to take the output of that call and specify it as a literal
+    # value when running the following:
+    # Want Dictionary  parm=<literal dictionary specification>
+    # The problem is that there is no way to specify a dictionary as a
+    # literal in Robot Framework.
+    # By having this program support variable assignments and multiple
+    # keywords, the user can invoke it with the following keyword string.
+    # ${my_dict}=  Create Dictionary  foo=bar ; Want Dictionary  ${my_dict}
 
-    cmd_buf = keyword_string.split("  ")
+    # The user can pass multiple lib/resource paths by separating them with a
+    # colon.
 
-    if lib_file_path != "":
+    lib_file_path_list = \
+        BuiltIn().get_variable_value("${lib_file_path}").split(":")
+    # Get rid of empty entry if it exists.
+    if lib_file_path_list[0] == "":
+        del lib_file_path_list[0]
+    for lib_file_path in lib_file_path_list:
         # We don't want global variable getting changed when an import is done
         # so we'll save it and restore it.
         quiet = int(BuiltIn().get_variable_value("${quiet}"))
@@ -37,22 +58,33 @@
             BuiltIn().import_resource(lib_file_path)
         BuiltIn().set_global_variable("${quiet}", quiet)
 
-    error_message = grp.sprint_error_report("Keyword \"" + cmd_buf[0] +
-                                            "\" does not exist.\n")
-    BuiltIn().keyword_should_exist(cmd_buf[0], msg=error_message)
+    # The user can pass multiple keyword strings by separating them with " ; ".
+    keyword_list = \
+        BuiltIn().get_variable_value("${keyword_string}").split(" ; ")
+    for keyword_string in keyword_list:
+        cmd_buf = keyword_string.split("  ")
+        if re.match(r"\$\{", cmd_buf[0]):
+            # This looks like an assignment (e.g. ${var}=  <keyword>).
+            # We'll extract the variable name, remove element 0 from
+            # cmd_buf and set the global variable with the results
+            # after running the keyword.
+            var_name = cmd_buf[0].strip("${}=")
+            del cmd_buf[0]
+        else:
+            var_name = ""
 
-    grp.rqprint_issuing_keyword(cmd_buf)
-    status, output = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
-    if status != "PASS":
-        error_message = grp.sprint_error_report("\"" + cmd_buf[0] +
-                                                "\" failed with the" +
-                                                " following error:\n" + output)
-        if not quiet:
-            grp.rprint(error_message, 'STDERR')
-        BuiltIn().fail(error_message)
+        test_mode = int(BuiltIn().get_variable_value("${test_mode}"))
+        grp.rqprint_issuing_keyword(cmd_buf, test_mode)
+        if test_mode:
+            return
 
-    if output is not None:
-        grp.rprint(output)
+        output = BuiltIn().run_keyword(*cmd_buf)
+
+        if var_name != "":
+            BuiltIn().set_global_variable("${" + var_name + "}", output)
+        else:
+            if output is not None:
+                grp.rprint_var(output)
 
 ###############################################################################