Pages through a pql_query and performs an action (output_function).

    Args:
      pql_query: str a statement filter to apply (the query should not include
                 the limit or the offset)
      output_function: the function to call to output the results (csv or in
                       memory)
      values: A dict of python objects or a list of raw SOAP values to bind
              to the pql_query.

def _PageThroughPqlSet(self, pql_query, output_function, values):
    """Pages through a pql_query and performs an action (output_function).

    Args:
      pql_query: str a statement filter to apply (the query should not include
                 the limit or the offset)
      output_function: the function to call to output the results (csv or in
                       memory)
      values: A dict of python objects or a list of raw SOAP values to bind
              to the pql_query.
    """
    if isinstance(values, dict):
      values = PQLHelper.GetQueryValuesFromDict(values, self._version)

    pql_service = self._GetPqlService()
    current_offset = 0

    while True:
      query_w_limit_offset = '%s LIMIT %d OFFSET %d' % (pql_query,
                                                        SUGGESTED_PAGE_LIMIT,
                                                        current_offset)
      response = pql_service.select({'query': query_w_limit_offset,
                                     'values': values})

      if 'rows' in response:
        # Write the header row only on first pull
        if current_offset == 0:
          header = response['columnTypes']
          output_function([label['labelName'] for label in header])

        entities = response['rows']
        result_set_size = len(entities)

        for entity in entities:
          output_function([self._ConvertValueForCsv(value) for value
                           in entity['values']])

        current_offset += result_set_size
        if result_set_size != SUGGESTED_PAGE_LIMIT:
          break
      else:
        break