Improved performance of create_func_def_string
In py3, create_func_def_string is slow. Since gen_print calls it
several times while being imported, this makes all programs that use
it start slower than necessary.
Change-Id: I384ea6ae103da39b3736c4f1013b5749b2e6e3d2
Signed-off-by: Michael Walsh <micwalsh@us.ibm.com>
diff --git a/lib/wrap_utils.py b/lib/wrap_utils.py
index 124d8c8..de678b3 100755
--- a/lib/wrap_utils.py
+++ b/lib/wrap_utils.py
@@ -6,105 +6,6 @@
additional functionality over and above what the base function provides).
"""
-import sys
-import inspect
-
-
-def create_wrapper_def_and_call(base_func_name,
- wrap_func_name):
- r"""
- Return a wrapper function definition line and a base function call line.
-
- This is a utility for helping to create wrapper functions.
-
- For example, if there existed a function with the following definition line:
- def sprint_foo_bar(headers=1):
-
- And the user wished to write a print_foo_bar wrapper function, they could call
- create_wrapper_def_and_call as follows:
-
- func_def_line, call_line = create_wrapper_def_and_call("sprint_foo_bar",
- "print_foo_bar")
-
- They would get the following results:
- func_def_line def print_foo_bar(headers=1):
- call_line sprint_foo_bar(headers=headers)
-
- The func_def_line is suitable as the definition line for the wrapper function. The call_line is suitable
- for use in the new wrapper function wherever it wishes to call the base function. By explicitly
- specifying each parm in the definition and the call line, we allow the caller of the wrapper function to
- refer to any given parm by name rather than having to specify parms positionally.
-
- Description of argument(s):
- base_func_name The name of the base function around which a wrapper is being created.
- wrap_func_name The name of the wrapper function being created.
- """
-
- # Get caller's module name. Note: that for the present we've hard-coded the stack_frame_ix value
- # because we expect a call stack to this function to be something like this:
- # caller
- # create_print_wrapper_funcs
- # create_func_def_string
- # create_wrapper_def_and_call
- stack_frame_ix = 3
- frame = inspect.stack()[stack_frame_ix]
- module = inspect.getmodule(frame[0])
- mod_name = module.__name__
-
- # Get a reference to the base function.
- base_func = getattr(sys.modules[mod_name], base_func_name)
- # Get the argument specification for the base function.
- base_arg_spec = inspect.getargspec(base_func)
- base_arg_list = base_arg_spec[0]
- num_args = len(base_arg_list)
- # Get the variable argument specification for the base function.
- var_args = base_arg_spec[1]
- if var_args is None:
- var_args = []
- else:
- var_args = ["*" + var_args]
- keyword_args = base_arg_spec[2]
- if keyword_args is None:
- keyword_args = []
- else:
- keyword_args = ["**" + keyword_args]
- if base_arg_spec[3] is None:
- base_default_list = []
- else:
- base_default_list = list(base_arg_spec[3])
- num_defaults = len(base_default_list)
- num_non_defaults = num_args - num_defaults
-
- # Create base_arg_default_string which is a reconstruction of the base function's argument list.
- # Example base_arg_default_string:
- # headers, last=2, first=[1]
- # First, create a new list where each entry is of the form "arg=default".
- base_arg_default_list = list(base_arg_list)
- for ix in range(num_non_defaults, len(base_arg_default_list)):
- base_default_ix = ix - num_non_defaults
- if isinstance(base_default_list[base_default_ix], str):
- default_string = "'" + base_default_list[base_default_ix] + "'"
- # Convert "\n" to "\\n".
- default_string = default_string.replace("\n", "\\n")
- else:
- default_string = str(base_default_list[base_default_ix])
- base_arg_default_list[ix] += "=" + default_string
- base_arg_default_string =\
- ', '.join(base_arg_default_list + var_args + keyword_args)
-
- # Create the argument string which can be used to call the base function.
- # Example call_arg_string:
- # headers=headers, last=last, first=first
- call_arg_string = ', '.join([val + "=" + val for val in base_arg_list]
- + var_args + keyword_args)
-
- # Compose the result values.
- func_def_line = "def " + wrap_func_name + "(" + base_arg_default_string +\
- "):"
- call_line = base_func_name + "(" + call_arg_string + ")"
-
- return func_def_line, call_line
-
def create_func_def_string(base_func_name,
wrap_func_name,
@@ -134,9 +35,8 @@
# Create the initial function definition list as a copy of the template.
func_def = list(func_body_template)
- # Call create_wrapper_def_and_call to get func_def_line and call_line.
- func_def_line, call_line = create_wrapper_def_and_call(base_func_name,
- wrap_func_name)
+ func_def_line = "def " + wrap_func_name + "(*args, **kwargs):"
+ call_line = base_func_name + "(*args, **kwargs)"
# Insert the func_def_line composed by create_wrapper_def_and_call is the first list entry.
func_def.insert(0, func_def_line)
# Make sure the replace_dict has a 'call_line'/call_line pair so that any '<call_line>' text gets