def portable_argspec(func):
if sys.version_info < (<NUM_LIT:3>, <NUM_LIT:0>):  <EOL><INDENT>argnames, varargs, varkw, defaults = inspect.getargspec(func)<EOL>annotations = {}<EOL><DEDENT>else:<EOL><INDENT>(<EOL>argnames, varargs, varkw, defaults, kwa, kwd, annotations<EOL>) = inspect.getfullargspec(func)<EOL><DEDENT>kw_boundary = len(argnames) - len(defaults) if defaults else len(argnames)<EOL>positional_params = argnames[:kw_boundary]<EOL>kw_params = argnames[kw_boundary:]<EOL>return positional_params, kw_params, varargs, defaults, annotations<EOL>
Given a function, return a tuple of
(positional_params, keyword_params, varargs, defaults, annotations)
where
* positional_params is a list of parameters that don't have default values
* keyword_params is a list of parameters that have default values
* varargs is the string name for variable arguments
* defaults is a dict of default values for the keyword parameters
* annotations is a dictionary of param_name: annotation pairs
    it may be empty, and on python 2 will always be empty.

This function is portable between Python 2 and Python 3, and does some
extra processing of the output from inspect.