sprint_varx indent, col1_width, fmt, delim, etc.
- sprint_varx():
- Changes to arguments:
- loc_col1_indent renamed to indent.
- loc_col1_width renamed to col1_width.
- Replaced hex arg with fmt arg. Made code changes to implement the
following fmt options:
- hexa
- octal
- binary
- blank
- terse
- quote_keys
- show_type
Also added support for the fmt arg in list form.
- Added support for delim arg.
- Did some code cleanup and optimization.
- General cleanup of code:
- Fixed spelling or wording errors in documentation.
- Changed "Description of arguments" to "Description of argument(s)".
- Changed informal use of "I" and "you" in documentation.
- Global value changes:
- col1_indent renamed to dft_indent.
- col1_width renamed to dft_col1_width.
- Changed is_dict() to return a code indicating the type of dictionary (vs
simply returning 1). Created constant functions to be used for the various
dictionary types.
- get_int_types(): New function to help clean up sprint_varx implementation.
- get_string_types(): New function to help clean up sprint_varx implementation.
- New valid_fmts(), create_fmt_definition(), list_pop() and parse_fmt() to
assist sprint_varx in processing new fmt argument.
- sprint_var(): Changed from hard-coding all arguments to using *args and
**kwargs.
- sprint_vars(): Added **kwargs to allow callers to specify named parms on
calls. Then removed support for positional values like indent and
col1_width.
- Changed print_var calls to use new arg names and new fmt values.
- Switched from print_varx to print_var where possible.
Change-Id: Ie754368d5b8424cd90842401ab3cad7ca1df7ca6
Signed-off-by: Michael Walsh <micwalsh@us.ibm.com>
diff --git a/lib/gen_print.py b/lib/gen_print.py
index 4cc16e0..f0bc76d 100755
--- a/lib/gen_print.py
+++ b/lib/gen_print.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python
r"""
-This module provides many valuable print functions such as sprint_var,
-sprint_time, sprint_error, sprint_call_stack.
+This module provides many print functions such as sprint_var, sprint_time,
+sprint_error, sprint_call_stack.
"""
import sys
@@ -13,6 +13,7 @@
import grp
import socket
import argparse
+import copy
try:
import __builtin__
except ImportError:
@@ -51,26 +52,25 @@
pgm_name_var_name = pgm_name.replace(".", "_")
# Initialize global values used as defaults by print_time, print_var, etc.
-col1_indent = 0
+dft_indent = 0
# Calculate default column width for print_var functions based on environment
# variable settings. The objective is to make the variable values line up
# nicely with the time stamps.
-col1_width = 29
+dft_col1_width = 29
NANOSECONDS = os.environ.get('NANOSECONDS', '1')
-
if NANOSECONDS == "1":
- col1_width = col1_width + 7
+ dft_col1_width = dft_col1_width + 7
SHOW_ELAPSED_TIME = os.environ.get('SHOW_ELAPSED_TIME', '1')
if SHOW_ELAPSED_TIME == "1":
if NANOSECONDS == "1":
- col1_width = col1_width + 14
+ dft_col1_width = dft_col1_width + 14
else:
- col1_width = col1_width + 7
+ dft_col1_width = dft_col1_width + 7
# Initialize some time variables used in module functions.
start_time = time.time()
@@ -122,7 +122,7 @@
r"""
Return the function name associated with the indicated stack frame.
- Description of arguments:
+ Description of argument(s):
stack_frame_ix The index of the stack frame whose
function name should be returned. If the
caller does not specify a value, this
@@ -153,9 +153,9 @@
Work around the inspect.stack() getcwd() failure by making "/tmp" the
current working directory.
- If the current working directory has been deleted, inspect.stack() will
- fail with "OSError: [Errno 2] No such file or directory" because it tries
- to do a getcwd().
+ NOTES: If the current working directory has been deleted, inspect.stack()
+ will fail with "OSError: [Errno 2] No such file or directory" because it
+ tries to do a getcwd().
This function will try to prevent this failure by detecting the scenario
in advance and making "/tmp" the current working directory.
@@ -174,8 +174,8 @@
return len(line) - len(line.lstrip(' '))
-# get_arg_name is not a print function per se. I have included it in this
-# module because it is used by sprint_var which is found in this module.
+# get_arg_name is not a print function per se. It has been included in this
+# module because it is used by sprint_var which is defined in this module.
def get_arg_name(var,
arg_num=1,
stack_frame_ix=1):
@@ -183,8 +183,8 @@
Return the "name" of an argument passed to a function. This could be a
literal or a variable name.
- Description of arguments:
- var The variable whose name you want returned.
+ Description of argument(s):
+ var The variable whose name is to be returned.
arg_num The arg number whose name is to be
returned. To illustrate how arg_num is
processed, suppose that a programmer codes
@@ -232,8 +232,9 @@
def test1(var):
# Getting the var name of the first arg to this function, test1.
- # Note, in this case, it doesn't matter what you pass as the first arg
- # to get_arg_name since it is the caller's variable name that matters.
+ # Note, in this case, it doesn't matter what is passed as the first
+ # arg to get_arg_name since it is the caller's variable name that
+ # matters.
dummy = 1
arg_num = 1
stack_frame = 2
@@ -248,8 +249,8 @@
"""
- # Note: I wish to avoid recursion so I refrain from calling any function
- # that calls this function (i.e. sprint_var, valid_value, etc.).
+ # Note: To avoid infinite recursion, avoid calling any function that
+ # calls this function (e.g. sprint_var, valid_value, etc.).
# The user can set environment variable "GET_ARG_NAME_DEBUG" to get debug
# output from this function.
@@ -272,9 +273,9 @@
print("")
print_dashes(0, 120)
print(sprint_func_name() + "() parms:")
- print_varx("var", var, 0, debug_indent)
- print_varx("arg_num", arg_num, 0, debug_indent)
- print_varx("stack_frame_ix", stack_frame_ix, 0, debug_indent)
+ print_varx("var", var, indent=debug_indent)
+ print_varx("arg_num", arg_num, indent=debug_indent)
+ print_varx("stack_frame_ix", stack_frame_ix, indent=debug_indent)
print("")
print_call_stack(debug_indent, 2)
@@ -300,15 +301,15 @@
stack_frame_ix += 1
if local_debug:
print("Adjusted stack_frame_ix...")
- print_varx("stack_frame_ix", stack_frame_ix, 0, debug_indent)
+ print_varx("stack_frame_ix", stack_frame_ix, indent=debug_indent)
real_called_func_name = sprint_func_name(stack_frame_ix)
module = inspect.getmodule(frame)
- # Though I would expect inspect.getsourcelines(frame) to get all module
+ # Though one would expect inspect.getsourcelines(frame) to get all module
# source lines if the frame is "<module>", it doesn't do that. Therefore,
- # for this special case, I will do inspect.getsourcelines(module).
+ # for this special case, do inspect.getsourcelines(module).
if function_name == "<module>":
source_lines, source_line_num =\
inspect.getsourcelines(module)
@@ -320,18 +321,18 @@
if local_debug:
print("\n Variables retrieved from inspect.stack() function:")
- print_varx("frame", frame, 0, debug_indent + 2)
- print_varx("filename", filename, 0, debug_indent + 2)
- print_varx("cur_line_no", cur_line_no, 0, debug_indent + 2)
- print_varx("function_name", function_name, 0, debug_indent + 2)
- print_varx("lines", lines, 0, debug_indent + 2)
- print_varx("index", index, 0, debug_indent + 2)
- print_varx("source_line_num", source_line_num, 0, debug_indent)
- print_varx("line_ix", line_ix, 0, debug_indent)
+ print_varx("frame", frame, indent=debug_indent + 2)
+ print_varx("filename", filename, indent=debug_indent + 2)
+ print_varx("cur_line_no", cur_line_no, indent=debug_indent + 2)
+ print_varx("function_name", function_name, indent=debug_indent + 2)
+ print_varx("lines", lines, indent=debug_indent + 2)
+ print_varx("index", index, indent=debug_indent + 2)
+ print_varx("source_line_num", source_line_num, indent=debug_indent)
+ print_varx("line_ix", line_ix, indent=debug_indent)
if local_debug_show_source:
- print_varx("source_lines", source_lines, 0, debug_indent)
- print_varx("real_called_func_name", real_called_func_name, 0,
- debug_indent)
+ print_varx("source_lines", source_lines, indent=debug_indent)
+ print_varx("real_called_func_name", real_called_func_name,
+ indent=debug_indent)
# Get a list of all functions defined for the module. Note that this
# doesn't work consistently when _run_exitfuncs is at the top of the stack
@@ -440,20 +441,20 @@
called_func_name = re.sub(called_func_name_regex, "\\4", composite_line)
arg_list_etc = "(" + re.sub(pre_args_regex, "", composite_line)
if local_debug:
- print_varx("aliases", aliases, 0, debug_indent)
- print_varx("import_name_regex", import_name_regex, 0, debug_indent)
- print_varx("func_name_regex", func_name_regex, 0, debug_indent)
- print_varx("pre_args_regex", pre_args_regex, 0, debug_indent)
- print_varx("start_line_ix", start_line_ix, 0, debug_indent)
- print_varx("end_line_ix", end_line_ix, 0, debug_indent)
- print_varx("composite_line", composite_line, 0, debug_indent)
- print_varx("lvalue_regex", lvalue_regex, 0, debug_indent)
- print_varx("lvalue_string", lvalue_string, 0, debug_indent)
- print_varx("lvalues", lvalues, 0, debug_indent)
- print_varx("called_func_name_regex", called_func_name_regex, 0,
- debug_indent)
- print_varx("called_func_name", called_func_name, 0, debug_indent)
- print_varx("arg_list_etc", arg_list_etc, 0, debug_indent)
+ print_varx("aliases", aliases, indent=debug_indent)
+ print_varx("import_name_regex", import_name_regex, indent=debug_indent)
+ print_varx("func_name_regex", func_name_regex, indent=debug_indent)
+ print_varx("pre_args_regex", pre_args_regex, indent=debug_indent)
+ print_varx("start_line_ix", start_line_ix, indent=debug_indent)
+ print_varx("end_line_ix", end_line_ix, indent=debug_indent)
+ print_varx("composite_line", composite_line, indent=debug_indent)
+ print_varx("lvalue_regex", lvalue_regex, indent=debug_indent)
+ print_varx("lvalue_string", lvalue_string, indent=debug_indent)
+ print_varx("lvalues", lvalues, indent=debug_indent)
+ print_varx("called_func_name_regex", called_func_name_regex,
+ indent=debug_indent)
+ print_varx("called_func_name", called_func_name, indent=debug_indent)
+ print_varx("arg_list_etc", arg_list_etc, indent=debug_indent)
# Parse arg list...
# Initialize...
@@ -500,8 +501,8 @@
argument = args_list[arg_num - 1]
if local_debug:
- print_varx("args_list", args_list, 0, debug_indent)
- print_varx("argument", argument, 0, debug_indent)
+ print_varx("args_list", args_list, indent=debug_indent)
+ print_varx("argument", argument, indent=debug_indent)
print_dashes(0, 120)
return argument
@@ -561,7 +562,7 @@
#(CDT) 2016/08/03 17:18:47.317339 - 0.000046 - Hi.
- Description of arguments.
+ Description of argument(s).
buffer This will be appended to the formatted
time string.
"""
@@ -622,7 +623,7 @@
#(CDT) 2016/08/03 17:12:05 - **ERROR** Oops.
- Description of arguments.
+ Description of argument(s).
buffer This will be appended to the formatted
error string.
"""
@@ -661,8 +662,8 @@
# Consider a single nibble whose signed values can range from -8 to 7
# (0x8 to 0x7). A value of 0x7 equals 0b0111. Therefore, its length
# in bits is 3. Since the negative bit (i.e. 0b1000) is not set, the
- # value 7 clearly will fit in one nibble. With -8 = 0x8 = 0b1000, you
- # have the smallest negative value that will fit. Note that it
+ # value 7 clearly will fit in one nibble. With -8 = 0x8 = 0b1000, one
+ # has the smallest negative value that will fit. Note that it
# requires 3 bits of 0. So by converting a number value of -8 to a
# working_number of 7, this function can accurately calculate the
# number of bits and therefore nibbles required to represent the
@@ -695,8 +696,8 @@
# Consider a single nibble whose signed values can range from -8 to 7
# (0x8 to 0x7). A value of 0x7 equals 0b0111. Therefore, its length
# in bits is 3. Since the negative bit (i.e. 0b1000) is not set, the
- # value 7 clearly will fit in one nibble. With -8 = 0x8 = 0b1000, you
- # have the smallest negative value that will fit. Note that it
+ # value 7 clearly will fit in one nibble. With -8 = 0x8 = 0b1000, one
+ # has the smallest negative value that will fit. Note that it
# requires 3 bits of 0. So by converting a number value of -8 to a
# working_number of 7, this function can accurately calculate the
# number of bits and therefore nibbles required to represent the
@@ -751,41 +752,285 @@
return _gen_print_dft_num_hex_digits_
+# Create constant functions to describe various types of dictionaries.
+def dict_type():
+ return 1
+
+
+def ordered_dict_type():
+ return 2
+
+
+def dot_dict_type():
+ return 3
+
+
+def normalized_dict_type():
+ return 4
+
+
def is_dict(var_value):
r"""
- Return 1 if var_value is a type of dictionary and 0 if it is not.
+ Return non-zero if var_value is a type of dictionary and 0 if it is not.
+
+ The specific non-zero value returned will indicate what type of dictionary
+ var_value is (see constant functions above).
+
+ Description of argument(s):
+ var_value The object to be analyzed to determine
+ whether it is a dictionary and if so, what
+ type of dictionary.
"""
type_is_dict = 0
if isinstance(var_value, dict):
- type_is_dict = 1
+ type_is_dict = dict_type()
try:
if isinstance(var_value, collections.OrderedDict):
- type_is_dict = 1
+ type_is_dict = ordered_dict_type()
except AttributeError:
pass
try:
if isinstance(var_value, DotDict):
- type_is_dict = 1
+ type_is_dict = dot_dict_type()
except NameError:
pass
try:
if isinstance(var_value, NormalizedDict):
- type_is_dict = 1
+ type_is_dict = normalized_dict_type()
except NameError:
pass
return type_is_dict
+def get_int_types():
+ r"""
+ Return a tuple consisting of the valid integer data types for the system
+ and version of python being run.
+
+ Example:
+ (int, long)
+ """
+
+ try:
+ int_types = (int, long)
+ except NameError:
+ int_types = (int,)
+ return int_types
+
+
+def get_string_types():
+ r"""
+ Return a tuple consisting of the valid string data types for the system
+ and version of python being run.
+
+ Example:
+ (str, unicode)
+ """
+
+ try:
+ string_types = (str, unicode)
+ except NameError:
+ string_types = (bytes, str)
+ return string_types
+
+
+def valid_fmts():
+ r"""
+ Return a list of the valid formats that can be specified for the fmt
+ argument of the sprint_varx function (defined below).
+ """
+
+ return [
+ 'hexa',
+ 'octal',
+ 'binary',
+ 'blank',
+ 'terse',
+ 'quote_keys',
+ 'show_type']
+
+
+def create_fmt_definition():
+ r"""
+ Create a string consisting of function-definition code that can be
+ executed to create constant fmt definition functions.
+
+ These functions can be used by callers of sprint_var/sprint_varx to set
+ the fmt argument correctly.
+
+ Likewise, the sprint_varx function will use these generated functions to
+ correctly interpret the fmt argument.
+
+ Example output from this function:
+
+ def hexa():
+ return 0x00000001
+ def octal_fmt():
+ return 0x00000002
+ etc.
+ """
+
+ buffer = ""
+ bits = 0x00000001
+ for fmt_name in valid_fmts():
+ buffer += "def " + fmt_name + "():\n"
+ buffer += " return " + "0x%08x" % bits + "\n"
+ bits = bits << 1
+ return buffer
+
+
+# Dynamically create fmt definitions (for use with the fmt argument of
+# sprint_varx function):
+exec(create_fmt_definition())
+
+
+def list_pop(a_list, index=0, default=None):
+ r"""
+ Pop the list entry indicated by the index and return the entry. If no
+ such entry exists, return default.
+
+ Note that the list passed to this function will be modified.
+
+ Description of argument(s):
+ a_list The list from which an entry is to be
+ popped.
+ index The index indicating which entry is to be
+ popped.
+ default The value to be returned if there is no
+ entry at the given index location.
+ """
+ try:
+ return a_list.pop(index)
+ except IndexError:
+ return default
+
+
+def parse_fmt(fmt):
+ r"""
+ Parse the fmt argument and return a tuple consisting of a format and a
+ child format.
+
+ This function was written for use by the sprint_varx function defined in
+ this module.
+
+ When sprint_varx is processing a multi-level object such as a list or
+ dictionary (which in turn may contain other lists or dictionaries), it
+ will use the fmt value to dictate the print formatting of the current
+ level and the child_fmt value to dictate the print formatting of
+ subordinate levels. Consider the following example:
+
+ python code example:
+
+ ord_dict = \
+ collections.OrderedDict([
+ ('one', 1),
+ ('two', 2),
+ ('sub',
+ collections.OrderedDict([
+ ('three', 3), ('four', 4)]))])
+
+ print_var(ord_dict)
+
+ This would generate the following output:
+
+ ord_dict:
+ ord_dict[one]: 1
+ ord_dict[two]: 2
+ ord_dict[sub]:
+ ord_dict[sub][three]: 3
+ ord_dict[sub][four]: 4
+
+ The first level in this example is the line that simply says "ord_dict".
+ The second level is comprised of the dictionary entries with the keys
+ 'one', 'two' and 'sub'. The third level is comprised of the last 2 lines
+ (i.e. printed values 3 and 4).
+
+ Given the data structure shown above, the programmer could code the
+ following where fmt is a simple integer value set by calling the terse()
+ function.
+
+ print_var(ord_dict, fmt=terse())
+
+ The output would look like this:
+
+ ord_dict:
+ [one]: 1
+ [two]: 2
+ [sub]:
+ [three]: 3
+ [four]: 4
+
+ Note the terse format where the name of the object ("ord_dict") is not
+ repeated on every line as it was in example #1.
+
+ If the programmer wishes to get more granular with the fmt argument,
+ he/she can specify it as a list where each entry corresponds to a level of
+ the object being printed. The last such list entry governs the print
+ formatting of all subordinate parts of the given object.
+
+ Look at each of the following code examples and their corresponding
+ output. See how the show_type() formatting affects the printing depending
+ on which position it occupies in the fmt list argument:
+
+ print_var(ord_dict, fmt=[show_type()])
+
+ ord_dict: <collections.OrderedDict>
+ ord_dict[one]: 1 <int>
+ ord_dict[two]: 2 <int>
+ ord_dict[sub]: <collections.OrderedDict>
+ ord_dict[sub][three]: 3 <int>
+ ord_dict[sub][four]: 4 <int>
+
+ print_var(ord_dict, fmt=[0, show_type()])
+
+ ord_dict:
+ ord_dict[one]: 1 <int>
+ ord_dict[two]: 2 <int>
+ ord_dict[sub]: <collections.OrderedDict>
+ ord_dict[sub][three]: 3 <int>
+ ord_dict[sub][four]: 4 <int>
+
+ print_var(ord_dict, fmt=[0, 0, show_type()])
+
+ ord_dict:
+ ord_dict[one]: 1
+ ord_dict[two]: 2
+ ord_dict[sub]:
+ ord_dict[sub][three]: 3 <int>
+ ord_dict[sub][four]: 4 <int>
+
+ Description of argument(s):
+ fmt The format argument such as is passed to
+ sprint_varx. This argument may be an
+ integer or a list of integers. See the
+ prolog of sprint_varx for more details.
+ """
+
+ # Make a deep copy of the fmt argument in order to avoid modifying the
+ # caller's fmt value when it is a list.
+ fmt = copy.deepcopy(fmt)
+ try:
+ # Assume fmt is a list. Pop the first element from the list.
+ first_element = list_pop(fmt, index=0, default=0)
+ # Return the first list element along with either 1) the remainder of
+ # the fmt list if not null or 2) another copy of the first element.
+ return first_element, fmt if len(fmt) else first_element
+ except AttributeError:
+ # fmt is not a list so treat it as a simple integer value.
+ return fmt, fmt
+
+
def sprint_varx(var_name,
var_value,
- hex=0,
- loc_col1_indent=col1_indent,
- loc_col1_width=col1_width,
+ fmt=0,
+ indent=dft_indent,
+ col1_width=dft_col1_width,
trailing_char="\n",
- key_list=None):
+ key_list=None,
+ delim=":"):
r"""
- Print the var name/value passed to it. If the caller lets loc_col1_width
+ Print the var name/value passed to it. If the caller lets col1_width
default, the printing lines up nicely with output generated by the
print_time functions.
@@ -822,21 +1067,44 @@
my_dict[two]: 2
my_dict[one]: 1
- Description of arguments.
+ Description of argument(s).
var_name The name of the variable to be printed.
var_value The value of the variable to be printed.
- 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. For string
- var_values, this will be interpreted as
- show_blanks which means that blank values
- will be printed as "<blank>". For dict
- var_values, this will be interpreted as
- terse format where keys are not repeated
- in the output.
- loc_col1_indent The number of spaces to indent the output.
- loc_col1_width The width of the output column containing
+ fmt A bit map to dictate the format of the
+ output. For printing multi-level objects
+ like lists and dictionaries, this argument
+ may also be a list of bit maps. The first
+ list element pertains to the highest level
+ of output, the second element pertains to
+ the 2nd level of output, etc. The last
+ element in the list pertains to all
+ subordinate levels. The bits can be set
+ using the dynamically created functionhs
+ above. Example: sprint_varx("var1", var1,
+ fmt=terse()). Note that these values can
+ be OR'ed together: print_var(var1, hexa()
+ | terse()). If the caller ORs mutually
+ exclusive bits (hexa() | octal()),
+ behavior is not guaranteed. The following
+ features are supported:
+ hexa Print all integer values in hexadecimal
+ format.
+ octal Print all integer values in octal format.
+ binary Print all integer values in binary format.
+ blank For blank string values, print "<blank>"
+ instead of an actual blank.
+ terse For structured values like dictionaries,
+ lists, etc. do not repeat the name of the
+ variable on each line to the right of the
+ key or subscript value. Example: print
+ "[key1]" instead of "my_dict[key1]".
+ quote_keys Quote dictionary keys in the output.
+ Example: my_dict['key1'] instead of
+ my_dict[key1].
+ show_type Show the type of the data in angled
+ brackets just to the right of the data.
+ indent The number of spaces to indent the output.
+ col1_width The width of the output column containing
the variable name. The default value of
this is adjusted so that the var_value
lines up with text printed via the
@@ -860,31 +1128,31 @@
names begin with "one" will be printed.
Note: This argument pertains only to
var_values which are dictionaries.
+ delim The value to be used to delimit the
+ variable name from the variable value in
+ the output.
"""
- # Determine the type
- try:
- int_types = (int, long)
- except NameError:
- int_types = (int,)
- try:
- string_types = (str, unicode)
- except NameError:
- string_types = (bytes, str)
- simple_types = int_types + string_types + (float, bool)
- if type(var_value) in simple_types \
- or var_value is None:
+ fmt, child_fmt = parse_fmt(fmt)
+
+ if fmt & show_type():
+ type_str = "<" + str(type(var_value)).split("'")[1] + ">"
+ # Compose object type categories.
+ int_types = get_int_types()
+ string_types = get_string_types()
+ simple_types = int_types + string_types + (float, bool, type, type(None))
+ # Determine the type.
+ if type(var_value) in simple_types:
# The data type is simple in the sense that it has no subordinate
# parts.
- # Adjust loc_col1_width.
- loc_col1_width = loc_col1_width - loc_col1_indent
- # See if the user wants the output in hex format.
- if hex:
- if type(var_value) not in int_types:
- value_format = "%s"
- if var_value == "":
- var_value = "<blank>"
- else:
+ # Adjust col1_width.
+ col1_width = col1_width - indent
+ # Set default value for value_format.
+ value_format = "%s"
+ # Process format requests.
+ if type(var_value) in int_types:
+ # Process format values pertaining to int types.
+ if fmt & hexa():
num_hex_digits = max(dft_num_hex_digits(),
get_req_num_hex_digits(var_value))
# Convert a negative number to its positive twos complement
@@ -893,24 +1161,52 @@
# "0xffffffffffffffff".
var_value = var_value & (2 ** (num_hex_digits * 4) - 1)
value_format = "0x%0" + str(num_hex_digits) + "x"
- else:
- value_format = "%s"
- format_string = "%" + str(loc_col1_indent) + "s%-" \
- + str(loc_col1_width) + "s" + value_format + trailing_char
+ elif fmt & octal():
+ value_format = "0o%016o"
+ elif fmt & binary():
+ num_digits, remainder = \
+ divmod(max(bit_length(var_value), 1), 8)
+ num_digits *= 8
+ if remainder:
+ num_digits += 8
+ num_digits += 2
+ value_format = '#0' + str(num_digits) + 'b'
+ var_value = format(var_value, value_format)
+ value_format = "%s"
+ elif type(var_value) in string_types:
+ # Process format values pertaining to string types.
+ if fmt & blank() and var_value == "":
+ value_format = "%s"
+ var_value = "<blank>"
+ elif type(var_value) is type:
+ var_value = str(var_value).split("'")[1]
+ format_string = "%" + str(indent) + "s%-" + str(col1_width) + "s" \
+ + value_format
+ if fmt & show_type():
+ if var_value != "":
+ format_string += " "
+ format_string += type_str
+ format_string += trailing_char
+ if fmt & terse():
+ # Strip everything leading up to the first left square brace.
+ var_name = re.sub(r".*\[", "[", var_name)
if value_format == "0x%08x":
- return format_string % ("", str(var_name) + ":",
+ return format_string % ("", str(var_name) + delim,
var_value & 0xffffffff)
else:
- return format_string % ("", str(var_name) + ":", var_value)
- elif isinstance(var_value, type):
- return sprint_varx(var_name, str(var_value).split("'")[1], hex,
- loc_col1_indent, loc_col1_width, trailing_char,
- key_list)
+ return format_string % ("", str(var_name) + delim, var_value)
else:
# The data type is complex in the sense that it has subordinate parts.
- format_string = "%" + str(loc_col1_indent) + "s%s\n"
- buffer = format_string % ("", var_name + ":")
- loc_col1_indent += 2
+ if fmt & terse():
+ # Strip everything leading up to the first square brace.
+ loc_var_name = re.sub(r".*\[", "[", var_name)
+ else:
+ loc_var_name = var_name
+ format_string = "%" + str(indent) + "s%s\n"
+ buffer = format_string % ("", loc_var_name + ":")
+ if fmt & show_type():
+ buffer = buffer.replace("\n", " " + type_str + "\n")
+ indent += 2
try:
length = len(var_value)
except TypeError:
@@ -918,6 +1214,10 @@
ix = 0
loc_trailing_char = "\n"
if is_dict(var_value):
+ if type(child_fmt) is list:
+ child_quote_keys = (child_fmt[0] & quote_keys())
+ else:
+ child_quote_keys = (child_fmt & quote_keys())
for key, value in var_value.items():
if key_list is not None:
key_list_regex = "^" + "|".join(key_list) + "$"
@@ -926,37 +1226,27 @@
ix += 1
if ix == length:
loc_trailing_char = trailing_char
- if hex:
- # Since hex is being used as a format type, we want it
- # turned off when processing integer dictionary values so
- # it is not interpreted as a hex indicator.
- loc_hex = not (isinstance(value, int))
- buffer += sprint_varx("[" + key + "]", value,
- loc_hex, loc_col1_indent,
- loc_col1_width,
- loc_trailing_char,
- key_list)
- else:
- buffer += sprint_varx(var_name + "[" + str(key) + "]",
- value, hex, loc_col1_indent,
- loc_col1_width, loc_trailing_char,
- key_list)
+ if child_quote_keys:
+ key = "'" + key + "'"
+ key = "[" + str(key) + "]"
+ buffer += sprint_varx(var_name + key, value, child_fmt, indent,
+ col1_width, loc_trailing_char, key_list)
elif type(var_value) in (list, tuple, set):
for key, value in enumerate(var_value):
ix += 1
if ix == length:
loc_trailing_char = trailing_char
- buffer += sprint_varx(var_name + "[" + str(key) + "]", value,
- hex, loc_col1_indent, loc_col1_width,
- loc_trailing_char, key_list)
+ key = "[" + str(key) + "]"
+ buffer += sprint_varx(var_name + key, value, child_fmt, indent,
+ col1_width, loc_trailing_char, key_list)
elif isinstance(var_value, argparse.Namespace):
for key in var_value.__dict__:
ix += 1
if ix == length:
loc_trailing_char = trailing_char
cmd_buf = "buffer += sprint_varx(var_name + \".\" + str(key)" \
- + ", var_value." + key + ", hex, loc_col1_indent," \
- + " loc_col1_width, loc_trailing_char, key_list)"
+ + ", var_value." + key + ", child_fmt, indent," \
+ + " col1_width, loc_trailing_char, key_list)"
exec(cmd_buf)
else:
var_type = type(var_value).__name__
@@ -964,11 +1254,11 @@
var_value = "<" + var_type + " type not supported by " + \
func_name + "()>"
value_format = "%s"
- loc_col1_indent -= 2
- # Adjust loc_col1_width.
- loc_col1_width = loc_col1_width - loc_col1_indent
- format_string = "%" + str(loc_col1_indent) + "s%-" \
- + str(loc_col1_width) + "s" + value_format + trailing_char
+ indent -= 2
+ # Adjust col1_width.
+ col1_width = col1_width - indent
+ format_string = "%" + str(indent) + "s%-" \
+ + str(col1_width) + "s" + value_format + trailing_char
return format_string % ("", str(var_name) + ":", var_value)
return buffer
@@ -976,109 +1266,59 @@
return ""
-def sprint_var(var_value,
- hex=0,
- loc_col1_indent=col1_indent,
- loc_col1_width=col1_width,
- trailing_char="\n",
- key_list=None):
+def sprint_var(*args, **kwargs):
r"""
- Figure out the name of the first argument for you and then call
+ Figure out the name of the first argument for the caller and then call
sprint_varx with it. Therefore, the following 2 calls are equivalent:
sprint_varx("var1", var1)
sprint_var(var1)
+
+ See sprint_varx for description of arguments.
"""
- # Get the name of the first variable passed to this function.
stack_frame = 2
caller_func_name = sprint_func_name(2)
if caller_func_name.endswith("print_var"):
stack_frame += 1
+ # Get the name of the first variable passed to this function.
var_name = get_arg_name(None, 1, stack_frame)
- return sprint_varx(var_name, var_value=var_value, hex=hex,
- loc_col1_indent=loc_col1_indent,
- loc_col1_width=loc_col1_width,
- trailing_char=trailing_char,
- key_list=key_list)
+ return sprint_varx(var_name, *args, **kwargs)
-def sprint_vars(*args):
+def sprint_vars(*args, **kwargs):
r"""
Sprint the values of one or more variables.
- Description of args:
- args:
- If the first argument is an integer, it will be interpreted to be the
- "indent" value.
- If the second argument is an integer, it will be interpreted to be the
- "col1_width" value.
- If the third argument is an integer, it will be interpreted to be the
- "hex" value.
- All remaining parms are considered variable names which are to be
- sprinted.
+ Description of argument(s):
+ args The variable values which are to be
+ printed.
+ kwargs See sprint_varx (above) for description of
+ additional arguments.
"""
- if len(args) == 0:
- return
-
- # Get the name of the first variable passed to this function.
stack_frame = 2
caller_func_name = sprint_func_name(2)
if caller_func_name.endswith("print_vars"):
stack_frame += 1
- parm_num = 1
-
- # Create list from args (which is a tuple) so that it can be modified.
- args_list = list(args)
-
- var_name = get_arg_name(None, parm_num, stack_frame)
- # See if parm 1 is to be interpreted as "indent".
- try:
- if isinstance(int(var_name), int):
- indent = int(var_name)
- args_list.pop(0)
- parm_num += 1
- except ValueError:
- indent = 0
-
- var_name = get_arg_name(None, parm_num, stack_frame)
- # See if parm 1 is to be interpreted as "col1_width".
- try:
- if isinstance(int(var_name), int):
- loc_col1_width = int(var_name)
- args_list.pop(0)
- parm_num += 1
- except ValueError:
- loc_col1_width = col1_width
-
- var_name = get_arg_name(None, parm_num, stack_frame)
- # See if parm 1 is to be interpreted as "hex".
- try:
- if isinstance(int(var_name), int):
- hex = int(var_name)
- args_list.pop(0)
- parm_num += 1
- except ValueError:
- hex = 0
-
buffer = ""
- for var_value in args_list:
- var_name = get_arg_name(None, parm_num, stack_frame)
- buffer += sprint_varx(var_name, var_value, hex, indent, loc_col1_width)
- parm_num += 1
+ arg_num = 1
+ for var_value in args:
+ var_name = get_arg_name(None, arg_num, stack_frame)
+ buffer += sprint_varx(var_name, var_value, **kwargs)
+ arg_num += 1
return buffer
-def sprint_dashes(indent=col1_indent,
+def sprint_dashes(indent=dft_indent,
width=80,
line_feed=1,
char="-"):
r"""
Return a string of dashes to the caller.
- Description of arguments:
+ Description of argument(s):
indent The number of characters to indent the
output.
width The width of the string of dashes.
@@ -1102,7 +1342,7 @@
Pre-pend the specified number of characters to the text string (i.e.
indent it) and return it.
- Description of arguments:
+ Description of argument(s):
text The string to be indented.
indent The number of characters to indent the
string.
@@ -1209,7 +1449,7 @@
59 /tmp/scr5.py
-------------------------------------------------------------------------
- Description of arguments:
+ Description of argument(s):
indent The number of characters to indent each
line of output.
stack_frame_ix The index of the first stack frame which
@@ -1235,7 +1475,7 @@
if ix < stack_frame_ix:
ix += 1
continue
- # I want the line number shown to be the line where you find the line
+ # Make the line number shown to be the line where one finds the line
# shown.
try:
line_num = str(current_stack[ix + 1][2])
@@ -1260,7 +1500,7 @@
#(CDT) 2016/08/25 17:54:27 - Executing: func1(x = 1)
- Description of arguments:
+ Description of argument(s):
stack_frame_ix The index of the stack frame whose
function info should be returned. If the
caller does not specify a value, this
@@ -1297,14 +1537,14 @@
of the run. It includes useful information like command line, pid,
userid, program parameters, etc.
- Description of arguments:
+ Description of argument(s):
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.
"""
- loc_col1_width = col1_width + indent
+ col1_width = dft_col1_width + indent
buffer = ""
if linefeed:
@@ -1319,14 +1559,14 @@
buffer += sindent(sprint_time() + "Program parameter values, etc.:\n\n",
indent)
buffer += sprint_varx("command_line", ' '.join(sys.argv), 0, indent,
- loc_col1_width)
+ 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,
- loc_col1_width)
+ col1_width)
buffer += sprint_varx(pgm_name_var_name + "_pgid", os.getpgrp(), 0, indent,
- loc_col1_width)
+ col1_width)
userid_num = str(os.geteuid())
try:
username = os.getlogin()
@@ -1336,19 +1576,19 @@
else:
username = "?"
buffer += sprint_varx("uid", userid_num + " (" + username
- + ")", 0, indent, loc_col1_width)
+ + ")", 0, indent, col1_width)
buffer += sprint_varx("gid", str(os.getgid()) + " ("
+ str(grp.getgrgid(os.getgid()).gr_name) + ")", 0,
- indent, loc_col1_width)
+ indent, col1_width)
buffer += sprint_varx("host_name", socket.gethostname(), 0, indent,
- loc_col1_width)
+ col1_width)
try:
DISPLAY = os.environ['DISPLAY']
except KeyError:
DISPLAY = ""
- buffer += sprint_varx("DISPLAY", DISPLAY, 0, indent,
- loc_col1_width)
- # I want to add code to print caller's parms.
+ buffer += sprint_var(DISPLAY, 0, indent,
+ col1_width)
+ # TODO: Add code to print caller's parms.
# __builtin__.arg_obj is created by the get_arg module function,
# gen_get_options.
@@ -1363,7 +1603,7 @@
for parm in parm_list:
parm_value = BuiltIn().get_variable_value("${" + parm + "}")
- buffer += sprint_varx(parm, parm_value, 0, indent, loc_col1_width)
+ buffer += sprint_varx(parm, parm_value, 0, indent, col1_width)
# Setting global program_pid.
BuiltIn().set_global_variable("${program_pid}", os.getpid())
@@ -1381,7 +1621,7 @@
Return a string with a standardized report which includes the caller's
error text, the call stack and the program header.
- Description of args:
+ Description of argument(s):
error_text The error text to be included in the
report. The caller should include any
needed linefeeds.
@@ -1432,9 +1672,9 @@
#(CDT) 2016/08/25 17:57:36 - Issuing: ls
- Description of args:
+ Description of argument(s):
cmd_buf The command to be executed by caller.
- test_mode With test_mode set, your output will look
+ test_mode With test_mode set, the output will look
like this:
#(CDT) 2016/08/25 17:57:36 - (test_mode) Issuing: ls
@@ -1475,7 +1715,7 @@
dprint functions defined dynamically below, i.e. it would not normally be
called for general use.
- Description of arguments.
+ Description of argument(s).
buffer This will be returned to the caller.
"""
@@ -1491,7 +1731,7 @@
by the qprint and dprint functions defined dynamically below, i.e. it
would not normally be called for general use.
- Description of arguments.
+ Description of argument(s).
buffer This will be returned to the caller.
"""
@@ -1511,7 +1751,7 @@
This function is intended for use only by other functions in this module.
- Description of arguments:
+ Description of argument(s):
buffer The string to be printed.
stream Either "stdout" or "stderr".
"""
@@ -1534,7 +1774,7 @@
This function is intended for use only by other functions in this module.
- Description of arguments:
+ Description of argument(s):
buffer The string to be logged.
"""
@@ -1550,7 +1790,7 @@
This function is intended for use only by other functions in this module.
- Description of arguments:
+ Description of argument(s):
buffer The string to be printed.
"""
@@ -1599,7 +1839,7 @@
my_func()
- Description of arguments:
+ Description of argument(s):
var_value The value to be returned (if not equal to
None).
default The value that is returned if var_value is