@property
    def arg(self):
        # XXX: move this introspection to __init__, and change
        #      the basic data-structure to not use pos_args and named_args.
        # XXX: think though... we want the binding to be updated if pos_args
        # and named_args is modified... so maybe this is an ok way to do it?
        #
        # XXX: extend something to deal with Lambda objects instead of
        # decorated python functions.
        #
        # http://docs.python.org/reference/expressions.html#calls
        #
        binding = {}

        fn = scope._impls[self.name]
        # XXX does not work for builtin functions
        defaults = fn.__defaults__  # right-aligned default values for params
        code = fn.__code__

        extra_args_ok = bool(code.co_flags & 0x04)
        extra_kwargs_ok = bool(code.co_flags & 0x08)

        # -- assert that my understanding of calling protocol is correct
        try:
            if extra_args_ok and extra_kwargs_ok:
                assert len(code.co_varnames) >= code.co_argcount + 2
                param_names = code.co_varnames[:code.co_argcount + 2]
                args_param = param_names[code.co_argcount]
                kwargs_param = param_names[code.co_argcount + 1]
                pos_params = param_names[:code.co_argcount]
            elif extra_kwargs_ok:
                assert len(code.co_varnames) >= code.co_argcount + 1
                param_names = code.co_varnames[:code.co_argcount + 1]
                kwargs_param = param_names[code.co_argcount]
                pos_params = param_names[:code.co_argcount]
            elif extra_args_ok:
                assert len(code.co_varnames) >= code.co_argcount + 1
                param_names = code.co_varnames[:code.co_argcount + 1]
                args_param = param_names[code.co_argcount]
                pos_params = param_names[:code.co_argcount]
            else:
                assert len(code.co_varnames) >= code.co_argcount
                param_names = code.co_varnames[:code.co_argcount]
                pos_params = param_names[:code.co_argcount]
        except AssertionError:
            print 'YIKES: MISUNDERSTANDING OF CALL PROTOCOL:',
            print code.co_argcount,
            print code.co_varnames,
            print '%x' % code.co_flags
            raise

        if extra_args_ok:
            binding[args_param] == []

        if extra_kwargs_ok:
            binding[kwargs_param] == {}

        if len(self.pos_args) > code.co_argcount and not extra_args_ok:
            raise TypeError('Argument count exceeds number of positional params')

        # -- bind positional arguments
        for param_i, arg_i in zip(param_names, self.pos_args):
            binding[param_i] = arg_i

        if extra_args_ok:
            # XXX: THIS IS NOT BEING TESTED AND IS OBVIOUSLY BROKEN
            binding[args_param].extend(args[code.co_argcount:])

        # -- bind keyword arguments
        for aname, aval in self.named_args:
            try:
                pos = pos_params.index(aname)
            except ValueError:
                if extra_kwargs_ok:
                    binding[kwargs_param][aname] = aval
                    continue
                else:
                    raise TypeError('Unrecognized keyword argument', aname)
            param = param_names[pos]
            if param in binding:
                raise TypeError('Duplicate argument for parameter', param)
            binding[param] = aval

        assert len(binding) <= len(param_names)

        if len(binding) < len(param_names):
            for p in param_names:
                if p not in binding:
                    binding[p] = MissingArgument

        return binding
dataset/ETHPy150Open hyperopt/hyperopt/hyperopt/pyll/base.py/Apply.arg/original