many arguments to be matched against the expected arguments so obtained from the function' introspection apidef catcher(*pargs**kargs)print('% % (pargskargs)catcher( ( ){catcher( = = = ( ){' ' ' ' ' ' arguments at calls the function object' api is available in older pythonsbut the func __code__ attribute is named func func_code in and earlierthe newer __code__ attribute is also redundantly available in and later for portability run dir call on function and code objects for more details code like the following would support and earlierthough the sys version_info result itself is similarly nonportable--it' named tuple in recent pythonsbut we can use offsets on newer and older pythons alikeimport sys for backward compatibility tuple(sys version_info[ is major release number ( 'final' code func __code__ if sys version_info[ = else func func_code argument assumptions given the decorated function' set of expected argument namesthe solution relies upon two constraints on argument passing order imposed by python (these still hold true in both and current releases)at the callall positional arguments appear before all keyword arguments in the defall nondefault arguments appear before all default arguments that isa nonkeyword argument cannot generally follow keyword argument at calland nondefault argument cannot follow default argument at definition all "name=valuesyntax must appear after any simple "namein both places as we've also learnedpython matches argument values passed by position to argument names in function headers from left to rightsuch that these values always match the leftmost names in headers keywords match by name insteadand given argument can receive only one value to simplify our workwe can also make the assumption that call is valid in general --that isthat all arguments either will receive values (by name or position)or will be omitted intentionally to pick up defaults this assumption won' necessarily holdbecause the function has not yet actually been called when the wrapper logic tests validity --the call may still fail later when invoked by the wrapper layerdue to incorrect argument passing as long as that doesn' cause the wrapper to fail any more badlythoughwe can finesse the validity of the call this helpsbecause validating calls before they are actually made would require us to emulate python' argument-matching algorithm in full--againtoo complex procedure for our tool examplevalidating function arguments