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,72 @@
1
+ import weakref
2
+
3
+ from kafka.future import Future
4
+
5
+
6
+ class WakeupNotifier:
7
+ """await wakeup(timeout_secs) when either ``timeout_secs`` elapses or
8
+ notify() is called -- whichever first. The notifier is safe to call
9
+ from any thread (it routes through call_soon_threadsafe).
10
+
11
+ Level-triggered: notify() arriving while no one is awaiting is latched
12
+ and consumed by the next ``__call__``. This closes a lost-wakeup race
13
+ where a caller's state mutation (e.g. ``cluster._need_update = True``)
14
+ and its ``notify()`` happen between another task's pre-await state
15
+ check and its ``await self._wakeup(...)``. Without latching, the
16
+ notification arrives at the IO thread before the task has registered
17
+ a future to signal, and the task would sleep for the full timeout
18
+ despite work being ready.
19
+
20
+ Used by the metadata refresh loop to sleep on its TTL while remaining
21
+ interruptible by external callers (e.g. KafkaProducer / KafkaConsumer
22
+ invoking cluster.request_update() from another thread).
23
+ """
24
+ def __init__(self, net):
25
+ self._net = weakref.proxy(net)
26
+ self._fut = None
27
+ # Set by ``_wakeup`` when no awaiter is registered; consumed by the
28
+ # next ``__call__``. All accesses run on the IO thread (notify
29
+ # routes through call_soon_threadsafe), so no lock is needed.
30
+ self._pending = False
31
+
32
+ def _wakeup(self):
33
+ if self._fut is not None and not self._fut.is_done:
34
+ self._fut.success(None)
35
+ else:
36
+ self._pending = True
37
+
38
+ async def __call__(self, timeout_secs=None):
39
+ if self._fut is not None:
40
+ raise RuntimeError('Concurrent access to WakeupNotifier!')
41
+ self._fut = Future()
42
+ if self._pending:
43
+ self._pending = False
44
+ self._fut.success(None)
45
+ if timeout_secs is not None:
46
+ try:
47
+ timer = self._net.call_later(timeout_secs, self._wakeup)
48
+ except ReferenceError:
49
+ return
50
+ else:
51
+ timer = None
52
+ try:
53
+ await self._fut
54
+ finally:
55
+ self._fut = None
56
+ if timer is not None and not timer.is_done:
57
+ try:
58
+ self._net.unschedule(timer)
59
+ except (ValueError, RuntimeError, ReferenceError):
60
+ pass
61
+
62
+ def notify(self):
63
+ # Always queue _wakeup on the IO thread. Skipping the queue when
64
+ # ``self._fut is None`` would re-introduce the lost-wakeup race:
65
+ # the check could pass before another thread enters ``__call__``
66
+ # and creates the future. Routing through the IO thread is one
67
+ # call_soon_threadsafe (~microseconds) and lets ``_wakeup`` decide
68
+ # under single-threaded semantics whether to signal or latch.
69
+ try:
70
+ self._net.call_soon_threadsafe(self._wakeup)
71
+ except ReferenceError:
72
+ pass
@@ -0,0 +1,8 @@
1
+ from .abc import Partitioner
2
+ from .default import DefaultPartitioner, murmur2
3
+ from .sticky import StickyPartitioner
4
+
5
+
6
+ __all__ = [
7
+ 'Partitioner', 'DefaultPartitioner', 'StickyPartitioner', 'murmur2'
8
+ ]
@@ -0,0 +1,8 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class Partitioner(ABC):
5
+ @abstractmethod
6
+ def partition(self, topic, key, serialized_key, value, serialized_value, cluster):
7
+ pass
8
+
@@ -0,0 +1,89 @@
1
+ import random
2
+
3
+ from .abc import Partitioner
4
+
5
+
6
+ class DefaultPartitioner(Partitioner):
7
+ """Default partitioner.
8
+
9
+ Hashes key to partition using murmur2 hashing (from java client)
10
+ If key is None, selects partition randomly from available,
11
+ or from all partitions if none are currently available
12
+ """
13
+ def partition(self, topic, key, serialized_key, value, serialized_value, cluster):
14
+ if topic not in cluster.topics():
15
+ raise ValueError("Topic %s not found in ClusterMetadata" % (topic,))
16
+ all_partitions = sorted(cluster.partitions_for_topic(topic))
17
+ available = list(cluster.available_partitions_for_topic(topic))
18
+ if serialized_key is not None:
19
+ idx = murmur2(serialized_key)
20
+ idx &= 0x7fffffff
21
+ idx %= len(all_partitions)
22
+ return all_partitions[idx]
23
+ pool = available if available else all_partitions
24
+ return random.choice(pool)
25
+
26
+
27
+ # https://github.com/apache/kafka/blob/0.8.2/clients/src/main/java/org/apache/kafka/common/utils/Utils.java#L244
28
+ def murmur2(data):
29
+ """Pure-python Murmur2 implementation.
30
+
31
+ Based on java client, see org.apache.kafka.common.utils.Utils.murmur2
32
+
33
+ Args:
34
+ data (bytes): opaque bytes
35
+
36
+ Returns: MurmurHash2 of data
37
+ """
38
+ length = len(data)
39
+ seed = 0x9747b28c
40
+ # 'm' and 'r' are mixing constants generated offline.
41
+ # They're not really 'magic', they just happen to work well.
42
+ m = 0x5bd1e995
43
+ r = 24
44
+
45
+ # Initialize the hash to a random value
46
+ h = seed ^ length
47
+ length4 = length // 4
48
+
49
+ for i in range(length4):
50
+ i4 = i * 4
51
+ k = ((data[i4 + 0] & 0xff) +
52
+ ((data[i4 + 1] & 0xff) << 8) +
53
+ ((data[i4 + 2] & 0xff) << 16) +
54
+ ((data[i4 + 3] & 0xff) << 24))
55
+ k &= 0xffffffff
56
+ k *= m
57
+ k &= 0xffffffff
58
+ k ^= (k % 0x100000000) >> r # k ^= k >>> r
59
+ k &= 0xffffffff
60
+ k *= m
61
+ k &= 0xffffffff
62
+
63
+ h *= m
64
+ h &= 0xffffffff
65
+ h ^= k
66
+ h &= 0xffffffff
67
+
68
+ # Handle the last few bytes of the input array
69
+ extra_bytes = length % 4
70
+ if extra_bytes >= 3:
71
+ h ^= (data[(length & ~3) + 2] & 0xff) << 16
72
+ h &= 0xffffffff
73
+ if extra_bytes >= 2:
74
+ h ^= (data[(length & ~3) + 1] & 0xff) << 8
75
+ h &= 0xffffffff
76
+ if extra_bytes >= 1:
77
+ h ^= (data[length & ~3] & 0xff)
78
+ h &= 0xffffffff
79
+ h *= m
80
+ h &= 0xffffffff
81
+
82
+ h ^= (h % 0x100000000) >> 13 # h >>> 13;
83
+ h &= 0xffffffff
84
+ h *= m
85
+ h &= 0xffffffff
86
+ h ^= (h % 0x100000000) >> 15 # h >>> 15;
87
+ h &= 0xffffffff
88
+
89
+ return h
@@ -0,0 +1,109 @@
1
+ """KIP-480 sticky partitioner.
2
+
3
+ Records with a non-None key are hashed to a partition just like
4
+ :class:`~kafka.partitioner.default.DefaultPartitioner`. Records with a
5
+ None key go to a *sticky* partition - i.e. the same partition is reused
6
+ for every null-key record on a topic until KafkaProducer signals that a
7
+ batch has been completed (via :meth:`StickyPartitioner.on_new_batch`),
8
+ at which point a different partition is picked.
9
+
10
+ The goal is to give the RecordAccumulator larger, denser batches for
11
+ null-key sends so per-batch overhead (CRC, compression, broker
12
+ round-trip) is amortized across more records. Java's benchmark in
13
+ KIP-480 reported substantial throughput/latency improvements over the
14
+ default-random behavior, though kafka-python is unlikely to see similar
15
+ improvements while predominantly CPU-bound on per-record overhead.
16
+ """
17
+
18
+ import random
19
+ import threading
20
+
21
+ from .default import DefaultPartitioner
22
+
23
+
24
+ class StickyPartitioner(DefaultPartitioner):
25
+ """Partitioner that sticks null-key records to one partition per
26
+ topic until ``on_new_batch`` rotates it.
27
+
28
+ Thread-safety: ``_sticky`` mutations are protected by ``_lock`` so
29
+ concurrent ``send()`` callers can't observe a torn read-modify-write.
30
+ """
31
+
32
+ def __init__(self):
33
+ self._sticky = {} # topic -> partition_id
34
+ self._lock = threading.Lock()
35
+
36
+ def partition(self, topic, key, serialized_key, value, serialized_value, cluster):
37
+ """Choose a partition for the next record.
38
+
39
+ Arguments:
40
+ topic (str): topic to partition on.
41
+ key (any): Unserialized key.
42
+ serialized_key (bytes or None): partitioning key.
43
+ value (any): Unserialized value.
44
+ serialized_value (bytes or None): serialized value.
45
+ cluster (ClusterMetadata): metadata for cluster; provides
46
+ all and available partitions for topic.
47
+
48
+ Raises:
49
+ ValueError: if topic is not in ClusterMetadata
50
+
51
+ Returns:
52
+ int: chosen partition ID.
53
+ """
54
+ if topic not in cluster.topics():
55
+ raise ValueError("Topic %s not found in ClusterMetadata" % (topic,))
56
+ if serialized_key is not None:
57
+ return super().partition(topic, key, serialized_key, value, serialized_value, cluster)
58
+ # Null key: reuse the sticky partition if still valid.
59
+ with self._lock:
60
+ partition = self._sticky.get(topic)
61
+ if partition is not None:
62
+ all_partitions = sorted(cluster.partitions_for_topic(topic))
63
+ available = list(cluster.available_partitions_for_topic(topic))
64
+ if available:
65
+ if partition in available:
66
+ return partition
67
+ elif partition in all_partitions:
68
+ return partition
69
+ # Stale (leader unavailable, topic shrunk); fall through to re-pick.
70
+ return self._pick_sticky_locked(topic, cluster)
71
+
72
+ def on_new_batch(self, topic, cluster, prev_partition):
73
+ """Hook called by ``KafkaProducer`` on the abort-for-new-batch
74
+ retry path: rotate the sticky for ``topic`` so the next
75
+ null-key record lands on a different partition.
76
+
77
+ Stale events (where another thread already rotated us off
78
+ ``prev_partition``) are no-ops.
79
+ """
80
+ with self._lock:
81
+ if self._sticky.get(topic) != prev_partition:
82
+ # Another caller already rotated us; don't override.
83
+ return
84
+ self._pick_sticky_locked(topic, cluster, avoid=prev_partition)
85
+
86
+ def _pick_sticky_locked(self, topic, cluster, avoid=None):
87
+ """Pick a new sticky partition for ``topic``. Must be called with
88
+ ``self._lock`` held. Returns None when the topic is no longer in
89
+ cluster metadata (caller is expected to no-op in that case)."""
90
+ all_partitions = cluster.partitions_for_topic(topic)
91
+ if not all_partitions:
92
+ return None
93
+ all_partitions = sorted(all_partitions)
94
+ available = list(cluster.available_partitions_for_topic(topic) or ())
95
+ if available:
96
+ if len(available) == 1:
97
+ partition = available[0]
98
+ else:
99
+ # >= 2 available: pick uniformly, avoiding ``avoid`` if set.
100
+ candidates = [p for p in available if p != avoid] if avoid is not None else available
101
+ if not candidates:
102
+ candidates = available
103
+ partition = random.choice(candidates)
104
+ else:
105
+ # No partitions are currently available - pick from the full
106
+ # set without enforcing ``!= avoid``
107
+ partition = random.choice(all_partitions)
108
+ self._sticky[topic] = partition
109
+ return partition
@@ -0,0 +1,5 @@
1
+ from kafka.producer.kafka import KafkaProducer
2
+
3
+ __all__ = [
4
+ 'KafkaProducer'
5
+ ]
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from kafka.cli.producer import run_cli
4
+
5
+ sys.exit(run_cli())
@@ -0,0 +1,101 @@
1
+ import collections
2
+ import threading
3
+
4
+ from kafka import errors as Errors
5
+ from kafka.future import Future
6
+ from kafka.util import Timer
7
+
8
+
9
+ class FutureProduceResult(Future):
10
+ __slots__ = ('topic_partition', '_latch')
11
+
12
+ def __init__(self, topic_partition):
13
+ super().__init__()
14
+ self.topic_partition = topic_partition
15
+ self._latch = threading.Event()
16
+
17
+ def success(self, value):
18
+ ret = super().success(value)
19
+ self._latch.set()
20
+ return ret
21
+
22
+ def failure(self, error):
23
+ ret = super().failure(error)
24
+ self._latch.set()
25
+ return ret
26
+
27
+ def wait(self, timeout=None):
28
+ # wait() on python2.6 returns None instead of the flag value
29
+ return self._latch.wait(timeout) or self._latch.is_set()
30
+
31
+
32
+ class FutureRecordMetadata(Future):
33
+ __slots__ = ('_produce_future', 'args')
34
+ def __init__(self, produce_future, batch_index, timestamp_ms, checksum, serialized_key_size, serialized_value_size, serialized_header_size):
35
+ super().__init__()
36
+ self._produce_future = produce_future
37
+ # packing args as a tuple is a minor speed optimization
38
+ self.args = (batch_index, timestamp_ms, checksum, serialized_key_size, serialized_value_size, serialized_header_size)
39
+ produce_future._add_cb_eb(self._produce_success, self.failure)
40
+
41
+ def _produce_success(self, result):
42
+ offset, produce_timestamp_ms, record_exceptions_fn = result
43
+
44
+ # Unpacking from args tuple is minor speed optimization
45
+ (batch_index, timestamp_ms, checksum,
46
+ serialized_key_size, serialized_value_size, serialized_header_size) = self.args
47
+
48
+ if record_exceptions_fn is not None:
49
+ self.failure(record_exceptions_fn(batch_index))
50
+ else:
51
+ # None is when Broker does not support the API (<0.10) and
52
+ # -1 is when the broker is configured for CREATE_TIME timestamps
53
+ if produce_timestamp_ms is not None and produce_timestamp_ms != -1:
54
+ timestamp_ms = produce_timestamp_ms
55
+ if offset != -1 and batch_index is not None:
56
+ offset += batch_index
57
+ tp = self._produce_future.topic_partition
58
+ metadata = RecordMetadata(tp[0], tp[1], tp, offset, timestamp_ms,
59
+ checksum, serialized_key_size,
60
+ serialized_value_size, serialized_header_size)
61
+ self.success(metadata)
62
+
63
+ def rebind(self, new_produce_future, new_batch_index):
64
+ """Rebind this future to a new produce future with a new batch index.
65
+
66
+ Used when a batch is split due to MESSAGE_TOO_LARGE. The original
67
+ FutureRecordMetadata is rebound to the new (smaller) batch's future.
68
+
69
+ This must be called from the sender thread while the old produce_future
70
+ has not been completed. Any user thread blocked in get() on the old
71
+ produce_future's latch will be woken and will re-wait on the new one.
72
+ """
73
+ old_produce_future = self._produce_future
74
+ self._produce_future = new_produce_future
75
+ _, timestamp_ms, checksum, sk, sv, sh = self.args
76
+ self.args = (new_batch_index, timestamp_ms, checksum, sk, sv, sh)
77
+ new_produce_future._add_cb_eb(self._produce_success, self.failure)
78
+ # Wake any thread blocked in get() so it re-waits on the new future.
79
+ # The old produce_future is never completed, so its stale callbacks
80
+ # (registered in __init__) will never fire.
81
+ old_produce_future._latch.set()
82
+
83
+ def get(self, timeout=None):
84
+ """Wait for up to timeout seconds for future to complete."""
85
+ # Loop because rebind() may wake us from the old produce_future's
86
+ # latch before the record is actually done. A batch may be split
87
+ # multiple times, so each rebind wakes us and we re-wait on the
88
+ # (possibly new) _produce_future.
89
+ timer = Timer(timeout * 1000 if timeout is not None else None)
90
+ while not self.is_done and not timer.expired:
91
+ if not self._produce_future.wait(timer.timeout_secs):
92
+ raise Errors.KafkaTimeoutError(
93
+ "Timeout after waiting for %s secs." % (timeout,))
94
+ if self.failed():
95
+ raise self.exception # pylint: disable-msg=raising-bad-type
96
+ return self.value
97
+
98
+
99
+ RecordMetadata = collections.namedtuple(
100
+ 'RecordMetadata', ['topic', 'partition', 'topic_partition', 'offset', 'timestamp',
101
+ 'checksum', 'serialized_key_size', 'serialized_value_size', 'serialized_header_size'])