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
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
import pyperf
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
test_data = [
|
|
6
|
+
(b"\x00", 0),
|
|
7
|
+
(b"\x01", -1),
|
|
8
|
+
(b"\x02", 1),
|
|
9
|
+
(b"\x7E", 63),
|
|
10
|
+
(b"\x7F", -64),
|
|
11
|
+
(b"\x80\x01", 64),
|
|
12
|
+
(b"\x81\x01", -65),
|
|
13
|
+
(b"\xFE\x7F", 8191),
|
|
14
|
+
(b"\xFF\x7F", -8192),
|
|
15
|
+
(b"\x80\x80\x01", 8192),
|
|
16
|
+
(b"\x81\x80\x01", -8193),
|
|
17
|
+
(b"\xFE\xFF\x7F", 1048575),
|
|
18
|
+
(b"\xFF\xFF\x7F", -1048576),
|
|
19
|
+
(b"\x80\x80\x80\x01", 1048576),
|
|
20
|
+
(b"\x81\x80\x80\x01", -1048577),
|
|
21
|
+
(b"\xFE\xFF\xFF\x7F", 134217727),
|
|
22
|
+
(b"\xFF\xFF\xFF\x7F", -134217728),
|
|
23
|
+
(b"\x80\x80\x80\x80\x01", 134217728),
|
|
24
|
+
(b"\x81\x80\x80\x80\x01", -134217729),
|
|
25
|
+
(b"\xFE\xFF\xFF\xFF\x7F", 17179869183),
|
|
26
|
+
(b"\xFF\xFF\xFF\xFF\x7F", -17179869184),
|
|
27
|
+
(b"\x80\x80\x80\x80\x80\x01", 17179869184),
|
|
28
|
+
(b"\x81\x80\x80\x80\x80\x01", -17179869185),
|
|
29
|
+
(b"\xFE\xFF\xFF\xFF\xFF\x7F", 2199023255551),
|
|
30
|
+
(b"\xFF\xFF\xFF\xFF\xFF\x7F", -2199023255552),
|
|
31
|
+
(b"\x80\x80\x80\x80\x80\x80\x01", 2199023255552),
|
|
32
|
+
(b"\x81\x80\x80\x80\x80\x80\x01", -2199023255553),
|
|
33
|
+
(b"\xFE\xFF\xFF\xFF\xFF\xFF\x7F", 281474976710655),
|
|
34
|
+
(b"\xFF\xFF\xFF\xFF\xFF\xFF\x7F", -281474976710656),
|
|
35
|
+
(b"\x80\x80\x80\x80\x80\x80\x80\x01", 281474976710656),
|
|
36
|
+
(b"\x81\x80\x80\x80\x80\x80\x80\x01", -281474976710657),
|
|
37
|
+
(b"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\x7F", 36028797018963967),
|
|
38
|
+
(b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F", -36028797018963968),
|
|
39
|
+
(b"\x80\x80\x80\x80\x80\x80\x80\x80\x01", 36028797018963968),
|
|
40
|
+
(b"\x81\x80\x80\x80\x80\x80\x80\x80\x01", -36028797018963969),
|
|
41
|
+
(b"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F", 4611686018427387903),
|
|
42
|
+
(b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F", -4611686018427387904),
|
|
43
|
+
(b"\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01", 4611686018427387904),
|
|
44
|
+
(b"\x81\x80\x80\x80\x80\x80\x80\x80\x80\x01", -4611686018427387905),
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
BENCH_VALUES_ENC = [
|
|
49
|
+
60, # 1 byte
|
|
50
|
+
-8192, # 2 bytes
|
|
51
|
+
1048575, # 3 bytes
|
|
52
|
+
134217727, # 4 bytes
|
|
53
|
+
-17179869184, # 5 bytes
|
|
54
|
+
2199023255551, # 6 bytes
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
BENCH_VALUES_DEC = [
|
|
58
|
+
b"\x7E", # 1 byte
|
|
59
|
+
b"\xFF\x7F", # 2 bytes
|
|
60
|
+
b"\xFE\xFF\x7F", # 3 bytes
|
|
61
|
+
b"\xFF\xFF\xFF\x7F", # 4 bytes
|
|
62
|
+
b"\x80\x80\x80\x80\x01", # 5 bytes
|
|
63
|
+
b"\xFE\xFF\xFF\xFF\xFF\x7F", # 6 bytes
|
|
64
|
+
]
|
|
65
|
+
BENCH_VALUES_DEC = list(map(bytearray, BENCH_VALUES_DEC))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _assert_valid_enc(enc_func):
|
|
69
|
+
for encoded, decoded in test_data:
|
|
70
|
+
assert enc_func(decoded) == encoded, decoded
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _assert_valid_dec(dec_func):
|
|
74
|
+
for encoded, decoded in test_data:
|
|
75
|
+
res, pos = dec_func(bytearray(encoded))
|
|
76
|
+
assert res == decoded, (decoded, res)
|
|
77
|
+
assert pos == len(encoded), (decoded, pos)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _assert_valid_size(size_func):
|
|
81
|
+
for encoded, decoded in test_data:
|
|
82
|
+
assert size_func(decoded) == len(encoded), decoded
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def encode_varint_1(num):
|
|
86
|
+
""" Encode an integer to a varint presentation. See
|
|
87
|
+
https://developers.google.com/protocol-buffers/docs/encoding?csw=1#varints
|
|
88
|
+
on how those can be produced.
|
|
89
|
+
|
|
90
|
+
Arguments:
|
|
91
|
+
num (int): Value to encode
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
bytearray: Encoded presentation of integer with length from 1 to 10
|
|
95
|
+
bytes
|
|
96
|
+
"""
|
|
97
|
+
# Shift sign to the end of number
|
|
98
|
+
num = (num << 1) ^ (num >> 63)
|
|
99
|
+
# Max 10 bytes. We assert those are allocated
|
|
100
|
+
buf = bytearray(10)
|
|
101
|
+
|
|
102
|
+
for i in range(10):
|
|
103
|
+
# 7 lowest bits from the number and set 8th if we still have pending
|
|
104
|
+
# bits left to encode
|
|
105
|
+
buf[i] = num & 0x7f | (0x80 if num > 0x7f else 0)
|
|
106
|
+
num = num >> 7
|
|
107
|
+
if num == 0:
|
|
108
|
+
break
|
|
109
|
+
else:
|
|
110
|
+
# Max size of endcoded double is 10 bytes for unsigned values
|
|
111
|
+
raise ValueError("Out of double range")
|
|
112
|
+
return buf[:i + 1]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def int2byte(i):
|
|
116
|
+
return bytes((i,))
|
|
117
|
+
|
|
118
|
+
def encode_varint_2(value):
|
|
119
|
+
value = (value << 1) ^ (value >> 63)
|
|
120
|
+
|
|
121
|
+
bits = value & 0x7f
|
|
122
|
+
value >>= 7
|
|
123
|
+
res = b""
|
|
124
|
+
while value:
|
|
125
|
+
res += int2byte(0x80 | bits)
|
|
126
|
+
bits = value & 0x7f
|
|
127
|
+
value >>= 7
|
|
128
|
+
return res + int2byte(bits)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def encode_varint_3(value, buf):
|
|
132
|
+
append = buf.append
|
|
133
|
+
value = (value << 1) ^ (value >> 63)
|
|
134
|
+
|
|
135
|
+
bits = value & 0x7f
|
|
136
|
+
value >>= 7
|
|
137
|
+
while value:
|
|
138
|
+
append(0x80 | bits)
|
|
139
|
+
bits = value & 0x7f
|
|
140
|
+
value >>= 7
|
|
141
|
+
append(bits)
|
|
142
|
+
return value
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def encode_varint_4(value):
|
|
146
|
+
value = (value << 1) ^ (value >> 63)
|
|
147
|
+
|
|
148
|
+
if value <= 0x7f: # 1 byte
|
|
149
|
+
return int2byte(value)
|
|
150
|
+
if value <= 0x3fff: # 2 bytes
|
|
151
|
+
return int2byte(0x80 | (value & 0x7f)) + int2byte(value >> 7)
|
|
152
|
+
if value <= 0x1fffff: # 3 bytes
|
|
153
|
+
return int2byte(0x80 | (value & 0x7f)) + \
|
|
154
|
+
int2byte(0x80 | ((value >> 7) & 0x7f)) + \
|
|
155
|
+
int2byte(value >> 14)
|
|
156
|
+
if value <= 0xfffffff: # 4 bytes
|
|
157
|
+
return int2byte(0x80 | (value & 0x7f)) + \
|
|
158
|
+
int2byte(0x80 | ((value >> 7) & 0x7f)) + \
|
|
159
|
+
int2byte(0x80 | ((value >> 14) & 0x7f)) + \
|
|
160
|
+
int2byte(value >> 21)
|
|
161
|
+
if value <= 0x7ffffffff: # 5 bytes
|
|
162
|
+
return int2byte(0x80 | (value & 0x7f)) + \
|
|
163
|
+
int2byte(0x80 | ((value >> 7) & 0x7f)) + \
|
|
164
|
+
int2byte(0x80 | ((value >> 14) & 0x7f)) + \
|
|
165
|
+
int2byte(0x80 | ((value >> 21) & 0x7f)) + \
|
|
166
|
+
int2byte(value >> 28)
|
|
167
|
+
else:
|
|
168
|
+
# Return to general algorithm
|
|
169
|
+
bits = value & 0x7f
|
|
170
|
+
value >>= 7
|
|
171
|
+
res = b""
|
|
172
|
+
while value:
|
|
173
|
+
res += int2byte(0x80 | bits)
|
|
174
|
+
bits = value & 0x7f
|
|
175
|
+
value >>= 7
|
|
176
|
+
return res + int2byte(bits)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def encode_varint_5(value, buf, pos=0):
|
|
180
|
+
value = (value << 1) ^ (value >> 63)
|
|
181
|
+
|
|
182
|
+
bits = value & 0x7f
|
|
183
|
+
value >>= 7
|
|
184
|
+
while value:
|
|
185
|
+
buf[pos] = 0x80 | bits
|
|
186
|
+
bits = value & 0x7f
|
|
187
|
+
value >>= 7
|
|
188
|
+
pos += 1
|
|
189
|
+
buf[pos] = bits
|
|
190
|
+
return pos + 1
|
|
191
|
+
|
|
192
|
+
def encode_varint_6(value, buf):
|
|
193
|
+
append = buf.append
|
|
194
|
+
value = (value << 1) ^ (value >> 63)
|
|
195
|
+
|
|
196
|
+
if value <= 0x7f: # 1 byte
|
|
197
|
+
append(value)
|
|
198
|
+
return 1
|
|
199
|
+
if value <= 0x3fff: # 2 bytes
|
|
200
|
+
append(0x80 | (value & 0x7f))
|
|
201
|
+
append(value >> 7)
|
|
202
|
+
return 2
|
|
203
|
+
if value <= 0x1fffff: # 3 bytes
|
|
204
|
+
append(0x80 | (value & 0x7f))
|
|
205
|
+
append(0x80 | ((value >> 7) & 0x7f))
|
|
206
|
+
append(value >> 14)
|
|
207
|
+
return 3
|
|
208
|
+
if value <= 0xfffffff: # 4 bytes
|
|
209
|
+
append(0x80 | (value & 0x7f))
|
|
210
|
+
append(0x80 | ((value >> 7) & 0x7f))
|
|
211
|
+
append(0x80 | ((value >> 14) & 0x7f))
|
|
212
|
+
append(value >> 21)
|
|
213
|
+
return 4
|
|
214
|
+
if value <= 0x7ffffffff: # 5 bytes
|
|
215
|
+
append(0x80 | (value & 0x7f))
|
|
216
|
+
append(0x80 | ((value >> 7) & 0x7f))
|
|
217
|
+
append(0x80 | ((value >> 14) & 0x7f))
|
|
218
|
+
append(0x80 | ((value >> 21) & 0x7f))
|
|
219
|
+
append(value >> 28)
|
|
220
|
+
return 5
|
|
221
|
+
else:
|
|
222
|
+
# Return to general algorithm
|
|
223
|
+
bits = value & 0x7f
|
|
224
|
+
value >>= 7
|
|
225
|
+
i = 0
|
|
226
|
+
while value:
|
|
227
|
+
append(0x80 | bits)
|
|
228
|
+
bits = value & 0x7f
|
|
229
|
+
value >>= 7
|
|
230
|
+
i += 1
|
|
231
|
+
append(bits)
|
|
232
|
+
return i
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def size_of_varint_1(value):
|
|
236
|
+
""" Number of bytes needed to encode an integer in variable-length format.
|
|
237
|
+
"""
|
|
238
|
+
value = (value << 1) ^ (value >> 63)
|
|
239
|
+
res = 0
|
|
240
|
+
while True:
|
|
241
|
+
res += 1
|
|
242
|
+
value = value >> 7
|
|
243
|
+
if value == 0:
|
|
244
|
+
break
|
|
245
|
+
return res
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def size_of_varint_2(value):
|
|
249
|
+
""" Number of bytes needed to encode an integer in variable-length format.
|
|
250
|
+
"""
|
|
251
|
+
value = (value << 1) ^ (value >> 63)
|
|
252
|
+
if value <= 0x7f:
|
|
253
|
+
return 1
|
|
254
|
+
if value <= 0x3fff:
|
|
255
|
+
return 2
|
|
256
|
+
if value <= 0x1fffff:
|
|
257
|
+
return 3
|
|
258
|
+
if value <= 0xfffffff:
|
|
259
|
+
return 4
|
|
260
|
+
if value <= 0x7ffffffff:
|
|
261
|
+
return 5
|
|
262
|
+
if value <= 0x3ffffffffff:
|
|
263
|
+
return 6
|
|
264
|
+
if value <= 0x1ffffffffffff:
|
|
265
|
+
return 7
|
|
266
|
+
if value <= 0xffffffffffffff:
|
|
267
|
+
return 8
|
|
268
|
+
if value <= 0x7fffffffffffffff:
|
|
269
|
+
return 9
|
|
270
|
+
return 10
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def _read_byte(memview, pos):
|
|
274
|
+
""" Read a byte from memoryview as an integer
|
|
275
|
+
|
|
276
|
+
Raises:
|
|
277
|
+
IndexError: if position is out of bounds
|
|
278
|
+
"""
|
|
279
|
+
return memview[pos]
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def decode_varint_1(buffer, pos=0):
|
|
283
|
+
""" Decode an integer from a varint presentation. See
|
|
284
|
+
https://developers.google.com/protocol-buffers/docs/encoding?csw=1#varints
|
|
285
|
+
on how those can be produced.
|
|
286
|
+
|
|
287
|
+
Arguments:
|
|
288
|
+
buffer (bytes-like): any object acceptable by ``memoryview``
|
|
289
|
+
pos (int): optional position to read from
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
(int, int): Decoded int value and next read position
|
|
293
|
+
"""
|
|
294
|
+
value = 0
|
|
295
|
+
shift = 0
|
|
296
|
+
memview = memoryview(buffer)
|
|
297
|
+
for i in range(pos, pos + 10):
|
|
298
|
+
try:
|
|
299
|
+
byte = _read_byte(memview, i)
|
|
300
|
+
except IndexError:
|
|
301
|
+
raise ValueError("End of byte stream")
|
|
302
|
+
if byte & 0x80 != 0:
|
|
303
|
+
value |= (byte & 0x7f) << shift
|
|
304
|
+
shift += 7
|
|
305
|
+
else:
|
|
306
|
+
value |= byte << shift
|
|
307
|
+
break
|
|
308
|
+
else:
|
|
309
|
+
# Max size of endcoded double is 10 bytes for unsigned values
|
|
310
|
+
raise ValueError("Out of double range")
|
|
311
|
+
# Normalize sign
|
|
312
|
+
return (value >> 1) ^ -(value & 1), i + 1
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def decode_varint_2(buffer, pos=0):
|
|
316
|
+
result = 0
|
|
317
|
+
shift = 0
|
|
318
|
+
while 1:
|
|
319
|
+
b = buffer[pos]
|
|
320
|
+
result |= ((b & 0x7f) << shift)
|
|
321
|
+
pos += 1
|
|
322
|
+
if not (b & 0x80):
|
|
323
|
+
# result = result_type(() & mask)
|
|
324
|
+
return ((result >> 1) ^ -(result & 1), pos)
|
|
325
|
+
shift += 7
|
|
326
|
+
if shift >= 64:
|
|
327
|
+
raise ValueError("Out of int64 range")
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def decode_varint_3(buffer, pos=0):
|
|
331
|
+
result = buffer[pos]
|
|
332
|
+
if not (result & 0x81):
|
|
333
|
+
return (result >> 1), pos + 1
|
|
334
|
+
if not (result & 0x80):
|
|
335
|
+
return (result >> 1) ^ (~0), pos + 1
|
|
336
|
+
|
|
337
|
+
result &= 0x7f
|
|
338
|
+
pos += 1
|
|
339
|
+
shift = 7
|
|
340
|
+
while 1:
|
|
341
|
+
b = buffer[pos]
|
|
342
|
+
result |= ((b & 0x7f) << shift)
|
|
343
|
+
pos += 1
|
|
344
|
+
if not (b & 0x80):
|
|
345
|
+
return ((result >> 1) ^ -(result & 1), pos)
|
|
346
|
+
shift += 7
|
|
347
|
+
if shift >= 64:
|
|
348
|
+
raise ValueError("Out of int64 range")
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
if __name__ == '__main__':
|
|
352
|
+
_assert_valid_enc(encode_varint_1)
|
|
353
|
+
_assert_valid_enc(encode_varint_2)
|
|
354
|
+
|
|
355
|
+
for encoded, decoded in test_data:
|
|
356
|
+
res = bytearray()
|
|
357
|
+
encode_varint_3(decoded, res)
|
|
358
|
+
assert res == encoded
|
|
359
|
+
|
|
360
|
+
_assert_valid_enc(encode_varint_4)
|
|
361
|
+
|
|
362
|
+
# import dis
|
|
363
|
+
# dis.dis(encode_varint_4)
|
|
364
|
+
|
|
365
|
+
for encoded, decoded in test_data:
|
|
366
|
+
res = bytearray(10)
|
|
367
|
+
written = encode_varint_5(decoded, res)
|
|
368
|
+
assert res[:written] == encoded
|
|
369
|
+
|
|
370
|
+
for encoded, decoded in test_data:
|
|
371
|
+
res = bytearray()
|
|
372
|
+
encode_varint_6(decoded, res)
|
|
373
|
+
assert res == encoded
|
|
374
|
+
|
|
375
|
+
_assert_valid_size(size_of_varint_1)
|
|
376
|
+
_assert_valid_size(size_of_varint_2)
|
|
377
|
+
_assert_valid_dec(decode_varint_1)
|
|
378
|
+
_assert_valid_dec(decode_varint_2)
|
|
379
|
+
_assert_valid_dec(decode_varint_3)
|
|
380
|
+
|
|
381
|
+
# import dis
|
|
382
|
+
# dis.dis(decode_varint_3)
|
|
383
|
+
|
|
384
|
+
runner = pyperf.Runner()
|
|
385
|
+
# Encode algorithms returning a bytes result
|
|
386
|
+
for bench_func in [
|
|
387
|
+
encode_varint_1,
|
|
388
|
+
encode_varint_2,
|
|
389
|
+
encode_varint_4]:
|
|
390
|
+
for i, value in enumerate(BENCH_VALUES_ENC):
|
|
391
|
+
runner.bench_func(
|
|
392
|
+
'{}_{}byte'.format(bench_func.__name__, i + 1),
|
|
393
|
+
bench_func, value)
|
|
394
|
+
|
|
395
|
+
# Encode algorithms writing to the buffer
|
|
396
|
+
for bench_func in [
|
|
397
|
+
encode_varint_3,
|
|
398
|
+
encode_varint_5,
|
|
399
|
+
encode_varint_6]:
|
|
400
|
+
for i, value in enumerate(BENCH_VALUES_ENC):
|
|
401
|
+
fname = bench_func.__name__
|
|
402
|
+
runner.timeit(
|
|
403
|
+
'{}_{}byte'.format(fname, i + 1),
|
|
404
|
+
stmt="{}({}, buffer)".format(fname, value),
|
|
405
|
+
setup="from __main__ import {}; buffer = bytearray(10)".format(
|
|
406
|
+
fname)
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
# Size algorithms
|
|
410
|
+
for bench_func in [
|
|
411
|
+
size_of_varint_1,
|
|
412
|
+
size_of_varint_2]:
|
|
413
|
+
for i, value in enumerate(BENCH_VALUES_ENC):
|
|
414
|
+
runner.bench_func(
|
|
415
|
+
'{}_{}byte'.format(bench_func.__name__, i + 1),
|
|
416
|
+
bench_func, value)
|
|
417
|
+
|
|
418
|
+
# Decode algorithms
|
|
419
|
+
for bench_func in [
|
|
420
|
+
decode_varint_1,
|
|
421
|
+
decode_varint_2,
|
|
422
|
+
decode_varint_3]:
|
|
423
|
+
for i, value in enumerate(BENCH_VALUES_DEC):
|
|
424
|
+
runner.bench_func(
|
|
425
|
+
'{}_{}byte'.format(bench_func.__name__, i + 1),
|
|
426
|
+
bench_func, value)
|
kafka/cli/__init__.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
USAGE = """\
|
|
4
|
+
usage: kafka-python {admin,consumer,producer} [options]
|
|
5
|
+
|
|
6
|
+
Top-level entry point for the kafka-python command-line tools.
|
|
7
|
+
|
|
8
|
+
kafka-python admin -- administrative client (topics, configs, groups, ...)
|
|
9
|
+
kafka-python consumer -- console consumer
|
|
10
|
+
kafka-python producer -- console producer
|
|
11
|
+
|
|
12
|
+
Run `kafka-python <subcommand> --help` for subcommand-specific options.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def run_cli(args=None):
|
|
17
|
+
if args is None:
|
|
18
|
+
args = sys.argv[1:]
|
|
19
|
+
|
|
20
|
+
if not args or args[0] in ('-h', '--help'):
|
|
21
|
+
sys.stdout.write(USAGE)
|
|
22
|
+
return 0 if args else 1
|
|
23
|
+
|
|
24
|
+
sub, rest = args[0], args[1:]
|
|
25
|
+
if sub == 'admin':
|
|
26
|
+
from kafka.cli.admin import run_cli as sub_run
|
|
27
|
+
elif sub == 'consumer':
|
|
28
|
+
from kafka.cli.consumer import run_cli as sub_run
|
|
29
|
+
elif sub == 'producer':
|
|
30
|
+
from kafka.cli.producer import run_cli as sub_run
|
|
31
|
+
else:
|
|
32
|
+
sys.stderr.write('kafka-python: unknown subcommand: %r\n' % sub)
|
|
33
|
+
sys.stderr.write(USAGE)
|
|
34
|
+
return 2
|
|
35
|
+
|
|
36
|
+
return sub_run(rest, prog='kafka-python %s' % sub)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
from pprint import pprint
|
|
5
|
+
|
|
6
|
+
from kafka.admin.client import KafkaAdminClient
|
|
7
|
+
from .acls import ACLsCommandGroup
|
|
8
|
+
from .cluster import ClusterCommandGroup
|
|
9
|
+
from .configs import ConfigsCommandGroup
|
|
10
|
+
from .groups import GroupsCommandGroup
|
|
11
|
+
from .partitions import PartitionsCommandGroup
|
|
12
|
+
from .topics import TopicsCommandGroup
|
|
13
|
+
from .transactions import TransactionsCommandGroup
|
|
14
|
+
from .users import UsersCommandGroup
|
|
15
|
+
from ..common import add_common_cli_args, configure_logging, build_connect_kwargs
|
|
16
|
+
from kafka.errors import BrokerResponseError
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
DEFAULT_COMMAND_GROUPS = (
|
|
20
|
+
ACLsCommandGroup, ClusterCommandGroup, ConfigsCommandGroup,
|
|
21
|
+
TopicsCommandGroup, PartitionsCommandGroup, GroupsCommandGroup,
|
|
22
|
+
TransactionsCommandGroup, UsersCommandGroup,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def main_parser(prog=None):
|
|
27
|
+
return build_parser(DEFAULT_COMMAND_GROUPS, prog=prog)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def build_parser(groups=(), prog=None):
|
|
31
|
+
parser = argparse.ArgumentParser(
|
|
32
|
+
prog=prog or 'python -m kafka.admin',
|
|
33
|
+
description='Kafka Admin Client',
|
|
34
|
+
)
|
|
35
|
+
add_common_cli_args(parser, bootstrap_required=False)
|
|
36
|
+
parser.add_argument_group('output').add_argument(
|
|
37
|
+
'--format', type=str, default='raw',
|
|
38
|
+
help='output format: raw|json')
|
|
39
|
+
groups_sub = parser.add_subparsers(dest='group', metavar='GROUP', title='Available command groups')
|
|
40
|
+
for group in groups:
|
|
41
|
+
group_parser = groups_sub.add_parser(group.GROUP, help=group.HELP)
|
|
42
|
+
group_parser.set_defaults(group=group_parser) # refcycle..
|
|
43
|
+
commands_sub = group_parser.add_subparsers(dest='command', metavar='COMMAND', title='Available commands')
|
|
44
|
+
for cmd in group.COMMANDS:
|
|
45
|
+
command_parser = commands_sub.add_parser(cmd.COMMAND, help=cmd.HELP)
|
|
46
|
+
options = command_parser.add_argument_group('command options')
|
|
47
|
+
cmd.add_arguments(options)
|
|
48
|
+
command_parser.set_defaults(command=cmd.command)
|
|
49
|
+
return parser
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def run_cli(args=None, prog=None):
|
|
53
|
+
parser = main_parser(prog=prog)
|
|
54
|
+
config = parser.parse_args(args)
|
|
55
|
+
if not config.group:
|
|
56
|
+
parser.print_help()
|
|
57
|
+
return 1
|
|
58
|
+
elif not config.command:
|
|
59
|
+
config.group.print_help()
|
|
60
|
+
return 1
|
|
61
|
+
if config.format not in ('raw', 'json'):
|
|
62
|
+
print(f'Unrecognized format: {config.format}')
|
|
63
|
+
return 1
|
|
64
|
+
|
|
65
|
+
configure_logging(config)
|
|
66
|
+
logger = logging.getLogger(__name__)
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
kwargs = build_connect_kwargs(config)
|
|
70
|
+
except ValueError as exc:
|
|
71
|
+
parser.print_usage()
|
|
72
|
+
print(f'{parser.prog}: {exc}')
|
|
73
|
+
return 1
|
|
74
|
+
client = KafkaAdminClient(**kwargs)
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
result = config.command(client, config)
|
|
78
|
+
if config.format == 'raw':
|
|
79
|
+
pprint(result)
|
|
80
|
+
elif config.format == 'json':
|
|
81
|
+
if hasattr(result, 'to_dict'):
|
|
82
|
+
result = result.to_dict()
|
|
83
|
+
print(json.dumps(result))
|
|
84
|
+
return 0
|
|
85
|
+
except BrokerResponseError as exc:
|
|
86
|
+
print(exc)
|
|
87
|
+
return 1
|
|
88
|
+
except ValueError as exc:
|
|
89
|
+
print(exc.args[0])
|
|
90
|
+
return 1
|
|
91
|
+
except AttributeError as exc:
|
|
92
|
+
logger.exception(exc)
|
|
93
|
+
parser.print_help()
|
|
94
|
+
return 1
|
|
95
|
+
except Exception:
|
|
96
|
+
logger.critical('Error!', exc_info=True)
|
|
97
|
+
return 1
|
|
98
|
+
finally:
|
|
99
|
+
client.close()
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# Commands TODO:
|
|
103
|
+
# --dry-run support
|
|
104
|
+
# --trace ?
|
|
105
|
+
|
|
106
|
+
# [cluster]
|
|
107
|
+
# unregister-broker (UnregisterBroker)
|
|
108
|
+
# add-raft-voter (AddRaftVoter)
|
|
109
|
+
# remove-raft-voter (RemoveRaftVoter)
|
|
110
|
+
# describe-quotas (DescribeClientQuotas)
|
|
111
|
+
# alter-quotas (AlterClientQuotas)
|
|
112
|
+
|
|
113
|
+
# [tokens] *DelegationTokenRequest
|
|
114
|
+
# create
|
|
115
|
+
# describe
|
|
116
|
+
# renew
|
|
117
|
+
# expire
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from kafka.admin._acls import (
|
|
2
|
+
ACL, ACLFilter, ACLOperation, ACLPermissionType, ACLResourcePatternType,
|
|
3
|
+
ResourceType, ResourcePattern, ResourcePatternFilter
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _enum_names(enum_cls):
|
|
8
|
+
return [e.name.lower() for e in enum_cls]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def add_acl_filter_args(parser):
|
|
12
|
+
"""Add arguments for building an ACLFilter (used by describe and delete)."""
|
|
13
|
+
parser.add_argument('--principal', type=str, default=None, help='ACL principal (e.g. User:alice)')
|
|
14
|
+
parser.add_argument('--host', type=str, default=None, help='ACL host (default: match any)')
|
|
15
|
+
parser.add_argument('--operation', type=str, default='any',
|
|
16
|
+
choices=_enum_names(ACLOperation),
|
|
17
|
+
help='ACL operation (default: any)')
|
|
18
|
+
parser.add_argument('--permission-type', type=str, default='any',
|
|
19
|
+
choices=_enum_names(ACLPermissionType),
|
|
20
|
+
help='ACL permission type (default: any)')
|
|
21
|
+
parser.add_argument('--resource-type', type=str, default='any',
|
|
22
|
+
choices=_enum_names(ResourceType),
|
|
23
|
+
help='Resource type (default: any)')
|
|
24
|
+
parser.add_argument('--resource-name', type=str, default=None, help='Resource name (* wildcards accepted)')
|
|
25
|
+
parser.add_argument('--pattern-type', type=str, default='any',
|
|
26
|
+
choices=_enum_names(ACLResourcePatternType),
|
|
27
|
+
help='Resource pattern type (default: any)')
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def add_acl_args(parser, required=False):
|
|
31
|
+
"""Add arguments for building a concrete ACL (used by create)."""
|
|
32
|
+
parser.add_argument('--principal', type=str, required=required, help='ACL principal (e.g. User:alice)')
|
|
33
|
+
parser.add_argument('--host', type=str, default='*', help='ACL host (default: *)')
|
|
34
|
+
parser.add_argument('--operation', type=str, required=required,
|
|
35
|
+
choices=_enum_names(ACLOperation),
|
|
36
|
+
help='ACL operation')
|
|
37
|
+
parser.add_argument('--permission-type', type=str, default='allow',
|
|
38
|
+
choices=_enum_names(ACLPermissionType),
|
|
39
|
+
help='ACL permission type (default: allow)')
|
|
40
|
+
parser.add_argument('--resource-type', type=str, required=required,
|
|
41
|
+
choices=_enum_names(ResourceType),
|
|
42
|
+
help='Resource type')
|
|
43
|
+
parser.add_argument('--resource-name', type=str, required=required, help='Resource name (* wildcards accepted)')
|
|
44
|
+
parser.add_argument('--pattern-type', type=str, default='literal',
|
|
45
|
+
choices=_enum_names(ACLResourcePatternType),
|
|
46
|
+
help='Resource pattern type (default: literal)')
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def acl_filter_from_args(args):
|
|
50
|
+
"""Build an ACLFilter from parsed CLI arguments."""
|
|
51
|
+
return ACLFilter(
|
|
52
|
+
principal=args.principal,
|
|
53
|
+
host=args.host,
|
|
54
|
+
operation=ACLOperation[args.operation.upper()],
|
|
55
|
+
permission_type=ACLPermissionType[args.permission_type.upper()],
|
|
56
|
+
resource_pattern=ResourcePatternFilter(
|
|
57
|
+
resource_type=ResourceType[args.resource_type.upper()],
|
|
58
|
+
resource_name=args.resource_name,
|
|
59
|
+
pattern_type=ACLResourcePatternType[args.pattern_type.upper()],
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def acl_from_args(args):
|
|
65
|
+
"""Build an ACL from parsed CLI arguments."""
|
|
66
|
+
return ACL(
|
|
67
|
+
principal=args.principal,
|
|
68
|
+
host=args.host or '*',
|
|
69
|
+
operation=ACLOperation[args.operation.upper()],
|
|
70
|
+
permission_type=ACLPermissionType[args.permission_type.upper()],
|
|
71
|
+
resource_pattern=ResourcePattern(
|
|
72
|
+
resource_type=ResourceType[args.resource_type.upper()],
|
|
73
|
+
resource_name=args.resource_name,
|
|
74
|
+
pattern_type=ACLResourcePatternType[args.pattern_type.upper()],
|
|
75
|
+
),
|
|
76
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .common import add_acl_args, acl_from_args
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CreateACLs:
|
|
5
|
+
COMMAND = 'create'
|
|
6
|
+
HELP = 'Create Kafka ACLs'
|
|
7
|
+
|
|
8
|
+
@classmethod
|
|
9
|
+
def add_arguments(cls, parser):
|
|
10
|
+
add_acl_args(parser, required=True)
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def command(cls, client, args):
|
|
14
|
+
acl = acl_from_args(args)
|
|
15
|
+
result = client.create_acls([acl])
|
|
16
|
+
return {
|
|
17
|
+
'succeeded': [repr(a) for a in result['succeeded']],
|
|
18
|
+
'failed': [str(e) for e in result['failed']],
|
|
19
|
+
}
|