import functools
from six import iteritems

_all_builtins = {}


class _Binder(object):
    def __init__(self, args, fn):
        self._args = args
        self._fn = fn


class _FunctionBinder(_Binder):
    def bind(self, **kwargs):
        # XXX: partial doesn't forward the docstring of the function.
        return functools.partial(self._fn, *[kwargs[i] for i in self._args])


class _VariableBinder(_Binder):
    def bind(self, **kwargs):
        return self._fn(*[kwargs[i] for i in self._args])


class _BuiltinDecorator(object):
    def __init__(self, binder):
        self.__binder = binder

    def __call__(self, *args):
        def wrapper(fn):
            bound = self.__binder(args, fn)
            _all_builtins[fn.__name__] = bound
            return bound
        return wrapper


builtin = _BuiltinDecorator(_FunctionBinder)()
builtin.globals = _BuiltinDecorator(_FunctionBinder)
builtin.variable = _BuiltinDecorator(_VariableBinder)


def bind(**kwargs):
    builtins = {}
    for k, v in iteritems(_all_builtins):
        builtins[k] = v.bind(builtins=builtins, **kwargs)

    return builtins


@builtin.variable('env')
def env(this_env):
    return this_env

import functools
import inspect
import sys
from six import iteritems

_all_builtins = {}


class _Binder(object):
    def __init__(self, args, fn):
        self._args = args
        self._fn = fn


class _FunctionBinder(_Binder):
    def bind(self, **kwargs):
        pre_args = tuple(kwargs[i] for i in self._args)

        @functools.wraps(self._fn)
        def wrapped(*args, **kwargs):
            return self._fn(*(pre_args + args), **kwargs)

        if sys.version_info >= (3, 3):
            sig = inspect.signature(wrapped)
            params = list(sig.parameters.values())[len(kwargs):]
            wrapped.__signature__ = inspect.Signature(params)
        return wrapped


class _VariableBinder(_Binder):
    def bind(self, **kwargs):
        return self._fn(*[kwargs[i] for i in self._args])


class _BuiltinDecorator(object):
    def __init__(self, binder):
        self.__binder = binder

    def __call__(self, *args):
        def wrapper(fn):
            bound = self.__binder(args, fn)
            _all_builtins[fn.__name__] = bound
            return bound
        return wrapper


builtin = _BuiltinDecorator(_FunctionBinder)()
builtin.globals = _BuiltinDecorator(_FunctionBinder)
builtin.variable = _BuiltinDecorator(_VariableBinder)


def bind(**kwargs):
    builtins = {}
    for k, v in iteritems(_all_builtins):
        builtins[k] = v.bind(builtins=builtins, **kwargs)

    return builtins


@builtin.variable('env')
def env(this_env):
    return this_env

Change how the wrappers work for builtin functions so that docs get forwarded correctly
Change how the wrappers work for builtin functions so that docs get forwarded correctly

  import functools
+ import inspect
+ import sys
  from six import iteritems
  
  _all_builtins = {}
  
  
  class _Binder(object):
      def __init__(self, args, fn):
          self._args = args
          self._fn = fn
  
  
  class _FunctionBinder(_Binder):
      def bind(self, **kwargs):
-         # XXX: partial doesn't forward the docstring of the function.
-         return functools.partial(self._fn, *[kwargs[i] for i in self._args])
+         pre_args = tuple(kwargs[i] for i in self._args)
+ 
+         @functools.wraps(self._fn)
+         def wrapped(*args, **kwargs):
+             return self._fn(*(pre_args + args), **kwargs)
+ 
+         if sys.version_info >= (3, 3):
+             sig = inspect.signature(wrapped)
+             params = list(sig.parameters.values())[len(kwargs):]
+             wrapped.__signature__ = inspect.Signature(params)
+         return wrapped
  
  
  class _VariableBinder(_Binder):
      def bind(self, **kwargs):
          return self._fn(*[kwargs[i] for i in self._args])
  
  
  class _BuiltinDecorator(object):
      def __init__(self, binder):
          self.__binder = binder
  
      def __call__(self, *args):
          def wrapper(fn):
              bound = self.__binder(args, fn)
              _all_builtins[fn.__name__] = bound
              return bound
          return wrapper
  
  
  builtin = _BuiltinDecorator(_FunctionBinder)()
  builtin.globals = _BuiltinDecorator(_FunctionBinder)
  builtin.variable = _BuiltinDecorator(_VariableBinder)
  
  
  def bind(**kwargs):
      builtins = {}
      for k, v in iteritems(_all_builtins):
          builtins[k] = v.bind(builtins=builtins, **kwargs)
  
      return builtins
  
  
  @builtin.variable('env')
  def env(this_env):
      return this_env
  
Change how the wrappers work for builtin functions so that docs get forwarded correctly
## Code Before:
import functools
from six import iteritems

_all_builtins = {}


class _Binder(object):
    def __init__(self, args, fn):
        self._args = args
        self._fn = fn


class _FunctionBinder(_Binder):
    def bind(self, **kwargs):
        # XXX: partial doesn't forward the docstring of the function.
        return functools.partial(self._fn, *[kwargs[i] for i in self._args])


class _VariableBinder(_Binder):
    def bind(self, **kwargs):
        return self._fn(*[kwargs[i] for i in self._args])


class _BuiltinDecorator(object):
    def __init__(self, binder):
        self.__binder = binder

    def __call__(self, *args):
        def wrapper(fn):
            bound = self.__binder(args, fn)
            _all_builtins[fn.__name__] = bound
            return bound
        return wrapper


builtin = _BuiltinDecorator(_FunctionBinder)()
builtin.globals = _BuiltinDecorator(_FunctionBinder)
builtin.variable = _BuiltinDecorator(_VariableBinder)


def bind(**kwargs):
    builtins = {}
    for k, v in iteritems(_all_builtins):
        builtins[k] = v.bind(builtins=builtins, **kwargs)

    return builtins


@builtin.variable('env')
def env(this_env):
    return this_env

## Instruction:
Change how the wrappers work for builtin functions so that docs get forwarded correctly
## Code After:
import functools
import inspect
import sys
from six import iteritems

_all_builtins = {}


class _Binder(object):
    def __init__(self, args, fn):
        self._args = args
        self._fn = fn


class _FunctionBinder(_Binder):
    def bind(self, **kwargs):
        pre_args = tuple(kwargs[i] for i in self._args)

        @functools.wraps(self._fn)
        def wrapped(*args, **kwargs):
            return self._fn(*(pre_args + args), **kwargs)

        if sys.version_info >= (3, 3):
            sig = inspect.signature(wrapped)
            params = list(sig.parameters.values())[len(kwargs):]
            wrapped.__signature__ = inspect.Signature(params)
        return wrapped


class _VariableBinder(_Binder):
    def bind(self, **kwargs):
        return self._fn(*[kwargs[i] for i in self._args])


class _BuiltinDecorator(object):
    def __init__(self, binder):
        self.__binder = binder

    def __call__(self, *args):
        def wrapper(fn):
            bound = self.__binder(args, fn)
            _all_builtins[fn.__name__] = bound
            return bound
        return wrapper


builtin = _BuiltinDecorator(_FunctionBinder)()
builtin.globals = _BuiltinDecorator(_FunctionBinder)
builtin.variable = _BuiltinDecorator(_VariableBinder)


def bind(**kwargs):
    builtins = {}
    for k, v in iteritems(_all_builtins):
        builtins[k] = v.bind(builtins=builtins, **kwargs)

    return builtins


@builtin.variable('env')
def env(this_env):
    return this_env
