docs: def parse_control_options(controls, variable_defaults=None):
    """ Parse a set of control options.
  
    Args:
      controls: The dictionary of control options.
      variable_defaults: If the controls are for a Query with variables, then this is the
          default variable values defined in the Query module. The options in the controls
          parameter can override these but if a variable has no 'value' property then we
          fall back to these.
  
    Returns:
      - the HTML for the controls.
      - the default values for the controls as a dict.
      - the list of DIV IDs of the controls.
  
    """
    controls_html = ''
    control_defaults = {}
    control_ids = []
    div_id = _html.Html.next_id()
    if variable_defaults is None:
      variable_defaults = {}
    for varname, control in list(controls.items()):
      label = control.get('label', varname)
      control_id = div_id + '__' + varname
      control_ids.append(control_id)
      value = control.get('value', variable_defaults.get(varname, None))
      # The user should usually specify the type but we will default to 'textbox' for strings
      # and 'set' for lists.
      if isinstance(value, basestring):
        type = 'textbox'
      elif isinstance(value, list):
        type = 'set'
      else:
        type = None
      type = control.get('type', type)
  
      if type == 'picker':
        choices = control.get('choices', value)
        if not isinstance(choices, list) or len(choices) == 0:
          raise Exception('picker control must specify a nonempty set of choices')
        if value is None:
          value = choices[0]
        choices_html = ''
        for i, choice in enumerate(choices):
          choices_html += "<option value=\"%s\" %s>%s</option>" % \
                          (choice, ("selected=\"selected\"" if choice == value else ''), choice)
        control_html = "{label}<select disabled id=\"{id}\">{choices}</select>" \
            .format(label=label, id=control_id, choices=choices_html)
      elif type == 'set':  # Multi-picker; implemented as checkboxes.
        # TODO(gram): consider using "name" property of the control to group checkboxes. That
        # way we can save the code of constructing and parsing control Ids with sequential
        #  numbers in it. Multiple checkboxes can share the same name.
        choices = control.get('choices', value)
        if not isinstance(choices, list) or len(choices) == 0:
          raise Exception('set control must specify a nonempty set of choices')
        if value is None:
          value = choices
        choices_html = ''
        control_ids[-1] = '%s:%d' % (control_id, len(choices))  # replace ID to include count.
        for i, choice in enumerate(choices):
          checked = choice in value
          choice_id = '%s:%d' % (control_id, i)
          # TODO(gram): we may want a 'Submit/Refresh button as we may not want to rerun
          # query on each checkbox change.
          choices_html += """
            <div>
              <label>
                <input type="checkbox" id="{id}" value="{choice}" {checked} disabled>
                {choice}
              </label>
            </div>
          """.format(id=choice_id, choice=choice, checked="checked" if checked else '')
        control_html = "{label}<div>{choices}</div>".format(label=label, choices=choices_html)
      elif type == 'checkbox':
        control_html = """
              <label>
                <input type="checkbox" id="{id}" {checked} disabled>
                {label}
              </label>
          """.format(label=label, id=control_id, checked="checked" if value else '')
      elif type == 'slider':
        min_ = control.get('min', None)
        max_ = control.get('max', None)
        if min_ is None or max_ is None:
          raise Exception('slider control must specify a min and max value')
        if max_ <= min_:
          raise Exception('slider control must specify a min value less than max value')
        step = control.get('step', 1 if isinstance(min_, int) and isinstance(max_, int)
                           else (float(max_ - min_) / 10.0))
        if value is None:
          value = min_
        control_html = """
          {label}
          <input type="text" class="gchart-slider_value" id="{id}_value" value="{value}" disabled/>
          <input type="range" class="gchart-slider" id="{id}" min="{min}" max="{max}" step="{step}"
              value="{value}" disabled/>
        """.format(label=label, id=control_id, value=value, min=min_, max=max_, step=step)
      elif type == 'textbox':
        if value is None:
          value = ''
        control_html = "{label}<input type=\"text\" value=\"{value}\" id=\"{id}\" disabled/>" \
            .format(label=label, value=value, id=control_id)
      else:
        raise Exception(
            'Unknown control type %s (expected picker, slider, checkbox, textbox or set)' % type)
  
      control_defaults[varname] = value
      controls_html += "<div class=\"gchart-control\">{control}</div>\n" \
          .format(control=control_html)
  
    controls_html = "<div class=\"gchart-controls\">{controls}</div>".format(controls=controls_html)
    return controls_html, control_defaults, control_ids