def make_decorator(func):
 def decorate(newfunc):
  if hasattr(func, 'compat_func_name'):
   name = func.compat_func_name
  else:
   name = func.__name__
  newfunc.__dict__ = func.__dict__
  newfunc.__doc__ = func.__doc__
  newfunc.__module__ = func.__module__
  if (not hasattr(newfunc, 'compat_co_firstlineno')):
   try:
    newfunc.compat_co_firstlineno = func.func_code.co_firstlineno
   except AttributeError:
    newfunc.compat_co_firstlineno = func.__code__.co_firstlineno
  try:
   newfunc.__name__ = name
  except TypeError:
   newfunc.compat_func_name = name
  return newfunc
 return decorate

def make_decorator ( func ) : def decorate ( newfunc ) : if hasattr ( func , 'compat_func_name' ) : name = func . compat_func_name else : name = func . __name__ newfunc . __dict__ = func . __dict__ newfunc . __doc__ = func . __doc__ newfunc . __module__ = func . __module__ if ( not hasattr ( newfunc , 'compat_co_firstlineno' ) ) : try : newfunc . compat_co_firstlineno = func . func_code . co_firstlineno except AttributeError : newfunc . compat_co_firstlineno = func . __code__ . co_firstlineno try : newfunc . __name__ = name except TypeError : newfunc . compat_func_name = name return newfunc return decorate
wraps a test decorator so as to properly replicate metadata of the decorated function .