Repository: confluentinc/confluent-kafka-python
Pull request #1873: KIP 848: Added support for DescribeConsumerGroup for consumer protocol groups 
Author: login: PratRanj07
Created: 2024-12-17T20:31:36Z | Merged: 2025-04-17T14:49:36Z

This PR intends to add support for DescribeConsumerGroup for the new consumer protocol.
The tests will fail till the changes in the librdkafka is merged to master.
Librdkafka PR: [https://github.com/https://github.com/https://github.com/confluentinc/librdkafka/pull/4941](KIP 848: Added support for DescribeConsumerGroup for consumer protocol groups)


Diff:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cc0ac4857..3b148fc02 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,16 @@
 # Confluent's Python client for Apache Kafka
 
+## v2.10.0
+
+v2.10.0 is a feature release with the following fixes and enhancements:
+
+- [KIP-848] Group Config is now supported in AlterConfigs, IncrementalAlterConfigs and DescribeConfigs. (#1856)
+- [KIP-848] `describe_consumer_groups()` now supports KIP-848 introduced `consumer` groups. Two new fields for consumer group type and target assignment have also been added. Type defines whether this group is a `classic` or `consumer` group. Target assignment is only valid for the `consumer` protocol and its defaults to NULL. (#1873).
+
+confluent-kafka-python v2.10.0 is based on librdkafka v2.10.0, see the
+[librdkafka release notes](https://github.com/confluentinc/librdkafka/releases/tag/v2.10.0)
+for a complete list of changes, enhancements, fixes and upgrade considerations.
+
 ## v2.9.0
 
 v2.9.0 is a feature release with the following fixes and enhancements:
diff --git a/docs/conf.py b/docs/conf.py
index 95fca1765..097484066 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -20,14 +20,14 @@
 ######################################################################
 # General information about the project.
 project = u'confluent-kafka'
-copyright = u'2016-2024, Confluent Inc.'
+copyright = u'2016-2025, Confluent Inc.'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '2.9.0'
+version = '2.10.0rc3'
 # The full version, including alpha/beta/rc tags.
 release = version
 ######################################################################
diff --git a/examples/adminapi.py b/examples/adminapi.py
index 54f119e02..0eb87216c 100755
--- a/examples/adminapi.py
+++ b/examples/adminapi.py
@@ -535,6 +535,7 @@ def example_describe_consumer_groups(a, args):
             print("Group Id: {}".format(g.group_id))
             print("  Is Simple          : {}".format(g.is_simple_consumer_group))
             print("  State              : {}".format(g.state))
+            print("  Type               : {}".format(g.type))
             print("  Partition Assignor : {}".format(g.partition_assignor))
             print(
                 f"  Coordinator        : {g.coordinator}")
@@ -548,6 +549,10 @@ def example_describe_consumer_groups(a, args):
                     print("    Assignments       :")
                     for toppar in member.assignment.topic_partitions:
                         print("      {} [{}]".format(toppar.topic, toppar.partition))
+                if member.target_assignment:
+                    print("    Target Assignments:")
+                    for toppar in member.target_assignment.topic_partitions:
+                        print(f"      {toppar.topic} [{toppar.partition}]")
             if (include_auth_ops):
                 print("  Authorized operations: ")
                 op_string = ""
diff --git a/examples/docker/Dockerfile.alpine b/examples/docker/Dockerfile.alpine
index c7f37fe4a..db08bad1e 100644
--- a/examples/docker/Dockerfile.alpine
+++ b/examples/docker/Dockerfile.alpine
@@ -30,7 +30,7 @@ FROM alpine:3.12
 
 COPY . /usr/src/confluent-kafka-python
 
-ENV LIBRDKAFKA_VERSION="v2.8.0"
+ENV LIBRDKAFKA_VERSION="v2.10.0-RC3"
 ENV KCAT_VERSION="master"
 ENV CKP_VERSION="master"
 
diff --git a/pyproject.toml b/pyproject.toml
index e581b8e45..c3b7aa814 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
 
 [project]
 name = "confluent-kafka"
-version = "2.9.0"
+version = "2.10.0rc3"
 description = "Confluent's Python client for Apache Kafka"
 classifiers = [
     "Development Status :: 5 - Production/Stable",
diff --git a/src/confluent_kafka/admin/_group.py b/src/confluent_kafka/admin/_group.py
index 964d62b2f..7823e976a 100644
--- a/src/confluent_kafka/admin/_group.py
+++ b/src/confluent_kafka/admin/_group.py
@@ -94,15 +94,18 @@ class MemberDescription:
         The host where the group member is running.
     assignment: MemberAssignment
         The assignment of the group member
+    target_assignment: MemberAssignment
+        The target assignment of the group member
     group_instance_id : str
         The instance id of the group member.
     """
 
-    def __init__(self, member_id, client_id, host, assignment, group_instance_id=None):
+    def __init__(self, member_id, client_id, host, assignment, group_instance_id=None, target_assignment=None):
         self.member_id = member_id
         self.client_id = client_id
         self.host = host
         self.assignment = assignment
+        self.target_assignment = target_assignment
         self.group_instance_id = group_instance_id
 
 
@@ -123,6 +126,8 @@ class ConsumerGroupDescription:
         Partition assignor.
     state : ConsumerGroupState
         Current state of the consumer group.
+    type  : ConsumerGroupType
+        Type of the consumer group.
     coordinator: Node
         Consumer group coordinator.
     authorized_operations: list(AclOperation)
@@ -130,7 +135,7 @@ class ConsumerGroupDescription:
     """
 
     def __init__(self, group_id, is_simple_consumer_group, members, partition_assignor, state,
-                 coordinator, authorized_operations=None):
+                 coordinator, authorized_operations=None, type=ConsumerGroupType.UNKNOWN):
         self.group_id = group_id
         self.is_simple_consumer_group = is_simple_consumer_group
         self.members = members
@@ -143,4 +148,6 @@ def __init__(self, group_id, is_simple_consumer_group, members, partition_assign
         self.partition_assignor = partition_assignor
         if state is not None:
             self.state = ConversionUtil.convert_to_enum(state, ConsumerGroupState)
+        if type is not None:
+            self.type = ConversionUtil.convert_to_enum(type, ConsumerGroupType)
         self.coordinator = coordinator
diff --git a/src/confluent_kafka/src/Admin.c b/src/confluent_kafka/src/Admin.c
index 5eeb5c4cd..451017ad6 100644
--- a/src/confluent_kafka/src/Admin.c
+++ b/src/confluent_kafka/src/Admin.c
@@ -3857,7 +3857,9 @@ static PyObject *Admin_c_MemberDescription_to_py(const rd_kafka_MemberDescriptio
         PyObject *args = NULL;
         PyObject *kwargs = NULL;
         PyObject *assignment = NULL;
+        PyObject *target_assignment = NULL;
         const rd_kafka_MemberAssignment_t *c_assignment;
+        const rd_kafka_MemberAssignment_t *c_target_assignment;
 
         MemberDescription_type = cfl_PyObject_lookup("confluent_kafka.admin",
                                                      "MemberDescription");
@@ -3892,6 +3894,15 @@ static PyObject *Admin_c_MemberDescription_to_py(const rd_kafka_MemberDescriptio
 
         PyDict_SetItemString(kwargs, "assignment", assignment);
 
+        c_target_assignment = rd_kafka_MemberDescription_target_assignment(c_member);
+        if(c_target_assignment) {
+                target_assignment = Admin_c_MemberAssignment_to_py(c_target_assignment);
+                if (!target_assignment) {
+                        goto err;
+                }
+                PyDict_SetItemString(kwargs, "target_assignment", target_assignment);
+        }
+
         args = PyTuple_New(0);
 
         member = PyObject_Call(MemberDescription_type, args, kwargs);
@@ -3900,6 +3911,7 @@ static PyObject *Admin_c_MemberDescription_to_py(const rd_kafka_MemberDescriptio
         Py_DECREF(kwargs);
         Py_DECREF(MemberDescription_type);
         Py_DECREF(assignment);
+        Py_XDECREF(target_assignment);
         return member;
 
 err:
@@ -3908,6 +3920,7 @@ static PyObject *Admin_c_MemberDescription_to_py(const rd_kafka_MemberDescriptio
         Py_XDECREF(kwargs);
         Py_XDECREF(MemberDescription_type);
         Py_XDECREF(assignment);
+        Py_XDECREF(target_assignment);
         Py_XDECREF(member);
         return NULL;
 }
@@ -4003,6 +4016,8 @@ static PyObject *Admin_c_ConsumerGroupDescription_to_py(
 
         cfl_PyDict_SetInt(kwargs, "state", rd_kafka_ConsumerGroupDescription_state(c_consumer_group_description));
 
+        cfl_PyDict_SetInt(kwargs, "type", rd_kafka_ConsumerGroupDescription_type(c_consumer_group_description));
+
         args = PyTuple_New(0);
 
         consumer_group_description = PyObject_Call(ConsumerGroupDescription_type, args, kwargs);
diff --git a/src/confluent_kafka/src/confluent_kafka.h b/src/confluent_kafka/src/confluent_kafka.h
index 12d7c14e1..871ce88af 100644
--- a/src/confluent_kafka/src/confluent_kafka.h
+++ b/src/confluent_kafka/src/confluent_kafka.h
@@ -42,8 +42,8 @@
  *  0xMMmmRRPP
  *  MM=major, mm=minor, RR=revision, PP=patchlevel (not used)
  */
-#define CFL_VERSION     0x02090000
-#define CFL_VERSION_STR "2.9.0"
+#define CFL_VERSION     0x020a0000
+#define CFL_VERSION_STR "2.10.0rc3"
 
 /**
  * Minimum required librdkafka version. This is checked both during
@@ -51,19 +51,19 @@
  * Make sure to keep the MIN_RD_KAFKA_VERSION, MIN_VER_ERRSTR and #error
  * defines and strings in sync.
  */
-#define MIN_RD_KAFKA_VERSION 0x020800ff
+#define MIN_RD_KAFKA_VERSION 0x020a00ff
 
 #ifdef __APPLE__
-#define MIN_VER_ERRSTR "confluent-kafka-python requires librdkafka v2.8.0 or later. Install the latest version of librdkafka from Homebrew by running `brew install librdkafka` or `brew upgrade librdkafka`"
+#define MIN_VER_ERRSTR "confluent-kafka-python requires librdkafka v2.10.0 or later. Install the latest version of librdkafka from Homebrew by running `brew install librdkafka` or `brew upgrade librdkafka`"
 #else
-#define MIN_VER_ERRSTR "confluent-kafka-python requires librdkafka v2.8.0 or later. Install the latest version of librdkafka from the Confluent repositories, see http://docs.confluent.io/current/installation.html"
+#define MIN_VER_ERRSTR "confluent-kafka-python requires librdkafka v2.10.0 or later. Install the latest version of librdkafka from the Confluent repositories, see http://docs.confluent.io/current/installation.html"
 #endif
 
 #if RD_KAFKA_VERSION < MIN_RD_KAFKA_VERSION
 #ifdef __APPLE__
-#error "confluent-kafka-python requires librdkafka v2.8.0 or later. Install the latest version of librdkafka from Homebrew by running `brew install librdkafka` or `brew upgrade librdkafka`"
+#error "confluent-kafka-python requires librdkafka v2.10.0 or later. Install the latest version of librdkafka from Homebrew by running `brew install librdkafka` or `brew upgrade librdkafka`"
 #else
-#error "confluent-kafka-python requires librdkafka v2.8.0 or later. Install the latest version of librdkafka from the Confluent repositories, see http://docs.confluent.io/current/installation.html"
+#error "confluent-kafka-python requires librdkafka v2.10.0 or later. Install the latest version of librdkafka from the Confluent repositories, see http://docs.confluent.io/current/installation.html"
 #endif
 #endif
 


Reviews:
user: login: pranavrth
body: Comment on Code part.
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-17T06:28:39Z
user: login: PratRanj07
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T07:42:06Z
user: login: emasab
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T10:55:30Z
user: login: emasab
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T12:08:12Z
user: login: PratRanj07
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T12:14:47Z
user: login: emasab
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T12:33:07Z
user: login: emasab
body: It's ok for me, reviewing the tests separately. Did some manual tests for the moment.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T14:07:47Z
user: login: pranavrth
body: LGTM!.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-17T14:48:56Z

Review comments:
diff_hunk: @@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+# Copyright 2024 Confluent Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from confluent_kafka import ConsumerGroupState, ConsumerGroupType, TopicPartition
+import uuid
+
+topic_prefix = "test-topic"
+
+
+def create_consumers(kafka_cluster, topic, group_id, client_id, Protocol):
+    conf = {'group.id': group_id,
+            'client.id': client_id,
+            'group.protocol': Protocol,
+            'enable.auto.commit': False,
+            'auto.offset.reset': 'earliest',
+            'debug': 'all'}
path: tests/integration/admin/test_describe_consumer_groups_compatability.py
user: login: pranavrth
body: Remove debug logging.
created_at: 2025-04-16T19:11:03Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+# Copyright 2024 Confluent Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from confluent_kafka import ConsumerGroupState, ConsumerGroupType, TopicPartition
+import uuid
+
+topic_prefix = "test-topic"
+
+
+def create_consumers(kafka_cluster, topic, group_id, client_id, Protocol):
path: tests/integration/admin/test_describe_consumer_groups_compatability.py
user: login: pranavrth
body: ```suggestion
def create_consumers(kafka_cluster, topic, group_id, client_id, group_protocol):
```
created_at: 2025-04-16T19:11:18Z
author_association: MEMBER
diff_hunk: @@ -548,6 +549,10 @@ def example_describe_consumer_groups(a, args):
                     print("    Assignments       :")
                     for toppar in member.assignment.topic_partitions:
                         print("      {} [{}]".format(toppar.topic, toppar.partition))
+                if member.target_assignment:
+                    print("    Target Assignments:")
+                    for toppar in member.target_assignment.topic_partitions:
+                        print("      {} [{}]".format(toppar.topic, toppar.partition))
path: examples/adminapi.py
user: login: pranavrth
body: ```suggestion
                if member.target_assignment:
                    print("    Target Assignments:")
                    for toppar in member.target_assignment.topic_partitions:
                        print(f"      {toppar.topic} [{toppar.partition)}]"
```
created_at: 2025-04-17T06:13:52Z
author_association: MEMBER
diff_hunk: @@ -94,15 +94,18 @@ class MemberDescription:
         The host where the group member is running.
     assignment: MemberAssignment
         The assignment of the group member
+    target_assignment: MemberAssignment
+        The target assignment of the group member
     group_instance_id : str
         The instance id of the group member.
     """
 
-    def __init__(self, member_id, client_id, host, assignment, group_instance_id=None):
+    def __init__(self, member_id, client_id, host, assignment, target_assignment, group_instance_id=None):
path: src/confluent_kafka/admin/_group.py
user: login: pranavrth
body: Don't change the API contract.

```suggestion
    def __init__(self, member_id, client_id, host, assignment, group_instance_id=None, target_assignment=None):
```
created_at: 2025-04-17T06:14:32Z
author_association: MEMBER
diff_hunk: @@ -123,14 +126,16 @@ class ConsumerGroupDescription:
         Partition assignor.
     state : ConsumerGroupState
         Current state of the consumer group.
+    type  : ConsumerGroupType
+        Type of the consumer group.
     coordinator: Node
         Consumer group coordinator.
     authorized_operations: list(AclOperation)
         AclOperations allowed for the consumer group.
     """
 
     def __init__(self, group_id, is_simple_consumer_group, members, partition_assignor, state,
-                 coordinator, authorized_operations=None):
+                 type, coordinator, authorized_operations=None):
path: src/confluent_kafka/admin/_group.py
user: login: pranavrth
body: Don't change API contract.

```suggestion
                 coordinator, authorized_operations=None, type=ConsumerGroupType.UNKNOWN):
```
created_at: 2025-04-17T06:24:17Z
author_association: MEMBER
diff_hunk: @@ -3892,6 +3893,15 @@ static PyObject *Admin_c_MemberDescription_to_py(const rd_kafka_MemberDescriptio
 
         PyDict_SetItemString(kwargs, "assignment", assignment);
 
+        c_target_assignment = rd_kafka_MemberDescription_target_assignment(c_member);
+        if(c_target_assignment) {
+                PyObject *target_assignment = Admin_c_MemberAssignment_to_py(c_target_assignment);
path: src/confluent_kafka/src/Admin.c
user: login: pranavrth
body:  - declare at top with `assignment`
 - Decrease refcount.
created_at: 2025-04-17T06:26:23Z
author_association: MEMBER
diff_hunk: @@ -3892,6 +3893,15 @@ static PyObject *Admin_c_MemberDescription_to_py(const rd_kafka_MemberDescriptio
 
         PyDict_SetItemString(kwargs, "assignment", assignment);
 
+        c_target_assignment = rd_kafka_MemberDescription_target_assignment(c_member);
+        if(c_target_assignment) {
+                PyObject *target_assignment = Admin_c_MemberAssignment_to_py(c_target_assignment);
+                if (!target_assignment) {
path: src/confluent_kafka/src/Admin.c
user: login: pranavrth
body: Check NULL case is working or not. target_assignment should be None in that case.
created_at: 2025-04-17T06:28:09Z
author_association: MEMBER
diff_hunk: @@ -3892,6 +3893,15 @@ static PyObject *Admin_c_MemberDescription_to_py(const rd_kafka_MemberDescriptio
 
         PyDict_SetItemString(kwargs, "assignment", assignment);
 
+        c_target_assignment = rd_kafka_MemberDescription_target_assignment(c_member);
+        if(c_target_assignment) {
+                PyObject *target_assignment = Admin_c_MemberAssignment_to_py(c_target_assignment);
+                if (!target_assignment) {
path: src/confluent_kafka/src/Admin.c
user: login: PratRanj07
body: Yes it is working
created_at: 2025-04-17T07:42:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+# Copyright 2024 Confluent Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from confluent_kafka import ConsumerGroupState, ConsumerGroupType, TopicPartition
+import uuid
+
+topic_prefix = "test-topic"
+
+
+def create_consumers(kafka_cluster, topic, group_id, client_id, group_protocol):
+    conf = {'group.id': group_id,
+            'client.id': client_id,
+            'group.protocol': group_protocol,
+            'enable.auto.commit': False,
+            'auto.offset.reset': 'earliest'}
+    consumer = kafka_cluster.consumer(conf)
+    consumer.subscribe([topic])
+    consumer.poll(10)
+    return consumer
+
+
+def verify_describe_consumer_groups(kafka_cluster, admin_client, topic):
+    def create_consumer_groups():
+        """Create consumer groups with new and old protocols."""
+        group_ids = {
+            "new1": f"test-group_new1-{uuid.uuid4()}",
+            "new2": f"test-group_new2-{uuid.uuid4()}",
+            "old1": f"test-group_old1-{uuid.uuid4()}",
+            "old2": f"test-group_old2-{uuid.uuid4()}",
+        }
+        client_ids = {
+            "new": ["test-client1", "test-client2"],
+            "old": ["test-client3", "test-client4"],
+        }
+
+        consumers = [
+            create_consumers(kafka_cluster, topic, group_ids["new1"], client_ids["new"][0], "consumer"),
+            create_consumers(kafka_cluster, topic, group_ids["new2"], client_ids["new"][1], "consumer"),
+            create_consumers(kafka_cluster, topic, group_ids["old1"], client_ids["old"][0], "classic"),
+            create_consumers(kafka_cluster, topic, group_ids["old2"], client_ids["old"][1], "classic"),
+        ]
+        return group_ids, client_ids, consumers
+
+    def verify_consumer_group_results(fs, expected_group_ids, expected_type, expected_clients):
+        """Verify the results of consumer group descriptions."""
+        for group_id, f in fs.items():
+            result = f.result()
+            assert result.group_id in expected_group_ids
+            assert result.is_simple_consumer_group is False
+            assert result.state == ConsumerGroupState.STABLE
+            assert result.type == expected_type
+            assert len(result.members) == 1
+            for member in result.members:
+                assert member.client_id in expected_clients
+                assert member.assignment.topic_partitions == partition
+
+    # Create consumer groups
+    group_ids, client_ids, consumers = create_consumer_groups()
+    partition = [TopicPartition(topic, 0)]
+
+    # Describe and verify new group protocol consumer groups
+    fs_new = admin_client.describe_consumer_groups([group_ids["new1"], group_ids["new2"]])
+    verify_consumer_group_results(fs_new, [group_ids["new1"], group_ids["new2"]],
+                                  ConsumerGroupType.CONSUMER, client_ids["new"])
+
+    # Describe and verify old group protocol consumer groups
+    fs_old = admin_client.describe_consumer_groups([group_ids["old1"], group_ids["old2"]])
+    verify_consumer_group_results(fs_old, [group_ids["old1"], group_ids["old2"]],
+                                  ConsumerGroupType.CLASSIC, client_ids["old"])
+
+    # Describe and verify all consumer groups
+    fs_all = admin_client.describe_consumer_groups(list(group_ids.values()))
+    for group_id, f in fs_all.items():
+        result = f.result()
+        assert result.group_id in group_ids.values()
+        assert result.is_simple_consumer_group is False
+        assert result.state == ConsumerGroupState.STABLE
+        if result.group_id in [group_ids["new1"], group_ids["new2"]]:
+            assert result.type == ConsumerGroupType.CONSUMER
+            assert result.members[0].client_id in client_ids["new"]
+        else:
+            assert result.type == ConsumerGroupType.CLASSIC
+            assert result.members[0].client_id in client_ids["old"]
+        assert result.members[0].assignment.topic_partitions == partition
+
+    # Close all consumers
+    for consumer in consumers:
+        consumer.close()
+
+
+def test_describe_consumer_groups_compatability(kafka_cluster):
path: tests/integration/admin/test_describe_consumer_groups_compatability.py
user: login: emasab
body: ```suggestion
def test_describe_consumer_groups_compatibility(kafka_cluster):
```
created_at: 2025-04-17T10:55:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+# Copyright 2024 Confluent Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from confluent_kafka import ConsumerGroupState, ConsumerGroupType, TopicPartition
+import uuid
+
+topic_prefix = "test-topic"
+
+
+def create_consumers(kafka_cluster, topic, group_id, client_id, group_protocol):
+    conf = {'group.id': group_id,
+            'client.id': client_id,
+            'group.protocol': group_protocol,
+            'enable.auto.commit': False,
+            'auto.offset.reset': 'earliest'}
+    consumer = kafka_cluster.consumer(conf)
+    consumer.subscribe([topic])
+    consumer.poll(10)
+    return consumer
+
+
+def verify_describe_consumer_groups(kafka_cluster, admin_client, topic):
+    def create_consumer_groups():
+        """Create consumer groups with new and old protocols."""
+        group_ids = {
+            "new1": f"test-group_new1-{uuid.uuid4()}",
+            "new2": f"test-group_new2-{uuid.uuid4()}",
+            "old1": f"test-group_old1-{uuid.uuid4()}",
+            "old2": f"test-group_old2-{uuid.uuid4()}",
+        }
+        client_ids = {
+            "new": ["test-client1", "test-client2"],
+            "old": ["test-client3", "test-client4"],
+        }
+
+        consumers = [
+            create_consumers(kafka_cluster, topic, group_ids["new1"], client_ids["new"][0], "consumer"),
+            create_consumers(kafka_cluster, topic, group_ids["new2"], client_ids["new"][1], "consumer"),
+            create_consumers(kafka_cluster, topic, group_ids["old1"], client_ids["old"][0], "classic"),
+            create_consumers(kafka_cluster, topic, group_ids["old2"], client_ids["old"][1], "classic"),
+        ]
+        return group_ids, client_ids, consumers
+
+    def verify_consumer_group_results(fs, expected_group_ids, expected_type, expected_clients):
+        """Verify the results of consumer group descriptions."""
+        for group_id, f in fs.items():
+            result = f.result()
+            assert result.group_id in expected_group_ids
+            assert result.is_simple_consumer_group is False
+            assert result.state == ConsumerGroupState.STABLE
+            assert result.type == expected_type
+            assert len(result.members) == 1
+            for member in result.members:
+                assert member.client_id in expected_clients
+                assert member.assignment.topic_partitions == partition
+
+    # Create consumer groups
+    group_ids, client_ids, consumers = create_consumer_groups()
+    partition = [TopicPartition(topic, 0)]
+
+    # Describe and verify new group protocol consumer groups
+    fs_new = admin_client.describe_consumer_groups([group_ids["new1"], group_ids["new2"]])
+    verify_consumer_group_results(fs_new, [group_ids["new1"], group_ids["new2"]],
+                                  ConsumerGroupType.CONSUMER, client_ids["new"])
+
+    # Describe and verify old group protocol consumer groups
+    fs_old = admin_client.describe_consumer_groups([group_ids["old1"], group_ids["old2"]])
+    verify_consumer_group_results(fs_old, [group_ids["old1"], group_ids["old2"]],
+                                  ConsumerGroupType.CLASSIC, client_ids["old"])
+
+    # Describe and verify all consumer groups
+    fs_all = admin_client.describe_consumer_groups(list(group_ids.values()))
+    for group_id, f in fs_all.items():
+        result = f.result()
+        assert result.group_id in group_ids.values()
+        assert result.is_simple_consumer_group is False
+        assert result.state == ConsumerGroupState.STABLE
+        if result.group_id in [group_ids["new1"], group_ids["new2"]]:
+            assert result.type == ConsumerGroupType.CONSUMER
+            assert result.members[0].client_id in client_ids["new"]
+        else:
+            assert result.type == ConsumerGroupType.CLASSIC
+            assert result.members[0].client_id in client_ids["old"]
+        assert result.members[0].assignment.topic_partitions == partition
+
+    # Close all consumers
+    for consumer in consumers:
+        consumer.close()
+
+
+def test_describe_consumer_groups_compatability(kafka_cluster):
path: tests/integration/admin/test_describe_consumer_groups_compatability.py
user: login: emasab
body: We should change the test `test_describe_operations.py` instead of adding this one. There's a test that is disabled with KIP-848 there.
Here it seems the `verify_describe_consumer_groups` test isn't run as it doesn't start with `test_` and isn't called by `test_describe_consumer_groups_compatibility`.

Better to move this tests to a different PR and merge them for GA.
created_at: 2025-04-17T12:08:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+# Copyright 2024 Confluent Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from confluent_kafka import ConsumerGroupState, ConsumerGroupType, TopicPartition
+import uuid
+
+topic_prefix = "test-topic"
+
+
+def create_consumers(kafka_cluster, topic, group_id, client_id, group_protocol):
+    conf = {'group.id': group_id,
+            'client.id': client_id,
+            'group.protocol': group_protocol,
+            'enable.auto.commit': False,
+            'auto.offset.reset': 'earliest'}
+    consumer = kafka_cluster.consumer(conf)
+    consumer.subscribe([topic])
+    consumer.poll(10)
+    return consumer
+
+
+def verify_describe_consumer_groups(kafka_cluster, admin_client, topic):
+    def create_consumer_groups():
+        """Create consumer groups with new and old protocols."""
+        group_ids = {
+            "new1": f"test-group_new1-{uuid.uuid4()}",
+            "new2": f"test-group_new2-{uuid.uuid4()}",
+            "old1": f"test-group_old1-{uuid.uuid4()}",
+            "old2": f"test-group_old2-{uuid.uuid4()}",
+        }
+        client_ids = {
+            "new": ["test-client1", "test-client2"],
+            "old": ["test-client3", "test-client4"],
+        }
+
+        consumers = [
+            create_consumers(kafka_cluster, topic, group_ids["new1"], client_ids["new"][0], "consumer"),
+            create_consumers(kafka_cluster, topic, group_ids["new2"], client_ids["new"][1], "consumer"),
+            create_consumers(kafka_cluster, topic, group_ids["old1"], client_ids["old"][0], "classic"),
+            create_consumers(kafka_cluster, topic, group_ids["old2"], client_ids["old"][1], "classic"),
+        ]
+        return group_ids, client_ids, consumers
+
+    def verify_consumer_group_results(fs, expected_group_ids, expected_type, expected_clients):
+        """Verify the results of consumer group descriptions."""
+        for group_id, f in fs.items():
+            result = f.result()
+            assert result.group_id in expected_group_ids
+            assert result.is_simple_consumer_group is False
+            assert result.state == ConsumerGroupState.STABLE
+            assert result.type == expected_type
+            assert len(result.members) == 1
+            for member in result.members:
+                assert member.client_id in expected_clients
+                assert member.assignment.topic_partitions == partition
+
+    # Create consumer groups
+    group_ids, client_ids, consumers = create_consumer_groups()
+    partition = [TopicPartition(topic, 0)]
+
+    # Describe and verify new group protocol consumer groups
+    fs_new = admin_client.describe_consumer_groups([group_ids["new1"], group_ids["new2"]])
+    verify_consumer_group_results(fs_new, [group_ids["new1"], group_ids["new2"]],
+                                  ConsumerGroupType.CONSUMER, client_ids["new"])
+
+    # Describe and verify old group protocol consumer groups
+    fs_old = admin_client.describe_consumer_groups([group_ids["old1"], group_ids["old2"]])
+    verify_consumer_group_results(fs_old, [group_ids["old1"], group_ids["old2"]],
+                                  ConsumerGroupType.CLASSIC, client_ids["old"])
+
+    # Describe and verify all consumer groups
+    fs_all = admin_client.describe_consumer_groups(list(group_ids.values()))
+    for group_id, f in fs_all.items():
+        result = f.result()
+        assert result.group_id in group_ids.values()
+        assert result.is_simple_consumer_group is False
+        assert result.state == ConsumerGroupState.STABLE
+        if result.group_id in [group_ids["new1"], group_ids["new2"]]:
+            assert result.type == ConsumerGroupType.CONSUMER
+            assert result.members[0].client_id in client_ids["new"]
+        else:
+            assert result.type == ConsumerGroupType.CLASSIC
+            assert result.members[0].client_id in client_ids["old"]
+        assert result.members[0].assignment.topic_partitions == partition
+
+    # Close all consumers
+    for consumer in consumers:
+        consumer.close()
+
+
+def test_describe_consumer_groups_compatability(kafka_cluster):
path: tests/integration/admin/test_describe_consumer_groups_compatability.py
user: login: PratRanj07
body: Removed it. Will raise a seperate PR for that
created_at: 2025-04-17T12:14:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,12 @@
 # Confluent's Python client for Apache Kafka
 
+## v2.10.0
+
+v2.10.0 is a feature release with the following fixes and enhancements:
+
+- [KIP-848] Group Config is now supported in AlterConfigs, IncrementalAlterConfigs and DescribeConfigs. (#1856)
+- [KIP-848] `describe_consumer_groups()` now supports KIP-848 introduced `consumer` groups. Two new fields for consumer group type and target assignment have also been added. Type defines whether this group is a `classic` or `consumer` group. Target assignment is only valid for the `consumer` protocol and its defaults to NULL. (#4922).
+
path: CHANGELOG.md
user: login: emasab
body: ```suggestion
confluent-kafka-python v2.10.0 is based on librdkafka v2.10.0, see the
[librdkafka release notes](https://github.com/confluentinc/librdkafka/releases/tag/v2.10.0)
for a complete list of changes, enhancements, fixes and upgrade considerations.
```
created_at: 2025-04-17T12:31:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,12 @@
 # Confluent's Python client for Apache Kafka
 
+## v2.10.0
+
+v2.10.0 is a feature release with the following fixes and enhancements:
+
+- [KIP-848] Group Config is now supported in AlterConfigs, IncrementalAlterConfigs and DescribeConfigs. (#1856)
+- [KIP-848] `describe_consumer_groups()` now supports KIP-848 introduced `consumer` groups. Two new fields for consumer group type and target assignment have also been added. Type defines whether this group is a `classic` or `consumer` group. Target assignment is only valid for the `consumer` protocol and its defaults to NULL. (#4922).
path: CHANGELOG.md
user: login: emasab
body: ```suggestion
- [KIP-848] `describe_consumer_groups()` now supports KIP-848 introduced `consumer` groups. Two new fields for consumer group type and target assignment have also been added. Type defines whether this group is a `classic` or `consumer` group. Target assignment is only valid for the `consumer` protocol and its defaults to NULL. (#1873).
```
created_at: 2025-04-17T12:32:35Z
author_association: CONTRIBUTOR

PR comments:
user: login: confluent-cla-assistant[bot]
created_at: 2024-12-17T20:31:47Z
body: :tada: All Contributor License Agreements have been signed. Ready to merge. <br/><sub>Please push an empty commit if you would like to re-run the checks to verify CLA status for all contributors.<sub>
author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-16T18:27:46Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 3 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 3 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-16T18:42:49Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 3 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 3 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T05:47:29Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 5 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 5 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T06:15:23Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 4 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 4 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T06:32:39Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 4 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 4 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T07:50:58Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 4 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 4 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T09:06:58Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 5 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 5 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T10:25:45Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 1 Issue
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 1 Code Smell

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T10:48:12Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 0 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 0 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T11:10:22Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 0 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 0 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T11:27:01Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 16.70% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 0 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 0 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T12:26:11Z
body: ![Passed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/passed.svg?sanitize=true)

# Analysis Details
## 0 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 0 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.10% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T12:35:35Z
body: ![Passed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/passed.svg?sanitize=true)

# Analysis Details
## 0 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 0 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.20% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T12:47:14Z
body: ![Passed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/passed.svg?sanitize=true)

# Analysis Details
## 0 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 0 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 16.70% Coverage (62.20% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-17T13:19:52Z
body: ![Passed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/passed.svg?sanitize=true)

# Analysis Details
## 0 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 0 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/0.svg?sanitize=true) 12.50% Coverage (62.00% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (1.00% Estimated after merge)

**Project ID:** confluent-kafka-python

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=confluent-kafka-python&pullRequest=1873)


author_association: NONE