code: def advanced_wrap(f, wrapper):
      
      f_sig = list(inspect.getargspec(f))
      wrap_sig = list(inspect.getargspec(wrapper))
  
      # Update the keyword arguments of the wrapper
      if f_sig[3] is None or f_sig[3] == []:
          f_sig[3], f_kwargs = [], []
      else:
          f_kwargs = f_sig[0][-len(f_sig[3]):]
  
      for key, default in zip(f_kwargs, f_sig[3]):
          wrap_sig[0].append(key)
          wrap_sig[3] = wrap_sig[3] + (default, )
  
      wrap_sig[2] = None  # Remove kwargs
      src = "lambda %s: " % (inspect.formatargspec(*wrap_sig)[1:-1])
      new_args = inspect.formatargspec(
          wrap_sig[0], wrap_sig[1], wrap_sig[2], f_kwargs,
          formatvalue=lambda x: '=' + x)
      src += 'wrapper%s\n' % new_args
  
      decorated = eval(src, locals())
      decorated.func = f
      return update_wrapper(decorated, f)
docs: Wrap a decorated function while keeping the same keyword arguments