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,479 @@
1
+ """Configuration management mixin for KafkaAdminClient.
2
+
3
+ Also defines ConfigResource and ConfigResourceType data classes.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from collections import defaultdict
9
+ from enum import IntEnum
10
+ import logging
11
+ from typing import TYPE_CHECKING
12
+
13
+ import kafka.errors as Errors
14
+ from kafka.protocol.admin import (
15
+ AlterConfigsRequest,
16
+ DescribeConfigsRequest,
17
+ IncrementalAlterConfigsRequest,
18
+ ListConfigResourcesRequest,
19
+ )
20
+ from kafka.util import EnumHelper
21
+
22
+ if TYPE_CHECKING:
23
+ from kafka.net.manager import KafkaConnectionManager
24
+
25
+ log = logging.getLogger(__name__)
26
+
27
+
28
+ class ConfigAdminMixin:
29
+ """Mixin providing configuration management methods for KafkaAdminClient."""
30
+ _manager: KafkaConnectionManager
31
+ config: dict
32
+
33
+ def _check_incremental_alter_configs_support(self):
34
+ # Broker Version >= (2, 3) has incremental alter configs
35
+ try:
36
+ self._manager.broker_version_data.api_version(IncrementalAlterConfigsRequest)
37
+ return True
38
+ except Errors.IncompatibleBrokerVersion:
39
+ return False
40
+
41
+ @staticmethod
42
+ def _incremental_configs_entries(configs):
43
+ if not configs:
44
+ return []
45
+ if not isinstance(configs, dict):
46
+ raise TypeError('alter_configs requires configs as a dict of '
47
+ '{key: (op, value)} or {key: value} (interpreted as SET)')
48
+ entries = []
49
+ for name, op_value in configs.items():
50
+ if isinstance(op_value, tuple):
51
+ op, value = op_value
52
+ else:
53
+ op, value = AlterConfigOp.SET, op_value
54
+ op_code = AlterConfigOp.value_for(op)
55
+ if op_code == AlterConfigOp.DELETE.value:
56
+ value = None
57
+ entries.append((name, op_code, value))
58
+ return entries
59
+
60
+ @staticmethod
61
+ def _describe_configs_entries(configs):
62
+ return list(configs.keys()) if isinstance(configs, dict) else configs
63
+
64
+ @staticmethod
65
+ def _alter_configs_entries(configs):
66
+ if not configs:
67
+ return []
68
+ elif not isinstance(configs, dict):
69
+ raise TypeError(f'configs should be a dict of {{key: value}}, found {type(configs)}')
70
+ entries = []
71
+ for name, op_value in configs.items():
72
+ if isinstance(op_value, tuple):
73
+ op, value = op_value
74
+ else:
75
+ op, value = AlterConfigOp.SET, op_value
76
+ op_code = AlterConfigOp.value_for(op)
77
+ if op_code != AlterConfigOp.SET.value:
78
+ raise ValueError(f'Non-incremental AlterConfigsRequest does not support operation {op} (SET only)')
79
+ entries.append((name, value))
80
+ return entries
81
+
82
+ @staticmethod
83
+ def _group_config_resources(config_resources):
84
+ broker_resources = defaultdict(list)
85
+ other_resources = []
86
+ for config_resource in config_resources:
87
+ if config_resource.resource_type in (ConfigResourceType.BROKER, ConfigResourceType.BROKER_LOGGER):
88
+ try:
89
+ broker_id = int(config_resource.name)
90
+ except ValueError:
91
+ raise ValueError("Broker resource names must be an integer or a string represented integer")
92
+ broker_resources[broker_id].append(config_resource)
93
+ else:
94
+ other_resources.append(config_resource)
95
+ return broker_resources, other_resources
96
+
97
+ @classmethod
98
+ def _describe_configs_request(cls, config_resources, include_synonyms=False):
99
+ min_version = 1 if include_synonyms else 0
100
+ return DescribeConfigsRequest(
101
+ resources=[(cr.resource_type, cr.name, cls._describe_configs_entries(cr.configs))
102
+ for cr in config_resources],
103
+ include_synonyms=include_synonyms,
104
+ min_version=min_version)
105
+
106
+ @staticmethod
107
+ def _get_config_source(config, resource_type):
108
+ if 'config_source' in config:
109
+ return ConfigSourceType.build_from(config['config_source'])
110
+ elif config['read_only'] and resource_type is ConfigResourceType.BROKER:
111
+ return ConfigSourceType.STATIC_BROKER_CONFIG
112
+ elif config.get('is_default', False):
113
+ return ConfigSourceType.DEFAULT_CONFIG
114
+ else:
115
+ return ConfigSourceType.dynamic_for_resource_type(resource_type)
116
+
117
+ @classmethod
118
+ def _should_skip_config(cls, config, config_filter, resource_type):
119
+ if config_filter == ConfigFilterType.DYNAMIC and config['read_only']:
120
+ return True
121
+ config_source = cls._get_config_source(config, resource_type)
122
+ if config_filter.should_skip(config_source):
123
+ return True
124
+ return False
125
+
126
+ @classmethod
127
+ def _process_config(cls, config, resource_type):
128
+ name = config.pop('name')
129
+ config_source = cls._get_config_source(config, resource_type)
130
+ config['config_source'] = config_source.name
131
+ if 'synonyms' in config:
132
+ for synonym in config['synonyms']:
133
+ synonym['source'] = ConfigSourceType(synonym['source']).name
134
+ if 'config_type' in config:
135
+ config['config_type'] = ConfigType(config['config_type']).name
136
+ return name
137
+
138
+ @classmethod
139
+ def _describe_configs_process_responses(cls, responses, config_filter='modified'):
140
+ config_filter = ConfigFilterType.build_from(config_filter)
141
+ ret = defaultdict(dict)
142
+ for response in responses:
143
+ for result in response.results:
144
+ resource_type = ConfigResourceType(result.resource_type)
145
+ resource_configs = {}
146
+ for config_struct in result.configs:
147
+ config = config_struct.to_dict()
148
+ name = cls._process_config(config, resource_type)
149
+ if not cls._should_skip_config(config, config_filter, resource_type):
150
+ resource_configs[name] = config
151
+ ret[resource_type.name.lower()][result.resource_name] = resource_configs
152
+ return dict(ret)
153
+
154
+ async def _async_describe_configs(self, config_resources, include_synonyms=False, config_filter='modified', flat=False):
155
+ broker_resources, other_resources = self._group_config_resources(config_resources)
156
+ responses = []
157
+ for broker_id, resources in broker_resources.items():
158
+ request = self._describe_configs_request(resources, include_synonyms)
159
+ responses.append(await self._manager.send(request, node_id=broker_id))
160
+ if other_resources:
161
+ request = self._describe_configs_request(other_resources, include_synonyms)
162
+ responses.append(await self._manager.send(request))
163
+ ret = self._describe_configs_process_responses(responses, config_filter)
164
+ if flat:
165
+ return [ret[resource.resource_type.name.lower()][resource.name]
166
+ for resource in config_resources]
167
+ else:
168
+ return ret
169
+
170
+ def describe_configs(self, config_resources, include_synonyms=False, config_filter='modified'):
171
+ """Fetch configuration parameters for one or more Kafka resources.
172
+
173
+ Arguments:
174
+ config_resources: An list of ConfigResource objects.
175
+ Any keys in ConfigResource.configs dict will be used to filter the
176
+ result. Setting the configs dict to None will get all values. An
177
+ empty dict will get zero values (as per Kafka protocol).
178
+
179
+ Keyword Arguments:
180
+ include_synonyms (bool, optional): If True, return synonyms in response. Not
181
+ supported by all versions. Default: False.
182
+ config_filter (ConfigFilterType or str): Modified returns only keys that have
183
+ non-default values; Dynamic returns all keys that can be modified with
184
+ alter_configs; All returns all available keys. Default: Modified.
185
+
186
+ Returns:
187
+ dict of {resource_type (str): {resource_name (str): {config_key: {config data}}}}
188
+ """
189
+ return self._manager.run(self._async_describe_configs, config_resources,
190
+ include_synonyms, config_filter)
191
+
192
+ @staticmethod
193
+ def _list_config_resources_process_response(response):
194
+ error_type = Errors.for_code(response.error_code)
195
+ if error_type is not Errors.NoError:
196
+ raise error_type(
197
+ "ListConfigResourcesRequest failed with response '{}'.".format(response))
198
+ ret = defaultdict(list)
199
+ for resource in response.config_resources:
200
+ resource_type = ConfigResourceType(resource.resource_type)
201
+ ret[resource_type.name.lower()].append(resource.resource_name)
202
+ return dict(ret)
203
+
204
+ async def _async_list_config_resources(self, resource_types=None):
205
+ wire_types = []
206
+ for rt in resource_types or []:
207
+ rt = ConfigResourceType.build_from(rt)
208
+ wire_types.append(rt.value)
209
+ request = ListConfigResourcesRequest(resource_types=wire_types)
210
+ response = await self._manager.send(request)
211
+ return self._list_config_resources_process_response(response)
212
+
213
+ def list_config_resources(self, resource_types=None):
214
+ """List config resources known to the cluster.
215
+
216
+ Useful for discovering resource types that have no separate enumeration
217
+ API (e.g. ``CLIENT_METRICS``, ``GROUP``). For ``TOPIC`` and ``BROKER``
218
+ the data is also available via ``Metadata`` / cluster descriptions.
219
+
220
+ Keyword Arguments:
221
+ resource_types (list, optional): Filter by resource type. Each entry
222
+ may be a :class:`ConfigResourceType` or its name (e.g. ``'TOPIC'``).
223
+ If None or empty, the broker returns all supported types.
224
+ Requires broker >= 4.1 for anything other than ``CLIENT_METRICS``.
225
+
226
+ Returns:
227
+ dict of {resource_type (str): [resource_name (str)]}
228
+ """
229
+ return self._manager.run(self._async_list_config_resources, resource_types)
230
+
231
+ async def _get_missing_modified_configs(self, config_resources):
232
+ resource_lookups = [ConfigResource(resource.resource_type, resource.name) for resource in config_resources]
233
+ dynamic_configs = await self._async_describe_configs(resource_lookups, config_filter='modified', flat=True)
234
+ missing_resource_configs = []
235
+ for resource, describe in zip(config_resources, dynamic_configs):
236
+ missing = {}
237
+ for config_key in describe:
238
+ if config_key not in resource.configs:
239
+ config_value = describe[config_key]['value']
240
+ if config_value is None:
241
+ continue
242
+ missing[config_key] = config_value
243
+ missing_resource_configs.append(missing)
244
+ return missing_resource_configs
245
+
246
+ async def _add_missing_dynamic_configs(self, config_resources):
247
+ # Add missing modified config values to resource list to avoid accidental resets
248
+ missing_resource_configs = await self._get_missing_modified_configs(config_resources)
249
+ for resource, missing in zip(config_resources, missing_resource_configs):
250
+ if not isinstance(missing, dict):
251
+ raise TypeError(f'missing configs: expected dict, found {type(missing)}')
252
+ resource.configs.update(missing)
253
+
254
+ async def _validate_dynamic_configs(self, config_resources):
255
+ resource_lookups = [ConfigResource(resource.resource_type, resource.name) for resource in config_resources]
256
+ dynamic_configs = await self._async_describe_configs(resource_lookups, config_filter='dynamic', flat=True)
257
+ for resource, describe in zip(config_resources, dynamic_configs):
258
+ unknown = set(resource.configs or []) - set(describe)
259
+ if unknown:
260
+ raise ValueError(f'Unrecognized configs: {unknown}')
261
+
262
+ @classmethod
263
+ def _alter_configs_request(cls, config_resources, validate_only=False, incremental=False):
264
+ if incremental:
265
+ return IncrementalAlterConfigsRequest(
266
+ resources=[(cr.resource_type, cr.name, cls._incremental_configs_entries(cr.configs))
267
+ for cr in config_resources],
268
+ validate_only=validate_only)
269
+ else:
270
+ return AlterConfigsRequest(
271
+ resources=[(cr.resource_type, cr.name, cls._alter_configs_entries(cr.configs))
272
+ for cr in config_resources],
273
+ validate_only=validate_only)
274
+
275
+ @staticmethod
276
+ def _alter_configs_process_responses(responses):
277
+ ret = defaultdict(dict)
278
+ for response in responses:
279
+ if response.error_code == 0:
280
+ result = 'OK'
281
+ else:
282
+ result = str(Errors.for_code(response.error_code)(response.error_message))
283
+ result_type = ConfigResourceType(response.resource_type).name.lower()
284
+ ret[result_type][response.resource_name] = result
285
+ return dict(ret)
286
+
287
+ async def _send_alter_configs_requests(self, config_resources, validate_only=False, incremental=False):
288
+ broker_resources, other_resources = self._group_config_resources(config_resources)
289
+ responses = []
290
+ for broker_id, resources in broker_resources.items():
291
+ request = self._alter_configs_request(resources, validate_only, incremental)
292
+ response = await self._manager.send(request, node_id=broker_id)
293
+ responses.extend(response.responses)
294
+ if other_resources:
295
+ request = self._alter_configs_request(other_resources, validate_only, incremental)
296
+ response = await self._manager.send(request)
297
+ responses.extend(response.responses)
298
+ return self._alter_configs_process_responses(responses)
299
+
300
+ async def _async_alter_configs(self, config_resources, validate_only=False, raise_on_unknown=True, incremental=None):
301
+ if raise_on_unknown:
302
+ await self._validate_dynamic_configs(config_resources)
303
+ if incremental is None:
304
+ incremental = self._check_incremental_alter_configs_support()
305
+ if not incremental:
306
+ await self._add_missing_dynamic_configs(config_resources)
307
+ return await self._send_alter_configs_requests(config_resources, validate_only, incremental)
308
+
309
+ def alter_configs(self, config_resources, validate_only=False, raise_on_unknown=True, incremental=None):
310
+ """Alter configuration parameters of one or more Kafka resources.
311
+
312
+ Arguments:
313
+ config_resources: A list of ConfigResource objects. Each resource's
314
+ ``configs`` must be a dict mapping config key to either
315
+ ``(op, value)`` (where ``op`` is an :class:`AlterConfigOp`,
316
+ its name, or its int value) or a bare value (interpreted as SET).
317
+ For DELETE operations the value is ignored and sent as null.
318
+ APPEND/SUBTRACT require broker >= 2.3. On older brokers only
319
+ SET is supported; non-SET ops raise ValueError. On older brokers
320
+ the client also fills in all other modified dynamic keys before
321
+ submitting, since AlterConfigsRequest resets any omitted key to
322
+ its default (be aware of the inherent race in that approach).
323
+ validate_only (bool, optional): If True, changes are sent to broker for
324
+ validation only. Changes will not be applied. Default: False
325
+ raise_on_unknown (bool, optional): If True, raises ValueError if any
326
+ config key is not recognized as a dynamic config for the resource.
327
+ incremental (bool, optional): Set to True/False to force use of
328
+ IncrementalAlterConfigs (True) or AlterConfigs (False).
329
+ By Default, the admin client will use IncrementalAlterConfigs
330
+ if supported by the broker, otherwise AlterConfigs.
331
+
332
+ Returns:
333
+ dict of {resource_type (str): {resource_name (str): Error/Result}}
334
+ """
335
+ return self._manager.run(self._async_alter_configs, config_resources, validate_only, raise_on_unknown, incremental)
336
+
337
+ async def _async_reset_configs(self, config_resources, validate_only=False, raise_on_unknown=True, incremental=None):
338
+ if raise_on_unknown:
339
+ await self._validate_dynamic_configs(config_resources)
340
+ if incremental is None:
341
+ incremental = self._check_incremental_alter_configs_support()
342
+
343
+ if not incremental:
344
+ # if no keys provided (full reset), submit as-is
345
+ # if keys are provided (partial reset), replace with missing
346
+ partial_resets = [resource for resource in config_resources if resource.configs]
347
+ missing_resource_configs = await self._get_missing_modified_configs(partial_resets)
348
+ for resource, missing in zip(partial_resets, missing_resource_configs):
349
+ resource.configs = missing
350
+ else:
351
+ # if no keys provided (full reset): mark all modified keys as DELETE
352
+ full_resets = [resource for resource in config_resources if not resource.configs]
353
+ missing_resource_configs = await self._get_missing_modified_configs(full_resets)
354
+ for resource, missing in zip(full_resets, missing_resource_configs):
355
+ resource.configs = missing
356
+ # Update all configs to DELETE:None
357
+ for resource in config_resources:
358
+ resource.configs = {key: (AlterConfigOp.DELETE, None)
359
+ for key in resource.configs}
360
+ return await self._send_alter_configs_requests(config_resources, validate_only, incremental)
361
+
362
+ def reset_configs(self, config_resources, validate_only=False, raise_on_unknown=True, incremental=None):
363
+ """Reset configuration parameters of one or more Kafka resources to defaults.
364
+
365
+ On 2.3+ brokers, the client will submit an IncrementalAlterConfigsRequest
366
+ with op DELETE for each resource/key. On older brokers, the client will
367
+ use submit an AlterConfigsRequest and attempt to include all modified
368
+ dynamic config values for each resource except the keys marked for reset.
369
+ (AlterConfigsRequest will reset any missing config key to its default).
370
+
371
+ Arguments:
372
+ config_resources: A list of ConfigResource objects. Each resource's
373
+ ``configs`` should be a list or dict of config keys to reset.
374
+ (if dict, the values are ignored).
375
+
376
+ Returns:
377
+ dict of {resource_type (str): {resource_name (str): Error/Result}}
378
+ """
379
+ return self._manager.run(self._async_reset_configs, config_resources, validate_only, raise_on_unknown, incremental)
380
+
381
+
382
+ class AlterConfigOp(EnumHelper, IntEnum):
383
+ SET = 0
384
+ DELETE = 1
385
+ APPEND = 2
386
+ SUBTRACT = 3
387
+
388
+
389
+ class ConfigFilterType(EnumHelper, IntEnum):
390
+ ALL = 0
391
+ DYNAMIC = 1
392
+ MODIFIED = 2
393
+ DEFAULT = 3
394
+ STATIC = 4
395
+
396
+ def should_skip(self, config_source):
397
+ if self is ConfigFilterType.MODIFIED:
398
+ return not config_source.is_modified()
399
+ elif self is ConfigFilterType.DEFAULT:
400
+ return config_source.is_modified()
401
+ elif self is ConfigFilterType.STATIC:
402
+ return config_source is not ConfigSourceType.STATIC_BROKER_CONFIG
403
+ return False
404
+
405
+
406
+ class ConfigResourceType(EnumHelper, IntEnum):
407
+ UNKNOWN = 0
408
+ TOPIC = 2
409
+ BROKER = 4
410
+ BROKER_LOGGER = 8
411
+ CLIENT_METRICS = 16
412
+ GROUP = 32
413
+
414
+
415
+ class ConfigResource:
416
+ """A class for specifying config resources.
417
+
418
+ Arguments:
419
+ resource_type (ConfigResourceType): the type of kafka resource
420
+ name (string): The name of the kafka resource
421
+ configs ([key] or {key : value}): config keys (values required to alter)
422
+ """
423
+ def __init__(self, resource_type, name, configs=None):
424
+ if not isinstance(resource_type, ConfigResourceType):
425
+ resource_type = ConfigResourceType[str(resource_type).upper()] # pylint: disable-msg=unsubscriptable-object
426
+ self.resource_type = resource_type
427
+ self.name = name
428
+ self.configs = configs
429
+
430
+ def __str__(self):
431
+ return f"ConfigResource {self.name}={self.resource_type}"
432
+
433
+ def __repr__(self):
434
+ return f"ConfigResource({self.resource_type}, {self.name}, {self.configs})"
435
+
436
+
437
+ class ConfigType(EnumHelper, IntEnum):
438
+ UNKNOWN = 0
439
+ BOOLEAN = 1
440
+ STRING = 2
441
+ INT = 3
442
+ SHORT = 4
443
+ LONG = 5
444
+ DOUBLE = 6
445
+ LIST = 7
446
+ CLASS = 8
447
+ PASSWORD = 9
448
+
449
+
450
+ class ConfigSourceType(EnumHelper, IntEnum):
451
+ UNKNOWN = 0
452
+ DYNAMIC_TOPIC_CONFIG = 1
453
+ DYNAMIC_BROKER_CONFIG = 2
454
+ DYNAMIC_DEFAULT_BROKER_CONFIG = 3
455
+ STATIC_BROKER_CONFIG = 4
456
+ DEFAULT_CONFIG = 5
457
+ DYNAMIC_BROKER_LOGGER_CONFIG = 6
458
+ DYNAMIC_CLIENT_METRICS_CONFIG = 7
459
+ DYNAMIC_GROUP_CONFIG = 8
460
+
461
+ def is_modified(self):
462
+ return self.value not in (3, 4, 5)
463
+
464
+ @classmethod
465
+ def dynamic_for_resource_type(cls, resource_type):
466
+ if resource_type is ConfigResourceType.UNKNOWN:
467
+ return ConfigSourceType.UNKNOWN
468
+ elif resource_type is ConfigResourceType.TOPIC:
469
+ return ConfigSourceType.DYNAMIC_TOPIC_CONFIG
470
+ elif resource_type is ConfigResourceType.BROKER:
471
+ return ConfigSourceType.DYNAMIC_BROKER_CONFIG
472
+ elif resource_type is ConfigResourceType.BROKER_LOGGER:
473
+ return ConfigSourceType.DYNAMIC_BROKER_LOGGER_CONFIG
474
+ elif resource_type is ConfigResourceType.CLIENT_METRICS:
475
+ return ConfigSourceType.DYNAMIC_CLIENT_METRICS_CONFIG
476
+ elif resource_type is ConfigResourceType.GROUP:
477
+ return ConfigSourceType.DYNAMIC_GROUP_CONFIG
478
+ else:
479
+ raise RuntimeError(f'Unrecognized resource type {resource_type}')