def preserve_sig(wrapper, orig_func, force=False):
    from utool._internal import meta_util_six
    from utool import util_str
    from utool import util_inspect
    if wrapper is orig_func:
        return orig_func
    orig_docstr = meta_util_six.get_funcdoc(orig_func)
    orig_docstr = '' if orig_docstr is None else orig_docstr
    orig_argspec = util_inspect.get_func_argspec(orig_func)
    wrap_name = meta_util_six.get_funccode(wrapper).co_name
    orig_name = meta_util_six.get_funcname(orig_func)
    _utinfo = {}
    _utinfo['orig_func'] = orig_func
    _utinfo['wrap_name'] = wrap_name
    _utinfo['orig_name'] = orig_name
    _utinfo['orig_argspec'] = orig_argspec
    if hasattr(wrapper, '_utinfo'):
        parent_wrapper_utinfo = wrapper._utinfo
        _utinfo['parent_wrapper_utinfo'] = parent_wrapper_utinfo
    if hasattr(orig_func, '_utinfo'):
        parent_orig_utinfo = orig_func._utinfo
        _utinfo['parent_orig_utinfo'] = parent_orig_utinfo
    building_docs = os.environ.get('UTOOL_AUTOGEN_SPHINX_RUNNING', 'OFF') == 'ON'
    if force or SIG_PRESERVE or building_docs:
        src_fmt = r'''
        def _wrp_preserve{defsig}:
            try:
                return wrapper{callsig}
            except Exception as ex:
                import utool as ut
                msg = ('Failure in signature preserving wrapper:\n')
                ut.printex(ex, msg)
                raise
        '''
        globals_ =  {'wrapper': wrapper}
        locals_ = {}
        argspec = inspect.getargspec(orig_func)
        (args, varargs, varkw, defaults) = argspec
        defsig = inspect.formatargspec(*argspec)
        callsig = inspect.formatargspec(*argspec[0:3])
        src_fmtdict = dict(defsig=defsig, callsig=callsig, orig_docstr=orig_docstr)
        src = textwrap.dedent(src_fmt).format(**src_fmtdict)
        code = compile(src, '<string>', 'exec')
        six.exec_(code, globals_, locals_)
        _wrp_preserve = functools.update_wrapper(locals_['_wrp_preserve'], orig_func)
        _utinfo['src'] = src
    else:
        _wrp_preserve = functools.update_wrapper(wrapper, orig_func)
    DEBUG_WRAPPED_DOCSTRING = False
    if DEBUG_WRAPPED_DOCSTRING:
        new_docstr_fmtstr = util_str.codeblock(
            '''
            Wrapped function {wrap_name}({orig_name})
            orig_argspec = {orig_argspec}
            orig_docstr = {orig_docstr}
            '''
        )
    else:
        new_docstr_fmtstr = util_str.codeblock(
            '''
            {orig_docstr}
            '''
        )
    new_docstr = new_docstr_fmtstr.format(
        wrap_name=wrap_name, orig_name=orig_name, orig_docstr=orig_docstr,
        orig_argspec=orig_argspec)
    meta_util_six.set_funcdoc(_wrp_preserve, new_docstr)
    _wrp_preserve._utinfo = _utinfo
    return _wrp_preserve