code: def _build_preprocessed_function(
      func, processors, args_defaults, varargs, varkw
  ):
      """
      Build a preprocessed function with the same signature as `func`.
  
      Uses `exec` internally to build a function that actually has the same
      signature as `func.
      """
      format_kwargs = {"func_name": func.__name__}
  
      def mangle(name):
          return "a" + uuid4().hex + name
  
      format_kwargs["mangled_func"] = mangled_funcname = mangle(
          func.__name__
      )
  
      def make_processor_assignment(arg, processor_name):
          template = "{arg} = {processor}({func}, '{arg}', {arg})"
          return template.format(
              arg=arg,
              processor=processor_name,
              func=mangled_funcname,
          )
  
      exec_globals = {mangled_funcname: func, "wraps": wraps}
      defaults_seen = 0
      default_name_template = "a" + uuid4().hex + "_%d"
      signature = []
      call_args = []
      assignments = []
      star_map = {
          varargs: "*",
          varkw: "**",
      }
  
      def name_as_arg(arg):
          return star_map.get(arg, "") + arg
  
      for arg, default in args_defaults:
          if default is NO_DEFAULT:
              signature.append(name_as_arg(arg))
          else:
              default_name = default_name_template % defaults_seen
              exec_globals[default_name] = default
              signature.append(
                  "=".join([name_as_arg(arg), default_name])
              )
              defaults_seen += 1
  
          if arg in processors:
              procname = mangle("_processor_" + arg)
              exec_globals[procname] = processors[arg]
              assignments.append(
                  make_processor_assignment(arg, procname)
              )
  
          call_args.append(name_as_arg(arg))
  
      exec_str = dedent(
          """\
          @wraps({wrapped_funcname})
          def {func_name}({signature}):
              {assignments}
              return {wrapped_funcname}({call_args})
          """
      ).format(
          func_name=func.__name__,
          signature=", ".join(signature),
          assignments="\n    ".join(assignments),
          wrapped_funcname=mangled_funcname,
          call_args=", ".join(call_args),
      )
      compiled = compile(
          exec_str,
          func.__code__.co_filename,
          mode="exec",
      )
  
      exec_locals = {}
      exec_(compiled, exec_globals, exec_locals)
      new_func = exec_locals[func.__name__]
  
      code = new_func.__code__
      args = {
          attr: getattr(code, attr)
          for attr in dir(code)
          if attr.startswith("co_")
      }
      # Copy the firstlineno out of the underlying function so that exceptions
      # get raised with the correct traceback.
      # This also makes dynamic source inspection (like IPython `??` operator)
      # work as intended.
      try:
          # Try to get the pycode object from the underlying function.
          original_code = func.__code__
      except AttributeError:
          try:
              # The underlying callable was not a function, try to grab the
              # `__func__.__code__` which exists on method objects.
              original_code = func.__func__.__code__
          except AttributeError:
              # The underlying callable does not have a `__code__`. There is
              # nothing for us to correct.
              return new_func
  
      args["co_firstlineno"] = original_code.co_firstlineno
      new_func.__code__ = CodeType(*map(getitem(args), _code_argorder))
      return new_func
  
file_path: zipline/zipline/utils/preprocess.py
imports: from textwrap import dedent
  from types import CodeType
  from uuid import uuid4
  from toolz.curried.operator import getitem
  from six import viewkeys, exec_, PY3
  from zipline.utils.compat import getargspec, wraps
label_desc: Use image node_id 3 for calling a global function with example usage: _build_preprocessed_function(func, processors, args_defaults, varargs, varkw) and returns: new_func, unknown, template, unknown, new_func