def accepts(*argtypes, **kwargtypes):
    """A function decorator to specify argument types of the function.

    Types may be specified either in the order that they appear in the
    function or via keyword arguments (just as if you were calling the
    function).

    Example usage:

      | @accepts(Positive0)
      | def square_root(x):
      |     ...
    """

    theseargtypes = [T.TypeFactory(a) for a in argtypes]
    thesekwargtypes = {k : T.TypeFactory(a) for k,a in kwargtypes.items()}
    def _decorator(func):
        # @accepts decorator
        f = func.__wrapped__ if hasattr(func, "__wrapped__") else func
        try:
            argtypes = inspect.getcallargs(f, *theseargtypes, **thesekwargtypes)
            argtypes = {k: v if issubclass(type(v), T.Type) else T.Constant(v)
                        for k,v in argtypes.items()}
        except TypeError:
            raise E.ArgumentTypeError("Invalid argument specification to @accepts in %s" % func.__qualname__)
        # Support keyword arguments.  Find the name of the **kwargs
        # parameter (not necessarily "kwargs") and set it to be a
        # dictionary of unspecified types.
        kwargname = U.get_func_kwargs_name(func)
        if kwargname in argtypes.keys():
            argtypes[kwargname] = T.KeywordArguments()
        # Support positional arguments.  Find the name of the *args
        # parameter (not necessarily "args") and set it to be an
        # unspecified type.
        posargname = U.get_func_posargs_name(func)
        if posargname in argtypes.keys():
            argtypes[posargname] = T.PositionalArguments() # TODO merge with actual argument names
        if U.has_fun_prop(func, "argtypes"):
            raise ValueError("Cannot set argument types twice")
        U.set_fun_prop(func, "argtypes", argtypes)
        return _wrap(func)
    return _decorator
A function decorator to specify argument types of the function.

    Types may be specified either in the order that they appear in the
    function or via keyword arguments (just as if you were calling the
    function).

    Example usage:

      | @accepts(Positive0)
      | def square_root(x):
      |     ...