def one_of_keyword_only(*valid_keywords):
def decorator(func):<EOL><INDENT>@functools.wraps(func)<EOL>def wrapper(*args, **kwargs):<EOL><INDENT>sentinel = object()<EOL>values = {}<EOL>for key in valid_keywords:<EOL><INDENT>kwarg_value = kwargs.pop(key, sentinel)<EOL>if kwarg_value is not sentinel:<EOL><INDENT>values[key] = kwarg_value<EOL><DEDENT><DEDENT>if kwargs:<EOL><INDENT>raise TypeError('<STR_LIT>'.format(kwargs))<EOL><DEDENT>if not values:<EOL><INDENT>raise TypeError('<STR_LIT>'.format('<STR_LIT:U+002CU+0020>'.join(valid_keywords)))<EOL><DEDENT>if len(values) > <NUM_LIT:1>:<EOL><INDENT>raise TypeError('<STR_LIT>'.format(<EOL>'<STR_LIT:U+002CU+0020>'.join(valid_keywords),<EOL>values<EOL>))<EOL><DEDENT>return func(*(args + values.popitem()))<EOL><DEDENT>return wrapper<EOL><DEDENT>return decorator<EOL>
Decorator to help make one-and-only-one keyword-only argument functions more reusable

    Notes:
        Decorated function should take 2 arguments, the first for the key, the second the value

    Examples:

        ::

            @one_of_keyword_only('a', 'b', 'c')
            def func(key, value):
                if key == 'a':
                    ...
                elif key == 'b':
                    ...
                else:
                    # key = 'c'
                    ...

            ...

            func(a=1)
            func(b=2)
            func(c=3)

            try:
                func(d=4)
            except TypeError:
                ...

            try:
                func(a=1, b=2)
            except TypeError:
                ...

    Args:
        *valid_keywords (str): All allowed keyword argument names

    Raises:
        TypeError: On decorated call, if 0 or 2+ arguments are provided or kwargs contains a key not in valid_keywords