docs: def bind_arguments(func, args, kwargs):
      """Bind the arguments provided into a dict.  When passed a function,
      a tuple of arguments and a dict of keyword arguments `bind_arguments`
      returns a dict of names as the function would see it.  This can be useful
      to implement a cache decorator that uses the function arguments to build
      the cache key based on the values of the arguments.
  
      :param func: the function the arguments should be bound for.
      :param args: tuple of positional arguments.
      :param kwargs: a dict of keyword arguments.
      :return: a :class:`dict` of bound keyword arguments.
      """
      (
          args,
          kwargs,
          missing,
          extra,
          extra_positional,
          arg_spec,
          vararg_var,
          kwarg_var,
      ) = _parse_signature(func)(args, kwargs)
      values = {}
      for (name, _has_default, _default), value in zip(arg_spec, args):
          values[name] = value
      if vararg_var is not None:
          values[vararg_var] = tuple(extra_positional)
      elif extra_positional:
          raise TypeError("too many positional arguments")
      if kwarg_var is not None:
          multikw = set(extra) & set([x[0] for x in arg_spec])
          if multikw:
              raise TypeError(
                  "got multiple values for keyword argument " + repr(next(iter(multikw)))
              )
          values[kwarg_var] = extra
      elif extra:
          raise TypeError("got unexpected keyword argument " + repr(next(iter(extra))))
      return values