Hi Todd

You wrote:

I guess the thing I don't understand is why you favor that API.  Could you please explain what you think are the advantages of your approach, ideally with some examples where you think your approach is clearer?

 I've created a github issue for this, which I'll answer here.
https://github.com/jfine2358/python-kwkey/issues/1

In kwkey, I provide 3 interfaces, namely the 'o' and 'K' interface, the jfine interface, and the sdaprano interface. I will explain my reasons, in that order.

Recall that we wish to emulate
   d[1, 2, a=3, b=4]
in current Python. I use
    d[o(1, 2, a=3, b=4)]
as a present day syntax that emulates the future syntax. I think this is sufficiently obvious, as to not require explanation.

When there are keyword arguments, 'o' gives an object of a new type, namely 'K'. The reason is backwards compatibility. Suppose instead
    >>> key = o(1, 2, a=3, b=4)
    >>> key == ((1, 2), dict(a=3, b=4))
    True

Now suppose that the expression
    d[(1, 2), dict(a=3, b=4)]
appears in legacy code. Because it's legacy code, it can't represent
    d[1, 2, a=3, b=4]
in the new syntax.  But how can I distinguish it? That's why I introduce a new class 'K'.

It's worth saying that 'o' used the K class only when it has to. This is to give legacy compatibility. Today,
    d[1, 2]
    d[(1, 2)]
are equivalent.

To finish on 'o' and 'K', so far as I can see, what I've done
1. Provides all information that would be available from a minimal syntax extension.
2. Doesn't provide any information beyond that (hence K used only when necessary).
3. It continues to work with an ordinary dict.
4. The C-Python implementation is minimal (provided adding K isn't too hard).

Now for the jfine interface, implemented by key_to_jfine signature changing decorator. Here I give what I think is a straightforward interface (for the function wrapped by the decorator) that will provide many programmers with an interface that is straightforward to use. In particular, for setitem the signature is
    fn(self, val, *key.argv, **dict(key.kwargs))

If you don't like the signatures you provide, choose your own signatures, and then if you wish to write a signature changing decorator.

Now for the sdaprano interface, implemented by the key_to_sdaprano signature changing decorator. Here I provide an interface to what is my understanding of Steven's proposal. This is so he and others can use it if they wish.

By the way, as previously noted
    d[1, 2]
    d[(1, 2)]
are at present equivalent. However, in the new syntax
    d[1, 2, a=3]
    d[(1, 2), a=3]
are not equivalent. (The first has three arguments, the second two, the first of which is a tuple.)

Finally, as to which interface is the better, I have as the implementer of kwkey tried to be neutral as to the various interfaces.

I hope this helps. If you wish, please ask for more information or help.

-- 
Jonathan