|  | #!/usr/bin/env python | 
|  |  | 
|  | r""" | 
|  | 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 | 
|  |  | 
|  | 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 get_quiet_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 parameters.  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 set_quiet_default(quiet=None, | 
|  | default=0): | 
|  |  | 
|  | r""" | 
|  | Return a default value for the quiet variable based on its current value, | 
|  | the value of global ${QUIET} and default. | 
|  |  | 
|  | Description of Arguments: | 
|  | quiet                           If this is set already, no default value | 
|  | is chosen.  Otherwise, it will be set to | 
|  | either the global ${QUIET} robot variable | 
|  | or to default (below). | 
|  | default                         The default value to be used if global | 
|  | ${QUIET} does not exist. | 
|  | """ | 
|  |  | 
|  | if quiet is None: | 
|  | # Set default quiet value. | 
|  | try: | 
|  | quiet = int(BuiltIn().get_variable_value("${quiet}")) | 
|  | except TypeError: | 
|  | quiet = int(default) | 
|  | quiet = int(quiet) | 
|  |  | 
|  | return quiet | 
|  |  | 
|  | ############################################################################### | 
|  |  | 
|  |  | 
|  | ############################################################################### | 
|  | def get_quiet(default=1): | 
|  |  | 
|  | r""" | 
|  | Get the value of robot variable "quiet" and return it.  If "quiet" is not | 
|  | defined, the "default" value is returned. | 
|  |  | 
|  | Description of arguments: | 
|  | default                         The value that is returned if robot | 
|  | variable "quiet" is not defined. | 
|  | """ | 
|  |  | 
|  | try: | 
|  | quiet = int(BuiltIn().get_variable_value("${quiet}")) | 
|  | except TypeError: | 
|  | quiet = default | 
|  |  | 
|  | return quiet | 
|  |  | 
|  | ############################################################################### | 
|  |  | 
|  |  | 
|  | ############################################################################### | 
|  | def get_debug(default=0): | 
|  |  | 
|  | r""" | 
|  | Get the value of robot variable "debug" and return it.  If "debug" is not | 
|  | defined, the "default" value is returned. | 
|  |  | 
|  | Description of arguments: | 
|  | default                         The value that is returned if robot | 
|  | variable "debug" is not defined. | 
|  | """ | 
|  |  | 
|  | try: | 
|  | debug = int(BuiltIn().get_variable_value("${debug}")) | 
|  | except TypeError: | 
|  | debug = default | 
|  |  | 
|  | return debug | 
|  |  | 
|  | ############################################################################### | 
|  |  | 
|  |  | 
|  | ############################################################################### | 
|  | 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) | 
|  |  | 
|  | ############################################################################### | 
|  |  | 
|  |  | 
|  | ############################################################################### | 
|  | 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. | 
|  |  | 
|  | Description of arguments: | 
|  | args: | 
|  | If the first argument is an integer, it will be interpreted to be the | 
|  | "hex" value. | 
|  | If the second argument is an integer, it will be interpreted to be the | 
|  | "indent" value. | 
|  | If the third argument is an integer, it will be interpreted to be the | 
|  | "col1_width" value. | 
|  | All remaining parms are considered variable names which are to be | 
|  | sprinted. | 
|  | """ | 
|  |  | 
|  | if len(args) == 0: | 
|  | return | 
|  |  | 
|  | # Create list from args (which is a tuple) so that it can be modified. | 
|  | args_list = list(args) | 
|  |  | 
|  | # See if parm 1 is to be interpreted as "hex". | 
|  | try: | 
|  | if type(int(args_list[0])) is int: | 
|  | hex = int(args_list[0]) | 
|  | args_list.pop(0) | 
|  | except ValueError: | 
|  | hex = 0 | 
|  |  | 
|  | # See if parm 2 is to be interpreted as "indent". | 
|  | try: | 
|  | if type(int(args_list[0])) is int: | 
|  | indent = int(args_list[0]) | 
|  | args_list.pop(0) | 
|  | except ValueError: | 
|  | indent = 0 | 
|  |  | 
|  | # See if parm 3 is to be interpreted as "col1_width". | 
|  | try: | 
|  | if type(int(args_list[0])) is int: | 
|  | loc_col1_width = int(args_list[0]) | 
|  | args_list.pop(0) | 
|  | except ValueError: | 
|  | loc_col1_width = gp.col1_width | 
|  |  | 
|  | buffer = "" | 
|  | for var_name in args_list: | 
|  | var_value = BuiltIn().get_variable_value("${" + str(var_name) + "}") | 
|  | buffer += gp.sprint_varx(var_name, var_value, hex, indent, | 
|  | loc_col1_width) | 
|  |  | 
|  | 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. | 
|  |  | 
|  | NOTE: Not all automatic variables are guaranteed to exist. | 
|  |  | 
|  | Description of arguments: | 
|  | headers                         This indicates that a header and footer | 
|  | should be printed. | 
|  | """ | 
|  |  | 
|  | buffer = "" | 
|  | if int(headers) == 1: | 
|  | buffer += gp.sprint_dashes() | 
|  | buffer += "Automatic Variables:" | 
|  |  | 
|  | buffer += \ | 
|  | sprint_vars( | 
|  | "TEST_NAME", "TEST_TAGS", "TEST_DOCUMENTATION", "TEST_STATUS", | 
|  | "TEST_DOCUMENTATION", "TEST_STATUS", "TEST_MESSAGE", | 
|  | "PREV_TEST_NAME", "PREV_TEST_STATUS", "PREV_TEST_MESSAGE", | 
|  | "SUITE_NAME", "SUITE_SOURCE", "SUITE_DOCUMENTATION", | 
|  | "SUITE_METADATA", "SUITE_STATUS", "SUITE_MESSAGE", | 
|  | "KEYWORD_STATUS", "KEYWORD_MESSAGE", "LOG_LEVEL", "OUTPUT_FILE", | 
|  | "LOG_FILE", "REPORT_FILE", "DEBUG_FILE", "OUTPUT_DIR") | 
|  |  | 
|  | if int(headers) == 1: | 
|  | buffer += gp.sprint_dashes() | 
|  |  | 
|  | 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. | 
|  |  | 
|  | # 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): | 
|  |  | 
|  | # def rprint_time(*args): | 
|  | #   s_func = getattr(gp, "sprint_time") | 
|  | #   BuiltIn().log_to_console(s_func(*args), | 
|  | #                            stream='STDIN', | 
|  | #                            no_newline=True) | 
|  |  | 
|  | # 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. | 
|  |  | 
|  | 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 | 
|  |  | 
|  | explicit_definitions = ['print', 'printn'] | 
|  |  | 
|  | func_names = list(my_ord_dict.fromkeys(func_names)) | 
|  |  | 
|  | if gen_robot_print_debug: | 
|  | rprintn() | 
|  | BuiltIn().log_to_console(gp.sprint_var(func_names), no_newline=True) | 
|  | rprintn() | 
|  |  | 
|  | for func_name in func_names: | 
|  |  | 
|  | 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)" | 
|  | ] | 
|  |  | 
|  | pgm_definition_string = '\n'.join(func_def) | 
|  | if gen_robot_print_debug: | 
|  | rprintn() | 
|  | rprintn(pgm_definition_string) | 
|  | exec(pgm_definition_string) | 
|  |  | 
|  | # 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 get_quiet():", | 
|  | "        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) | 
|  |  | 
|  | # 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 get_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) | 
|  |  | 
|  | # 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) | 
|  | exec(cmd_buf) | 
|  |  | 
|  | ############################################################################### |