Adding new function and fixing some bugs in general purpose py files.
gen_args.py:
sprint_args()
I made corrections to col1_width processing when indent is not zero.
gen_print.py:
get_arg_name:
I fixed a bug.
sprint_varx:
I added support for printing OrderedDict objects and robot DotDict objects.
I added support for having the hex arg double as a "print None" for string objects.
sprint_pgm_header:
I added support for linefeed arg.
sissuing:
I added support for test_mode parm.
sprintn:
New function.
gen_valid.py:
svalid_value:
New function:
valid_value:
Now calls svalid_value.
svalid_integer:
New function:
valid_integer:
Now calls svalid_integer.
Change-Id: I161086d1148e4559fcc57b7d749cc3fb810dc19f
Signed-off-by: Michael Walsh <micwalsh@us.ibm.com>
diff --git a/lib/gen_arg.py b/lib/gen_arg.py
index 1a57411..72638cc 100755
--- a/lib/gen_arg.py
+++ b/lib/gen_arg.py
@@ -177,10 +177,13 @@
of output.
"""
+ loc_col1_width = gp.col1_width + indent
+
buffer = ""
for key in arg_obj.__dict__:
- buffer += gp.sprint_varx(key, getattr(arg_obj, key), 0, indent)
+ buffer += gp.sprint_varx(key, getattr(arg_obj, key), 0, indent,
+ loc_col1_width)
return buffer
diff --git a/lib/gen_print.py b/lib/gen_print.py
index 6310122..e7efb16 100755
--- a/lib/gen_print.py
+++ b/lib/gen_print.py
@@ -15,6 +15,13 @@
import argparse
import __builtin__
import logging
+import collections
+
+running_from_robot = 1
+try:
+ from robot.utils import DotDict
+except ImportError:
+ running_from_robot = 0
import gen_arg as ga
@@ -206,7 +213,14 @@
composite_line = lines[0].strip()
called_func_name = sprint_func_name(stack_frame_ix)
- if not re.match(r".*" + called_func_name, composite_line):
+ # Needed to add a right anchor to func_regex for cases like this where
+ # there is an arg whose name is a substring of the function name. So the
+ # function name needs to be bounded on the right by zero or more spaces
+ # and a left parenthesis.
+ # if not valid_value(whatever, valid_values=["one", "two"]):
+ func_regex = ".*" + called_func_name + "[ ]*\("
+ # if not re.match(r".*" + called_func_name, composite_line):
+ if not re.match(func_regex, composite_line):
# The called function name was not found in the composite line. The
# caller may be using a function alias.
# I added code to handle pvar, qpvar, dpvar, etc. aliases.
@@ -214,10 +228,15 @@
# sprint_func_name() returns the non-alias version, i.e. "print_var".
# Adjusting for that here.
alias = re.sub("print_var", "pvar", called_func_name)
+ if local_debug:
+ print_varx("alias", alias, 0, debug_indent)
called_func_name = alias
+ func_regex = ".*" + called_func_name + "[ ]*\("
- arg_list_etc = re.sub(".*" + called_func_name, "", composite_line)
+ # arg_list_etc = re.sub(".*" + called_func_name, "", composite_line)
+ arg_list_etc = "(" + re.sub(func_regex, "", composite_line)
if local_debug:
+ print_varx("func_regex", func_regex, 0, debug_indent)
print_varx("called_func_name", called_func_name, 0, debug_indent)
print_varx("composite_line", composite_line, 0, debug_indent)
print_varx("arg_list_etc", arg_list_etc, 0, debug_indent)
@@ -457,7 +476,10 @@
hex This indicates that the value should be
printed in hex format. It is the user's
responsibility to ensure that a var_value
- contains a valid hex number.
+ contains a valid hex number. For string
+ var_values, this will be interpreted as
+ show_blanks which means that blank values
+ will be printed as "<blank>".
loc_col1_indent The number of spaces to indent the output.
loc_col1_width The width of the output column containing
the variable name. The default value of
@@ -478,7 +500,12 @@
loc_col1_width = loc_col1_width - loc_col1_indent
# See if the user wants the output in hex format.
if hex:
- value_format = "0x%08x"
+ if type(var_value) in (str, unicode):
+ value_format = "%s"
+ if var_value is "":
+ var_value = "<blank>"
+ else:
+ value_format = "0x%08x"
else:
value_format = "%s"
format_string = "%" + str(loc_col1_indent) + "s%-" \
@@ -495,7 +522,16 @@
pass
ix = 0
loc_trailing_char = "\n"
- if type(var_value) is dict:
+ type_is_dict = 0
+ try:
+ if type(var_value) in (dict, collections.OrderedDict):
+ type_is_dict = 1
+ except AttributeError:
+ type_is_dict = 0
+ if running_from_robot:
+ if type(var_value) is DotDict:
+ type_is_dict = 1
+ if type_is_dict:
for key, value in var_value.iteritems():
ix += 1
if ix == length:
@@ -794,7 +830,8 @@
###############################################################################
-def sprint_pgm_header(indent=0):
+def sprint_pgm_header(indent=0,
+ linefeed=1):
r"""
Return a standardized header that programs should print at the beginning
@@ -804,26 +841,37 @@
Description of arguments:
indent The number of characters to indent each
line of output.
+ linefeed Indicates whether a line feed be included
+ at the beginning and end of the report.
"""
- buffer = "\n"
+ loc_col1_width = col1_width + indent
+
+ buffer = ""
+ if linefeed:
+ buffer = "\n"
buffer += sindent(sprint_time() + "Running " + pgm_name + ".\n", indent)
buffer += sindent(sprint_time() + "Program parameter values, etc.:\n\n",
indent)
- buffer += sprint_varx("command_line", ' '.join(sys.argv), 0, indent)
+ buffer += sprint_varx("command_line", ' '.join(sys.argv), 0, indent,
+ loc_col1_width)
# We want the output to show a customized name for the pid and pgid but
# we want it to look like a valid variable name. Therefore, we'll use
# pgm_name_var_name which was set when this module was imported.
- buffer += sprint_varx(pgm_name_var_name + "_pid", os.getpid(), 0, indent)
- buffer += sprint_varx(pgm_name_var_name + "_pgid", os.getpgrp(), 0, indent)
+ buffer += sprint_varx(pgm_name_var_name + "_pid", os.getpid(), 0, indent,
+ loc_col1_width)
+ buffer += sprint_varx(pgm_name_var_name + "_pgid", os.getpgrp(), 0, indent,
+ loc_col1_width)
buffer += sprint_varx("uid", str(os.geteuid()) + " (" + os.getlogin() +
- ")", 0, indent)
+ ")", 0, indent, loc_col1_width)
buffer += sprint_varx("gid", str(os.getgid()) + " (" +
str(grp.getgrgid(os.getgid()).gr_name) + ")", 0,
- indent)
- buffer += sprint_varx("host_name", socket.gethostname(), 0, indent)
- buffer += sprint_varx("DISPLAY", os.environ['DISPLAY'], 0, indent)
+ indent, loc_col1_width)
+ buffer += sprint_varx("host_name", socket.gethostname(), 0, indent,
+ loc_col1_width)
+ buffer += sprint_varx("DISPLAY", os.environ['DISPLAY'], 0, indent,
+ loc_col1_width)
# I want to add code to print caller's parms.
# __builtin__.arg_obj is created by the get_arg module function,
@@ -833,7 +881,8 @@
except AttributeError:
pass
- buffer += "\n"
+ if linefeed:
+ buffer += "\n"
return buffer
@@ -878,7 +927,8 @@
###############################################################################
-def sissuing(cmd_buf):
+def sissuing(cmd_buf,
+ test_mode=0):
r"""
Return a line indicating a command that the program is about to execute.
@@ -886,11 +936,20 @@
Sample output for a cmd_buf of "ls"
#(CDT) 2016/08/25 17:57:36 - Issuing: ls
+
Description of args:
cmd_buf The command to be executed by caller.
+ test_mode With test_mode set, your output will look
+ like this:
+
+ #(CDT) 2016/08/25 17:57:36 - (test_mode) Issuing: ls
+
"""
- buffer = sprint_time() + "Issuing: " + cmd_buf + "\n"
+ buffer = sprint_time()
+ if test_mode:
+ buffer += "(test_mode) "
+ buffer += "Issuing: " + cmd_buf + "\n"
return buffer
@@ -911,6 +970,7 @@
total_time_string = "%0.6f" % total_time
buffer += sprint_varx(pgm_name_var_name + "_runtime", total_time_string)
+ buffer += "\n"
return buffer
@@ -929,6 +989,25 @@
buffer This will be returned to the caller.
"""
+ return str(buffer)
+
+###############################################################################
+
+
+###############################################################################
+def sprintn(buffer=""):
+
+ r"""
+ Simply return the user's buffer with a line feed. This function is used
+ by the qprint and dprint functions defined dynamically below, i.e. it
+ would not normally be called for general use.
+
+ Description of arguments.
+ buffer This will be returned to the caller.
+ """
+
+ buffer = str(buffer) + "\n"
+
return buffer
###############################################################################
@@ -959,9 +1038,10 @@
# func_names contains a list of all print functions which should be created
# from their sprint counterparts.
func_names = ['print_time', 'print_timen', 'print_error', 'print_varx',
- 'print_var', 'print_dashes', 'print_call_stack',
+ 'print_var', 'print_dashes', 'indent', 'print_call_stack',
'print_func_name', 'print_executing', 'print_pgm_header',
- 'issuing', 'print_pgm_footer', 'print_error_report', 'print']
+ 'issuing', 'print_pgm_footer', 'print_error_report', 'print',
+ 'printn']
for func_name in func_names:
if func_name == "print":
diff --git a/lib/gen_valid.py b/lib/gen_valid.py
index 1a52ace..e0337b4 100755
--- a/lib/gen_valid.py
+++ b/lib/gen_valid.py
@@ -10,15 +10,15 @@
import gen_print as gp
-
###############################################################################
-def valid_value(var_value,
- invalid_values=[""],
- valid_values=[]):
+def svalid_value(var_value,
+ invalid_values=[],
+ valid_values=[],
+ var_name=""):
r"""
- Return True if var_value is a valid value. Otherwise, return False and
- print an error message to stderr.
+ Return an empty string if var_value is a valid value. Otherwise, return
+ an error string.
Description of arguments:
var_value The value being validated.
@@ -30,50 +30,135 @@
valid_values A list of invalid values. var_value must
be equal to one of these values to be
considered valid.
+ var_name The name of the variable whose value is
+ passed in var_value. This parameter is
+ normally unnecessary as this function can
+ figure out the var_name. This is provided
+ for Robot callers. In this scenario, we
+ are unable to get the variable name
+ ourselves.
"""
+ success_message = ""
+ error_message = ""
+ stack_frame_ix = 3
+
len_valid_values = len(valid_values)
len_invalid_values = len(invalid_values)
if len_valid_values > 0 and len_invalid_values > 0:
- gp.print_error_report("Programmer error - You must provide either an" +
- " invalid_values list or a valid_values" +
- " list but NOT both.")
- return False
+ error_message += "Programmer error - You must provide either an" +\
+ " invalid_values list or a valid_values" +\
+ " list but NOT both.\n" +\
+ gp.sprint_var(invalid_values) +\
+ gp.sprint_var(valid_values)
+ return error_message
+ show_blanks = 1
if len_valid_values > 0:
# Processing the valid_values list.
if var_value in valid_values:
- return True
- var_name = gp.get_arg_name(0, 1, 2)
- gp.print_error_report("The following variable has an invalid" +
- " value:\n" +
- gp.sprint_varx(var_name, var_value) +
- "\nIt must be one of the following values:\n" +
- gp.sprint_varx("valid_values", valid_values))
- return False
+ return success_message
+ if var_name == "":
+ var_name = gp.get_arg_name(0, 1, stack_frame_ix)
+ error_message += "The following variable has an invalid" +\
+ " value:\n" +\
+ gp.sprint_varx(var_name, var_value, show_blanks) +\
+ "\nIt must be one of the following values:\n" +\
+ gp.sprint_varx("valid_values", valid_values,
+ show_blanks)
+ return error_message
if len_invalid_values == 0:
- gp.print_error_report("Programmer error - You must provide either an" +
- " invalid_values list or a valid_values" +
- " list. Both are empty.")
- return False
+ # Assign default value.
+ invalid_values = [""]
# Assertion: We have an invalid_values list. Processing it now.
if var_value not in invalid_values:
- return True
+ return success_message
- var_name = gp.get_arg_name(0, 1, 2)
- gp.print_error_report("The following variable has an invalid value:\n" +
- gp.sprint_varx(var_name, var_value) + "\nIt must" +
- " NOT be one of the following values:\n" +
- gp.sprint_varx("invalid_values", invalid_values))
- return False
+ if var_name == "":
+ var_name = gp.get_arg_name(0, 1, stack_frame_ix)
+ error_message += "The following variable has an invalid value:\n" +\
+ gp.sprint_varx(var_name, var_value, show_blanks) +\
+ "\nIt must NOT be one of the following values:\n" +\
+ gp.sprint_varx("invalid_values", invalid_values,
+ show_blanks)
+ return error_message
###############################################################################
###############################################################################
-def valid_integer(var_value):
+def valid_value(var_value,
+ invalid_values=[],
+ valid_values=[],
+ var_name=""):
+
+ r"""
+ Return True if var_value is a valid value. Otherwise, return False and
+ print an error message to stderr.
+
+ Description of arguments:
+ (See description of arguments for svalid_value (above).
+ """
+
+ error_message = svalid_value(var_value, invalid_values, valid_values,
+ var_name)
+
+ if not error_message == "":
+ gp.print_error_report(error_message)
+ return False
+ return True
+
+###############################################################################
+
+
+###############################################################################
+def svalid_integer(var_value,
+ var_name=""):
+
+ r"""
+ Return an empty string if var_value is a valid integer. Otherwise, return
+ an error string.
+
+ Description of arguments:
+ var_value The value being validated.
+ var_name The name of the variable whose value is
+ passed in var_value. This parameter is
+ normally unnecessary as this function can
+ figure out the var_name. This is provided
+ for Robot callers. In this scenario, we
+ are unable to get the variable name
+ ourselves.
+ """
+
+ # This currently allows floats which is not good.
+
+ success_message = ""
+ error_message = ""
+ try:
+ if type(int(var_value)) is int:
+ return success_message
+ except ValueError:
+ pass
+
+ # If we get to this point, the validation has failed.
+ if var_name is "":
+ stack_index = 3
+ var_name = gp.get_arg_name(0, 1, stack_index)
+
+ show_blanks = 1
+ error_message += "Invalid integer value:\n" +\
+ gp.sprint_varx(var_name, var_value, show_blanks)
+
+ return error_message
+
+###############################################################################
+
+
+###############################################################################
+def valid_integer(var_value,
+ var_name=""):
r"""
Return True if var_value is a valid integer. Otherwise, return False and
@@ -85,20 +170,11 @@
# This currently allows floats which is not good.
- try:
- if type(int(var_value)) is int:
- return True
- except ValueError:
- pass
+ error_message = svalid_integer(var_value, var_name)
- # If we get to this point, the validation has failed.
-
- var_name = gp.get_arg_name(0, 1, 2)
- gp.print_varx("var_name", var_name)
-
- gp.print_error_report("Invalid integer value:\n" +
- gp.sprint_varx(var_name, var_value))
-
- return False
+ if not error_message == "":
+ gp.print_error_report(error_message)
+ return False
+ return True
###############################################################################