docs: 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