Any comments on this?  I ended up making reduce work using a metaclass:

class KwargsNewMetaclass(type):

    """
    This metaclass reimplements __reduce__ so that it tries to call
    __getnewargs_ex__.  If that doesn't work, it falls back to __getnewargs__.

    In the first case, it will pass the keyword arguments to object.__new__.

    It also exposes a kwargs_new static method that can be overridden for
    use by __reduce__.
    """

    @staticmethod
    def kwargs_new(cls, new_kwargs, *new_args):
        retval = cls.__new__(cls, *new_args, **new_kwargs)
        retval.__init__(*new_args, **new_kwargs)
        return retval

    def __new__(cls, name, bases, classdict):
        result = super().__new__(cls, name, bases, classdict)

        def __reduce__(self):
            try:
                getnewargs_ex = self.__getnewargs_ex__
            except AttributeError:
                new_args, new_kwargs = (self.__getnewargs__(), {})
            else:
                new_args, new_kwargs = getnewargs_ex()
            return (self.kwargs_new(cls),
                    (type(self), new_kwargs,) + tuple(new_args),
                    self.__getstate__())
        result.__reduce__ = __reduce__
        return result


On Sunday, March 23, 2014 6:20:41 PM UTC-4, Neil Girdhar wrote:
Currently __reduce__ returns up to five things:

(1) self.__new__ (or a substitute)
(2) the result of __getnewargs__, which returns a tuple of positional arguments for __new__,
(3) the result of __getstate__, which returns an object to be passed to __setstate__
(4) an iterator of values for appending to a sequence
(5) an iterator of key-value pairs for setting on a string.

Python 3.4 added the very useful (for me) __getnewargs_ex__, which returns a pair:
(1) a tuple of positional arguments for __new__
(2) a dict of keyword arguments for __new__

Therefore, I am proposing that __reduce__ return somehow these keyword arguments for __new__.

Best,
Neil