def _get_function_args()

in src/python/pants/help/build_dictionary_info_extracter.py [0:0]


  def _get_function_args(cls, func):
    arg_descriptions = cls.get_arg_descriptions_from_docstring(func)
    argspec = inspect.getfullargspec(func) if PY3 else inspect.getargspec(func)
    arg_names = argspec.args
    if arg_names and arg_names[0] in {'self', 'cls'}:
      arg_names = arg_names[1:]
    num_defaulted_args = len(argspec.defaults) if argspec.defaults is not None else 0
    first_defaulted_arg = len(arg_names) - num_defaulted_args
    for i in range(0, first_defaulted_arg):
      yield FunctionArg(arg_names[i], arg_descriptions.pop(arg_names[i], ''), False, None)
    for i in range(first_defaulted_arg, len(arg_names)):
      yield FunctionArg(arg_names[i], arg_descriptions.pop(arg_names[i], ''), True,
                        argspec.defaults[i - first_defaulted_arg])
    if argspec.varargs:
      yield FunctionArg('*{}'.format(argspec.varargs), arg_descriptions.pop(argspec.varargs, None),
                        False, None)

    kw = argspec.varkw if PY3 else argspec.keywords
    if kw:
      # Any remaining arg_descriptions are for kwargs.
      for arg_name, descr in arg_descriptions.items():
        # Get the default value out of the description, if present.
        mo = cls._get_default_value_re().search(descr)
        default_value = mo.group(1) if mo else None
        descr_sans_default = '{}{}'.format(descr[:mo.start()], descr[mo.end():]) if mo else descr
        yield FunctionArg(arg_name, descr_sans_default, True, default_value)