

def recreate_function(func, module=None, name=None, add_args=[], firstlineno=None):
    'Recreate a function, replacing some info.\n\n    :param func: Function object.\n    :param module: Module to contribute to.\n    :param add_args: Additional arguments to add to function.\n\n    :return: Function copy.\n    '

    def get_code(func):
        return (func.__code__ if six.PY3 else func.func_code)

    def set_code(func, code):
        if six.PY3:
            func.__code__ = code
        else:
            func.func_code = code
    argnames = ['co_argcount', 'co_nlocals', 'co_stacksize', 'co_flags', 'co_code', 'co_consts', 'co_names', 'co_varnames', 'co_filename', 'co_name', 'co_firstlineno', 'co_lnotab', 'co_freevars', 'co_cellvars']
    if six.PY3:
        argnames.insert(1, 'co_kwonlyargcount')
    for arg in get_args(func):
        if (arg in add_args):
            add_args.remove(arg)
    args = []
    code = get_code(func)
    for arg in argnames:
        if ((module is not None) and (arg == 'co_filename')):
            args.append(module.__file__)
        elif ((name is not None) and (arg == 'co_name')):
            args.append(name)
        elif (arg == 'co_argcount'):
            args.append((getattr(code, arg) + len(add_args)))
        elif (arg == 'co_varnames'):
            co_varnames = getattr(code, arg)
            args.append(((co_varnames[:code.co_argcount] + tuple(add_args)) + co_varnames[code.co_argcount:]))
        elif (arg == 'co_firstlineno'):
            args.append((firstlineno if firstlineno else 1))
        else:
            args.append(getattr(code, arg))
    set_code(func, CodeType(*args))
    if (name is not None):
        func.__name__ = name
    return func

dataset/ETHPy150Open pytest-dev/pytest-bdd/pytest_bdd/steps.py recreate_function/original