blob: e08c4e75ba36ff458f90c906cab51627ab652b38 [file] [log] [blame]
Michael Walshde791732016-09-06 14:25:24 -05001#!/usr/bin/env python
2
3r"""
4This module provides many valuable print functions such as sprint_var,
5sprint_time, sprint_error, sprint_call_stack.
6"""
7
8import sys
9import os
10import time
11import inspect
12import re
13import grp
14import socket
15import argparse
Michael Walsh7423c012016-10-04 10:27:21 -050016import __builtin__
17import logging
Michael Walshbec416d2016-11-10 08:54:52 -060018import collections
19
Michael Walshbec416d2016-11-10 08:54:52 -060020try:
21 from robot.utils import DotDict
22except ImportError:
Michael Walsha6723f22016-11-22 11:12:01 -060023 pass
Michael Walsh7423c012016-10-04 10:27:21 -050024
25import gen_arg as ga
Michael Walshde791732016-09-06 14:25:24 -050026
27# Setting these variables for use both inside this module and by programs
28# importing this module.
29pgm_dir_path = sys.argv[0]
30pgm_name = os.path.basename(pgm_dir_path)
Michael Walsh7423c012016-10-04 10:27:21 -050031pgm_dir_name = re.sub("/" + pgm_name, "", pgm_dir_path) + "/"
32
Michael Walshde791732016-09-06 14:25:24 -050033
34# Some functions (e.g. sprint_pgm_header) have need of a program name value
35# that looks more like a valid variable name. Therefore, we'll swap odd
36# characters like "." out for underscores.
37pgm_name_var_name = pgm_name.replace(".", "_")
38
39# Initialize global values used as defaults by print_time, print_var, etc.
40col1_indent = 0
41
42# Calculate default column width for print_var functions based on environment
43# variable settings. The objective is to make the variable values line up
44# nicely with the time stamps.
45col1_width = 29
46if 'NANOSECONDS' in os.environ:
47 NANOSECONDS = os.environ['NANOSECONDS']
48else:
49 NANOSECONDS = 0
50
51if NANOSECONDS == "1":
52 col1_width = col1_width + 7
53
54if 'SHOW_ELAPSED_TIME' in os.environ:
55 SHOW_ELAPSED_TIME = os.environ['SHOW_ELAPSED_TIME']
56else:
57 SHOW_ELAPSED_TIME = 0
58
59if SHOW_ELAPSED_TIME == "1":
60 if NANOSECONDS == "1":
61 col1_width = col1_width + 14
62 else:
63 col1_width = col1_width + 7
64
65# Initialize some time variables used in module functions.
66start_time = time.time()
67sprint_time_last_seconds = start_time
68
Michael Walsh7423c012016-10-04 10:27:21 -050069try:
70 # The user can set environment variable "GEN_PRINT_DEBUG" to get debug
71 # output from this module.
Michael Walsha6723f22016-11-22 11:12:01 -060072 gen_print_debug = int(os.environ['GEN_PRINT_DEBUG'])
Michael Walsh7423c012016-10-04 10:27:21 -050073except KeyError:
74 gen_print_debug = 0
75
Michael Walshde791732016-09-06 14:25:24 -050076
77###############################################################################
78def sprint_func_name(stack_frame_ix=None):
79
80 r"""
81 Return the function name associated with the indicated stack frame.
82
83 Description of arguments:
84 stack_frame_ix The index of the stack frame whose
85 function name should be returned. If the
86 caller does not specifiy a value, this
87 function will set the value to 1 which is
88 the index of the caller's stack frame. If
89 the caller is the wrapper function
90 "print_func_name", this function will bump
91 it up by 1.
92 """
93
94 # If user specified no stack_frame_ix, we'll set it to a proper default
95 # value.
96 if stack_frame_ix is None:
97 func_name = sys._getframe().f_code.co_name
98 caller_func_name = sys._getframe(1).f_code.co_name
99 if func_name[1:] == caller_func_name:
100 stack_frame_ix = 2
101 else:
102 stack_frame_ix = 1
103
104 func_name = sys._getframe(stack_frame_ix).f_code.co_name
105
106 return func_name
107
108###############################################################################
109
110
111# get_arg_name is not a print function per se. I have included it in this
112# module because it is used by sprint_var which is found in this module.
113###############################################################################
114def get_arg_name(var,
115 arg_num=1,
116 stack_frame_ix=1):
117
118 r"""
119 Return the "name" of an argument passed to a function. This could be a
120 literal or a variable name.
121
122 Description of arguements:
123 var The variable whose name you want returned.
124 arg_num The arg number (1 through n) whose name
125 you wish to have returned. This value
126 should not exceed the number of arguments
127 allowed by the target function.
128 stack_frame_ix The stack frame index of the target
129 function. This value must be 1 or
130 greater. 1 would indicate get_arg_name's
131 stack frame. 2 would be the caller of
132 get_arg_name's stack frame, etc.
133
134 Example 1:
135
136 my_var = "mike"
137 var_name = get_arg_name(my_var)
138
139 In this example, var_name will receive the value "my_var".
140
141 Example 2:
142
143 def test1(var):
144 # Getting the var name of the first arg to this function, test1.
145 # Note, in this case, it doesn't matter what you pass as the first arg
146 # to get_arg_name since it is the caller's variable name that matters.
147 dummy = 1
148 arg_num = 1
149 stack_frame = 2
150 var_name = get_arg_name(dummy, arg_num, stack_frame)
151
152 # Mainline...
153
154 another_var = "whatever"
155 test1(another_var)
156
157 In this example, var_name will be set to "another_var".
158
159 """
160
161 # Note: I wish to avoid recursion so I refrain from calling any function
162 # that calls this function (i.e. sprint_var, valid_value, etc.).
163
Michael Walsh23e7f492017-01-10 11:34:47 -0600164 # The user can set environment variable "GET_ARG_NAME_DEBUG" to get debug
165 # output from this function.
166 local_debug = int(os.environ.get('GET_ARG_NAME_DEBUG', 0))
167 # In addition to GET_ARG_NAME_DEBUG, the user can set environment
168 # variable "GET_ARG_NAME_SHOW_SOURCE" to have this function include source
169 # code in the debug output.
170 local_debug_show_source = int(
171 os.environ.get('GET_ARG_NAME_SHOW_SOURCE', 0))
Michael Walshde791732016-09-06 14:25:24 -0500172
173 if arg_num < 1:
174 print_error("Programmer error - Variable \"arg_num\" has an invalid" +
175 " value of \"" + str(arg_num) + "\". The value must be" +
176 " an integer that is greater than 0.\n")
177 # What is the best way to handle errors? Raise exception? I'll
178 # revisit later.
179 return
180 if stack_frame_ix < 1:
181 print_error("Programmer error - Variable \"stack_frame_ix\" has an" +
182 " invalid value of \"" + str(stack_frame_ix) + "\". The" +
183 " value must be an integer that is greater than or equal" +
184 " to 1.\n")
185 return
186
187 if local_debug:
188 debug_indent = 2
Michael Walsh23e7f492017-01-10 11:34:47 -0600189 print("")
190 print_dashes(0, 120)
Michael Walshde791732016-09-06 14:25:24 -0500191 print(sprint_func_name() + "() parms:")
192 print_varx("var", var, 0, debug_indent)
193 print_varx("arg_num", arg_num, 0, debug_indent)
194 print_varx("stack_frame_ix", stack_frame_ix, 0, debug_indent)
Michael Walsh23e7f492017-01-10 11:34:47 -0600195 print("")
196 print_call_stack(debug_indent, 2)
Michael Walshde791732016-09-06 14:25:24 -0500197
Michael Walsh23e7f492017-01-10 11:34:47 -0600198 for count in range(0, 2):
199 try:
200 frame, filename, cur_line_no, function_name, lines, index = \
201 inspect.stack()[stack_frame_ix]
202 except IndexError:
203 print_error("Programmer error - The caller has asked for" +
204 " information about the stack frame at index \"" +
205 str(stack_frame_ix) + "\". However, the stack" +
206 " only contains " + str(len(inspect.stack())) +
207 " entries. Therefore the stack frame index is out" +
208 " of range.\n")
209 return
210 if filename != "<string>":
211 break
212 # filename of "<string>" may mean that the function in question was
213 # defined dynamically and therefore its code stack is inaccessible.
214 # This may happen with functions like "rqprint_var". In this case,
215 # we'll increment the stack_frame_ix and try again.
216 stack_frame_ix += 1
217 if local_debug:
218 print("Adjusted stack_frame_ix...")
219 print_varx("stack_frame_ix", stack_frame_ix, 0, debug_indent)
Michael Walshde791732016-09-06 14:25:24 -0500220
221 called_func_name = sprint_func_name(stack_frame_ix)
Michael Walsh23e7f492017-01-10 11:34:47 -0600222
223 module = inspect.getmodule(frame)
224
225 # Though I would expect inspect.getsourcelines(frame) to get all module
226 # source lines if the frame is "<module>", it doesn't do that. Therefore,
227 # for this special case, I will do inspect.getsourcelines(module).
228 if function_name == "<module>":
229 source_lines, source_line_num =\
230 inspect.getsourcelines(module)
231 line_ix = cur_line_no - source_line_num - 1
232 else:
233 source_lines, source_line_num =\
234 inspect.getsourcelines(frame)
235 line_ix = cur_line_no - source_line_num
236
237 if local_debug:
238 print("\n Variables retrieved from inspect.stack() function:")
239 print_varx("frame", frame, 0, debug_indent + 2)
240 print_varx("filename", filename, 0, debug_indent + 2)
241 print_varx("cur_line_no", cur_line_no, 0, debug_indent + 2)
242 print_varx("function_name", function_name, 0, debug_indent + 2)
243 print_varx("lines", lines, 0, debug_indent + 2)
244 print_varx("index", index, 0, debug_indent + 2)
245 print_varx("source_line_num", source_line_num, 0, debug_indent)
246 print_varx("line_ix", line_ix, 0, debug_indent)
247 if local_debug_show_source:
248 print_varx("source_lines", source_lines, 0, debug_indent)
249 print_varx("called_func_name", called_func_name, 0, debug_indent)
250
251 # Get a list of all functions defined for the module. Note that this
252 # doesn't work consistently when _run_exitfuncs is at the top of the stack
253 # (i.e. if we're running an exit function). I've coded a work-around
254 # below for this deficiency.
255 all_functions = inspect.getmembers(module, inspect.isfunction)
256
257 # Get called_func_id by searching for our function in the list of all
258 # functions.
259 called_func_id = None
260 for func_name, function in all_functions:
261 if func_name == called_func_name:
262 called_func_id = id(function)
263 break
264 # NOTE: The only time I've found that called_func_id can't be found is
265 # when we're running from an exit function.
266
267 # Look for other functions in module with matching id.
268 aliases = set([called_func_name])
269 for func_name, function in all_functions:
270 if func_name == called_func_name:
271 continue
272 func_id = id(function)
273 if func_id == called_func_id:
274 aliases.add(func_name)
275
276 # In most cases, my general purpose code above will find all aliases.
277 # However, for the odd case (i.e. running from exit function), I've added
278 # code to handle pvar, qpvar, dpvar, etc. aliases explicitly since they
279 # are defined in this module and used frequently.
280 # pvar is an alias for print_var.
281 aliases.add(re.sub("print_var", "pvar", called_func_name))
282
283 func_regex = ".*(" + '|'.join(aliases) + ")[ ]*\("
284
285 # Search backward through source lines looking for the calling function
286 # name.
287 found = False
288 for start_line_ix in range(line_ix, 0, -1):
289 # Skip comment lines.
290 if re.match(r"[ ]*#", source_lines[start_line_ix]):
291 continue
292 if re.match(func_regex, source_lines[start_line_ix]):
293 found = True
294 break
295 if not found:
296 print_error("Programmer error - Could not find the source line with" +
297 " a reference to function \"" + called_func_name + "\".\n")
298 return
299
300 # Search forward through the source lines looking for a line with the
301 # same indentation as the start time. The end of our composite line
302 # should be the line preceding that line.
303 start_indent = len(source_lines[start_line_ix]) -\
304 len(source_lines[start_line_ix].lstrip(' '))
305 end_line_ix = line_ix
306 for end_line_ix in range(line_ix + 1, len(source_lines)):
307 if source_lines[end_line_ix].strip() == "":
308 continue
309 line_indent = len(source_lines[end_line_ix]) -\
310 len(source_lines[end_line_ix].lstrip(' '))
311 if line_indent == start_indent:
312 end_line_ix -= 1
313 break
314
315 # Join the start line through the end line into a composite line.
316 composite_line = ''.join(map(str.strip,
317 source_lines[start_line_ix:end_line_ix + 1]))
Michael Walsh7423c012016-10-04 10:27:21 -0500318
Michael Walshbec416d2016-11-10 08:54:52 -0600319 # arg_list_etc = re.sub(".*" + called_func_name, "", composite_line)
320 arg_list_etc = "(" + re.sub(func_regex, "", composite_line)
Michael Walshde791732016-09-06 14:25:24 -0500321 if local_debug:
Michael Walsh23e7f492017-01-10 11:34:47 -0600322 print_varx("aliases", aliases, 0, debug_indent)
Michael Walshbec416d2016-11-10 08:54:52 -0600323 print_varx("func_regex", func_regex, 0, debug_indent)
Michael Walsh23e7f492017-01-10 11:34:47 -0600324 print_varx("start_line_ix", start_line_ix, 0, debug_indent)
325 print_varx("end_line_ix", end_line_ix, 0, debug_indent)
Michael Walshde791732016-09-06 14:25:24 -0500326 print_varx("composite_line", composite_line, 0, debug_indent)
327 print_varx("arg_list_etc", arg_list_etc, 0, debug_indent)
328
329 # Parse arg list...
330 # Initialize...
331 nest_level = -1
332 arg_ix = 0
Michael Walsh7423c012016-10-04 10:27:21 -0500333 args_list = [""]
Michael Walshde791732016-09-06 14:25:24 -0500334 for ix in range(0, len(arg_list_etc)):
335 char = arg_list_etc[ix]
336 # Set the nest_level based on whether we've encounted a parenthesis.
337 if char == "(":
338 nest_level += 1
339 if nest_level == 0:
340 continue
341 elif char == ")":
342 nest_level -= 1
343 if nest_level < 0:
344 break
345
346 # If we reach a comma at base nest level, we are done processing an
Michael Walsh7423c012016-10-04 10:27:21 -0500347 # argument so we increment arg_ix and initialize a new args_list entry.
Michael Walshde791732016-09-06 14:25:24 -0500348 if char == "," and nest_level == 0:
349 arg_ix += 1
Michael Walsh7423c012016-10-04 10:27:21 -0500350 args_list.append("")
Michael Walshde791732016-09-06 14:25:24 -0500351 continue
352
Michael Walsh7423c012016-10-04 10:27:21 -0500353 # For any other character, we append it it to the current arg list
Michael Walshde791732016-09-06 14:25:24 -0500354 # entry.
Michael Walsh7423c012016-10-04 10:27:21 -0500355 args_list[arg_ix] += char
Michael Walshde791732016-09-06 14:25:24 -0500356
357 # Trim whitespace from each list entry.
Michael Walsh7423c012016-10-04 10:27:21 -0500358 args_list = [arg.strip() for arg in args_list]
Michael Walshde791732016-09-06 14:25:24 -0500359
Michael Walsh7423c012016-10-04 10:27:21 -0500360 if arg_num > len(args_list):
Michael Walshde791732016-09-06 14:25:24 -0500361 print_error("Programmer error - The caller has asked for the name of" +
362 " argument number \"" + str(arg_num) + "\" but there " +
Michael Walsh7423c012016-10-04 10:27:21 -0500363 "were only \"" + str(len(args_list)) + "\" args used:\n" +
364 sprint_varx("args_list", args_list))
Michael Walshde791732016-09-06 14:25:24 -0500365 return
366
Michael Walsh7423c012016-10-04 10:27:21 -0500367 argument = args_list[arg_num - 1]
Michael Walshde791732016-09-06 14:25:24 -0500368
369 if local_debug:
Michael Walsh7423c012016-10-04 10:27:21 -0500370 print_varx("args_list", args_list, 0, debug_indent)
Michael Walshde791732016-09-06 14:25:24 -0500371 print_varx("argument", argument, 0, debug_indent)
Michael Walsh23e7f492017-01-10 11:34:47 -0600372 print_dashes(0, 120)
Michael Walshde791732016-09-06 14:25:24 -0500373
374 return argument
375
376###############################################################################
377
378
379###############################################################################
380def sprint_time(buffer=""):
381
382 r"""
383 Return the time in the following format.
384
385 Example:
386
387 The following python code...
388
389 sys.stdout.write(sprint_time())
390 sys.stdout.write("Hi.\n")
391
392 Will result in the following type of output:
393
394 #(CDT) 2016/07/08 15:25:35 - Hi.
395
396 Example:
397
398 The following python code...
399
400 sys.stdout.write(sprint_time("Hi.\n"))
401
402 Will result in the following type of output:
403
404 #(CDT) 2016/08/03 17:12:05 - Hi.
405
406 The following environment variables will affect the formatting as
407 described:
408 NANOSECONDS This will cause the time stamps to be
409 precise to the microsecond (Yes, it
410 probably should have been named
411 MICROSECONDS but the convention was set
412 long ago so we're sticking with it).
413 Example of the output when environment
414 variable NANOSECONDS=1.
415
416 #(CDT) 2016/08/03 17:16:25.510469 - Hi.
417
418 SHOW_ELAPSED_TIME This will cause the elapsed time to be
419 included in the output. This is the
420 amount of time that has elapsed since the
421 last time this function was called. The
422 precision of the elapsed time field is
423 also affected by the value of the
424 NANOSECONDS environment variable. Example
425 of the output when environment variable
426 NANOSECONDS=0 and SHOW_ELAPSED_TIME=1.
427
428 #(CDT) 2016/08/03 17:17:40 - 0 - Hi.
429
430 Example of the output when environment variable NANOSECONDS=1 and
431 SHOW_ELAPSED_TIME=1.
432
433 #(CDT) 2016/08/03 17:18:47.317339 - 0.000046 - Hi.
434
435 Description of arguments.
436 buffer This will be appended to the formatted
437 time string.
438 """
439
440 global NANOSECONDS
441 global SHOW_ELAPSED_TIME
442 global sprint_time_last_seconds
443
444 seconds = time.time()
445 loc_time = time.localtime(seconds)
446 nanoseconds = "%0.6f" % seconds
447 pos = nanoseconds.find(".")
448 nanoseconds = nanoseconds[pos:]
449
450 time_string = time.strftime("#(%Z) %Y/%m/%d %H:%M:%S", loc_time)
451 if NANOSECONDS == "1":
452 time_string = time_string + nanoseconds
453
454 if SHOW_ELAPSED_TIME == "1":
455 cur_time_seconds = seconds
456 math_string = "%9.9f" % cur_time_seconds + " - " + "%9.9f" % \
457 sprint_time_last_seconds
458 elapsed_seconds = eval(math_string)
459 if NANOSECONDS == "1":
460 elapsed_seconds = "%11.6f" % elapsed_seconds
461 else:
462 elapsed_seconds = "%4i" % elapsed_seconds
463 sprint_time_last_seconds = cur_time_seconds
464 time_string = time_string + " - " + elapsed_seconds
465
466 return time_string + " - " + buffer
467
468###############################################################################
469
470
471###############################################################################
472def sprint_timen(buffer=""):
473
474 r"""
475 Append a line feed to the buffer, pass it to sprint_time and return the
476 result.
477 """
478
479 return sprint_time(buffer + "\n")
480
481###############################################################################
482
483
484###############################################################################
485def sprint_error(buffer=""):
486
487 r"""
488 Return a standardized error string. This includes:
489 - A time stamp
490 - The "**ERROR**" string
491 - The caller's buffer string.
492
493 Example:
494
495 The following python code...
496
497 print(sprint_error("Oops.\n"))
498
499 Will result in the following type of output:
500
501 #(CDT) 2016/08/03 17:12:05 - **ERROR** Oops.
502
503 Description of arguments.
504 buffer This will be appended to the formatted
505 error string.
506 """
507
508 return sprint_time() + "**ERROR** " + buffer
509
510###############################################################################
511
512
513###############################################################################
514def sprint_varx(var_name,
515 var_value,
516 hex=0,
517 loc_col1_indent=col1_indent,
Michael Walsh7423c012016-10-04 10:27:21 -0500518 loc_col1_width=col1_width,
519 trailing_char="\n"):
Michael Walshde791732016-09-06 14:25:24 -0500520
521 r"""
522 Print the var name/value passed to it. If the caller lets loc_col1_width
523 default, the printing lines up nicely with output generated by the
524 print_time functions.
525
526 Note that the sprint_var function (defined below) can be used to call this
527 function so that the programmer does not need to pass the var_name.
528 sprint_var will figure out the var_name. The sprint_var function is the
529 one that would normally be used by the general user.
530
531 For example, the following python code:
532
533 first_name = "Mike"
534 print_time("Doing this...\n")
535 print_varx("first_name", first_name)
536 print_time("Doing that...\n")
537
538 Will generate output like this:
539
540 #(CDT) 2016/08/10 17:34:42.847374 - 0.001285 - Doing this...
541 first_name: Mike
542 #(CDT) 2016/08/10 17:34:42.847510 - 0.000136 - Doing that...
543
544 This function recognizes several complex types of data such as dict, list
545 or tuple.
546
547 For example, the following python code:
548
549 my_dict = dict(one=1, two=2, three=3)
550 print_var(my_dict)
551
552 Will generate the following output:
553
554 my_dict:
555 my_dict[three]: 3
556 my_dict[two]: 2
557 my_dict[one]: 1
558
559 Description of arguments.
560 var_name The name of the variable to be printed.
561 var_value The value of the variable to be printed.
562 hex This indicates that the value should be
563 printed in hex format. It is the user's
564 responsibility to ensure that a var_value
Michael Walshbec416d2016-11-10 08:54:52 -0600565 contains a valid hex number. For string
566 var_values, this will be interpreted as
567 show_blanks which means that blank values
568 will be printed as "<blank>".
Michael Walshde791732016-09-06 14:25:24 -0500569 loc_col1_indent The number of spaces to indent the output.
570 loc_col1_width The width of the output column containing
571 the variable name. The default value of
572 this is adjusted so that the var_value
573 lines up with text printed via the
574 print_time function.
Michael Walsh7423c012016-10-04 10:27:21 -0500575 trailing_char The character to be used at the end of the
576 returned string. The default value is a
577 line feed.
578 """
Michael Walshde791732016-09-06 14:25:24 -0500579
580 # Determine the type
581 if type(var_value) in (int, float, bool, str, unicode) \
582 or var_value is None:
583 # The data type is simple in the sense that it has no subordinate
584 # parts.
Michael Walsh7423c012016-10-04 10:27:21 -0500585 # Adjust loc_col1_width.
586 loc_col1_width = loc_col1_width - loc_col1_indent
Michael Walshde791732016-09-06 14:25:24 -0500587 # See if the user wants the output in hex format.
588 if hex:
Michael Walsh18176322016-11-15 15:11:21 -0600589 if type(var_value) not in (int, long):
Michael Walshbec416d2016-11-10 08:54:52 -0600590 value_format = "%s"
Michael Walsh2795edc2016-12-13 16:00:33 -0600591 if var_value == "":
Michael Walshbec416d2016-11-10 08:54:52 -0600592 var_value = "<blank>"
593 else:
594 value_format = "0x%08x"
Michael Walshde791732016-09-06 14:25:24 -0500595 else:
596 value_format = "%s"
597 format_string = "%" + str(loc_col1_indent) + "s%-" \
Michael Walsh7423c012016-10-04 10:27:21 -0500598 + str(loc_col1_width) + "s" + value_format + trailing_char
Michael Walshde791732016-09-06 14:25:24 -0500599 return format_string % ("", var_name + ":", var_value)
600 else:
601 # The data type is complex in the sense that it has subordinate parts.
602 format_string = "%" + str(loc_col1_indent) + "s%s\n"
603 buffer = format_string % ("", var_name + ":")
604 loc_col1_indent += 2
Michael Walsh7423c012016-10-04 10:27:21 -0500605 try:
606 length = len(var_value)
607 except TypeError:
Michael Walsh23e7f492017-01-10 11:34:47 -0600608 length = 0
Michael Walsh7423c012016-10-04 10:27:21 -0500609 ix = 0
610 loc_trailing_char = "\n"
Michael Walshbec416d2016-11-10 08:54:52 -0600611 type_is_dict = 0
Michael Walsh23e7f492017-01-10 11:34:47 -0600612 if type(var_value) is dict:
613 type_is_dict = 1
614 if not type_is_dict:
615 try:
616 if type(var_value) is collections.OrderedDict:
617 type_is_dict = 1
618 except AttributeError:
619 pass
Michael Walsh86de0d22016-12-05 10:13:15 -0600620 if not type_is_dict:
Michael Walsha6723f22016-11-22 11:12:01 -0600621 try:
622 if type(var_value) is DotDict:
623 type_is_dict = 1
624 except NameError:
625 pass
Michael Walshbec416d2016-11-10 08:54:52 -0600626 if type_is_dict:
Michael Walshde791732016-09-06 14:25:24 -0500627 for key, value in var_value.iteritems():
Michael Walsh7423c012016-10-04 10:27:21 -0500628 ix += 1
629 if ix == length:
630 loc_trailing_char = trailing_char
Michael Walshde791732016-09-06 14:25:24 -0500631 buffer += sprint_varx(var_name + "[" + key + "]", value, hex,
Michael Walsh7423c012016-10-04 10:27:21 -0500632 loc_col1_indent, loc_col1_width,
633 loc_trailing_char)
634 elif type(var_value) in (list, tuple, set):
Michael Walshde791732016-09-06 14:25:24 -0500635 for key, value in enumerate(var_value):
Michael Walsh7423c012016-10-04 10:27:21 -0500636 ix += 1
637 if ix == length:
638 loc_trailing_char = trailing_char
Michael Walshde791732016-09-06 14:25:24 -0500639 buffer += sprint_varx(var_name + "[" + str(key) + "]", value,
Michael Walsh7423c012016-10-04 10:27:21 -0500640 hex, loc_col1_indent, loc_col1_width,
641 loc_trailing_char)
Michael Walshde791732016-09-06 14:25:24 -0500642 elif type(var_value) is argparse.Namespace:
643 for key in var_value.__dict__:
Michael Walsh7423c012016-10-04 10:27:21 -0500644 ix += 1
645 if ix == length:
646 loc_trailing_char = trailing_char
Michael Walshde791732016-09-06 14:25:24 -0500647 cmd_buf = "buffer += sprint_varx(var_name + \".\" + str(key)" \
Michael Walsh7423c012016-10-04 10:27:21 -0500648 + ", var_value." + key + ", hex, loc_col1_indent," \
649 + " loc_col1_width, loc_trailing_char)"
Michael Walshde791732016-09-06 14:25:24 -0500650 exec(cmd_buf)
651 else:
652 var_type = type(var_value).__name__
653 func_name = sys._getframe().f_code.co_name
Michael Walsh7423c012016-10-04 10:27:21 -0500654 var_value = "<" + var_type + " type not supported by " + \
655 func_name + "()>"
Michael Walshde791732016-09-06 14:25:24 -0500656 value_format = "%s"
657 loc_col1_indent -= 2
Michael Walsh7423c012016-10-04 10:27:21 -0500658 # Adjust loc_col1_width.
659 loc_col1_width = loc_col1_width - loc_col1_indent
Michael Walshde791732016-09-06 14:25:24 -0500660 format_string = "%" + str(loc_col1_indent) + "s%-" \
Michael Walsh7423c012016-10-04 10:27:21 -0500661 + str(loc_col1_width) + "s" + value_format + trailing_char
Michael Walshde791732016-09-06 14:25:24 -0500662 return format_string % ("", var_name + ":", var_value)
Michael Walsh23e7f492017-01-10 11:34:47 -0600663
Michael Walshde791732016-09-06 14:25:24 -0500664 return buffer
665
666 return ""
667
668###############################################################################
669
670
671###############################################################################
672def sprint_var(*args):
673
674 r"""
675 Figure out the name of the first argument for you and then call
676 sprint_varx with it. Therefore, the following 2 calls are equivalent:
677 sprint_varx("var1", var1)
678 sprint_var(var1)
679 """
680
681 # Get the name of the first variable passed to this function.
682 stack_frame = 2
Michael Walsh7423c012016-10-04 10:27:21 -0500683 caller_func_name = sprint_func_name(2)
684 if caller_func_name.endswith("print_var"):
Michael Walshde791732016-09-06 14:25:24 -0500685 stack_frame += 1
686 var_name = get_arg_name(None, 1, stack_frame)
687 return sprint_varx(var_name, *args)
688
689###############################################################################
690
691
692###############################################################################
Michael Walsh18176322016-11-15 15:11:21 -0600693def sprint_vars(*args):
694
695 r"""
696 Sprint the values of one or more variables.
697
698 Description of args:
699 args:
700 If the first argument is an integer, it will be interpreted to be the
701 "indent" value.
702 If the second argument is an integer, it will be interpreted to be the
703 "col1_width" value.
704 If the third argument is an integer, it will be interpreted to be the
705 "hex" value.
706 All remaining parms are considered variable names which are to be
707 sprinted.
708 """
709
710 if len(args) == 0:
711 return
712
713 # Get the name of the first variable passed to this function.
714 stack_frame = 2
715 caller_func_name = sprint_func_name(2)
716 if caller_func_name.endswith("print_vars"):
717 stack_frame += 1
718
719 parm_num = 1
720
721 # Create list from args (which is a tuple) so that it can be modified.
722 args_list = list(args)
723
724 var_name = get_arg_name(None, parm_num, stack_frame)
725 # See if parm 1 is to be interpreted as "indent".
726 try:
727 if type(int(var_name)) is int:
728 indent = int(var_name)
729 args_list.pop(0)
730 parm_num += 1
731 except ValueError:
732 indent = 0
733
734 var_name = get_arg_name(None, parm_num, stack_frame)
735 # See if parm 1 is to be interpreted as "col1_width".
736 try:
737 if type(int(var_name)) is int:
738 loc_col1_width = int(var_name)
739 args_list.pop(0)
740 parm_num += 1
741 except ValueError:
742 loc_col1_width = col1_width
743
744 var_name = get_arg_name(None, parm_num, stack_frame)
745 # See if parm 1 is to be interpreted as "hex".
746 try:
747 if type(int(var_name)) is int:
748 hex = int(var_name)
749 args_list.pop(0)
750 parm_num += 1
751 except ValueError:
752 hex = 0
753
754 buffer = ""
755 for var_value in args_list:
756 var_name = get_arg_name(None, parm_num, stack_frame)
757 buffer += sprint_varx(var_name, var_value, hex, indent, loc_col1_width)
758 parm_num += 1
759
760 return buffer
761
762###############################################################################
763
764
765###############################################################################
Michael Walsh7423c012016-10-04 10:27:21 -0500766def lprint_varx(var_name,
767 var_value,
768 hex=0,
769 loc_col1_indent=col1_indent,
770 loc_col1_width=col1_width,
771 log_level=getattr(logging, 'INFO')):
772
773 r"""
774 Send sprint_varx output to logging.
775 """
776
777 logging.log(log_level, sprint_varx(var_name, var_value, hex,
778 loc_col1_indent, loc_col1_width, ""))
779
780###############################################################################
781
782
783###############################################################################
784def lprint_var(*args):
785
786 r"""
787 Figure out the name of the first argument for you and then call
788 lprint_varx with it. Therefore, the following 2 calls are equivalent:
789 lprint_varx("var1", var1)
790 lprint_var(var1)
791 """
792
793 # Get the name of the first variable passed to this function.
794 stack_frame = 2
795 caller_func_name = sprint_func_name(2)
796 if caller_func_name.endswith("print_var"):
797 stack_frame += 1
798 var_name = get_arg_name(None, 1, stack_frame)
799 lprint_varx(var_name, *args)
800
801###############################################################################
802
803
804###############################################################################
805def sprint_dashes(indent=col1_indent,
806 width=80,
807 line_feed=1,
808 char="-"):
Michael Walshde791732016-09-06 14:25:24 -0500809
810 r"""
811 Return a string of dashes to the caller.
812
813 Description of arguements:
814 indent The number of characters to indent the
815 output.
816 width The width of the string of dashes.
817 line_feed Indicates whether the output should end
818 with a line feed.
Michael Walsh7423c012016-10-04 10:27:21 -0500819 char The character to be repeated in the output
820 string.
Michael Walshde791732016-09-06 14:25:24 -0500821 """
822
Michael Walsh7423c012016-10-04 10:27:21 -0500823 width = int(width)
Michael Walsh23e7f492017-01-10 11:34:47 -0600824 buffer = " " * int(indent) + char * width
Michael Walshde791732016-09-06 14:25:24 -0500825 if line_feed:
826 buffer += "\n"
827
828 return buffer
829
830###############################################################################
831
832
833###############################################################################
Michael Walsh7423c012016-10-04 10:27:21 -0500834def sindent(text="",
835 indent=0):
836
837 r"""
838 Pre-pend the specified number of characters to the text string (i.e.
839 indent it) and return it.
840
841 Description of arguments:
842 text The string to be indented.
843 indent The number of characters to indent the
844 string.
845 """
846
847 format_string = "%" + str(indent) + "s%s"
848 buffer = format_string % ("", text)
849
850 return buffer
851
852###############################################################################
853
854
855###############################################################################
856def sprint_call_stack(indent=0,
857 stack_frame_ix=0):
Michael Walshde791732016-09-06 14:25:24 -0500858
859 r"""
860 Return a call stack report for the given point in the program with line
861 numbers, function names and function parameters and arguments.
862
863 Sample output:
864
865 -------------------------------------------------------------------------
866 Python function call stack
867
868 Line # Function name and arguments
869 ------ ------------------------------------------------------------------
870 424 sprint_call_stack ()
871 4 print_call_stack ()
872 31 func1 (last_name = 'walsh', first_name = 'mikey')
873 59 /tmp/scr5.py
874 -------------------------------------------------------------------------
875
876 Description of arguments:
877 indent The number of characters to indent each
878 line of output.
879 stack_frame_ix The index of the first stack frame which
880 is to be returned.
881 """
882
883 buffer = ""
Michael Walsh7423c012016-10-04 10:27:21 -0500884 buffer += sprint_dashes(indent)
885 buffer += sindent("Python function call stack\n\n", indent)
886 buffer += sindent("Line # Function name and arguments\n", indent)
887 buffer += sprint_dashes(indent, 6, 0) + " " + sprint_dashes(0, 73)
Michael Walshde791732016-09-06 14:25:24 -0500888
889 # Grab the current program stack.
890 current_stack = inspect.stack()
891
892 # Process each frame in turn.
893 format_string = "%6s %s\n"
Michael Walsh7423c012016-10-04 10:27:21 -0500894 ix = 0
Michael Walshde791732016-09-06 14:25:24 -0500895 for stack_frame in current_stack:
Michael Walsh7423c012016-10-04 10:27:21 -0500896 if ix < stack_frame_ix:
897 ix += 1
898 continue
Michael Walsh23e7f492017-01-10 11:34:47 -0600899 # I want the line number shown to be the line where you find the line
900 # shown.
901 try:
902 line_num = str(current_stack[ix + 1][2])
903 except IndexError:
904 line_num = ""
Michael Walshde791732016-09-06 14:25:24 -0500905 func_name = str(stack_frame[3])
906 if func_name == "?":
907 # "?" is the name used when code is not in a function.
908 func_name = "(none)"
909
910 if func_name == "<module>":
Michael Walsh7423c012016-10-04 10:27:21 -0500911 # If the func_name is the "main" program, we simply get the
912 # command line call string.
Michael Walshde791732016-09-06 14:25:24 -0500913 func_and_args = ' '.join(sys.argv)
914 else:
915 # Get the program arguments.
916 arg_vals = inspect.getargvalues(stack_frame[0])
917 function_parms = arg_vals[0]
918 frame_locals = arg_vals[3]
919
Michael Walsh7423c012016-10-04 10:27:21 -0500920 args_list = []
Michael Walshde791732016-09-06 14:25:24 -0500921 for arg_name in function_parms:
922 # Get the arg value from frame locals.
923 arg_value = frame_locals[arg_name]
Michael Walsh7423c012016-10-04 10:27:21 -0500924 args_list.append(arg_name + " = " + repr(arg_value))
925 args_str = "(" + ', '.join(map(str, args_list)) + ")"
Michael Walshde791732016-09-06 14:25:24 -0500926
927 # Now we need to print this in a nicely-wrapped way.
928 func_and_args = func_name + " " + args_str
929
Michael Walsh23e7f492017-01-10 11:34:47 -0600930 buffer += sindent(format_string % (line_num, func_and_args), indent)
Michael Walsh7423c012016-10-04 10:27:21 -0500931 ix += 1
Michael Walshde791732016-09-06 14:25:24 -0500932
Michael Walsh7423c012016-10-04 10:27:21 -0500933 buffer += sprint_dashes(indent)
Michael Walshde791732016-09-06 14:25:24 -0500934
935 return buffer
936
937###############################################################################
938
939
940###############################################################################
941def sprint_executing(stack_frame_ix=None):
942
943 r"""
944 Print a line indicating what function is executing and with what parameter
945 values. This is useful for debugging.
946
947 Sample output:
948
949 #(CDT) 2016/08/25 17:54:27 - Executing: func1 (x = 1)
950
951 Description of arguments:
952 stack_frame_ix The index of the stack frame whose
953 function info should be returned. If the
954 caller does not specifiy a value, this
955 function will set the value to 1 which is
956 the index of the caller's stack frame. If
957 the caller is the wrapper function
958 "print_executing", this function will bump
959 it up by 1.
960 """
961
962 # If user wants default stack_frame_ix.
963 if stack_frame_ix is None:
964 func_name = sys._getframe().f_code.co_name
965 caller_func_name = sys._getframe(1).f_code.co_name
Michael Walsh7423c012016-10-04 10:27:21 -0500966 if caller_func_name.endswith(func_name[1:]):
Michael Walshde791732016-09-06 14:25:24 -0500967 stack_frame_ix = 2
968 else:
969 stack_frame_ix = 1
970
971 stack_frame = inspect.stack()[stack_frame_ix]
972
973 func_name = str(stack_frame[3])
974 if func_name == "?":
975 # "?" is the name used when code is not in a function.
976 func_name = "(none)"
977
978 if func_name == "<module>":
979 # If the func_name is the "main" program, we simply get the command
980 # line call string.
981 func_and_args = ' '.join(sys.argv)
982 else:
983 # Get the program arguments.
984 arg_vals = inspect.getargvalues(stack_frame[0])
985 function_parms = arg_vals[0]
986 frame_locals = arg_vals[3]
987
Michael Walsh7423c012016-10-04 10:27:21 -0500988 args_list = []
Michael Walshde791732016-09-06 14:25:24 -0500989 for arg_name in function_parms:
990 # Get the arg value from frame locals.
991 arg_value = frame_locals[arg_name]
Michael Walsh7423c012016-10-04 10:27:21 -0500992 args_list.append(arg_name + " = " + repr(arg_value))
993 args_str = "(" + ', '.join(map(str, args_list)) + ")"
Michael Walshde791732016-09-06 14:25:24 -0500994
995 # Now we need to print this in a nicely-wrapped way.
996 func_and_args = func_name + " " + args_str
997
998 return sprint_time() + "Executing: " + func_and_args + "\n"
999
1000###############################################################################
1001
1002
1003###############################################################################
Michael Walshbec416d2016-11-10 08:54:52 -06001004def sprint_pgm_header(indent=0,
1005 linefeed=1):
Michael Walshde791732016-09-06 14:25:24 -05001006
1007 r"""
1008 Return a standardized header that programs should print at the beginning
1009 of the run. It includes useful information like command line, pid,
1010 userid, program parameters, etc.
1011
Michael Walsh7423c012016-10-04 10:27:21 -05001012 Description of arguments:
1013 indent The number of characters to indent each
1014 line of output.
Michael Walshbec416d2016-11-10 08:54:52 -06001015 linefeed Indicates whether a line feed be included
1016 at the beginning and end of the report.
Michael Walshde791732016-09-06 14:25:24 -05001017 """
1018
Michael Walshbec416d2016-11-10 08:54:52 -06001019 loc_col1_width = col1_width + indent
1020
1021 buffer = ""
1022 if linefeed:
1023 buffer = "\n"
Michael Walsh7423c012016-10-04 10:27:21 -05001024
1025 buffer += sindent(sprint_time() + "Running " + pgm_name + ".\n", indent)
1026 buffer += sindent(sprint_time() + "Program parameter values, etc.:\n\n",
1027 indent)
Michael Walshbec416d2016-11-10 08:54:52 -06001028 buffer += sprint_varx("command_line", ' '.join(sys.argv), 0, indent,
1029 loc_col1_width)
Michael Walsh7423c012016-10-04 10:27:21 -05001030 # We want the output to show a customized name for the pid and pgid but
1031 # we want it to look like a valid variable name. Therefore, we'll use
Michael Walshde791732016-09-06 14:25:24 -05001032 # pgm_name_var_name which was set when this module was imported.
Michael Walshbec416d2016-11-10 08:54:52 -06001033 buffer += sprint_varx(pgm_name_var_name + "_pid", os.getpid(), 0, indent,
1034 loc_col1_width)
1035 buffer += sprint_varx(pgm_name_var_name + "_pgid", os.getpgrp(), 0, indent,
1036 loc_col1_width)
Michael Walsh86de0d22016-12-05 10:13:15 -06001037 userid_num = str(os.geteuid())
1038 try:
1039 username = os.getlogin()
1040 except OSError:
1041 if userid_num == "0":
1042 username = "root"
1043 else:
1044 username = "?"
1045 buffer += sprint_varx("uid", userid_num + " (" + username +
Michael Walshbec416d2016-11-10 08:54:52 -06001046 ")", 0, indent, loc_col1_width)
Michael Walshde791732016-09-06 14:25:24 -05001047 buffer += sprint_varx("gid", str(os.getgid()) + " (" +
Michael Walsh7423c012016-10-04 10:27:21 -05001048 str(grp.getgrgid(os.getgid()).gr_name) + ")", 0,
Michael Walshbec416d2016-11-10 08:54:52 -06001049 indent, loc_col1_width)
1050 buffer += sprint_varx("host_name", socket.gethostname(), 0, indent,
1051 loc_col1_width)
Michael Walsh86de0d22016-12-05 10:13:15 -06001052 try:
1053 DISPLAY = os.environ['DISPLAY']
1054 except KeyError:
1055 DISPLAY = ""
1056 buffer += sprint_varx("DISPLAY", DISPLAY, 0, indent,
Michael Walshbec416d2016-11-10 08:54:52 -06001057 loc_col1_width)
Michael Walshde791732016-09-06 14:25:24 -05001058 # I want to add code to print caller's parms.
1059
Michael Walsh7423c012016-10-04 10:27:21 -05001060 # __builtin__.arg_obj is created by the get_arg module function,
1061 # gen_get_options.
1062 try:
1063 buffer += ga.sprint_args(__builtin__.arg_obj, indent)
1064 except AttributeError:
1065 pass
1066
Michael Walshbec416d2016-11-10 08:54:52 -06001067 if linefeed:
1068 buffer += "\n"
Michael Walshde791732016-09-06 14:25:24 -05001069
1070 return buffer
1071
1072###############################################################################
1073
1074
1075###############################################################################
Michael Walsh7423c012016-10-04 10:27:21 -05001076def sprint_error_report(error_text="\n",
1077 indent=2):
1078
1079 r"""
1080 Return a string with a standardized report which includes the caller's
1081 error text, the call stack and the program header.
1082
1083 Description of args:
1084 error_text The error text to be included in the
1085 report. The caller should include any
1086 needed linefeeds.
1087 indent The number of characters to indent each
1088 line of output.
1089 """
1090
1091 buffer = ""
1092 buffer += sprint_dashes(width=120, char="=")
1093 buffer += sprint_error(error_text)
1094 buffer += "\n"
1095 # Calling sprint_call_stack with stack_frame_ix of 0 causes it to show
1096 # itself and this function in the call stack. This is not helpful to a
1097 # debugger and is therefore clutter. We will adjust the stack_frame_ix to
1098 # hide that information.
1099 stack_frame_ix = 2
1100 caller_func_name = sprint_func_name(2)
1101 if caller_func_name.endswith("print_error_report"):
1102 stack_frame_ix += 1
1103 buffer += sprint_call_stack(indent, stack_frame_ix)
1104 buffer += sprint_pgm_header(indent)
1105 buffer += sprint_dashes(width=120, char="=")
1106
1107 return buffer
1108
1109###############################################################################
1110
1111
1112###############################################################################
Michael Walsh18176322016-11-15 15:11:21 -06001113def sprint_issuing(cmd_buf,
1114 test_mode=0):
Michael Walshde791732016-09-06 14:25:24 -05001115
1116 r"""
1117 Return a line indicating a command that the program is about to execute.
1118
1119 Sample output for a cmd_buf of "ls"
1120
1121 #(CDT) 2016/08/25 17:57:36 - Issuing: ls
Michael Walshbec416d2016-11-10 08:54:52 -06001122
Michael Walshde791732016-09-06 14:25:24 -05001123 Description of args:
1124 cmd_buf The command to be executed by caller.
Michael Walshbec416d2016-11-10 08:54:52 -06001125 test_mode With test_mode set, your output will look
1126 like this:
1127
1128 #(CDT) 2016/08/25 17:57:36 - (test_mode) Issuing: ls
1129
Michael Walshde791732016-09-06 14:25:24 -05001130 """
1131
Michael Walshbec416d2016-11-10 08:54:52 -06001132 buffer = sprint_time()
1133 if test_mode:
1134 buffer += "(test_mode) "
1135 buffer += "Issuing: " + cmd_buf + "\n"
Michael Walshde791732016-09-06 14:25:24 -05001136
1137 return buffer
1138
1139###############################################################################
1140
1141
1142###############################################################################
1143def sprint_pgm_footer():
1144
1145 r"""
1146 Return a standardized footer that programs should print at the end of the
1147 program run. It includes useful information like total run time, etc.
1148 """
1149
1150 buffer = "\n" + sprint_time() + "Finished running " + pgm_name + ".\n\n"
1151
1152 total_time = time.time() - start_time
1153 total_time_string = "%0.6f" % total_time
1154
Michael Walsh7423c012016-10-04 10:27:21 -05001155 buffer += sprint_varx(pgm_name_var_name + "_runtime", total_time_string)
Michael Walshbec416d2016-11-10 08:54:52 -06001156 buffer += "\n"
Michael Walsh7423c012016-10-04 10:27:21 -05001157
1158 return buffer
1159
1160###############################################################################
1161
1162
1163###############################################################################
1164def sprint(buffer=""):
1165
1166 r"""
1167 Simply return the user's buffer. This function is used by the qprint and
1168 dprint functions defined dynamically below, i.e. it would not normally be
1169 called for general use.
1170
1171 Description of arguments.
1172 buffer This will be returned to the caller.
1173 """
Michael Walshde791732016-09-06 14:25:24 -05001174
Michael Walshbec416d2016-11-10 08:54:52 -06001175 return str(buffer)
1176
1177###############################################################################
1178
1179
1180###############################################################################
1181def sprintn(buffer=""):
1182
1183 r"""
1184 Simply return the user's buffer with a line feed. This function is used
1185 by the qprint and dprint functions defined dynamically below, i.e. it
1186 would not normally be called for general use.
1187
1188 Description of arguments.
1189 buffer This will be returned to the caller.
1190 """
1191
1192 buffer = str(buffer) + "\n"
1193
Michael Walshde791732016-09-06 14:25:24 -05001194 return buffer
1195
1196###############################################################################
1197
1198
1199###############################################################################
1200# In the following section of code, we will dynamically create print versions
1201# for each of the sprint functions defined above. So, for example, where we
1202# have an sprint_time() function defined above that returns the time to the
Michael Walsh7423c012016-10-04 10:27:21 -05001203# caller in a string, we will create a corresponding print_time() function
1204# that will print that string directly to stdout.
Michael Walshde791732016-09-06 14:25:24 -05001205
1206# It can be complicated to follow what's being creaed by the exec statement
1207# below. Here is an example of the print_time() function that will be created:
1208
1209# def print_time(*args):
1210# s_funcname = "s" + sys._getframe().f_code.co_name
1211# s_func = getattr(sys.modules[__name__], s_funcname)
1212# sys.stdout.write(s_func(*args))
1213
1214# Here are comments describing the 3 lines in the body of the created function.
1215# Calculate the "s" version of this function name (e.g. if this function name
1216# is print_time, we want s_funcname to be "sprint_time".
1217# Put a reference to the "s" version of this function in s_func.
Michael Walsh7423c012016-10-04 10:27:21 -05001218# Call the "s" version of this function passing it all of our arguments.
1219# Write the result to stdout.
Michael Walshde791732016-09-06 14:25:24 -05001220
1221# func_names contains a list of all print functions which should be created
1222# from their sprint counterparts.
1223func_names = ['print_time', 'print_timen', 'print_error', 'print_varx',
Michael Walsh18176322016-11-15 15:11:21 -06001224 'print_var', 'print_vars', 'print_dashes', 'indent',
1225 'print_call_stack', 'print_func_name', 'print_executing',
1226 'print_pgm_header', 'print_issuing', 'print_pgm_footer',
1227 'print_error_report', 'print', 'printn']
Michael Walshde791732016-09-06 14:25:24 -05001228
1229for func_name in func_names:
Michael Walsh7423c012016-10-04 10:27:21 -05001230 if func_name == "print":
1231 continue
Michael Walshde791732016-09-06 14:25:24 -05001232 # Create abbreviated aliases (e.g. spvar is an alias for sprint_var).
1233 alias = re.sub("print_", "p", func_name)
Michael Walsh7423c012016-10-04 10:27:21 -05001234 pgm_definition_string = "s" + alias + " = s" + func_name
1235 if gen_print_debug:
1236 print(pgm_definition_string)
1237 exec(pgm_definition_string)
Michael Walshde791732016-09-06 14:25:24 -05001238
1239for func_name in func_names:
Michael Walsh7423c012016-10-04 10:27:21 -05001240 if func_name == "print_error" or func_name == "print_error_report":
Michael Walshde791732016-09-06 14:25:24 -05001241 output_stream = "stderr"
1242 else:
1243 output_stream = "stdout"
1244 func_def = \
1245 [
1246 "def " + func_name + "(*args):",
1247 " s_func_name = \"s\" + sys._getframe().f_code.co_name",
1248 " s_func = getattr(sys.modules[__name__], s_func_name)",
1249 " sys." + output_stream + ".write(s_func(*args))",
1250 " sys." + output_stream + ".flush()"
1251 ]
Michael Walsh7423c012016-10-04 10:27:21 -05001252 if func_name != "print":
1253 pgm_definition_string = '\n'.join(func_def)
1254 if gen_print_debug:
1255 print(pgm_definition_string)
1256 exec(pgm_definition_string)
1257
1258 # Now define "q" versions of each print function.
1259 func_def = \
1260 [
1261 "def q" + func_name + "(*args):",
1262 " if __builtin__.quiet: return",
1263 " s_func_name = \"s" + func_name + "\"",
1264 " s_func = getattr(sys.modules[__name__], s_func_name)",
1265 " sys." + output_stream + ".write(s_func(*args))",
1266 " sys." + output_stream + ".flush()"
1267 ]
1268
Michael Walshde791732016-09-06 14:25:24 -05001269 pgm_definition_string = '\n'.join(func_def)
Michael Walsh7423c012016-10-04 10:27:21 -05001270 if gen_print_debug:
1271 print(pgm_definition_string)
Michael Walshde791732016-09-06 14:25:24 -05001272 exec(pgm_definition_string)
1273
Michael Walsh7423c012016-10-04 10:27:21 -05001274 # Now define "d" versions of each print function.
1275 func_def = \
1276 [
1277 "def d" + func_name + "(*args):",
1278 " if not __builtin__.debug: return",
1279 " s_func_name = \"s" + func_name + "\"",
1280 " s_func = getattr(sys.modules[__name__], s_func_name)",
1281 " sys." + output_stream + ".write(s_func(*args))",
1282 " sys." + output_stream + ".flush()"
1283 ]
1284
1285 pgm_definition_string = '\n'.join(func_def)
1286 if gen_print_debug:
1287 print(pgm_definition_string)
1288 exec(pgm_definition_string)
1289
1290 # Now define "l" versions of each print function.
1291 func_def = \
1292 [
1293 "def l" + func_name + "(*args):",
1294 " s_func_name = \"s" + func_name + "\"",
1295 " s_func = getattr(sys.modules[__name__], s_func_name)",
1296 " logging.log(getattr(logging, 'INFO'), s_func(*args))",
1297 ]
1298
1299 if func_name != "print_varx" and func_name != "print_var":
1300 pgm_definition_string = '\n'.join(func_def)
1301 if gen_print_debug:
1302 print(pgm_definition_string)
1303 exec(pgm_definition_string)
1304
1305 if func_name == "print":
1306 continue
1307
Michael Walshde791732016-09-06 14:25:24 -05001308 # Create abbreviated aliases (e.g. pvar is an alias for print_var).
1309 alias = re.sub("print_", "p", func_name)
Michael Walsh7423c012016-10-04 10:27:21 -05001310 pgm_definition_string = alias + " = " + func_name
1311 if gen_print_debug:
1312 print(pgm_definition_string)
1313 exec(pgm_definition_string)
1314
1315 # Create abbreviated aliases (e.g. qpvar is an alias for qprint_var).
1316 alias = re.sub("print_", "p", func_name)
1317 pgm_definition_string = "q" + alias + " = q" + func_name
1318 if gen_print_debug:
1319 print(pgm_definition_string)
1320 exec(pgm_definition_string)
1321
1322 # Create abbreviated aliases (e.g. dpvar is an alias for dprint_var).
1323 alias = re.sub("print_", "p", func_name)
1324 pgm_definition_string = "d" + alias + " = d" + func_name
1325 if gen_print_debug:
1326 print(pgm_definition_string)
1327 exec(pgm_definition_string)
1328
1329 # Create abbreviated aliases (e.g. lpvar is an alias for lprint_var).
1330 alias = re.sub("print_", "p", func_name)
1331 pgm_definition_string = "l" + alias + " = l" + func_name
1332 if gen_print_debug:
1333 print(pgm_definition_string)
1334 exec(pgm_definition_string)
Michael Walshde791732016-09-06 14:25:24 -05001335
1336###############################################################################