class_docstr: This class manages the coordination process with the consumer coordinator.
docstr: Returns list of preferred (protocols, metadata)
docstr_tok: ["Returns","list","of","preferred","(","protocols",",","metadata",")"]
code: def group_protocols(self):
      """Returns list of preferred (protocols, metadata)"""
      if self._subscription.subscription is None:
          raise Errors.IllegalStateError(
              "Consumer has not subscribed to topics"
          )
      # dpkp note: I really dislike this.
      # why? because we are using this strange method group_protocols,
      # which is seemingly innocuous, to set internal state (_joined_subscription)
      # that is later used to check whether metadata has changed since we joined a group
      # but there is no guarantee that this method, group_protocols, will get called
      # in the correct sequence or that it will only be called when we want it to be.
      # So this really should be moved elsewhere, but I don't have the energy to
      # work that out right now. If you read this at some later date after the mutable
      # state has bitten you... I'm sorry! It mimics the java client, and that's the
      # best I've got for now.
      self._joined_subscription = set(self._subscription.subscription)
      metadata_list = []
      for assignor in self.config["assignors"]:
          metadata = assignor.metadata(self._joined_subscription)
          group_protocol = (assignor.name, metadata)
          metadata_list.append(group_protocol)
      return metadata_list
  
imports: from __future__ import absolute_import, division
  import collections
  import copy
  import functools
  import logging
  import time
  from kafka.vendor import six
  from kafka.coordinator.base import BaseCoordinator, Generation
  from kafka.coordinator.assignors.range import RangePartitionAssignor
  from kafka.coordinator.assignors.roundrobin import RoundRobinPartitionAssignor
  from kafka.coordinator.assignors.sticky.sticky_assignor import StickyPartitionAssignor
  from kafka.coordinator.protocol import ConsumerProtocol
  import kafka.errors
  from kafka.future import Future
  from kafka.metrics import AnonMeasurable
  from kafka.metrics.stats import Avg, Count, Max, Rate
  from kafka.protocol.commit import OffsetCommitRequest, OffsetFetchRequest
  from kafka.structs import OffsetAndMetadata, TopicPartition
  from kafka.util import WeakMethod
label_desc: Use image node_id 4 for calling the ConsumerCoordinator obj's underlying member method code with example usage: obj.group_protocols() and returns: metadata_list