kafka-python 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kafka/__init__.py +34 -0
- kafka/__main__.py +5 -0
- kafka/admin/__init__.py +29 -0
- kafka/admin/__main__.py +5 -0
- kafka/admin/_acls.py +355 -0
- kafka/admin/_cluster.py +359 -0
- kafka/admin/_configs.py +479 -0
- kafka/admin/_groups.py +754 -0
- kafka/admin/_partitions.py +595 -0
- kafka/admin/_topics.py +281 -0
- kafka/admin/_transactions.py +450 -0
- kafka/admin/_users.py +194 -0
- kafka/admin/client.py +373 -0
- kafka/benchmarks/__init__.py +0 -0
- kafka/benchmarks/consumer_performance.py +138 -0
- kafka/benchmarks/load_example.py +109 -0
- kafka/benchmarks/producer_encode_path.py +201 -0
- kafka/benchmarks/producer_performance.py +161 -0
- kafka/benchmarks/profile_protocol.py +138 -0
- kafka/benchmarks/protocol_old_vs_new.py +447 -0
- kafka/benchmarks/record_batch_compose.py +77 -0
- kafka/benchmarks/record_batch_read.py +82 -0
- kafka/benchmarks/varint_speed.py +426 -0
- kafka/cli/__init__.py +36 -0
- kafka/cli/admin/__init__.py +117 -0
- kafka/cli/admin/acls/__init__.py +9 -0
- kafka/cli/admin/acls/common.py +76 -0
- kafka/cli/admin/acls/create.py +19 -0
- kafka/cli/admin/acls/delete.py +23 -0
- kafka/cli/admin/acls/describe.py +16 -0
- kafka/cli/admin/cluster/__init__.py +14 -0
- kafka/cli/admin/cluster/describe.py +11 -0
- kafka/cli/admin/cluster/describe_quorum.py +11 -0
- kafka/cli/admin/cluster/features.py +52 -0
- kafka/cli/admin/cluster/log_dirs.py +43 -0
- kafka/cli/admin/cluster/versions.py +33 -0
- kafka/cli/admin/configs/__init__.py +10 -0
- kafka/cli/admin/configs/alter.py +43 -0
- kafka/cli/admin/configs/common.py +17 -0
- kafka/cli/admin/configs/describe.py +30 -0
- kafka/cli/admin/configs/list.py +16 -0
- kafka/cli/admin/configs/reset.py +20 -0
- kafka/cli/admin/groups/__init__.py +16 -0
- kafka/cli/admin/groups/alter_offsets.py +30 -0
- kafka/cli/admin/groups/delete.py +11 -0
- kafka/cli/admin/groups/delete_offsets.py +29 -0
- kafka/cli/admin/groups/describe.py +11 -0
- kafka/cli/admin/groups/list.py +28 -0
- kafka/cli/admin/groups/list_offsets.py +29 -0
- kafka/cli/admin/groups/remove_members.py +40 -0
- kafka/cli/admin/groups/reset_offsets.py +139 -0
- kafka/cli/admin/partitions/__init__.py +21 -0
- kafka/cli/admin/partitions/alter_reassignments.py +37 -0
- kafka/cli/admin/partitions/create.py +27 -0
- kafka/cli/admin/partitions/delete_records.py +31 -0
- kafka/cli/admin/partitions/describe.py +36 -0
- kafka/cli/admin/partitions/elect_leaders.py +53 -0
- kafka/cli/admin/partitions/list_offsets.py +88 -0
- kafka/cli/admin/partitions/list_reassignments.py +35 -0
- kafka/cli/admin/topics/__init__.py +10 -0
- kafka/cli/admin/topics/create.py +13 -0
- kafka/cli/admin/topics/delete.py +19 -0
- kafka/cli/admin/topics/describe.py +18 -0
- kafka/cli/admin/topics/list.py +11 -0
- kafka/cli/admin/transactions/__init__.py +17 -0
- kafka/cli/admin/transactions/abort.py +38 -0
- kafka/cli/admin/transactions/describe.py +24 -0
- kafka/cli/admin/transactions/describe_producers.py +29 -0
- kafka/cli/admin/transactions/find_hanging.py +26 -0
- kafka/cli/admin/transactions/list.py +37 -0
- kafka/cli/admin/users/__init__.py +8 -0
- kafka/cli/admin/users/alter_user_scram_credentials.py +34 -0
- kafka/cli/admin/users/describe_user_scram_credentials.py +15 -0
- kafka/cli/common.py +95 -0
- kafka/cli/consumer/__init__.py +63 -0
- kafka/cli/producer/__init__.py +57 -0
- kafka/cluster.py +824 -0
- kafka/codec.py +325 -0
- kafka/consumer/__init__.py +5 -0
- kafka/consumer/__main__.py +5 -0
- kafka/consumer/fetcher.py +2012 -0
- kafka/consumer/group.py +1347 -0
- kafka/consumer/subscription_state.py +897 -0
- kafka/coordinator/__init__.py +0 -0
- kafka/coordinator/assignors/__init__.py +0 -0
- kafka/coordinator/assignors/abstract.py +90 -0
- kafka/coordinator/assignors/cooperative_sticky.py +167 -0
- kafka/coordinator/assignors/range.py +81 -0
- kafka/coordinator/assignors/roundrobin.py +101 -0
- kafka/coordinator/assignors/sticky/StickyAssignorUserData.json +37 -0
- kafka/coordinator/assignors/sticky/__init__.py +0 -0
- kafka/coordinator/assignors/sticky/partition_movements.py +149 -0
- kafka/coordinator/assignors/sticky/sorted_set.py +63 -0
- kafka/coordinator/assignors/sticky/sticky_assignor.py +665 -0
- kafka/coordinator/assignors/sticky/user_data.py +8 -0
- kafka/coordinator/base.py +1215 -0
- kafka/coordinator/consumer.py +1224 -0
- kafka/coordinator/heartbeat.py +82 -0
- kafka/coordinator/subscription.py +34 -0
- kafka/errors.py +1004 -0
- kafka/future.py +166 -0
- kafka/metrics/__init__.py +13 -0
- kafka/metrics/compound_stat.py +33 -0
- kafka/metrics/dict_reporter.py +81 -0
- kafka/metrics/kafka_metric.py +36 -0
- kafka/metrics/measurable.py +27 -0
- kafka/metrics/measurable_stat.py +13 -0
- kafka/metrics/metric_config.py +33 -0
- kafka/metrics/metric_name.py +105 -0
- kafka/metrics/metrics.py +261 -0
- kafka/metrics/metrics_reporter.py +53 -0
- kafka/metrics/quota.py +41 -0
- kafka/metrics/stat.py +19 -0
- kafka/metrics/stats/__init__.py +15 -0
- kafka/metrics/stats/avg.py +24 -0
- kafka/metrics/stats/count.py +17 -0
- kafka/metrics/stats/histogram.py +99 -0
- kafka/metrics/stats/max_stat.py +17 -0
- kafka/metrics/stats/min_stat.py +19 -0
- kafka/metrics/stats/percentile.py +14 -0
- kafka/metrics/stats/percentiles.py +75 -0
- kafka/metrics/stats/rate.py +118 -0
- kafka/metrics/stats/sampled_stat.py +99 -0
- kafka/metrics/stats/sensor.py +136 -0
- kafka/metrics/stats/total.py +15 -0
- kafka/net/__init__.py +19 -0
- kafka/net/compat.py +165 -0
- kafka/net/connection.py +593 -0
- kafka/net/http_connect.py +144 -0
- kafka/net/inet.py +122 -0
- kafka/net/manager.py +451 -0
- kafka/net/metrics.py +149 -0
- kafka/net/sasl/__init__.py +32 -0
- kafka/net/sasl/abc.py +28 -0
- kafka/net/sasl/gssapi.py +95 -0
- kafka/net/sasl/msk.py +245 -0
- kafka/net/sasl/oauth.py +98 -0
- kafka/net/sasl/plain.py +42 -0
- kafka/net/sasl/scram.py +135 -0
- kafka/net/sasl/sspi.py +111 -0
- kafka/net/selector.py +644 -0
- kafka/net/socks5.py +262 -0
- kafka/net/transport.py +415 -0
- kafka/net/wakeup_notifier.py +72 -0
- kafka/partitioner/__init__.py +8 -0
- kafka/partitioner/abc.py +8 -0
- kafka/partitioner/default.py +89 -0
- kafka/partitioner/sticky.py +109 -0
- kafka/producer/__init__.py +5 -0
- kafka/producer/__main__.py +5 -0
- kafka/producer/future.py +101 -0
- kafka/producer/kafka.py +1123 -0
- kafka/producer/producer_batch.py +192 -0
- kafka/producer/record_accumulator.py +647 -0
- kafka/producer/sender.py +884 -0
- kafka/producer/transaction_manager.py +1326 -0
- kafka/protocol/__init__.py +0 -0
- kafka/protocol/admin/__init__.py +29 -0
- kafka/protocol/admin/acl.py +83 -0
- kafka/protocol/admin/acl.pyi +375 -0
- kafka/protocol/admin/client_quotas.py +14 -0
- kafka/protocol/admin/client_quotas.pyi +265 -0
- kafka/protocol/admin/cluster.py +31 -0
- kafka/protocol/admin/cluster.pyi +620 -0
- kafka/protocol/admin/configs.py +22 -0
- kafka/protocol/admin/configs.pyi +437 -0
- kafka/protocol/admin/groups.py +24 -0
- kafka/protocol/admin/groups.pyi +261 -0
- kafka/protocol/admin/topics.py +53 -0
- kafka/protocol/admin/topics.pyi +982 -0
- kafka/protocol/admin/transactions.py +18 -0
- kafka/protocol/admin/transactions.pyi +311 -0
- kafka/protocol/admin/users.py +14 -0
- kafka/protocol/admin/users.pyi +223 -0
- kafka/protocol/api_data.py +125 -0
- kafka/protocol/api_header.py +55 -0
- kafka/protocol/api_key.py +97 -0
- kafka/protocol/api_message.py +277 -0
- kafka/protocol/broker_version_data.py +246 -0
- kafka/protocol/consumer/__init__.py +13 -0
- kafka/protocol/consumer/fetch.py +16 -0
- kafka/protocol/consumer/fetch.pyi +298 -0
- kafka/protocol/consumer/group.py +38 -0
- kafka/protocol/consumer/group.pyi +824 -0
- kafka/protocol/consumer/metadata.py +30 -0
- kafka/protocol/consumer/metadata.pyi +89 -0
- kafka/protocol/consumer/offsets.py +75 -0
- kafka/protocol/consumer/offsets.pyi +288 -0
- kafka/protocol/data_container.py +166 -0
- kafka/protocol/frame.py +30 -0
- kafka/protocol/generate_stubs.py +468 -0
- kafka/protocol/metadata/__init__.py +10 -0
- kafka/protocol/metadata/api_versions.py +41 -0
- kafka/protocol/metadata/api_versions.pyi +128 -0
- kafka/protocol/metadata/find_coordinator.py +19 -0
- kafka/protocol/metadata/find_coordinator.pyi +105 -0
- kafka/protocol/metadata/metadata.py +34 -0
- kafka/protocol/metadata/metadata.pyi +160 -0
- kafka/protocol/old/__init__.py +0 -0
- kafka/protocol/old/abstract.py +17 -0
- kafka/protocol/old/add_offsets_to_txn.py +54 -0
- kafka/protocol/old/add_partitions_to_txn.py +71 -0
- kafka/protocol/old/admin.py +1086 -0
- kafka/protocol/old/api.py +205 -0
- kafka/protocol/old/api_versions.py +133 -0
- kafka/protocol/old/commit.py +355 -0
- kafka/protocol/old/consumer_protocol.py +36 -0
- kafka/protocol/old/end_txn.py +53 -0
- kafka/protocol/old/fetch.py +408 -0
- kafka/protocol/old/find_coordinator.py +72 -0
- kafka/protocol/old/group.py +451 -0
- kafka/protocol/old/init_producer_id.py +42 -0
- kafka/protocol/old/list_offsets.py +186 -0
- kafka/protocol/old/metadata.py +290 -0
- kafka/protocol/old/offset_for_leader_epoch.py +133 -0
- kafka/protocol/old/produce.py +247 -0
- kafka/protocol/old/sasl_authenticate.py +38 -0
- kafka/protocol/old/sasl_handshake.py +39 -0
- kafka/protocol/old/struct.py +87 -0
- kafka/protocol/old/txn_offset_commit.py +73 -0
- kafka/protocol/old/types.py +440 -0
- kafka/protocol/parser.py +191 -0
- kafka/protocol/producer/__init__.py +7 -0
- kafka/protocol/producer/produce.py +17 -0
- kafka/protocol/producer/produce.pyi +197 -0
- kafka/protocol/producer/transaction.py +30 -0
- kafka/protocol/producer/transaction.pyi +663 -0
- kafka/protocol/sasl.py +52 -0
- kafka/protocol/sasl.pyi +126 -0
- kafka/protocol/schemas/__init__.py +7 -0
- kafka/protocol/schemas/fields/__init__.py +7 -0
- kafka/protocol/schemas/fields/array.py +127 -0
- kafka/protocol/schemas/fields/base.py +156 -0
- kafka/protocol/schemas/fields/codecs/__init__.py +12 -0
- kafka/protocol/schemas/fields/codecs/encode_buffer.py +82 -0
- kafka/protocol/schemas/fields/codecs/tagged_fields.py +109 -0
- kafka/protocol/schemas/fields/codecs/types.py +505 -0
- kafka/protocol/schemas/fields/codegen.py +40 -0
- kafka/protocol/schemas/fields/simple.py +127 -0
- kafka/protocol/schemas/fields/struct.py +357 -0
- kafka/protocol/schemas/fields/struct_array.py +142 -0
- kafka/protocol/schemas/load_json.py +42 -0
- kafka/protocol/schemas/resources/AddOffsetsToTxnRequest.json +40 -0
- kafka/protocol/schemas/resources/AddOffsetsToTxnResponse.json +35 -0
- kafka/protocol/schemas/resources/AddPartitionsToTxnRequest.json +65 -0
- kafka/protocol/schemas/resources/AddPartitionsToTxnResponse.json +60 -0
- kafka/protocol/schemas/resources/AlterClientQuotasRequest.json +47 -0
- kafka/protocol/schemas/resources/AlterClientQuotasResponse.json +41 -0
- kafka/protocol/schemas/resources/AlterConfigsRequest.json +43 -0
- kafka/protocol/schemas/resources/AlterConfigsResponse.json +39 -0
- kafka/protocol/schemas/resources/AlterPartitionReassignmentsRequest.json +42 -0
- kafka/protocol/schemas/resources/AlterPartitionReassignmentsResponse.json +47 -0
- kafka/protocol/schemas/resources/AlterReplicaLogDirsRequest.json +41 -0
- kafka/protocol/schemas/resources/AlterReplicaLogDirsResponse.json +41 -0
- kafka/protocol/schemas/resources/AlterUserScramCredentialsRequest.json +45 -0
- kafka/protocol/schemas/resources/AlterUserScramCredentialsResponse.json +35 -0
- kafka/protocol/schemas/resources/ApiVersionsRequest.json +34 -0
- kafka/protocol/schemas/resources/ApiVersionsResponse.json +79 -0
- kafka/protocol/schemas/resources/ConsumerProtocolAssignment.json +42 -0
- kafka/protocol/schemas/resources/ConsumerProtocolSubscription.json +49 -0
- kafka/protocol/schemas/resources/CreateAclsRequest.json +46 -0
- kafka/protocol/schemas/resources/CreateAclsResponse.json +37 -0
- kafka/protocol/schemas/resources/CreatePartitionsRequest.json +47 -0
- kafka/protocol/schemas/resources/CreatePartitionsResponse.json +41 -0
- kafka/protocol/schemas/resources/CreateTopicsRequest.json +65 -0
- kafka/protocol/schemas/resources/CreateTopicsResponse.json +72 -0
- kafka/protocol/schemas/resources/DeleteAclsRequest.json +46 -0
- kafka/protocol/schemas/resources/DeleteAclsResponse.json +59 -0
- kafka/protocol/schemas/resources/DeleteGroupsRequest.json +30 -0
- kafka/protocol/schemas/resources/DeleteGroupsResponse.json +36 -0
- kafka/protocol/schemas/resources/DeleteRecordsRequest.json +42 -0
- kafka/protocol/schemas/resources/DeleteRecordsResponse.json +43 -0
- kafka/protocol/schemas/resources/DeleteTopicsRequest.json +43 -0
- kafka/protocol/schemas/resources/DeleteTopicsResponse.json +52 -0
- kafka/protocol/schemas/resources/DescribeAclsRequest.json +43 -0
- kafka/protocol/schemas/resources/DescribeAclsResponse.json +55 -0
- kafka/protocol/schemas/resources/DescribeClientQuotasRequest.json +37 -0
- kafka/protocol/schemas/resources/DescribeClientQuotasResponse.json +47 -0
- kafka/protocol/schemas/resources/DescribeClusterRequest.json +35 -0
- kafka/protocol/schemas/resources/DescribeClusterResponse.json +56 -0
- kafka/protocol/schemas/resources/DescribeConfigsRequest.json +42 -0
- kafka/protocol/schemas/resources/DescribeConfigsResponse.json +69 -0
- kafka/protocol/schemas/resources/DescribeGroupsRequest.json +38 -0
- kafka/protocol/schemas/resources/DescribeGroupsResponse.json +74 -0
- kafka/protocol/schemas/resources/DescribeLogDirsRequest.json +38 -0
- kafka/protocol/schemas/resources/DescribeLogDirsResponse.json +65 -0
- kafka/protocol/schemas/resources/DescribeProducersRequest.json +32 -0
- kafka/protocol/schemas/resources/DescribeProducersResponse.json +55 -0
- kafka/protocol/schemas/resources/DescribeQuorumRequest.json +39 -0
- kafka/protocol/schemas/resources/DescribeQuorumResponse.json +82 -0
- kafka/protocol/schemas/resources/DescribeTopicPartitionsRequest.json +40 -0
- kafka/protocol/schemas/resources/DescribeTopicPartitionsResponse.json +66 -0
- kafka/protocol/schemas/resources/DescribeTransactionsRequest.json +27 -0
- kafka/protocol/schemas/resources/DescribeTransactionsResponse.json +52 -0
- kafka/protocol/schemas/resources/DescribeUserScramCredentialsRequest.json +30 -0
- kafka/protocol/schemas/resources/DescribeUserScramCredentialsResponse.json +45 -0
- kafka/protocol/schemas/resources/ElectLeadersRequest.json +41 -0
- kafka/protocol/schemas/resources/ElectLeadersResponse.json +45 -0
- kafka/protocol/schemas/resources/EndTxnRequest.json +43 -0
- kafka/protocol/schemas/resources/EndTxnResponse.json +41 -0
- kafka/protocol/schemas/resources/FetchRequest.json +125 -0
- kafka/protocol/schemas/resources/FetchResponse.json +124 -0
- kafka/protocol/schemas/resources/FindCoordinatorRequest.json +43 -0
- kafka/protocol/schemas/resources/FindCoordinatorResponse.json +58 -0
- kafka/protocol/schemas/resources/HeartbeatRequest.json +39 -0
- kafka/protocol/schemas/resources/HeartbeatResponse.json +35 -0
- kafka/protocol/schemas/resources/IncrementalAlterConfigsRequest.json +44 -0
- kafka/protocol/schemas/resources/IncrementalAlterConfigsResponse.json +38 -0
- kafka/protocol/schemas/resources/InitProducerIdRequest.json +50 -0
- kafka/protocol/schemas/resources/InitProducerIdResponse.json +47 -0
- kafka/protocol/schemas/resources/JoinGroupRequest.json +63 -0
- kafka/protocol/schemas/resources/JoinGroupResponse.json +69 -0
- kafka/protocol/schemas/resources/LeaveGroupRequest.json +47 -0
- kafka/protocol/schemas/resources/LeaveGroupResponse.json +47 -0
- kafka/protocol/schemas/resources/ListConfigResourcesRequest.json +31 -0
- kafka/protocol/schemas/resources/ListConfigResourcesResponse.json +37 -0
- kafka/protocol/schemas/resources/ListGroupsRequest.json +36 -0
- kafka/protocol/schemas/resources/ListGroupsResponse.json +49 -0
- kafka/protocol/schemas/resources/ListOffsetsRequest.json +72 -0
- kafka/protocol/schemas/resources/ListOffsetsResponse.json +71 -0
- kafka/protocol/schemas/resources/ListPartitionReassignmentsRequest.json +34 -0
- kafka/protocol/schemas/resources/ListPartitionReassignmentsResponse.json +46 -0
- kafka/protocol/schemas/resources/ListTransactionsRequest.json +40 -0
- kafka/protocol/schemas/resources/ListTransactionsResponse.json +42 -0
- kafka/protocol/schemas/resources/MetadataRequest.json +56 -0
- kafka/protocol/schemas/resources/MetadataResponse.json +101 -0
- kafka/protocol/schemas/resources/OffsetCommitRequest.json +76 -0
- kafka/protocol/schemas/resources/OffsetCommitResponse.json +71 -0
- kafka/protocol/schemas/resources/OffsetDeleteRequest.json +39 -0
- kafka/protocol/schemas/resources/OffsetDeleteResponse.json +42 -0
- kafka/protocol/schemas/resources/OffsetFetchRequest.json +76 -0
- kafka/protocol/schemas/resources/OffsetFetchResponse.json +107 -0
- kafka/protocol/schemas/resources/OffsetForLeaderEpochRequest.json +52 -0
- kafka/protocol/schemas/resources/OffsetForLeaderEpochResponse.json +51 -0
- kafka/protocol/schemas/resources/ProduceRequest.json +73 -0
- kafka/protocol/schemas/resources/ProduceResponse.json +96 -0
- kafka/protocol/schemas/resources/RequestHeader.json +44 -0
- kafka/protocol/schemas/resources/ResponseHeader.json +26 -0
- kafka/protocol/schemas/resources/SaslAuthenticateRequest.json +29 -0
- kafka/protocol/schemas/resources/SaslAuthenticateResponse.json +34 -0
- kafka/protocol/schemas/resources/SaslHandshakeRequest.json +31 -0
- kafka/protocol/schemas/resources/SaslHandshakeResponse.json +32 -0
- kafka/protocol/schemas/resources/SyncGroupRequest.json +56 -0
- kafka/protocol/schemas/resources/SyncGroupResponse.json +46 -0
- kafka/protocol/schemas/resources/TxnOffsetCommitRequest.json +68 -0
- kafka/protocol/schemas/resources/TxnOffsetCommitResponse.json +47 -0
- kafka/protocol/schemas/resources/UpdateFeaturesRequest.json +43 -0
- kafka/protocol/schemas/resources/UpdateFeaturesResponse.json +39 -0
- kafka/protocol/schemas/resources/WriteTxnMarkersRequest.json +49 -0
- kafka/protocol/schemas/resources/WriteTxnMarkersResponse.json +45 -0
- kafka/protocol/schemas/resources/__init__.py +0 -0
- kafka/record/__init__.py +3 -0
- kafka/record/_crc32c.py +161 -0
- kafka/record/abc.py +144 -0
- kafka/record/default_records.py +782 -0
- kafka/record/legacy_records.py +587 -0
- kafka/record/memory_records.py +255 -0
- kafka/record/util.py +135 -0
- kafka/serializer/__init__.py +4 -0
- kafka/serializer/abstract.py +20 -0
- kafka/serializer/default.py +16 -0
- kafka/serializer/json.py +17 -0
- kafka/serializer/wrapper.py +21 -0
- kafka/structs.py +69 -0
- kafka/util.py +159 -0
- kafka/vendor/__init__.py +0 -0
- kafka/version.py +1 -0
- kafka_python-3.0.0.dist-info/METADATA +319 -0
- kafka_python-3.0.0.dist-info/RECORD +373 -0
- kafka_python-3.0.0.dist-info/WHEEL +5 -0
- kafka_python-3.0.0.dist-info/entry_points.txt +2 -0
- kafka_python-3.0.0.dist-info/licenses/LICENSE +202 -0
- kafka_python-3.0.0.dist-info/top_level.txt +1 -0
kafka/admin/_topics.py
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"""Topic management mixin for KafkaAdminClient.
|
|
2
|
+
|
|
3
|
+
Also defines NewTopic data class.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import time
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
import uuid
|
|
12
|
+
|
|
13
|
+
import kafka.errors as Errors
|
|
14
|
+
from kafka.errors import IncompatibleBrokerVersion
|
|
15
|
+
from kafka.protocol.admin import CreateTopicsRequest, DeleteTopicsRequest, CreatePartitionsRequest
|
|
16
|
+
from ._configs import ConfigResourceType
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from kafka.net.manager import KafkaConnectionManager
|
|
20
|
+
|
|
21
|
+
log = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TopicAdminMixin:
|
|
25
|
+
"""Mixin providing topic management methods for KafkaAdminClient."""
|
|
26
|
+
_manager: KafkaConnectionManager
|
|
27
|
+
config: dict
|
|
28
|
+
|
|
29
|
+
def list_topics(self):
|
|
30
|
+
"""Retrieve a list of all topic names in the cluster.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
A list of topic name strings.
|
|
34
|
+
"""
|
|
35
|
+
metadata = self._manager.run(self._get_cluster_metadata, None)
|
|
36
|
+
return [t['name'] for t in metadata['topics']]
|
|
37
|
+
|
|
38
|
+
def describe_topics(self, topics=None):
|
|
39
|
+
"""Fetch metadata for the specified topics or all topics if None.
|
|
40
|
+
|
|
41
|
+
Keyword Arguments:
|
|
42
|
+
topics (list, optional): A list of topic names or
|
|
43
|
+
:class:`uuid.UUID` topic ids (KIP-516). Strings and UUIDs may
|
|
44
|
+
be mixed. Describing by id requires broker >= 2.8
|
|
45
|
+
(MetadataRequest v12+); name-based describe works on any
|
|
46
|
+
broker. If None, metadata for all topics is retrieved.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
A list of dicts describing each topic (including partition info).
|
|
50
|
+
"""
|
|
51
|
+
metadata = self._manager.run(self._get_cluster_metadata, topics)
|
|
52
|
+
return metadata['topics']
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
def _process_create_topics_input(new_topics):
|
|
56
|
+
_Topic = CreateTopicsRequest.CreatableTopic
|
|
57
|
+
_Assignment = _Topic.CreatableReplicaAssignment
|
|
58
|
+
_Config = _Topic.CreatableTopicConfig
|
|
59
|
+
topics = []
|
|
60
|
+
if isinstance(new_topics, dict):
|
|
61
|
+
# {topic_name: {num_partitions:, replication_factor:, assignments: {partition: [broker_ids]}, configs: {key: value}}
|
|
62
|
+
for topic, data in new_topics.items():
|
|
63
|
+
configs = data.get('configs', {})
|
|
64
|
+
topics.append(_Topic(
|
|
65
|
+
name=topic,
|
|
66
|
+
num_partitions=data.get('num_partitions', -1),
|
|
67
|
+
replication_factor=data.get('replication_factor', -1),
|
|
68
|
+
assignments=[_Assignment(partition_index=partition_id, broker_ids=replicas)
|
|
69
|
+
for partition_id, replicas in data.get('assignments', {}).items()],
|
|
70
|
+
configs=[_Config(name=config_key, value=config_value)
|
|
71
|
+
for config_key, config_value in data.get('configs', {}).items()]
|
|
72
|
+
))
|
|
73
|
+
elif all(isinstance(v, str) for v in new_topics):
|
|
74
|
+
for new_topic in new_topics:
|
|
75
|
+
topics.append(_Topic(name=new_topic, num_partitions=-1, replication_factor=-1))
|
|
76
|
+
else:
|
|
77
|
+
if all(isinstance(v, NewTopic) for v in new_topics):
|
|
78
|
+
for new_topic in new_topics:
|
|
79
|
+
topics.append(_Topic(
|
|
80
|
+
name=new_topic.name,
|
|
81
|
+
num_partitions=new_topic.num_partitions,
|
|
82
|
+
replication_factor=new_topic.replication_factor,
|
|
83
|
+
assignments=[_Assignment(partition_index=partition_id, broker_ids=replicas)
|
|
84
|
+
for partition_id, replicas in new_topic.replica_assignments.items()],
|
|
85
|
+
configs=[_Config(name=config_key, value=config_value)
|
|
86
|
+
for config_key, config_value in new_topic.topic_configs.items()]
|
|
87
|
+
))
|
|
88
|
+
if not topics:
|
|
89
|
+
raise ValueError(f"No valid topics found in new_topics: {new_topics}")
|
|
90
|
+
return topics
|
|
91
|
+
|
|
92
|
+
def create_topics(self, new_topics, timeout_ms=None, validate_only=False, raise_errors=True,
|
|
93
|
+
wait_for_metadata=False):
|
|
94
|
+
"""Create new topics in the cluster.
|
|
95
|
+
|
|
96
|
+
Arguments:
|
|
97
|
+
new_topics: A list of topic names, or a dict mapping each topic
|
|
98
|
+
name to a dict of options (all keys optional)::
|
|
99
|
+
|
|
100
|
+
{topic_name: {num_partitions: int (default -1),
|
|
101
|
+
replication_factor: int (default -1),
|
|
102
|
+
assignments: {partition_id: [broker_ids]},
|
|
103
|
+
configs: {key: value}}}
|
|
104
|
+
|
|
105
|
+
List of NewTopic objects is deprecated.
|
|
106
|
+
Note: for brokers < 2.4, num_partitions and replication_factor
|
|
107
|
+
are required and must be provided via dict or [NewTopic].
|
|
108
|
+
|
|
109
|
+
Keyword Arguments:
|
|
110
|
+
timeout_ms (numeric, optional): Milliseconds to wait for new topics to be created
|
|
111
|
+
before the broker returns.
|
|
112
|
+
validate_only (bool, optional): If True, don't actually create new topics.
|
|
113
|
+
Not supported by all versions. Default: False
|
|
114
|
+
raise_errors (bool, optional): Whether to raise errors as exceptions. Default True.
|
|
115
|
+
wait_for_metadata (bool, optional): If True, block until each new topic is visible
|
|
116
|
+
in broker metadata with a leader assigned for every partition. Default: False
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
dict of CreateTopicsResponse key/vals.
|
|
120
|
+
"""
|
|
121
|
+
if validate_only and wait_for_metadata:
|
|
122
|
+
raise ValueError('validate_only and wait_for_metadata are mutually exclusive')
|
|
123
|
+
timeout_ms = self._validate_timeout(timeout_ms)
|
|
124
|
+
if validate_only and self._manager.broker_version < (0, 10, 2):
|
|
125
|
+
raise IncompatibleBrokerVersion(
|
|
126
|
+
"validate_only requires CreateTopicsRequest >= v1, which is not supported by Kafka {}."
|
|
127
|
+
.format(self._manager.broker_version))
|
|
128
|
+
|
|
129
|
+
topics = self._process_create_topics_input(new_topics)
|
|
130
|
+
if self._manager.broker_version < (2, 4):
|
|
131
|
+
if any(topic.num_partitions == -1 or topic.replication_factor == -1 for topic in topics):
|
|
132
|
+
raise IncompatibleBrokerVersion(
|
|
133
|
+
"Broker version {} requires explicit num_partitions and replication_factor"
|
|
134
|
+
.format(self._manager.broker_version))
|
|
135
|
+
|
|
136
|
+
request = CreateTopicsRequest(
|
|
137
|
+
topics=topics,
|
|
138
|
+
timeout_ms=timeout_ms,
|
|
139
|
+
validate_only=validate_only,
|
|
140
|
+
)
|
|
141
|
+
def response_errors(r):
|
|
142
|
+
for topic in r.topics:
|
|
143
|
+
yield Errors.for_code(topic.error_code)
|
|
144
|
+
response = self._manager.run(self._send_request_to_controller, request, response_errors, raise_errors)
|
|
145
|
+
if wait_for_metadata:
|
|
146
|
+
self.wait_for_topics([new_topic.name for new_topic in request.topics])
|
|
147
|
+
result = response.to_dict()
|
|
148
|
+
result.pop('throttle_time_ms', None)
|
|
149
|
+
for topic in result['topics']:
|
|
150
|
+
configs = topic.pop('configs', None)
|
|
151
|
+
if configs:
|
|
152
|
+
processed_configs = {}
|
|
153
|
+
for config in configs:
|
|
154
|
+
name = self._process_config(config, ConfigResourceType.TOPIC)
|
|
155
|
+
processed_configs[name] = config
|
|
156
|
+
topic['configs'] = processed_configs
|
|
157
|
+
return result
|
|
158
|
+
|
|
159
|
+
def wait_for_topics(self, topic_names, timeout_ms=10000):
|
|
160
|
+
"""Block until each of the given topics is ready to use.
|
|
161
|
+
|
|
162
|
+
CreateTopicsResponse only confirms that the broker accepted the create
|
|
163
|
+
request; propagating the new topics into the broker's metadata cache --
|
|
164
|
+
and electing a leader for every partition -- can lag behind, especially
|
|
165
|
+
on KRaft clusters. This method polls :meth:`describe_topics` at a fixed
|
|
166
|
+
interval until every requested topic both:
|
|
167
|
+
|
|
168
|
+
- is returned with ``error_code == 0``, and
|
|
169
|
+
- has ``error_code == 0`` and a leader assigned (``leader_id >= 0``)
|
|
170
|
+
for every partition.
|
|
171
|
+
|
|
172
|
+
Arguments:
|
|
173
|
+
topic_names ([str]): Topic names to wait for.
|
|
174
|
+
|
|
175
|
+
Keyword Arguments:
|
|
176
|
+
timeout_ms (numeric, optional): Maximum milliseconds to wait.
|
|
177
|
+
Default: 10000.
|
|
178
|
+
|
|
179
|
+
Raises:
|
|
180
|
+
KafkaTimeoutError: if any topic is still not ready when the
|
|
181
|
+
deadline expires.
|
|
182
|
+
"""
|
|
183
|
+
if not topic_names:
|
|
184
|
+
return
|
|
185
|
+
topic_names = list(topic_names)
|
|
186
|
+
deadline = time.monotonic() + (timeout_ms / 1000.0)
|
|
187
|
+
pending = {name: 'not yet queried' for name in topic_names}
|
|
188
|
+
while True:
|
|
189
|
+
try:
|
|
190
|
+
topics = self.describe_topics(topics=topic_names)
|
|
191
|
+
except Exception as exc:
|
|
192
|
+
log.debug('describe_topics failed while waiting for topic visibility: %s', exc)
|
|
193
|
+
topics = []
|
|
194
|
+
by_name = {t.get('name'): t for t in topics}
|
|
195
|
+
pending = {}
|
|
196
|
+
for name in topic_names:
|
|
197
|
+
reason = self._topic_not_ready_reason(by_name.get(name))
|
|
198
|
+
if reason is not None:
|
|
199
|
+
pending[name] = reason
|
|
200
|
+
if not pending:
|
|
201
|
+
return
|
|
202
|
+
if time.monotonic() >= deadline:
|
|
203
|
+
raise Errors.KafkaTimeoutError(
|
|
204
|
+
'Topics not ready after %sms: %s' % (timeout_ms, pending))
|
|
205
|
+
time.sleep(0.1)
|
|
206
|
+
|
|
207
|
+
@staticmethod
|
|
208
|
+
def _topic_not_ready_reason(topic_info):
|
|
209
|
+
"""Return a string reason if ``topic_info`` isn't ready, else None."""
|
|
210
|
+
if topic_info is None:
|
|
211
|
+
return 'missing from metadata response'
|
|
212
|
+
error_code = topic_info.get('error_code', 0)
|
|
213
|
+
if error_code != 0:
|
|
214
|
+
return Errors.for_code(error_code).__name__
|
|
215
|
+
partitions = topic_info.get('partitions') or []
|
|
216
|
+
if not partitions:
|
|
217
|
+
return 'no partitions reported'
|
|
218
|
+
bad = []
|
|
219
|
+
for p in partitions:
|
|
220
|
+
p_err = p.get('error_code', 0)
|
|
221
|
+
idx = p.get('partition_index')
|
|
222
|
+
if p_err != 0:
|
|
223
|
+
bad.append('p%s=%s' % (idx, Errors.for_code(p_err).__name__))
|
|
224
|
+
continue
|
|
225
|
+
if p.get('leader_id', -1) < 0:
|
|
226
|
+
bad.append('p%s=no leader' % idx)
|
|
227
|
+
if bad:
|
|
228
|
+
return ','.join(bad)
|
|
229
|
+
return None
|
|
230
|
+
|
|
231
|
+
def delete_topics(self, topics, timeout_ms=None, raise_errors=True):
|
|
232
|
+
"""Delete topics from the cluster.
|
|
233
|
+
|
|
234
|
+
Arguments:
|
|
235
|
+
topics ([str]): A list of topic name strings or uuid.UUID ids.
|
|
236
|
+
|
|
237
|
+
Keyword Arguments:
|
|
238
|
+
timeout_ms (numeric, optional): Milliseconds to wait for topics to be deleted
|
|
239
|
+
before the broker returns.
|
|
240
|
+
raise_errors (bool, optional): Whether to raise errors as exceptions. Default True.
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
dict of DeleteTopicsResponse key/vals (version-dependent)
|
|
244
|
+
"""
|
|
245
|
+
timeout_ms = self._validate_timeout(timeout_ms)
|
|
246
|
+
_Topic = DeleteTopicsRequest.DeleteTopicState
|
|
247
|
+
request = DeleteTopicsRequest(
|
|
248
|
+
topics=[_Topic(topic_id=topic) if isinstance(topic, uuid.UUID) else _Topic(name=topic)
|
|
249
|
+
for topic in topics],
|
|
250
|
+
timeout_ms=timeout_ms)
|
|
251
|
+
def response_errors(r):
|
|
252
|
+
for response in r.responses:
|
|
253
|
+
yield Errors.for_code(response.error_code)
|
|
254
|
+
response = self._manager.run(self._send_request_to_controller, request, response_errors, raise_errors)
|
|
255
|
+
result = response.to_dict()
|
|
256
|
+
result.pop('throttle_time_ms', None)
|
|
257
|
+
result['topics'] = result.pop('responses')
|
|
258
|
+
return result
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class NewTopic:
|
|
262
|
+
"""DEPRECATED: A class for new topic creation.
|
|
263
|
+
|
|
264
|
+
Arguments:
|
|
265
|
+
name (string): name of the topic
|
|
266
|
+
num_partitions (int): number of partitions, or -1 if
|
|
267
|
+
replica_assignment has been specified
|
|
268
|
+
replication_factor (int): replication factor, or -1 if
|
|
269
|
+
replica assignment is specified
|
|
270
|
+
replica_assignments (dict of int: [int]): A mapping containing
|
|
271
|
+
partition id and replicas to assign to it.
|
|
272
|
+
topic_configs (dict of str: str): A mapping of config key
|
|
273
|
+
and value for the topic.
|
|
274
|
+
"""
|
|
275
|
+
def __init__(self, name, num_partitions=-1, replication_factor=-1,
|
|
276
|
+
replica_assignments=None, topic_configs=None):
|
|
277
|
+
self.name = name
|
|
278
|
+
self.num_partitions = num_partitions
|
|
279
|
+
self.replication_factor = replication_factor
|
|
280
|
+
self.replica_assignments = replica_assignments or {}
|
|
281
|
+
self.topic_configs = topic_configs or {}
|