import collections
import ast


def parse_function_info_name(function_info):
  """Takes a FunctionInfo and returns (function_name, list_of_args).
  Args:
    function_info: A FunctionInfo namedtuple.
  Returns:
    A tuple (function_name, list_of_args, constant_kwargs), where function_name
    is a string, list_of_args is a list of strings, and constant_kwargs is a
    dict mapping argument names to their constant literal values. For example,
    if the FunctionInfo's name is 'tf.foo.bar(x, axis, baz=True)', then
    this function would return ('tf.foo.bar', ['x', 'axis'], {'baz': True}).
  Raises:
    ValueError: If the FunctionInfo's name is not properly formatted.
  """
  name = function_info.name

  if name.count('(') != 1:
    raise ValueError("The FunctionInfo's name must have exactly one open "
                     "parenthesis.")
  if name.count(')') != 1 or name[-1] != ')':
    raise ValueError("The FunctionInfo's name must have exactly one close "
                     "parenthesis, at the end of the name.")

  open_paren = name.index('(')
  close_paren = name.index(')')
  function_name = name[ : open_paren]
  arg_list = name[open_paren + 1 : close_paren]
  split_by_comma = [arg.strip() for arg in arg_list.split(',')]
  list_of_args = []
  constant_kwargs = collections.OrderedDict()
  for part in split_by_comma:
    if '=' in part:
      kwarg_name, literal_as_string = [x.strip() for x in part.split('=')]
      constant_kwargs[kwarg_name] = ast.literal_eval(literal_as_string)
    else:
      list_of_args.append(part)
  return function_name, list_of_args, constant_kwargs