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.
Files changed (373) hide show
  1. kafka/__init__.py +34 -0
  2. kafka/__main__.py +5 -0
  3. kafka/admin/__init__.py +29 -0
  4. kafka/admin/__main__.py +5 -0
  5. kafka/admin/_acls.py +355 -0
  6. kafka/admin/_cluster.py +359 -0
  7. kafka/admin/_configs.py +479 -0
  8. kafka/admin/_groups.py +754 -0
  9. kafka/admin/_partitions.py +595 -0
  10. kafka/admin/_topics.py +281 -0
  11. kafka/admin/_transactions.py +450 -0
  12. kafka/admin/_users.py +194 -0
  13. kafka/admin/client.py +373 -0
  14. kafka/benchmarks/__init__.py +0 -0
  15. kafka/benchmarks/consumer_performance.py +138 -0
  16. kafka/benchmarks/load_example.py +109 -0
  17. kafka/benchmarks/producer_encode_path.py +201 -0
  18. kafka/benchmarks/producer_performance.py +161 -0
  19. kafka/benchmarks/profile_protocol.py +138 -0
  20. kafka/benchmarks/protocol_old_vs_new.py +447 -0
  21. kafka/benchmarks/record_batch_compose.py +77 -0
  22. kafka/benchmarks/record_batch_read.py +82 -0
  23. kafka/benchmarks/varint_speed.py +426 -0
  24. kafka/cli/__init__.py +36 -0
  25. kafka/cli/admin/__init__.py +117 -0
  26. kafka/cli/admin/acls/__init__.py +9 -0
  27. kafka/cli/admin/acls/common.py +76 -0
  28. kafka/cli/admin/acls/create.py +19 -0
  29. kafka/cli/admin/acls/delete.py +23 -0
  30. kafka/cli/admin/acls/describe.py +16 -0
  31. kafka/cli/admin/cluster/__init__.py +14 -0
  32. kafka/cli/admin/cluster/describe.py +11 -0
  33. kafka/cli/admin/cluster/describe_quorum.py +11 -0
  34. kafka/cli/admin/cluster/features.py +52 -0
  35. kafka/cli/admin/cluster/log_dirs.py +43 -0
  36. kafka/cli/admin/cluster/versions.py +33 -0
  37. kafka/cli/admin/configs/__init__.py +10 -0
  38. kafka/cli/admin/configs/alter.py +43 -0
  39. kafka/cli/admin/configs/common.py +17 -0
  40. kafka/cli/admin/configs/describe.py +30 -0
  41. kafka/cli/admin/configs/list.py +16 -0
  42. kafka/cli/admin/configs/reset.py +20 -0
  43. kafka/cli/admin/groups/__init__.py +16 -0
  44. kafka/cli/admin/groups/alter_offsets.py +30 -0
  45. kafka/cli/admin/groups/delete.py +11 -0
  46. kafka/cli/admin/groups/delete_offsets.py +29 -0
  47. kafka/cli/admin/groups/describe.py +11 -0
  48. kafka/cli/admin/groups/list.py +28 -0
  49. kafka/cli/admin/groups/list_offsets.py +29 -0
  50. kafka/cli/admin/groups/remove_members.py +40 -0
  51. kafka/cli/admin/groups/reset_offsets.py +139 -0
  52. kafka/cli/admin/partitions/__init__.py +21 -0
  53. kafka/cli/admin/partitions/alter_reassignments.py +37 -0
  54. kafka/cli/admin/partitions/create.py +27 -0
  55. kafka/cli/admin/partitions/delete_records.py +31 -0
  56. kafka/cli/admin/partitions/describe.py +36 -0
  57. kafka/cli/admin/partitions/elect_leaders.py +53 -0
  58. kafka/cli/admin/partitions/list_offsets.py +88 -0
  59. kafka/cli/admin/partitions/list_reassignments.py +35 -0
  60. kafka/cli/admin/topics/__init__.py +10 -0
  61. kafka/cli/admin/topics/create.py +13 -0
  62. kafka/cli/admin/topics/delete.py +19 -0
  63. kafka/cli/admin/topics/describe.py +18 -0
  64. kafka/cli/admin/topics/list.py +11 -0
  65. kafka/cli/admin/transactions/__init__.py +17 -0
  66. kafka/cli/admin/transactions/abort.py +38 -0
  67. kafka/cli/admin/transactions/describe.py +24 -0
  68. kafka/cli/admin/transactions/describe_producers.py +29 -0
  69. kafka/cli/admin/transactions/find_hanging.py +26 -0
  70. kafka/cli/admin/transactions/list.py +37 -0
  71. kafka/cli/admin/users/__init__.py +8 -0
  72. kafka/cli/admin/users/alter_user_scram_credentials.py +34 -0
  73. kafka/cli/admin/users/describe_user_scram_credentials.py +15 -0
  74. kafka/cli/common.py +95 -0
  75. kafka/cli/consumer/__init__.py +63 -0
  76. kafka/cli/producer/__init__.py +57 -0
  77. kafka/cluster.py +824 -0
  78. kafka/codec.py +325 -0
  79. kafka/consumer/__init__.py +5 -0
  80. kafka/consumer/__main__.py +5 -0
  81. kafka/consumer/fetcher.py +2012 -0
  82. kafka/consumer/group.py +1347 -0
  83. kafka/consumer/subscription_state.py +897 -0
  84. kafka/coordinator/__init__.py +0 -0
  85. kafka/coordinator/assignors/__init__.py +0 -0
  86. kafka/coordinator/assignors/abstract.py +90 -0
  87. kafka/coordinator/assignors/cooperative_sticky.py +167 -0
  88. kafka/coordinator/assignors/range.py +81 -0
  89. kafka/coordinator/assignors/roundrobin.py +101 -0
  90. kafka/coordinator/assignors/sticky/StickyAssignorUserData.json +37 -0
  91. kafka/coordinator/assignors/sticky/__init__.py +0 -0
  92. kafka/coordinator/assignors/sticky/partition_movements.py +149 -0
  93. kafka/coordinator/assignors/sticky/sorted_set.py +63 -0
  94. kafka/coordinator/assignors/sticky/sticky_assignor.py +665 -0
  95. kafka/coordinator/assignors/sticky/user_data.py +8 -0
  96. kafka/coordinator/base.py +1215 -0
  97. kafka/coordinator/consumer.py +1224 -0
  98. kafka/coordinator/heartbeat.py +82 -0
  99. kafka/coordinator/subscription.py +34 -0
  100. kafka/errors.py +1004 -0
  101. kafka/future.py +166 -0
  102. kafka/metrics/__init__.py +13 -0
  103. kafka/metrics/compound_stat.py +33 -0
  104. kafka/metrics/dict_reporter.py +81 -0
  105. kafka/metrics/kafka_metric.py +36 -0
  106. kafka/metrics/measurable.py +27 -0
  107. kafka/metrics/measurable_stat.py +13 -0
  108. kafka/metrics/metric_config.py +33 -0
  109. kafka/metrics/metric_name.py +105 -0
  110. kafka/metrics/metrics.py +261 -0
  111. kafka/metrics/metrics_reporter.py +53 -0
  112. kafka/metrics/quota.py +41 -0
  113. kafka/metrics/stat.py +19 -0
  114. kafka/metrics/stats/__init__.py +15 -0
  115. kafka/metrics/stats/avg.py +24 -0
  116. kafka/metrics/stats/count.py +17 -0
  117. kafka/metrics/stats/histogram.py +99 -0
  118. kafka/metrics/stats/max_stat.py +17 -0
  119. kafka/metrics/stats/min_stat.py +19 -0
  120. kafka/metrics/stats/percentile.py +14 -0
  121. kafka/metrics/stats/percentiles.py +75 -0
  122. kafka/metrics/stats/rate.py +118 -0
  123. kafka/metrics/stats/sampled_stat.py +99 -0
  124. kafka/metrics/stats/sensor.py +136 -0
  125. kafka/metrics/stats/total.py +15 -0
  126. kafka/net/__init__.py +19 -0
  127. kafka/net/compat.py +165 -0
  128. kafka/net/connection.py +593 -0
  129. kafka/net/http_connect.py +144 -0
  130. kafka/net/inet.py +122 -0
  131. kafka/net/manager.py +451 -0
  132. kafka/net/metrics.py +149 -0
  133. kafka/net/sasl/__init__.py +32 -0
  134. kafka/net/sasl/abc.py +28 -0
  135. kafka/net/sasl/gssapi.py +95 -0
  136. kafka/net/sasl/msk.py +245 -0
  137. kafka/net/sasl/oauth.py +98 -0
  138. kafka/net/sasl/plain.py +42 -0
  139. kafka/net/sasl/scram.py +135 -0
  140. kafka/net/sasl/sspi.py +111 -0
  141. kafka/net/selector.py +644 -0
  142. kafka/net/socks5.py +262 -0
  143. kafka/net/transport.py +415 -0
  144. kafka/net/wakeup_notifier.py +72 -0
  145. kafka/partitioner/__init__.py +8 -0
  146. kafka/partitioner/abc.py +8 -0
  147. kafka/partitioner/default.py +89 -0
  148. kafka/partitioner/sticky.py +109 -0
  149. kafka/producer/__init__.py +5 -0
  150. kafka/producer/__main__.py +5 -0
  151. kafka/producer/future.py +101 -0
  152. kafka/producer/kafka.py +1123 -0
  153. kafka/producer/producer_batch.py +192 -0
  154. kafka/producer/record_accumulator.py +647 -0
  155. kafka/producer/sender.py +884 -0
  156. kafka/producer/transaction_manager.py +1326 -0
  157. kafka/protocol/__init__.py +0 -0
  158. kafka/protocol/admin/__init__.py +29 -0
  159. kafka/protocol/admin/acl.py +83 -0
  160. kafka/protocol/admin/acl.pyi +375 -0
  161. kafka/protocol/admin/client_quotas.py +14 -0
  162. kafka/protocol/admin/client_quotas.pyi +265 -0
  163. kafka/protocol/admin/cluster.py +31 -0
  164. kafka/protocol/admin/cluster.pyi +620 -0
  165. kafka/protocol/admin/configs.py +22 -0
  166. kafka/protocol/admin/configs.pyi +437 -0
  167. kafka/protocol/admin/groups.py +24 -0
  168. kafka/protocol/admin/groups.pyi +261 -0
  169. kafka/protocol/admin/topics.py +53 -0
  170. kafka/protocol/admin/topics.pyi +982 -0
  171. kafka/protocol/admin/transactions.py +18 -0
  172. kafka/protocol/admin/transactions.pyi +311 -0
  173. kafka/protocol/admin/users.py +14 -0
  174. kafka/protocol/admin/users.pyi +223 -0
  175. kafka/protocol/api_data.py +125 -0
  176. kafka/protocol/api_header.py +55 -0
  177. kafka/protocol/api_key.py +97 -0
  178. kafka/protocol/api_message.py +277 -0
  179. kafka/protocol/broker_version_data.py +246 -0
  180. kafka/protocol/consumer/__init__.py +13 -0
  181. kafka/protocol/consumer/fetch.py +16 -0
  182. kafka/protocol/consumer/fetch.pyi +298 -0
  183. kafka/protocol/consumer/group.py +38 -0
  184. kafka/protocol/consumer/group.pyi +824 -0
  185. kafka/protocol/consumer/metadata.py +30 -0
  186. kafka/protocol/consumer/metadata.pyi +89 -0
  187. kafka/protocol/consumer/offsets.py +75 -0
  188. kafka/protocol/consumer/offsets.pyi +288 -0
  189. kafka/protocol/data_container.py +166 -0
  190. kafka/protocol/frame.py +30 -0
  191. kafka/protocol/generate_stubs.py +468 -0
  192. kafka/protocol/metadata/__init__.py +10 -0
  193. kafka/protocol/metadata/api_versions.py +41 -0
  194. kafka/protocol/metadata/api_versions.pyi +128 -0
  195. kafka/protocol/metadata/find_coordinator.py +19 -0
  196. kafka/protocol/metadata/find_coordinator.pyi +105 -0
  197. kafka/protocol/metadata/metadata.py +34 -0
  198. kafka/protocol/metadata/metadata.pyi +160 -0
  199. kafka/protocol/old/__init__.py +0 -0
  200. kafka/protocol/old/abstract.py +17 -0
  201. kafka/protocol/old/add_offsets_to_txn.py +54 -0
  202. kafka/protocol/old/add_partitions_to_txn.py +71 -0
  203. kafka/protocol/old/admin.py +1086 -0
  204. kafka/protocol/old/api.py +205 -0
  205. kafka/protocol/old/api_versions.py +133 -0
  206. kafka/protocol/old/commit.py +355 -0
  207. kafka/protocol/old/consumer_protocol.py +36 -0
  208. kafka/protocol/old/end_txn.py +53 -0
  209. kafka/protocol/old/fetch.py +408 -0
  210. kafka/protocol/old/find_coordinator.py +72 -0
  211. kafka/protocol/old/group.py +451 -0
  212. kafka/protocol/old/init_producer_id.py +42 -0
  213. kafka/protocol/old/list_offsets.py +186 -0
  214. kafka/protocol/old/metadata.py +290 -0
  215. kafka/protocol/old/offset_for_leader_epoch.py +133 -0
  216. kafka/protocol/old/produce.py +247 -0
  217. kafka/protocol/old/sasl_authenticate.py +38 -0
  218. kafka/protocol/old/sasl_handshake.py +39 -0
  219. kafka/protocol/old/struct.py +87 -0
  220. kafka/protocol/old/txn_offset_commit.py +73 -0
  221. kafka/protocol/old/types.py +440 -0
  222. kafka/protocol/parser.py +191 -0
  223. kafka/protocol/producer/__init__.py +7 -0
  224. kafka/protocol/producer/produce.py +17 -0
  225. kafka/protocol/producer/produce.pyi +197 -0
  226. kafka/protocol/producer/transaction.py +30 -0
  227. kafka/protocol/producer/transaction.pyi +663 -0
  228. kafka/protocol/sasl.py +52 -0
  229. kafka/protocol/sasl.pyi +126 -0
  230. kafka/protocol/schemas/__init__.py +7 -0
  231. kafka/protocol/schemas/fields/__init__.py +7 -0
  232. kafka/protocol/schemas/fields/array.py +127 -0
  233. kafka/protocol/schemas/fields/base.py +156 -0
  234. kafka/protocol/schemas/fields/codecs/__init__.py +12 -0
  235. kafka/protocol/schemas/fields/codecs/encode_buffer.py +82 -0
  236. kafka/protocol/schemas/fields/codecs/tagged_fields.py +109 -0
  237. kafka/protocol/schemas/fields/codecs/types.py +505 -0
  238. kafka/protocol/schemas/fields/codegen.py +40 -0
  239. kafka/protocol/schemas/fields/simple.py +127 -0
  240. kafka/protocol/schemas/fields/struct.py +357 -0
  241. kafka/protocol/schemas/fields/struct_array.py +142 -0
  242. kafka/protocol/schemas/load_json.py +42 -0
  243. kafka/protocol/schemas/resources/AddOffsetsToTxnRequest.json +40 -0
  244. kafka/protocol/schemas/resources/AddOffsetsToTxnResponse.json +35 -0
  245. kafka/protocol/schemas/resources/AddPartitionsToTxnRequest.json +65 -0
  246. kafka/protocol/schemas/resources/AddPartitionsToTxnResponse.json +60 -0
  247. kafka/protocol/schemas/resources/AlterClientQuotasRequest.json +47 -0
  248. kafka/protocol/schemas/resources/AlterClientQuotasResponse.json +41 -0
  249. kafka/protocol/schemas/resources/AlterConfigsRequest.json +43 -0
  250. kafka/protocol/schemas/resources/AlterConfigsResponse.json +39 -0
  251. kafka/protocol/schemas/resources/AlterPartitionReassignmentsRequest.json +42 -0
  252. kafka/protocol/schemas/resources/AlterPartitionReassignmentsResponse.json +47 -0
  253. kafka/protocol/schemas/resources/AlterReplicaLogDirsRequest.json +41 -0
  254. kafka/protocol/schemas/resources/AlterReplicaLogDirsResponse.json +41 -0
  255. kafka/protocol/schemas/resources/AlterUserScramCredentialsRequest.json +45 -0
  256. kafka/protocol/schemas/resources/AlterUserScramCredentialsResponse.json +35 -0
  257. kafka/protocol/schemas/resources/ApiVersionsRequest.json +34 -0
  258. kafka/protocol/schemas/resources/ApiVersionsResponse.json +79 -0
  259. kafka/protocol/schemas/resources/ConsumerProtocolAssignment.json +42 -0
  260. kafka/protocol/schemas/resources/ConsumerProtocolSubscription.json +49 -0
  261. kafka/protocol/schemas/resources/CreateAclsRequest.json +46 -0
  262. kafka/protocol/schemas/resources/CreateAclsResponse.json +37 -0
  263. kafka/protocol/schemas/resources/CreatePartitionsRequest.json +47 -0
  264. kafka/protocol/schemas/resources/CreatePartitionsResponse.json +41 -0
  265. kafka/protocol/schemas/resources/CreateTopicsRequest.json +65 -0
  266. kafka/protocol/schemas/resources/CreateTopicsResponse.json +72 -0
  267. kafka/protocol/schemas/resources/DeleteAclsRequest.json +46 -0
  268. kafka/protocol/schemas/resources/DeleteAclsResponse.json +59 -0
  269. kafka/protocol/schemas/resources/DeleteGroupsRequest.json +30 -0
  270. kafka/protocol/schemas/resources/DeleteGroupsResponse.json +36 -0
  271. kafka/protocol/schemas/resources/DeleteRecordsRequest.json +42 -0
  272. kafka/protocol/schemas/resources/DeleteRecordsResponse.json +43 -0
  273. kafka/protocol/schemas/resources/DeleteTopicsRequest.json +43 -0
  274. kafka/protocol/schemas/resources/DeleteTopicsResponse.json +52 -0
  275. kafka/protocol/schemas/resources/DescribeAclsRequest.json +43 -0
  276. kafka/protocol/schemas/resources/DescribeAclsResponse.json +55 -0
  277. kafka/protocol/schemas/resources/DescribeClientQuotasRequest.json +37 -0
  278. kafka/protocol/schemas/resources/DescribeClientQuotasResponse.json +47 -0
  279. kafka/protocol/schemas/resources/DescribeClusterRequest.json +35 -0
  280. kafka/protocol/schemas/resources/DescribeClusterResponse.json +56 -0
  281. kafka/protocol/schemas/resources/DescribeConfigsRequest.json +42 -0
  282. kafka/protocol/schemas/resources/DescribeConfigsResponse.json +69 -0
  283. kafka/protocol/schemas/resources/DescribeGroupsRequest.json +38 -0
  284. kafka/protocol/schemas/resources/DescribeGroupsResponse.json +74 -0
  285. kafka/protocol/schemas/resources/DescribeLogDirsRequest.json +38 -0
  286. kafka/protocol/schemas/resources/DescribeLogDirsResponse.json +65 -0
  287. kafka/protocol/schemas/resources/DescribeProducersRequest.json +32 -0
  288. kafka/protocol/schemas/resources/DescribeProducersResponse.json +55 -0
  289. kafka/protocol/schemas/resources/DescribeQuorumRequest.json +39 -0
  290. kafka/protocol/schemas/resources/DescribeQuorumResponse.json +82 -0
  291. kafka/protocol/schemas/resources/DescribeTopicPartitionsRequest.json +40 -0
  292. kafka/protocol/schemas/resources/DescribeTopicPartitionsResponse.json +66 -0
  293. kafka/protocol/schemas/resources/DescribeTransactionsRequest.json +27 -0
  294. kafka/protocol/schemas/resources/DescribeTransactionsResponse.json +52 -0
  295. kafka/protocol/schemas/resources/DescribeUserScramCredentialsRequest.json +30 -0
  296. kafka/protocol/schemas/resources/DescribeUserScramCredentialsResponse.json +45 -0
  297. kafka/protocol/schemas/resources/ElectLeadersRequest.json +41 -0
  298. kafka/protocol/schemas/resources/ElectLeadersResponse.json +45 -0
  299. kafka/protocol/schemas/resources/EndTxnRequest.json +43 -0
  300. kafka/protocol/schemas/resources/EndTxnResponse.json +41 -0
  301. kafka/protocol/schemas/resources/FetchRequest.json +125 -0
  302. kafka/protocol/schemas/resources/FetchResponse.json +124 -0
  303. kafka/protocol/schemas/resources/FindCoordinatorRequest.json +43 -0
  304. kafka/protocol/schemas/resources/FindCoordinatorResponse.json +58 -0
  305. kafka/protocol/schemas/resources/HeartbeatRequest.json +39 -0
  306. kafka/protocol/schemas/resources/HeartbeatResponse.json +35 -0
  307. kafka/protocol/schemas/resources/IncrementalAlterConfigsRequest.json +44 -0
  308. kafka/protocol/schemas/resources/IncrementalAlterConfigsResponse.json +38 -0
  309. kafka/protocol/schemas/resources/InitProducerIdRequest.json +50 -0
  310. kafka/protocol/schemas/resources/InitProducerIdResponse.json +47 -0
  311. kafka/protocol/schemas/resources/JoinGroupRequest.json +63 -0
  312. kafka/protocol/schemas/resources/JoinGroupResponse.json +69 -0
  313. kafka/protocol/schemas/resources/LeaveGroupRequest.json +47 -0
  314. kafka/protocol/schemas/resources/LeaveGroupResponse.json +47 -0
  315. kafka/protocol/schemas/resources/ListConfigResourcesRequest.json +31 -0
  316. kafka/protocol/schemas/resources/ListConfigResourcesResponse.json +37 -0
  317. kafka/protocol/schemas/resources/ListGroupsRequest.json +36 -0
  318. kafka/protocol/schemas/resources/ListGroupsResponse.json +49 -0
  319. kafka/protocol/schemas/resources/ListOffsetsRequest.json +72 -0
  320. kafka/protocol/schemas/resources/ListOffsetsResponse.json +71 -0
  321. kafka/protocol/schemas/resources/ListPartitionReassignmentsRequest.json +34 -0
  322. kafka/protocol/schemas/resources/ListPartitionReassignmentsResponse.json +46 -0
  323. kafka/protocol/schemas/resources/ListTransactionsRequest.json +40 -0
  324. kafka/protocol/schemas/resources/ListTransactionsResponse.json +42 -0
  325. kafka/protocol/schemas/resources/MetadataRequest.json +56 -0
  326. kafka/protocol/schemas/resources/MetadataResponse.json +101 -0
  327. kafka/protocol/schemas/resources/OffsetCommitRequest.json +76 -0
  328. kafka/protocol/schemas/resources/OffsetCommitResponse.json +71 -0
  329. kafka/protocol/schemas/resources/OffsetDeleteRequest.json +39 -0
  330. kafka/protocol/schemas/resources/OffsetDeleteResponse.json +42 -0
  331. kafka/protocol/schemas/resources/OffsetFetchRequest.json +76 -0
  332. kafka/protocol/schemas/resources/OffsetFetchResponse.json +107 -0
  333. kafka/protocol/schemas/resources/OffsetForLeaderEpochRequest.json +52 -0
  334. kafka/protocol/schemas/resources/OffsetForLeaderEpochResponse.json +51 -0
  335. kafka/protocol/schemas/resources/ProduceRequest.json +73 -0
  336. kafka/protocol/schemas/resources/ProduceResponse.json +96 -0
  337. kafka/protocol/schemas/resources/RequestHeader.json +44 -0
  338. kafka/protocol/schemas/resources/ResponseHeader.json +26 -0
  339. kafka/protocol/schemas/resources/SaslAuthenticateRequest.json +29 -0
  340. kafka/protocol/schemas/resources/SaslAuthenticateResponse.json +34 -0
  341. kafka/protocol/schemas/resources/SaslHandshakeRequest.json +31 -0
  342. kafka/protocol/schemas/resources/SaslHandshakeResponse.json +32 -0
  343. kafka/protocol/schemas/resources/SyncGroupRequest.json +56 -0
  344. kafka/protocol/schemas/resources/SyncGroupResponse.json +46 -0
  345. kafka/protocol/schemas/resources/TxnOffsetCommitRequest.json +68 -0
  346. kafka/protocol/schemas/resources/TxnOffsetCommitResponse.json +47 -0
  347. kafka/protocol/schemas/resources/UpdateFeaturesRequest.json +43 -0
  348. kafka/protocol/schemas/resources/UpdateFeaturesResponse.json +39 -0
  349. kafka/protocol/schemas/resources/WriteTxnMarkersRequest.json +49 -0
  350. kafka/protocol/schemas/resources/WriteTxnMarkersResponse.json +45 -0
  351. kafka/protocol/schemas/resources/__init__.py +0 -0
  352. kafka/record/__init__.py +3 -0
  353. kafka/record/_crc32c.py +161 -0
  354. kafka/record/abc.py +144 -0
  355. kafka/record/default_records.py +782 -0
  356. kafka/record/legacy_records.py +587 -0
  357. kafka/record/memory_records.py +255 -0
  358. kafka/record/util.py +135 -0
  359. kafka/serializer/__init__.py +4 -0
  360. kafka/serializer/abstract.py +20 -0
  361. kafka/serializer/default.py +16 -0
  362. kafka/serializer/json.py +17 -0
  363. kafka/serializer/wrapper.py +21 -0
  364. kafka/structs.py +69 -0
  365. kafka/util.py +159 -0
  366. kafka/vendor/__init__.py +0 -0
  367. kafka/version.py +1 -0
  368. kafka_python-3.0.0.dist-info/METADATA +319 -0
  369. kafka_python-3.0.0.dist-info/RECORD +373 -0
  370. kafka_python-3.0.0.dist-info/WHEEL +5 -0
  371. kafka_python-3.0.0.dist-info/entry_points.txt +2 -0
  372. kafka_python-3.0.0.dist-info/licenses/LICENSE +202 -0
  373. 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,9 @@
1
+ from .create import CreateACLs
2
+ from .delete import DeleteACLs
3
+ from .describe import DescribeACLs
4
+
5
+
6
+ class ACLsCommandGroup:
7
+ GROUP = 'acls'
8
+ HELP = 'Manage Kafka ACLs'
9
+ COMMANDS = [DescribeACLs, CreateACLs, DeleteACLs]
@@ -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
+ }