r"""

    parse_return_type

    Args:
        sourcecode (?):

    Returns:
        tuple: (return_type, return_name, return_header)

    Ignore:
        testcase
        automated_helpers query_vsone_verified

    CommandLine:
        python -m utool.util_inspect parse_return_type
        python -m utool.util_inspect --test-parse_return_type


    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_inspect import *  # NOQA
        >>> import utool as ut
        >>> sourcecode = ut.codeblock(
        ...     'def foo(tmp=False):\n'
        ...     '    bar = True\n'
        ...     '    return bar\n'
        ... )
        >>> returninfo = parse_return_type(sourcecode)
        >>> result = ut.repr2(returninfo)
        >>> print(result)
        ('?', 'bar', 'Returns', '')

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_inspect import *  # NOQA
        >>> import utool as ut
        >>> sourcecode = ut.codeblock(
        ...     'def foo(tmp=False):\n'
        ...     '    return True\n'
        ... )
        >>> returninfo = parse_return_type(sourcecode)
        >>> result = ut.repr2(returninfo)
        >>> print(result)
        ('bool', 'True', 'Returns', '')

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_inspect import *  # NOQA
        >>> import utool as ut
        >>> sourcecode = ut.codeblock(
        ...     'def foo(tmp=False):\n'
        ...     '    for i in range(2): \n'
        ...     '        yield i\n'
        ... )
        >>> returninfo = parse_return_type(sourcecode)
        >>> result = ut.repr2(returninfo)
        >>> print(result)
        ('?', 'i', 'Yields', '')

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_inspect import *  # NOQA
        >>> import utool as ut
        >>> sourcecode = ut.codeblock(
        ...     'def foo(tmp=False):\n'
        ...     '    if tmp is True:\n'
        ...     '        return (True, False)\n'
        ...     '    elif tmp is False:\n'
        ...     '        return 1\n'
        ...     '    else:\n'
        ...     '        bar = baz()\n'
        ...     '        return bar\n'
        ... )
        >>> returninfo = parse_return_type(sourcecode)
        >>> result = ut.repr2(returninfo)
        >>> print(result)
        ('tuple', '(True, False)', 'Returns', '')

def parse_return_type(sourcecode):
    r"""

    parse_return_type

    Args:
        sourcecode (?):

    Returns:
        tuple: (return_type, return_name, return_header)

    Ignore:
        testcase
        automated_helpers query_vsone_verified

    CommandLine:
        python -m utool.util_inspect parse_return_type
        python -m utool.util_inspect --test-parse_return_type


    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_inspect import *  # NOQA
        >>> import utool as ut
        >>> sourcecode = ut.codeblock(
        ...     'def foo(tmp=False):\n'
        ...     '    bar = True\n'
        ...     '    return bar\n'
        ... )
        >>> returninfo = parse_return_type(sourcecode)
        >>> result = ut.repr2(returninfo)
        >>> print(result)
        ('?', 'bar', 'Returns', '')

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_inspect import *  # NOQA
        >>> import utool as ut
        >>> sourcecode = ut.codeblock(
        ...     'def foo(tmp=False):\n'
        ...     '    return True\n'
        ... )
        >>> returninfo = parse_return_type(sourcecode)
        >>> result = ut.repr2(returninfo)
        >>> print(result)
        ('bool', 'True', 'Returns', '')

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_inspect import *  # NOQA
        >>> import utool as ut
        >>> sourcecode = ut.codeblock(
        ...     'def foo(tmp=False):\n'
        ...     '    for i in range(2): \n'
        ...     '        yield i\n'
        ... )
        >>> returninfo = parse_return_type(sourcecode)
        >>> result = ut.repr2(returninfo)
        >>> print(result)
        ('?', 'i', 'Yields', '')

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_inspect import *  # NOQA
        >>> import utool as ut
        >>> sourcecode = ut.codeblock(
        ...     'def foo(tmp=False):\n'
        ...     '    if tmp is True:\n'
        ...     '        return (True, False)\n'
        ...     '    elif tmp is False:\n'
        ...     '        return 1\n'
        ...     '    else:\n'
        ...     '        bar = baz()\n'
        ...     '        return bar\n'
        ... )
        >>> returninfo = parse_return_type(sourcecode)
        >>> result = ut.repr2(returninfo)
        >>> print(result)
        ('tuple', '(True, False)', 'Returns', '')
    """
    import ast
    return_type, return_name, return_header = (None, None, None)

    if sourcecode is None:
        return return_type, return_name, return_header, None

    sourcecode = 'from __future__ import print_function\n' + sourcecode

    pt = ast.parse(sourcecode)
    import utool as ut
    debug = ut.get_argflag('--debug-parse-return')
    #debug = True

    if debug:
        import astor
        print('\nSource:')
        print(sourcecode)
        print('\nParse:')
        print(astor.dump(pt))
        print('... starting')

    def print_visit(type_, node):
        if debug:
            import utool as ut
            print('+---')
            print('\nVISIT %s node = %r' % (type_, node,))
            print('node.__dict__ = ' + ut.repr2(node.__dict__, nl=True))
            print('L___')

    def get_node_name_and_type(node):
        if isinstance(node, ast.Tuple):
            tupnode_list = node.elts
            tupleid = '(%s)' % (', '.join([str(get_node_name_and_type(tupnode)[1]) for tupnode in tupnode_list]))
            node_type = 'tuple'
            node_name = tupleid
        elif isinstance(node, ast.Dict):
            node_type = 'dict'
            node_name = None
        elif isinstance(node, ast.Name):
            node_name = node.id
            node_type = '?'
            if node_name in ['True', 'False']:
                node_type = 'bool'
            elif node_name == 'None':
                node_type = 'None'
        elif six.PY3 and isinstance(node, ast.NameConstant):
            node_name = str(node.value)
            node_type = '?'
            if node_name in ['True', 'False', True, False]:
                node_type = 'bool'
            elif node_name in ['None', None]:
                node_type = 'None'
        else:
            node_name = None
            node_type = '?'
            #node_type = 'ADD_TO_GET_NODE_NAME_AND_TYPE: ' + str(type(node.value))
        return node_type, node_name

    class ReturnVisitor(ast.NodeVisitor):
        def init(self):
            self.found_nodes = []
            self.return_header = None

        def visit_FunctionDef(self, node):
            print_visit('FunctionDef', node)
            # TODO: ignore subfunction return types
            ast.NodeVisitor.generic_visit(self, node)

        def visit_Return(self, node):
            print_visit('Return', node)
            ast.NodeVisitor.generic_visit(self, node)
            return_value = node.value
            print_visit('ReturnValue', return_value)
            self.found_nodes.append(return_value)
            self.return_header = 'Returns'

        def visit_Yield(self, node):
            print_visit('Yield', node)
            ast.NodeVisitor.generic_visit(self, node)
            return_value = node.value
            print_visit('YieldValue', return_value)
            self.found_nodes.append(return_value)
            self.return_header = 'Yields'
    try:
        self = ReturnVisitor()
        self.init()
        self.visit(pt)
        return_header = self.return_header
        if len(self.found_nodes) > 0:
            # hack rectify multiple return values
            node = self.found_nodes[0]
            return_type, return_name = get_node_name_and_type(node)
        else:
            return_name = None
            return_type = 'None'

    except Exception:
        if debug:
            raise

    return_desc = ''

    if return_type == '?':
        tup = infer_arg_types_and_descriptions([return_name], [])
        argtype_list, argdesc_list, argdefault_list, hasdefault_list = tup
        return_type = argtype_list[0]
        return_desc = argdesc_list[0]

    return return_type, return_name, return_header, return_desc