def parse_funcdef(s, trim_string_markers=True, trim_sequence_markers=True):
    """Tokenize and parse a function definition

    Args:
        s (str): function definition
        trim_string_markers (bool): if an annotation is a string
            then remove the surrounding quotes

    Returns:
        tuple: (funcname, parameters, return_annotation)

        prameters are dicts that look like
            {'name': 'param_name', 'default': '', 'annotation': ''}
    """
    tree = STTree(s)
    funcdef = tree.find('funcdef')
    funcname = str(funcdef.find_all(token.NAME, max_depth=1)[1])

    # parse parameters
    params = []

    argslist = funcdef.find('typedargslist')
    if argslist:
        tfpdefs = argslist.find_all('tfpdef', max_depth=1)
    else:
        tfpdefs = []

    lone_star = argslist.find(token.STAR, max_depth=1)
    lone_star_idx = lone_star.index if lone_star else sys.maxsize
    # nxt = lone_star.get_next_sibling() if lone_star else None
    # if nxt and nxt.toknum == token.COMMA:
    #     lone_star_idx = lone_star.index
    # else:
    #     lone_star = None
    #     lone_star_idx = sys.maxsize

    for p in tfpdefs:
        default_value = None
        default_type = None
        annotation = ""
        is_vararg = False
        is_kwarg = False
        is_optional = False

        name_node = p.find(token.NAME, max_depth=1)
        name = str(name_node)
        marker = p.find_next_sibling((token.STAR, token.DOUBLESTAR),
                                     max_distance=1, direction=-1)
        if marker:
            if marker.toknum == token.STAR:
                is_vararg = True
            elif marker.toknum == token.DOUBLESTAR:
                is_kwarg = True
            name = str(marker) + name

        # get default value if one exists
        default_marker = p.get_next_sibling()
        if default_marker and default_marker.toknum == token.EQUAL:
            is_optional = True
            default_value = default_marker.get_next_sibling().format()
            default_type = _extract_type(default_value)

        # get annotation if one exists
        annotation_token = p.find(token.COLON)
        if annotation_token:
            annotation = p.format(start=annotation_token, ends=False)

        # lone_star_idx + 1 keeps kwonly == False for vararg
        params.append(dict(name=name, default_value=default_value,
                           default_type=default_type, annotation=annotation,
                           is_optional=is_optional, is_vararg=is_vararg,
                           is_kwarg=is_kwarg,
                           kwonly=p.index > lone_star_idx + 1))

    # parse the return annotation
    rarrow = funcdef.find(token.RARROW, max_depth=1)
    if rarrow:
        annot_end = rarrow.find_next_sibling(token.COLON)
        ret_annotation = funcdef.format(start=rarrow, stop=annot_end,
                                        ends=False)
    else:
        ret_annotation = ""


    _sanitize = lambda s: _trim_enclosing(s, quotes=trim_string_markers,
                                          sequence_markers=trim_sequence_markers)
    if trim_string_markers:
        for p in params:
            if p['annotation']:
                p['annotation'] = _sanitize(p['annotation'])
        ret_annotation = _sanitize(ret_annotation)

    return funcname, params, ret_annotation
dataset/ETHPy150Open KristoforMaynard/SublimeAutoDocstring/dparse.py/parse_funcdef/original