Re-factoring of gen_robot_print

- Removed superflous functions (e.g. rprintn) for which gen_print.py functions
  can be substituted.
- Improved doc strings
- Made use of gp.create_print_wrapper_funcs to create dynamic functions.

Change-Id: Iade8a0fca619bf45da1a5dfaeab0d152c0b0d567
Signed-off-by: Michael Walsh <micwalsh@us.ibm.com>
diff --git a/lib/gen_robot_print.py b/lib/gen_robot_print.py
index 4430865..d6c9506 100755
--- a/lib/gen_robot_print.py
+++ b/lib/gen_robot_print.py
@@ -4,65 +4,25 @@
 This file contains functions useful for printing to stdout from robot programs.
 """
 
-import sys
 import re
 import os
 
-try:
-    from robot.utils import DotDict as my_ord_dict
-except ImportError:
-    from collections import OrderedDict as my_ord_dict
-
 import gen_print as gp
+import wrap_utils as wu
 
 from robot.libraries.BuiltIn import BuiltIn
-from robot.api import logger
 
-try:
-    # The user can set environment variable "GEN_ROBOT_PRINT_DEBUG" to get
-    # debug output from this module.
-    gen_robot_print_debug = int(os.environ['GEN_ROBOT_PRINT_DEBUG'])
-except KeyError:
-    gen_robot_print_debug = 0
-
-
-def rprint(buffer="",
-           stream="STDOUT"):
-    r"""
-    rprint stands for "Robot Print".  This keyword will print the user's
-    buffer to the console.  This keyword does not write a linefeed.  It is the
-    responsibility of the caller to include a line feed if desired.  This
-    keyword is essentially an alias for "Log to Console  <string>  <stream>".
-
-    Description of arguments:
-    buffer                          The value that is to written to stdout.
-    """
-
-    BuiltIn().log_to_console(gp.replace_passwords(str(buffer)),
-                             no_newline=True, stream=stream)
-
-
-def rprintn(buffer="",
-            stream='STDOUT'):
-    r"""
-    rprintn stands for "Robot print with linefeed".  This keyword will print
-    the user's buffer to the console along with a linefeed.  It is basically
-    an abbreviated form of "Log go Console  <string>  <stream>"
-
-    Description of arguments:
-    buffer                          The value that is to written to stdout.
-    """
-
-    BuiltIn().log_to_console(gp.replace_passwords(buffer), no_newline=False,
-                             stream=stream)
+gen_robot_print_debug = int(os.environ.get('GEN_ROBOT_PRINT_DEBUG', '0'))
 
 
 def sprint_vars(*args):
     r"""
-    sprint_vars stands for "String Print Vars".  This is a robot redefinition
-    of the sprint_vars function in gen_print.py.  Given a list of variable
-    names, this keyword will string print each variable name and value such
-    that the value lines up in the same column as messages printed with rptime.
+    Sprint the values of one or more variables to the console.
+
+    This is a robot re=definition of the sprint_vars function in gen_print.py.
+    Given a list of variable names, this keyword will string print each
+    variable name and value such that each value lines up in the same column
+    as messages printed with sprint_time().
 
     Description of arguments:
     args:
@@ -115,65 +75,10 @@
     return buffer
 
 
-def sprint_pgm_header(indent=0):
-    r"""
-    Sprint a standardized header that robot programs should print at the
-    beginning of the run.  The header includes useful information like command
-    line, pid, userid, program parameters, etc.  Callers need to have declared
-    a global @{parm_list} variable which contains the names of all program
-    parameters.
-    """
-
-    # This function is deprecated since the caller may now call the gen_print
-    # version directly.
-    return gp.sprint_pgm_header(indent, linefeed=1)
-
-
-def sprint_error_report(error_text="\n"):
-    r"""
-    Print a standardized error report that robot programs should print on
-    failure.  The report includes useful information like error text, command
-    line, pid, userid, program parameters, etc.  Callers must have declared a
-    @{parm_list} variable which contains the names of all program parameters.
-    """
-
-    # This function is deprecated.  The caller is advised to call the
-    # gen_print version of this function directly.
-
-    return gp.sprint_error_report(error_text)
-
-
-def sprint_issuing_keyword(cmd_buf,
-                           test_mode=0):
-    r"""
-    Return a line indicating a robot command (i.e. keyword + args) that the
-    program is about to execute.
-
-    For example, for the following robot code...
-
-    @{cmd_buf}=  Set Variable  Set Environment Variable  VAR1  1
-    rdprint_issuing_keyword
-
-    The output would look something like this:
-
-    #(CDT) 2016/10/27 12:04:21 - Issuing: Set Environment Variable  VAR1  1
-
-    Description of args:
-    cmd_buf                         A list containing the keyword and
-                                    arguments to be run.
-    """
-
-    buffer = ""
-    cmd_buf_str = '  '.join([str(element) for element in cmd_buf])
-    buffer += gp.sprint_issuing(cmd_buf_str, int(test_mode))
-
-    return buffer
-
-
 def sprint_auto_vars(headers=0):
     r"""
-    This keyword will string print all of the Automatic Variables described in
-    the Robot User's Guide using rprint_vars.
+    String print all of the Automatic Variables described in the Robot User's
+    Guide using sprint_vars.
 
     NOTE: Not all automatic variables are guaranteed to exist.
 
@@ -203,120 +108,55 @@
     return buffer
 
 
-# In the following section of code, we will dynamically create robot versions
-# of print functions for each of the sprint functions defined in the
-# gen_print.py module.  So, for example, where we have an sprint_time()
-# function defined above that returns the time to the caller in a string, we
-# will create a corresponding rprint_time() function that will print that
-# string directly to stdout.
+def gp_debug_print(buffer):
+    r"""
+    Print the buffer value only if gen_print_debug is set.
 
-# It can be complicated to follow what's being created by the exec statement
-# below.  Here is an example of the rprint_time() function that will be
-# created (as of the time of this writing):
+    This function is intended for use only by other functions in this module.
 
-# def rprint_time(*args):
-#   s_func = getattr(gp, "sprint_time")
-#   BuiltIn().log_to_console(s_func(*args),
-#                            stream='STDIN',
-#                            no_newline=True)
+    Description of arguments:
+    buffer                          The string to be printed.
+    """
 
-# Here are comments describing the lines in the body of the created function.
-# Put a reference to the "s" version of this function in s_func.
-# Call the "s" version of this function passing it all of our arguments.  Log
-# the result to the console.
+    if not gen_robot_print_debug:
+        return
 
-robot_prefix = "r"
-robot_func_names =\
-    [
-        'print_error_report', 'print_pgm_header',
-        'print_issuing_keyword', 'print_vars', 'print_auto_vars'
-    ]
-func_names = gp.func_names + robot_func_names
+    gp.gp_print(buffer)
 
-explicit_definitions = ['print', 'printn']
 
-func_names = list(my_ord_dict.fromkeys(func_names))
+# In the following section of code, we will dynamically create print versions
+# for several of the sprint functions defined above.  So, for example, where
+# we have an sprint_vars() function defined above that returns formatted
+# variable print outs in a string, we will create a corresponding print_vars()
+# function that will print that string directly to stdout.
 
-if gen_robot_print_debug:
-    rprintn()
-    BuiltIn().log_to_console(gp.sprint_var(func_names), no_newline=True)
-    rprintn()
+# It can be complicated to follow what's being created below.  Here is an
+# example of the rprint_vars() function that will be created:
 
-for func_name in func_names:
+# def rprint_vars(*args):
+#     gp.gp_print(gp.replace_passwords(sprint_vars(*args)), stream='stdout')
 
-    if func_name not in explicit_definitions:
-        # The print_var function's job is to figure out the name of arg 1 and
-        # then call print_varx.  This is not currently supported for robot
-        # programs.  Though it IS supported for python modules.
-        if func_name == "print_error" or func_name == "print_error_report":
-            output_stream = "STDERR"
-        else:
-            output_stream = "STDIN"
-        if func_name in robot_func_names:
-            object_name = "__import__(__name__)"
-        else:
-            object_name = "gp"
-        func_def = \
-            [
-                "def " + robot_prefix + func_name + "(*args):",
-                "    s_func = getattr(" + object_name + ", \"s" + func_name
-                + "\")",
-                "    BuiltIn().log_to_console"
-                + "(gp.replace_passwords(s_func(*args)),"
-                " stream='" + output_stream + "',"
-                " no_newline=True)"
-            ]
+replace_dict = {'output_stream': 'stdout', 'mod_qualifier': 'gp.'}
 
-        pgm_definition_string = '\n'.join(func_def)
-        if gen_robot_print_debug:
-            rprintn()
-            rprintn(pgm_definition_string)
-        exec(pgm_definition_string)
+gp_debug_print("gp.robot_env: " + str(gp.robot_env) + "\n")
 
-    # Now define "q" versions of each print function.  The q functions only
-    # print if global robot var "quiet" is 0.  If the global var quiet is not
-    # defined, it will be treated as though it were "1", i.e. no printing will
-    # be done.
-    func_def = \
-        [
-            "def rq" + func_name + "(*args):",
-            "    if int(gp.get_var_value(None, 0, \"quiet\")): return",
-            "    r" + func_name + "(*args)"
-        ]
+# func_names contains a list of all print functions which should be created
+# from their sprint counterparts.
+func_names = [
+    'print_vars', 'print_auto_vars'
+]
 
-    pgm_definition_string = '\n'.join(func_def)
-    if gen_robot_print_debug:
-        rprintn(pgm_definition_string)
-    exec(pgm_definition_string)
+# stderr_func_names is a list of functions whose output should go to stderr
+# rather than stdout.
+stderr_func_names = []
 
-    # Now define "d" versions of each print function.  The d functions only
-    # print if global robot var "debug" is 1.
-    func_def = \
-        [
-            "def rd" + func_name + "(*args):",
-            "    if not int(gp.get_var_value(None, 0, \"debug\")): return",
-            "    r" + func_name + "(*args)"
-        ]
-
-    pgm_definition_string = '\n'.join(func_def)
-    if gen_robot_print_debug:
-        rprintn(pgm_definition_string)
-    exec(pgm_definition_string)
-
-    # Create shorter aliases.
-    prefixes = ["", "q", "d"]
-    alias = re.sub("print_", "p", func_name)
-    for prefix2 in prefixes:
-        cmd_buf = robot_prefix + prefix2 + alias + " = " + robot_prefix +\
-            prefix2 + func_name
-        if gen_robot_print_debug:
-            rprintn(cmd_buf)
-        exec(cmd_buf)
+func_defs = gp.create_print_wrapper_funcs(func_names, stderr_func_names,
+                                          replace_dict, "r")
+gp_debug_print(func_defs)
+exec(func_defs)
 
 # Define an alias.  rpvar is just a special case of rpvars where the args
 # list contains only one element.
 cmd_buf = "rpvar = rpvars"
-if gen_robot_print_debug:
-    rprintn()
-    rprintn(cmd_buf)
+gp_debug_print("\n" + cmd_buf + "\n")
 exec(cmd_buf)