These are several decorators that I wrote tangentially for the Python 2 project I was working on. Exceptions are the closest possible mirrors created by Python 3 functions that use keyword syntax for arguments only.
They do not prohibit positional arguments, but may require / restrict keyword arguments. You can create another decorator that would ban positional arguments.
import functools def original_wrapped_function(f): try: while True: f = f.__wrapped__ except AttributeError: return f def restrict_kwargs(*allowed_keywords): def restrict_kwargs_decorator(func): @functools.wraps(original_wrapped_function(func)) def restrict_wrapper(*args, **kwargs): for keyword in kwargs: if keyword not in allowed_keywords: msg = "%s() got an unexpected keyword argument '%s'" raise TypeError(msg % (func.__name__, keyword)) return func(*args, **kwargs) restrict_wrapper.__wrapped__ = func return restrict_wrapper return restrict_kwargs_decorator def require_kwargs(*required_keywords): def require_kwargs_decorator(func): @functools.wraps(original_wrapped_function(func)) def require_wrapper(*args, **kwargs): missing_keywords = [] for keyword in required_keywords: if keyword not in kwargs: missing_keywords.append(keyword) if missing_keywords: func_name = func.__name__ count = len(missing_keywords) if count == 1: arg_word = 'argument' missing_keywords_str = "'%s'" % missing_keywords[0] else: arg_word = 'arguments' and_join_str = ' and ' if count == 2 else ', and ' missing_keywords_str = ', '.join( ("'%s'" % mk) for mk in missing_keywords[:-1]) missing_keywords_str = and_join_str.join(( missing_keywords_str, ("'%s'" % missing_keywords[-1]))) msg = "%s() missing %d required keyword-only %s: %s" raise TypeError(msg % (func_name, count, arg_word, missing_keywords_str)) return func(*args, **kwargs) require_wrapper.__wrapped__ = func return require_wrapper return require_kwargs_decorator def exact_kwargs(*exact_keywords): def exact_kwargs_decorator(func): @restrict_kwargs(*exact_keywords) @require_kwargs(*exact_keywords) @functools.wraps(original_wrapped_function(func)) def exact_wrapper(*args, **kwargs): return func(*args, **kwargs) exact_wrapper.__wrapped__ = func return exact_wrapper return exact_kwargs_decorator
Some examples:
>>> @restrict_kwargs('five', 'six') ... def test_restrict_kwargs(arg1, arg2, *moreargs, **kwargs): ... return (arg1, arg2, moreargs, kwargs) ... >>> >>> @require_kwargs('five', 'six') ... def test_require_kwargs(arg1, arg2, *moreargs, **kwargs): ... return (arg1, arg2, moreargs, kwargs) ... >>> >>> @exact_kwargs('five', 'six') ... def test_exact_kwargs(arg1, arg2, *moreargs, **kwargs): ... return (arg1, arg2, moreargs, kwargs) ... >>> >>> >>> >>> test_restrict_kwargs(1, 2, 3, 4, five=5) (1, 2, (3, 4), {'five': 5}) >>> >>> test_restrict_kwargs(1, 2, 3, 4, five=5, six=6) (1, 2, (3, 4), {'six': 6, 'five': 5}) >>> >>> test_restrict_kwargs(1, 2, 3, 4, five=5, six=6, seven=7) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "SO_31939890.py", line 19, in restrict_wrapper raise TypeError(msg % (func.__name__, keyword)) TypeError: test_restrict_kwargs() got an unexpected keyword argument 'seven' >>> >>> >>> >>> test_require_kwargs(1, 2, 3, 4, five=5) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "SO_31939890.py", line 49, in require_wrapper missing_keywords_str)) TypeError: test_require_kwargs() missing 1 required keyword-only argument: 'six' >>> >>> test_require_kwargs(1, 2, 3, 4, five=5, six=6) (1, 2, (3, 4), {'six': 6, 'five': 5}) >>> >>> test_require_kwargs(1, 2, 3, 4, five=5, six=6, seven=7) (1, 2, (3, 4), {'seven': 7, 'six': 6, 'five': 5}) >>> >>> >>> >>> test_exact_kwargs(1, 2, 3, 4, five=5) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "SO_31939890.py", line 20, in restrict_wrapper return func(*args, **kwargs) File "SO_31939890.py", line 49, in require_wrapper missing_keywords_str)) TypeError: test_exact_kwargs() missing 1 required keyword-only argument: 'six' >>> >>> test_exact_kwargs(1, 2, 3, 4, five=5, six=6) (1, 2, (3, 4), {'six': 6, 'five': 5}) >>> >>> test_exact_kwargs(1, 2, 3, 4, five=5, six=6, seven=7) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "SO_31939890.py", line 19, in restrict_wrapper raise TypeError(msg % (func.__name__, keyword)) TypeError: test_exact_kwargs() got an unexpected keyword argument 'seven' >>>