blob: 20120ff2b2849a1d279cd0d88d7c6f36e387abd7 [file] [log] [blame]
Michael Walshde791732016-09-06 14:25:24 -05001#!/usr/bin/env python
2
3r"""
4This file contains functions useful for printing to stdout from robot programs.
5"""
6
7import sys
8import re
Michael Walsh18176322016-11-15 15:11:21 -06009import os
Michael Walsh7423c012016-10-04 10:27:21 -050010
Michael Walsha6723f22016-11-22 11:12:01 -060011try:
12 from robot.utils import DotDict as my_ord_dict
13except ImportError:
14 from collections import OrderedDict as my_ord_dict
15
Michael Walshde791732016-09-06 14:25:24 -050016import gen_print as gp
Michael Walsh7423c012016-10-04 10:27:21 -050017
Michael Walshde791732016-09-06 14:25:24 -050018from robot.libraries.BuiltIn import BuiltIn
19from robot.api import logger
20
Michael Walsh18176322016-11-15 15:11:21 -060021try:
22 # The user can set environment variable "GEN_ROBOT_PRINT_DEBUG" to get
23 # debug output from this module.
Michael Walsha6723f22016-11-22 11:12:01 -060024 gen_robot_print_debug = int(os.environ['GEN_ROBOT_PRINT_DEBUG'])
Michael Walsh18176322016-11-15 15:11:21 -060025except KeyError:
26 gen_robot_print_debug = 0
27
28
Michael Walshde791732016-09-06 14:25:24 -050029###############################################################################
Michael Walsh0fa47622017-02-20 16:11:34 -060030def get_quiet_default(var_value,
31 default=0):
32
33 r"""
34 If var_value is not None, return it. Otherwise, return the global
35 variable of the same name, if it exists. If not, return default.
36
37 This is meant for use by functions needing help assigning dynamic default
38 values to their parameters. Example:
39
40 def func1(parm1=None):
41
42 parm1 = global_default(parm1, 0)
43
44 Description of arguments:
45 var_value The value being evaluated.
46 default The value to be returned if var_value is
47 None AND the global
48 variable of the same name does not exist.
49 """
50
51 var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
52
53 return dft(var_value, get_mod_global(var_name, 0))
54
55###############################################################################
56
57
58###############################################################################
Michael Walsh18176322016-11-15 15:11:21 -060059def set_quiet_default(quiet=None,
60 default=0):
Michael Walshde791732016-09-06 14:25:24 -050061
Michael Walsh18176322016-11-15 15:11:21 -060062 r"""
63 Return a default value for the quiet variable based on its current value,
64 the value of global ${QUIET} and default.
Michael Walshde791732016-09-06 14:25:24 -050065
Michael Walsh18176322016-11-15 15:11:21 -060066 Description of Arguments:
67 quiet If this is set already, no default value
68 is chosen. Otherwise, it will be set to
69 either the global ${QUIET} robot variable
70 or to default (below).
71 default The default value to be used if global
72 ${QUIET} does not exist.
73 """
Michael Walshde791732016-09-06 14:25:24 -050074
Michael Walsh18176322016-11-15 15:11:21 -060075 if quiet is None:
76 # Set default quiet value.
77 try:
78 quiet = int(BuiltIn().get_variable_value("${quiet}"))
79 except TypeError:
80 quiet = int(default)
81 quiet = int(quiet)
Michael Walshde791732016-09-06 14:25:24 -050082
Michael Walsh18176322016-11-15 15:11:21 -060083 return quiet
Michael Walshde791732016-09-06 14:25:24 -050084
85###############################################################################
86
87
88###############################################################################
Michael Walshafa7a1b2016-12-09 14:02:48 -060089def get_quiet(default=1):
90
91 r"""
92 Get the value of robot variable "quiet" and return it. If "quiet" is not
93 defined, the "default" value is returned.
94
95 Description of arguments:
96 default The value that is returned if robot
97 variable "quiet" is not defined.
98 """
99
100 try:
101 quiet = int(BuiltIn().get_variable_value("${quiet}"))
102 except TypeError:
103 quiet = default
104
105 return quiet
106
107###############################################################################
108
109
110###############################################################################
111def get_debug(default=0):
112
113 r"""
114 Get the value of robot variable "debug" and return it. If "debug" is not
115 defined, the "default" value is returned.
116
117 Description of arguments:
118 default The value that is returned if robot
119 variable "debug" is not defined.
120 """
121
122 try:
123 debug = int(BuiltIn().get_variable_value("${debug}"))
124 except TypeError:
125 debug = default
126
127 return debug
128
129###############################################################################
130
131
132###############################################################################
Michael Walsh7423c012016-10-04 10:27:21 -0500133def rprint(buffer="",
134 stream="STDOUT"):
Michael Walshde791732016-09-06 14:25:24 -0500135
136 r"""
137 rprint stands for "Robot Print". This keyword will print the user's
138 buffer to the console. This keyword does not write a linefeed. It is the
139 responsibility of the caller to include a line feed if desired. This
Michael Walsh18176322016-11-15 15:11:21 -0600140 keyword is essentially an alias for "Log to Console <string> <stream>".
Michael Walshde791732016-09-06 14:25:24 -0500141
142 Description of arguments:
143 buffer The value that is to written to stdout.
144 """
145
Michael Walsh82acf002017-05-04 14:33:05 -0500146 BuiltIn().log_to_console(gp.replace_passwords(str(buffer)),
147 no_newline=True, stream=stream)
Michael Walshde791732016-09-06 14:25:24 -0500148
149###############################################################################
150
151
152###############################################################################
Michael Walsh7423c012016-10-04 10:27:21 -0500153def rprintn(buffer="",
154 stream='STDOUT'):
Michael Walshde791732016-09-06 14:25:24 -0500155
156 r"""
157 rprintn stands for "Robot print with linefeed". This keyword will print
158 the user's buffer to the console along with a linefeed. It is basically
Michael Walsh7423c012016-10-04 10:27:21 -0500159 an abbreviated form of "Log go Console <string> <stream>"
Michael Walshde791732016-09-06 14:25:24 -0500160
161 Description of arguments:
162 buffer The value that is to written to stdout.
163 """
164
Michael Walsh82acf002017-05-04 14:33:05 -0500165 BuiltIn().log_to_console(gp.replace_passwords(buffer), no_newline=False,
166 stream=stream)
Michael Walshde791732016-09-06 14:25:24 -0500167
168###############################################################################
169
170
171###############################################################################
Michael Walsh18176322016-11-15 15:11:21 -0600172def sprint_vars(*args):
Michael Walshde791732016-09-06 14:25:24 -0500173
174 r"""
Michael Walsh18176322016-11-15 15:11:21 -0600175 sprint_vars stands for "String Print Vars". This is a robot redefinition
176 of the sprint_vars function in gen_print.py. Given a list of variable
177 names, this keyword will string print each variable name and value such
178 that the value lines up in the same column as messages printed with rptime.
179
180 Description of arguments:
181 args:
182 If the first argument is an integer, it will be interpreted to be the
Michael Walsh18176322016-11-15 15:11:21 -0600183 "hex" value.
Michael Walshc4da0cb2017-01-10 11:31:05 -0600184 If the second argument is an integer, it will be interpreted to be the
185 "indent" value.
186 If the third argument is an integer, it will be interpreted to be the
187 "col1_width" value.
Michael Walsh18176322016-11-15 15:11:21 -0600188 All remaining parms are considered variable names which are to be
189 sprinted.
190 """
191
192 if len(args) == 0:
193 return
194
195 # Create list from args (which is a tuple) so that it can be modified.
196 args_list = list(args)
197
Michael Walshc4da0cb2017-01-10 11:31:05 -0600198 # See if parm 1 is to be interpreted as "hex".
199 try:
200 if type(int(args_list[0])) is int:
201 hex = int(args_list[0])
202 args_list.pop(0)
203 except ValueError:
204 hex = 0
205
206 # See if parm 2 is to be interpreted as "indent".
Michael Walsh18176322016-11-15 15:11:21 -0600207 try:
208 if type(int(args_list[0])) is int:
209 indent = int(args_list[0])
210 args_list.pop(0)
211 except ValueError:
212 indent = 0
213
Michael Walshc4da0cb2017-01-10 11:31:05 -0600214 # See if parm 3 is to be interpreted as "col1_width".
Michael Walsh18176322016-11-15 15:11:21 -0600215 try:
216 if type(int(args_list[0])) is int:
217 loc_col1_width = int(args_list[0])
218 args_list.pop(0)
219 except ValueError:
220 loc_col1_width = gp.col1_width
221
Michael Walsh18176322016-11-15 15:11:21 -0600222 buffer = ""
223 for var_name in args_list:
Michael Walsh0fa47622017-02-20 16:11:34 -0600224 var_value = BuiltIn().get_variable_value("${" + str(var_name) + "}")
Michael Walsh18176322016-11-15 15:11:21 -0600225 buffer += gp.sprint_varx(var_name, var_value, hex, indent,
226 loc_col1_width)
227
228 return buffer
229
230###############################################################################
231
232
233###############################################################################
234def sprint_pgm_header(indent=0):
235
236 r"""
237 Sprint a standardized header that robot programs should print at the
238 beginning of the run. The header includes useful information like command
239 line, pid, userid, program parameters, etc. Callers need to have declared
240 a global @{parm_list} variable which contains the names of all program
241 parameters.
242 """
243
Michael Walshdb6e68a2017-05-23 17:55:31 -0500244 # This function is deprecated since the caller may now call the gen_print
245 # version directly.
246 return gp.sprint_pgm_header(indent, linefeed=1)
Michael Walsh18176322016-11-15 15:11:21 -0600247
248###############################################################################
249
250
251###############################################################################
252def sprint_error_report(error_text="\n"):
253
254 r"""
255 Print a standardized error report that robot programs should print on
256 failure. The report includes useful information like error text, command
257 line, pid, userid, program parameters, etc. Callers must have declared a
258 @{parm_list} variable which contains the names of all program parameters.
259 """
260
Michael Walshdb6e68a2017-05-23 17:55:31 -0500261 # This function is deprecated. The caller is advised to call the
262 # gen_print version of this function directly.
Michael Walshafa7a1b2016-12-09 14:02:48 -0600263
Michael Walshdb6e68a2017-05-23 17:55:31 -0500264 return gp.sprint_error_report(error_text)
Michael Walsh18176322016-11-15 15:11:21 -0600265
266###############################################################################
267
268
269###############################################################################
270def sprint_issuing_keyword(cmd_buf,
271 test_mode=0):
272
273 r"""
274 Return a line indicating a robot command (i.e. keyword + args) that the
275 program is about to execute.
276
277 For example, for the following robot code...
278
279 @{cmd_buf}= Set Variable Set Environment Variable VAR1 1
280 rdprint_issuing_keyword
281
282 The output would look something like this:
283
284 #(CDT) 2016/10/27 12:04:21 - Issuing: Set Environment Variable VAR1 1
285
286 Description of args:
287 cmd_buf A list containing the keyword and
288 arguments to be run.
289 """
290
291 buffer = ""
292 cmd_buf_str = ' '.join([str(element) for element in cmd_buf])
293 buffer += gp.sprint_issuing(cmd_buf_str, int(test_mode))
294
295 return buffer
296
297###############################################################################
298
299
300###############################################################################
301def sprint_auto_vars(headers=0):
302
303 r"""
304 This keyword will string print all of the Automatic Variables described in
305 the Robot User's Guide using rprint_vars.
Michael Walshde791732016-09-06 14:25:24 -0500306
307 NOTE: Not all automatic variables are guaranteed to exist.
308
309 Description of arguments:
310 headers This indicates that a header and footer
Michael Walsh18176322016-11-15 15:11:21 -0600311 should be printed.
Michael Walshde791732016-09-06 14:25:24 -0500312 """
313
Michael Walsh18176322016-11-15 15:11:21 -0600314 buffer = ""
Michael Walshde791732016-09-06 14:25:24 -0500315 if int(headers) == 1:
Michael Walsh18176322016-11-15 15:11:21 -0600316 buffer += gp.sprint_dashes()
317 buffer += "Automatic Variables:"
Michael Walshde791732016-09-06 14:25:24 -0500318
Michael Walsh18176322016-11-15 15:11:21 -0600319 buffer += \
320 sprint_vars(
321 "TEST_NAME", "TEST_TAGS", "TEST_DOCUMENTATION", "TEST_STATUS",
322 "TEST_DOCUMENTATION", "TEST_STATUS", "TEST_MESSAGE",
323 "PREV_TEST_NAME", "PREV_TEST_STATUS", "PREV_TEST_MESSAGE",
324 "SUITE_NAME", "SUITE_SOURCE", "SUITE_DOCUMENTATION",
325 "SUITE_METADATA", "SUITE_STATUS", "SUITE_MESSAGE",
326 "KEYWORD_STATUS", "KEYWORD_MESSAGE", "LOG_LEVEL", "OUTPUT_FILE",
327 "LOG_FILE", "REPORT_FILE", "DEBUG_FILE", "OUTPUT_DIR")
Michael Walshde791732016-09-06 14:25:24 -0500328
329 if int(headers) == 1:
Michael Walsh18176322016-11-15 15:11:21 -0600330 buffer += gp.sprint_dashes()
331
332 return buffer
Michael Walshde791732016-09-06 14:25:24 -0500333
334###############################################################################
335
336
337###############################################################################
Michael Walsh18176322016-11-15 15:11:21 -0600338# In the following section of code, we will dynamically create robot versions
339# of print functions for each of the sprint functions defined in the
340# gen_print.py module. So, for example, where we have an sprint_time()
341# function defined above that returns the time to the caller in a string, we
342# will create a corresponding rprint_time() function that will print that
343# string directly to stdout.
Michael Walshde791732016-09-06 14:25:24 -0500344
Michael Walsh18176322016-11-15 15:11:21 -0600345# It can be complicated to follow what's being created by the exec statement
346# below. Here is an example of the rprint_time() function that will be
347# created (as of the time of this writing):
Michael Walshde791732016-09-06 14:25:24 -0500348
Michael Walsh18176322016-11-15 15:11:21 -0600349# def rprint_time(*args):
350# s_func = getattr(gp, "sprint_time")
351# BuiltIn().log_to_console(s_func(*args),
352# stream='STDIN',
353# no_newline=True)
Michael Walshde791732016-09-06 14:25:24 -0500354
Michael Walsh18176322016-11-15 15:11:21 -0600355# Here are comments describing the lines in the body of the created function.
356# Put a reference to the "s" version of this function in s_func.
357# Call the "s" version of this function passing it all of our arguments. Log
358# the result to the console.
Michael Walshde791732016-09-06 14:25:24 -0500359
Michael Walsh18176322016-11-15 15:11:21 -0600360robot_prefix = "r"
361robot_func_names =\
362 [
363 'print_error_report', 'print_pgm_header',
364 'print_issuing_keyword', 'print_vars', 'print_auto_vars'
365 ]
366func_names = gp.func_names + robot_func_names
Michael Walsha6723f22016-11-22 11:12:01 -0600367
Michael Walshafa7a1b2016-12-09 14:02:48 -0600368explicit_definitions = ['print', 'printn']
369
Michael Walsha6723f22016-11-22 11:12:01 -0600370func_names = list(my_ord_dict.fromkeys(func_names))
371
372if gen_robot_print_debug:
373 rprintn()
374 BuiltIn().log_to_console(gp.sprint_var(func_names), no_newline=True)
375 rprintn()
376
Michael Walsh18176322016-11-15 15:11:21 -0600377for func_name in func_names:
Michael Walshde791732016-09-06 14:25:24 -0500378
Michael Walshafa7a1b2016-12-09 14:02:48 -0600379 if func_name not in explicit_definitions:
380 # The print_var function's job is to figure out the name of arg 1 and
381 # then call print_varx. This is not currently supported for robot
382 # programs. Though it IS supported for python modules.
383 if func_name == "print_error" or func_name == "print_error_report":
384 output_stream = "STDERR"
385 else:
386 output_stream = "STDIN"
387 if func_name in robot_func_names:
388 object_name = "__import__(__name__)"
389 else:
390 object_name = "gp"
391 func_def = \
392 [
393 "def " + robot_prefix + func_name + "(*args):",
394 " s_func = getattr(" + object_name + ", \"s" + func_name +
395 "\")",
Michael Walsh82acf002017-05-04 14:33:05 -0500396 " BuiltIn().log_to_console" +
397 "(gp.replace_passwords(s_func(*args)),"
Michael Walshafa7a1b2016-12-09 14:02:48 -0600398 " stream='" + output_stream + "',"
399 " no_newline=True)"
400 ]
401
402 pgm_definition_string = '\n'.join(func_def)
403 if gen_robot_print_debug:
404 rprintn()
405 rprintn(pgm_definition_string)
406 exec(pgm_definition_string)
Michael Walsh18176322016-11-15 15:11:21 -0600407
408 # Now define "q" versions of each print function. The q functions only
409 # print if global robot var "quiet" is 0. If the global var quiet is not
410 # defined, it will be treated as though it were "1", i.e. no printing will
411 # be done.
412 func_def = \
413 [
414 "def rq" + func_name + "(*args):",
Michael Walshafa7a1b2016-12-09 14:02:48 -0600415 " if get_quiet():",
416 " return",
417 " r" + func_name + "(*args)"
Michael Walsh18176322016-11-15 15:11:21 -0600418 ]
419
420 pgm_definition_string = '\n'.join(func_def)
421 if gen_robot_print_debug:
422 rprintn(pgm_definition_string)
423 exec(pgm_definition_string)
424
425 # Now define "d" versions of each print function. The d functions only
426 # print if global robot var "debug" is 1.
427 func_def = \
428 [
429 "def rd" + func_name + "(*args):",
Michael Walshafa7a1b2016-12-09 14:02:48 -0600430 " if not get_debug():",
431 " return",
432 " r" + func_name + "(*args)"
Michael Walsh18176322016-11-15 15:11:21 -0600433 ]
434
435 pgm_definition_string = '\n'.join(func_def)
436 if gen_robot_print_debug:
437 rprintn(pgm_definition_string)
438 exec(pgm_definition_string)
439
Michael Walshafa7a1b2016-12-09 14:02:48 -0600440 # Create shorter aliases.
Michael Walsha6723f22016-11-22 11:12:01 -0600441 prefixes = ["", "q", "d"]
Michael Walsh18176322016-11-15 15:11:21 -0600442 alias = re.sub("print_", "p", func_name)
Michael Walsha6723f22016-11-22 11:12:01 -0600443 for prefix2 in prefixes:
444 cmd_buf = robot_prefix + prefix2 + alias + " = " + robot_prefix +\
445 prefix2 + func_name
446 if gen_robot_print_debug:
447 rprintn(cmd_buf)
448 exec(cmd_buf)
Michael Walsh18176322016-11-15 15:11:21 -0600449
450# Define an alias. rpvar is just a special case of rpvars where the args
451# list contains only one element.
452cmd_buf = "rpvar = rpvars"
453if gen_robot_print_debug:
Michael Walsha6723f22016-11-22 11:12:01 -0600454 rprintn()
Michael Walsh18176322016-11-15 15:11:21 -0600455 rprintn(cmd_buf)
456exec(cmd_buf)
Michael Walshde791732016-09-06 14:25:24 -0500457
458###############################################################################