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,587 @@
1
+ # See:
2
+ # https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/\
3
+ # apache/kafka/common/record/LegacyRecord.java
4
+
5
+ # Builder and reader implementation for V0 and V1 record versions. As of Kafka
6
+ # 0.11.0.0 those were replaced with V2, thus the Legacy naming.
7
+
8
+ # The schema is given below (see
9
+ # https://kafka.apache.org/protocol#protocol_message_sets for more details):
10
+
11
+ # MessageSet => [Offset MessageSize Message]
12
+ # Offset => int64
13
+ # MessageSize => int32
14
+
15
+ # v0
16
+ # Message => Crc MagicByte Attributes Key Value
17
+ # Crc => int32
18
+ # MagicByte => int8
19
+ # Attributes => int8
20
+ # Key => bytes
21
+ # Value => bytes
22
+
23
+ # v1 (supported since 0.10.0)
24
+ # Message => Crc MagicByte Attributes Key Value
25
+ # Crc => int32
26
+ # MagicByte => int8
27
+ # Attributes => int8
28
+ # Timestamp => int64
29
+ # Key => bytes
30
+ # Value => bytes
31
+
32
+ # The message attribute bits are given below:
33
+ # * Unused (4-7)
34
+ # * Timestamp Type (3) (added in V1)
35
+ # * Compression Type (0-2)
36
+
37
+ # Note that when compression is enabled (see attributes above), the whole
38
+ # array of MessageSet's is compressed and places into a message as the `value`.
39
+ # Only the parent message is marked with `compression` bits in attributes.
40
+
41
+ # The CRC covers the data from the Magic byte to the end of the message.
42
+
43
+
44
+ import struct
45
+ import time
46
+
47
+ from kafka.record.abc import ABCRecord, ABCRecordBatch, ABCRecordBatchBuilder
48
+ from kafka.record.util import calc_crc32
49
+
50
+ from kafka.codec import (
51
+ gzip_encode, snappy_encode, lz4_encode, lz4_encode_old_kafka,
52
+ gzip_decode, snappy_decode, lz4_decode, lz4_decode_old_kafka,
53
+ )
54
+ import kafka.codec as codecs
55
+ from kafka.errors import CorruptRecordError, UnsupportedCodecError
56
+
57
+
58
+ class LegacyRecordBase:
59
+
60
+ __slots__ = ()
61
+
62
+ HEADER_STRUCT_V0 = struct.Struct(
63
+ ">q" # BaseOffset => Int64
64
+ "i" # Length => Int32
65
+ "I" # CRC => Int32
66
+ "b" # Magic => Int8
67
+ "b" # Attributes => Int8
68
+ )
69
+ HEADER_STRUCT_V1 = struct.Struct(
70
+ ">q" # BaseOffset => Int64
71
+ "i" # Length => Int32
72
+ "I" # CRC => Int32
73
+ "b" # Magic => Int8
74
+ "b" # Attributes => Int8
75
+ "q" # timestamp => Int64
76
+ )
77
+
78
+ LOG_OVERHEAD = CRC_OFFSET = struct.calcsize(
79
+ ">q" # Offset
80
+ "i" # Size
81
+ )
82
+ MAGIC_OFFSET = LOG_OVERHEAD + struct.calcsize(
83
+ ">I" # CRC
84
+ )
85
+ # Those are used for fast size calculations
86
+ RECORD_OVERHEAD_V0 = struct.calcsize(
87
+ ">I" # CRC
88
+ "b" # magic
89
+ "b" # attributes
90
+ "i" # Key length
91
+ "i" # Value length
92
+ )
93
+ RECORD_OVERHEAD_V1 = struct.calcsize(
94
+ ">I" # CRC
95
+ "b" # magic
96
+ "b" # attributes
97
+ "q" # timestamp
98
+ "i" # Key length
99
+ "i" # Value length
100
+ )
101
+
102
+ KEY_OFFSET_V0 = HEADER_STRUCT_V0.size
103
+ KEY_OFFSET_V1 = HEADER_STRUCT_V1.size
104
+ KEY_LENGTH = VALUE_LENGTH = struct.calcsize(">i") # Bytes length is Int32
105
+
106
+ CODEC_MASK = 0x07
107
+ CODEC_NONE = 0x00
108
+ CODEC_GZIP = 0x01
109
+ CODEC_SNAPPY = 0x02
110
+ CODEC_LZ4 = 0x03
111
+ TIMESTAMP_TYPE_MASK = 0x08
112
+
113
+ LOG_APPEND_TIME = 1
114
+ CREATE_TIME = 0
115
+
116
+ NO_TIMESTAMP = -1
117
+
118
+ def _assert_has_codec(self, compression_type):
119
+ if compression_type == self.CODEC_GZIP:
120
+ checker, name = codecs.has_gzip, "gzip"
121
+ elif compression_type == self.CODEC_SNAPPY:
122
+ checker, name = codecs.has_snappy, "snappy"
123
+ elif compression_type == self.CODEC_LZ4:
124
+ checker, name = codecs.has_lz4, "lz4"
125
+ else:
126
+ raise UnsupportedCodecError(
127
+ "Unrecognized compression type")
128
+ if not checker():
129
+ raise UnsupportedCodecError(
130
+ "Libraries for {} compression codec not found".format(name))
131
+
132
+
133
+ class LegacyRecordBatch(ABCRecordBatch, LegacyRecordBase):
134
+
135
+ __slots__ = ("_buffer", "_magic", "_offset", "_length", "_crc", "_timestamp",
136
+ "_attributes", "_decompressed")
137
+
138
+ def __init__(self, buffer, magic):
139
+ self._buffer = memoryview(buffer)
140
+ self._magic = magic
141
+
142
+ offset, length, crc, magic_, attrs, timestamp = self._read_header(0)
143
+ assert length == len(buffer) - self.LOG_OVERHEAD
144
+ assert magic == magic_
145
+
146
+ self._offset = offset
147
+ self._length = length
148
+ self._crc = crc
149
+ self._timestamp = timestamp
150
+ self._attributes = attrs
151
+ self._decompressed = False
152
+
153
+ @property
154
+ def base_offset(self):
155
+ return self._offset
156
+
157
+ @property
158
+ def size_in_bytes(self):
159
+ return self._length + self.LOG_OVERHEAD
160
+
161
+ @property
162
+ def timestamp_type(self):
163
+ """0 for CreateTime; 1 for LogAppendTime; None if unsupported.
164
+
165
+ Value is determined by broker; produced messages should always set to 0
166
+ Requires Kafka >= 0.10 / message version >= 1
167
+ """
168
+ if self._magic == 0:
169
+ return None
170
+ elif self._attributes & self.TIMESTAMP_TYPE_MASK:
171
+ return 1
172
+ else:
173
+ return 0
174
+
175
+ @property
176
+ def compression_type(self):
177
+ return self._attributes & self.CODEC_MASK
178
+
179
+ @property
180
+ def magic(self):
181
+ return self._magic
182
+
183
+ def validate_crc(self):
184
+ # memoryview avoids a full-body copy when slicing the bytearray.
185
+ crc = calc_crc32(memoryview(self._buffer)[self.MAGIC_OFFSET:])
186
+ return self._crc == crc
187
+
188
+ def _decompress(self, key_offset):
189
+ # Copy of `_read_key_value`, but uses memoryview
190
+ pos = key_offset
191
+ key_size = struct.unpack_from(">i", self._buffer, pos)[0]
192
+ pos += self.KEY_LENGTH
193
+ if key_size != -1:
194
+ pos += key_size
195
+ value_size = struct.unpack_from(">i", self._buffer, pos)[0]
196
+ pos += self.VALUE_LENGTH
197
+ if value_size == -1:
198
+ raise CorruptRecordError("Value of compressed message is None")
199
+ else:
200
+ data = self._buffer[pos:pos + value_size]
201
+
202
+ compression_type = self.compression_type
203
+ self._assert_has_codec(compression_type)
204
+ if compression_type == self.CODEC_GZIP:
205
+ uncompressed = gzip_decode(data)
206
+ elif compression_type == self.CODEC_SNAPPY:
207
+ uncompressed = snappy_decode(data.tobytes())
208
+ elif compression_type == self.CODEC_LZ4:
209
+ if self._magic == 0:
210
+ uncompressed = lz4_decode_old_kafka(data.tobytes())
211
+ else:
212
+ uncompressed = lz4_decode(data.tobytes())
213
+ return uncompressed # pylint: disable=E0606
214
+
215
+ def _read_header(self, pos):
216
+ if self._magic == 0:
217
+ offset, length, crc, magic_read, attrs = \
218
+ self.HEADER_STRUCT_V0.unpack_from(self._buffer, pos)
219
+ timestamp = None
220
+ else:
221
+ offset, length, crc, magic_read, attrs, timestamp = \
222
+ self.HEADER_STRUCT_V1.unpack_from(self._buffer, pos)
223
+ return offset, length, crc, magic_read, attrs, timestamp
224
+
225
+ def _read_all_headers(self):
226
+ pos = 0
227
+ msgs = []
228
+ buffer_len = len(self._buffer)
229
+ while pos < buffer_len:
230
+ header = self._read_header(pos)
231
+ msgs.append((header, pos))
232
+ pos += self.LOG_OVERHEAD + header[1] # length
233
+ return msgs
234
+
235
+ def _read_key_value(self, pos):
236
+ key_size = struct.unpack_from(">i", self._buffer, pos)[0]
237
+ pos += self.KEY_LENGTH
238
+ if key_size == -1:
239
+ key = None
240
+ else:
241
+ key = self._buffer[pos:pos + key_size].tobytes()
242
+ pos += key_size
243
+
244
+ value_size = struct.unpack_from(">i", self._buffer, pos)[0]
245
+ pos += self.VALUE_LENGTH
246
+ if value_size == -1:
247
+ value = None
248
+ else:
249
+ value = self._buffer[pos:pos + value_size].tobytes()
250
+ return key, value
251
+
252
+ def _crc_bytes(self, msg_pos, length):
253
+ # memoryview avoids copying the message bytes out of the batch buffer
254
+ # just to hand them to calc_crc32 later in LegacyRecord.validate_crc.
255
+ return memoryview(self._buffer)[
256
+ msg_pos + self.MAGIC_OFFSET:msg_pos + self.LOG_OVERHEAD + length]
257
+
258
+ def __iter__(self):
259
+ if self._magic == 1:
260
+ key_offset = self.KEY_OFFSET_V1
261
+ else:
262
+ key_offset = self.KEY_OFFSET_V0
263
+ timestamp_type = self.timestamp_type
264
+
265
+ if self.compression_type:
266
+ # In case we will call iter again
267
+ if not self._decompressed:
268
+ self._buffer = memoryview(self._decompress(key_offset))
269
+ self._decompressed = True
270
+
271
+ # If relative offset is used, we need to decompress the entire
272
+ # message first to compute the absolute offset.
273
+ headers = self._read_all_headers()
274
+ if self._magic > 0:
275
+ msg_header, _ = headers[-1]
276
+ absolute_base_offset = self._offset - msg_header[0]
277
+ else:
278
+ absolute_base_offset = -1
279
+
280
+ for header, msg_pos in headers:
281
+ offset, length, crc, _, attrs, timestamp = header
282
+ # There should only ever be a single layer of compression
283
+ assert not attrs & self.CODEC_MASK, (
284
+ 'MessageSet at offset %d appears double-compressed. This '
285
+ 'should not happen -- check your producers!' % (offset,))
286
+
287
+ # When magic value is greater than 0, the timestamp
288
+ # of a compressed message depends on the
289
+ # timestamp type of the wrapper message:
290
+ if timestamp_type == self.LOG_APPEND_TIME:
291
+ timestamp = self._timestamp
292
+
293
+ if absolute_base_offset >= 0:
294
+ offset += absolute_base_offset
295
+
296
+ key, value = self._read_key_value(msg_pos + key_offset)
297
+ crc_bytes = self._crc_bytes(msg_pos, length)
298
+ yield LegacyRecord(
299
+ self._magic, offset, timestamp, timestamp_type,
300
+ key, value, crc, crc_bytes)
301
+ else:
302
+ key, value = self._read_key_value(key_offset)
303
+ crc_bytes = self._crc_bytes(0, len(self._buffer) - self.LOG_OVERHEAD)
304
+ yield LegacyRecord(
305
+ self._magic, self._offset, self._timestamp, timestamp_type,
306
+ key, value, self._crc, crc_bytes)
307
+
308
+
309
+ class LegacyRecord(ABCRecord):
310
+
311
+ __slots__ = ("_magic", "_offset", "_timestamp", "_timestamp_type", "_key", "_value",
312
+ "_crc", "_crc_bytes")
313
+
314
+ def __init__(self, magic, offset, timestamp, timestamp_type, key, value, crc, crc_bytes):
315
+ self._magic = magic
316
+ self._offset = offset
317
+ self._timestamp = timestamp
318
+ self._timestamp_type = timestamp_type
319
+ self._key = key
320
+ self._value = value
321
+ self._crc = crc
322
+ self._crc_bytes = crc_bytes
323
+
324
+ @property
325
+ def magic(self):
326
+ return self._magic
327
+
328
+ @property
329
+ def offset(self):
330
+ return self._offset
331
+
332
+ @property
333
+ def timestamp(self):
334
+ """ Epoch milliseconds
335
+ """
336
+ return self._timestamp
337
+
338
+ @property
339
+ def timestamp_type(self):
340
+ """ CREATE_TIME(0) or APPEND_TIME(1)
341
+ """
342
+ return self._timestamp_type
343
+
344
+ @property
345
+ def key(self):
346
+ """ Bytes key or None
347
+ """
348
+ return self._key
349
+
350
+ @property
351
+ def value(self):
352
+ """ Bytes value or None
353
+ """
354
+ return self._value
355
+
356
+ @property
357
+ def headers(self):
358
+ return []
359
+
360
+ @property
361
+ def checksum(self):
362
+ return self._crc
363
+
364
+ def validate_crc(self):
365
+ crc = calc_crc32(self._crc_bytes)
366
+ return self._crc == crc
367
+
368
+ @property
369
+ def size_in_bytes(self):
370
+ return LegacyRecordBatchBuilder.estimate_size_in_bytes(self._magic, None, self._key, self._value)
371
+
372
+ def __repr__(self):
373
+ return (
374
+ "LegacyRecord(magic={!r} offset={!r}, timestamp={!r}, timestamp_type={!r},"
375
+ " key={!r}, value={!r}, crc={!r})".format(
376
+ self._magic, self._offset, self._timestamp, self._timestamp_type,
377
+ self._key, self._value, self._crc)
378
+ )
379
+
380
+
381
+ class LegacyRecordBatchBuilder(ABCRecordBatchBuilder, LegacyRecordBase):
382
+
383
+ __slots__ = ("_magic", "_compression_type", "_batch_size", "_buffer")
384
+
385
+ def __init__(self, magic, compression_type, batch_size):
386
+ self._magic = magic
387
+ self._compression_type = compression_type
388
+ self._batch_size = batch_size
389
+ self._buffer = bytearray()
390
+
391
+ def append(self, offset, timestamp, key, value, headers=None):
392
+ """ Append message to batch.
393
+ """
394
+ assert not headers, "Headers not supported in v0/v1"
395
+ # Check types
396
+ if type(offset) != int:
397
+ raise TypeError(offset)
398
+ if self._magic == 0:
399
+ timestamp = self.NO_TIMESTAMP
400
+ elif timestamp is None:
401
+ timestamp = int(time.time() * 1000)
402
+ elif type(timestamp) != int:
403
+ raise TypeError(
404
+ "`timestamp` should be int, but {} provided".format(
405
+ type(timestamp)))
406
+ if not (key is None or
407
+ isinstance(key, (bytes, bytearray, memoryview))):
408
+ raise TypeError(
409
+ "Not supported type for key: {}".format(type(key)))
410
+ if not (value is None or
411
+ isinstance(value, (bytes, bytearray, memoryview))):
412
+ raise TypeError(
413
+ "Not supported type for value: {}".format(type(value)))
414
+
415
+ # Check if we have room for another message
416
+ pos = len(self._buffer)
417
+ size = self.size_in_bytes(offset, timestamp, key, value)
418
+ # We always allow at least one record to be appended
419
+ if offset != 0 and pos + size >= self._batch_size:
420
+ return None
421
+
422
+ # Allocate proper buffer length
423
+ self._buffer.extend(bytearray(size))
424
+
425
+ # Encode message
426
+ crc = self._encode_msg(pos, offset, timestamp, key, value)
427
+
428
+ return LegacyRecordMetadata(offset, crc, size, timestamp)
429
+
430
+ def _encode_msg(self, start_pos, offset, timestamp, key, value,
431
+ attributes=0):
432
+ """ Encode msg data into the `msg_buffer`, which should be allocated
433
+ to at least the size of this message.
434
+ """
435
+ magic = self._magic
436
+ buf = self._buffer
437
+ pos = start_pos
438
+
439
+ # Write key and value
440
+ pos += self.KEY_OFFSET_V0 if magic == 0 else self.KEY_OFFSET_V1
441
+
442
+ if key is None:
443
+ struct.pack_into(">i", buf, pos, -1)
444
+ pos += self.KEY_LENGTH
445
+ else:
446
+ key_size = len(key)
447
+ struct.pack_into(">i", buf, pos, key_size)
448
+ pos += self.KEY_LENGTH
449
+ buf[pos: pos + key_size] = key
450
+ pos += key_size
451
+
452
+ if value is None:
453
+ struct.pack_into(">i", buf, pos, -1)
454
+ pos += self.VALUE_LENGTH
455
+ else:
456
+ value_size = len(value)
457
+ struct.pack_into(">i", buf, pos, value_size)
458
+ pos += self.VALUE_LENGTH
459
+ buf[pos: pos + value_size] = value
460
+ pos += value_size
461
+ length = (pos - start_pos) - self.LOG_OVERHEAD
462
+
463
+ # Write msg header. Note, that Crc will be updated later
464
+ if magic == 0:
465
+ self.HEADER_STRUCT_V0.pack_into(
466
+ buf, start_pos,
467
+ offset, length, 0, magic, attributes)
468
+ else:
469
+ self.HEADER_STRUCT_V1.pack_into(
470
+ buf, start_pos,
471
+ offset, length, 0, magic, attributes, timestamp)
472
+
473
+ # Calculate CRC for msg
474
+ crc_data = memoryview(buf)[start_pos + self.MAGIC_OFFSET:]
475
+ crc = calc_crc32(crc_data)
476
+ struct.pack_into(">I", buf, start_pos + self.CRC_OFFSET, crc)
477
+ return crc
478
+
479
+ def _maybe_compress(self):
480
+ if self._compression_type:
481
+ self._assert_has_codec(self._compression_type)
482
+ data = bytes(self._buffer)
483
+ if self._compression_type == self.CODEC_GZIP:
484
+ compressed = gzip_encode(data)
485
+ elif self._compression_type == self.CODEC_SNAPPY:
486
+ compressed = snappy_encode(data)
487
+ elif self._compression_type == self.CODEC_LZ4:
488
+ if self._magic == 0:
489
+ compressed = lz4_encode_old_kafka(data)
490
+ else:
491
+ compressed = lz4_encode(data)
492
+ size = self.size_in_bytes(
493
+ 0, timestamp=0, key=None, value=compressed) # pylint: disable=E0606
494
+ # We will try to reuse the same buffer if we have enough space
495
+ if size > len(self._buffer):
496
+ self._buffer = bytearray(size)
497
+ else:
498
+ del self._buffer[size:]
499
+ self._encode_msg(
500
+ start_pos=0,
501
+ offset=0, timestamp=0, key=None, value=compressed,
502
+ attributes=self._compression_type)
503
+ return True
504
+ return False
505
+
506
+ def build(self):
507
+ """Compress batch to be ready for send"""
508
+ self._maybe_compress()
509
+ return self._buffer
510
+
511
+ def size(self):
512
+ """ Return current size of data written to buffer
513
+ """
514
+ return len(self._buffer)
515
+
516
+ # Size calculations. Just copied Java's implementation
517
+
518
+ def size_in_bytes(self, offset, timestamp, key, value, headers=None):
519
+ """ Actual size of message to add
520
+ """
521
+ assert not headers, "Headers not supported in v0/v1"
522
+ magic = self._magic
523
+ return self.LOG_OVERHEAD + self.record_size(magic, key, value)
524
+
525
+ @classmethod
526
+ def record_size(cls, magic, key, value):
527
+ message_size = cls.record_overhead(magic)
528
+ if key is not None:
529
+ message_size += len(key)
530
+ if value is not None:
531
+ message_size += len(value)
532
+ return message_size
533
+
534
+ @classmethod
535
+ def record_overhead(cls, magic):
536
+ assert magic in [0, 1], "Not supported magic"
537
+ if magic == 0:
538
+ return cls.RECORD_OVERHEAD_V0
539
+ else:
540
+ return cls.RECORD_OVERHEAD_V1
541
+
542
+ @classmethod
543
+ def estimate_size_in_bytes(cls, magic, compression_type, key, value):
544
+ """ Upper bound estimate of record size.
545
+ """
546
+ assert magic in [0, 1], "Not supported magic"
547
+ # In case of compression we may need another overhead for inner msg
548
+ if compression_type:
549
+ return (
550
+ cls.LOG_OVERHEAD + cls.record_overhead(magic) +
551
+ cls.record_size(magic, key, value)
552
+ )
553
+ return cls.LOG_OVERHEAD + cls.record_size(magic, key, value)
554
+
555
+
556
+ class LegacyRecordMetadata:
557
+
558
+ __slots__ = ("_crc", "_size", "_timestamp", "_offset")
559
+
560
+ def __init__(self, offset, crc, size, timestamp):
561
+ self._offset = offset
562
+ self._crc = crc
563
+ self._size = size
564
+ self._timestamp = timestamp
565
+
566
+ @property
567
+ def offset(self):
568
+ return self._offset
569
+
570
+ @property
571
+ def crc(self):
572
+ return self._crc
573
+
574
+ @property
575
+ def size(self):
576
+ return self._size
577
+
578
+ @property
579
+ def timestamp(self):
580
+ return self._timestamp
581
+
582
+ def __repr__(self):
583
+ return (
584
+ "LegacyRecordMetadata(offset={!r}, crc={!r}, size={!r},"
585
+ " timestamp={!r})".format(
586
+ self._offset, self._crc, self._size, self._timestamp)
587
+ )