How to tell what kwargs are supported by a function

Is there any way to tell through code whether a function supports a particular kwarg or not? I have a list of args in a Dict, and I need to filter this Dict to those that are supported by the function being called but short of calling the function, and catching the Exception for unrecognized kwarg, I cannot figure out how to tell in advance if an arg is supported or not.

I don’t need to check arg types (though that would be useful), just their names.

Edit: Thanks everyone, this problem has now been solved. I use the following code that appears to work in versions of Julia >= 0.4:

function getKWArgs(f::Function, m::Union{Method,Void}=nothing)
    mts = methods(f)
    # In Julia 0.4, methods() returns a MethodTable
    # In Julia 0.6 it returns a MethodList that has an `mt` property with the MethodTable
    if isa(mts, MethodTable)
        table = mts
    elseif isdefined(mts, :mt)
        table =
        return Symbol[]
    mts = collect(mts)
    # If there's no kwsorter in the MethodTable, this function does not accept kwargs
    if !isdefined(table, :kwsorter)
        return Symbol[]
    method_index = 1
    if m == nothing
        m = mts[method_index]
        method_index = findfirst(x -> m == x, mts)
    kwsorter = collect(methods(table.kwsorter))[method_index]
    if isdefined(Base, :kwarg_decl)
        # Julia 0.6 has Base.kwarg_decl to get kwargs
        #   Code from
        kwargs = Base.kwarg_decl(m, typeof(kwsorter))
        if isa(kwargs, Vector) && length(kwargs) > 0
            filter!(arg -> !occursin("#", string(arg)), kwargs)
            # Keywords *may* not be sorted correctly. We move the vararg one to the end.
            local index = findfirst(arg -> endswith(string(arg), "..."), kwargs)
            if index != nothing
                kwargs[index], kwargs[end] = kwargs[end], kwargs[index]
            return kwargs
        # Julia 0.4 needs us to parse the kwsorter code as a string and pull out the kwargs
        # The only caveat is that we cannot tell if there is a vararg at the end. It's only
        # possible to tell if there are non kw varargs (ie, before the ;)
        kwargs = map(
                x -> Symbol(split(x, ",")[1][2:end]),  # String processing is faster than eval/parse
                    x -> startswith(x, ":") && !endswith(x, ",0"),    # Non-kwargs have the third arg set to 0. kwargs have it set to 2 or 34 and could be other values
                            string(kwsorter.func.code),               # Convert the kwsorter code to a string to parse it because we can't get anything out of :AST
                            r"^.*Any\[Any\[(Any\[.*?)(Any\[symbol\(\"##index|, *:\(begin).*"s,
        return kwargs
    return Symbol[]

There is an example in DocStringExtensions.jl, but this is almost surely not something you want to keep doing at runtime.

It is very likely that you want to redesign your algorithm, eg keep a some table of what functions do what, and just call them conditional on that, or use some form of dispatch.

Another option is to make your function accept any kwargs and ignore them, e.g.

julia> f(; x = 1, kwargs...) = x

julia> f(hello = 5)

It isn’t my function to change though otherwise this would have been the simplest solution.


Our plan is to automate the building of this table by running a lookup the first time we see a function and on subsequent calls just using the cached value.

It’s not that we want to call functions conditionally. We receive a bunch of filters from the web UI. We have a “router” function that does things like parsing the JSON into a Dict and doing type checking and input validation/sanitisation on all the filters before passing them on to the routed function. The only thing left is to make sure we only send the supported subset of filters to the specified function and drop the others.

I do this type of things (1, 2, 3) in GMT.jl to allow aliases in kwargs. Maybe you could filter your allowed kwargs in a similar way.

Maybe of help: