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,118 @@
1
+ from kafka.metrics.measurable_stat import AbstractMeasurableStat
2
+ from kafka.metrics.stats.sampled_stat import AbstractSampledStat
3
+
4
+
5
+ class TimeUnit:
6
+ _names = {
7
+ 'nanosecond': 0,
8
+ 'microsecond': 1,
9
+ 'millisecond': 2,
10
+ 'second': 3,
11
+ 'minute': 4,
12
+ 'hour': 5,
13
+ 'day': 6,
14
+ }
15
+
16
+ NANOSECONDS = _names['nanosecond']
17
+ MICROSECONDS = _names['microsecond']
18
+ MILLISECONDS = _names['millisecond']
19
+ SECONDS = _names['second']
20
+ MINUTES = _names['minute']
21
+ HOURS = _names['hour']
22
+ DAYS = _names['day']
23
+
24
+ @staticmethod
25
+ def get_name(time_unit):
26
+ return TimeUnit._names[time_unit]
27
+
28
+
29
+ class Rate(AbstractMeasurableStat):
30
+ """
31
+ The rate of the given quantity. By default this is the total observed
32
+ over a set of samples from a sampled statistic divided by the elapsed
33
+ time over the sample windows. Alternative AbstractSampledStat
34
+ implementations can be provided, however, to record the rate of
35
+ occurrences (e.g. the count of values measured over the time interval)
36
+ or other such values.
37
+ """
38
+ __slots__ = ('_stat', '_unit')
39
+
40
+ def __init__(self, time_unit=TimeUnit.SECONDS, sampled_stat=None):
41
+ self._stat = sampled_stat or SampledTotal()
42
+ self._unit = time_unit
43
+
44
+ def unit_name(self):
45
+ return TimeUnit.get_name(self._unit)
46
+
47
+ def record(self, config, value, time_ms):
48
+ self._stat.record(config, value, time_ms)
49
+
50
+ def measure(self, config, now):
51
+ value = self._stat.measure(config, now)
52
+ return float(value) / self.convert(self.window_size(config, now))
53
+
54
+ def window_size(self, config, now):
55
+ # purge old samples before we compute the window size
56
+ self._stat.purge_obsolete_samples(config, now)
57
+
58
+ """
59
+ Here we check the total amount of time elapsed since the oldest
60
+ non-obsolete window. This give the total window_size of the batch
61
+ which is the time used for Rate computation. However, there is
62
+ an issue if we do not have sufficient data for e.g. if only
63
+ 1 second has elapsed in a 30 second window, the measured rate
64
+ will be very high. Hence we assume that the elapsed time is
65
+ always N-1 complete windows plus whatever fraction of the final
66
+ window is complete.
67
+
68
+ Note that we could simply count the amount of time elapsed in
69
+ the current window and add n-1 windows to get the total time,
70
+ but this approach does not account for sleeps. AbstractSampledStat
71
+ only creates samples whenever record is called, if no record is
72
+ called for a period of time that time is not accounted for in
73
+ window_size and produces incorrect results.
74
+ """
75
+ total_elapsed_time_ms = now - self._stat.oldest(now).last_window_ms
76
+ # Check how many full windows of data we have currently retained
77
+ num_full_windows = int(total_elapsed_time_ms / config.time_window_ms)
78
+ min_full_windows = config.samples - 1
79
+
80
+ # If the available windows are less than the minimum required,
81
+ # add the difference to the totalElapsedTime
82
+ if num_full_windows < min_full_windows:
83
+ total_elapsed_time_ms += ((min_full_windows - num_full_windows) *
84
+ config.time_window_ms)
85
+
86
+ return total_elapsed_time_ms
87
+
88
+ def convert(self, time_ms):
89
+ if self._unit == TimeUnit.NANOSECONDS:
90
+ return time_ms * 1000.0 * 1000.0
91
+ elif self._unit == TimeUnit.MICROSECONDS:
92
+ return time_ms * 1000.0
93
+ elif self._unit == TimeUnit.MILLISECONDS:
94
+ return time_ms
95
+ elif self._unit == TimeUnit.SECONDS:
96
+ return time_ms / 1000.0
97
+ elif self._unit == TimeUnit.MINUTES:
98
+ return time_ms / (60.0 * 1000.0)
99
+ elif self._unit == TimeUnit.HOURS:
100
+ return time_ms / (60.0 * 60.0 * 1000.0)
101
+ elif self._unit == TimeUnit.DAYS:
102
+ return time_ms / (24.0 * 60.0 * 60.0 * 1000.0)
103
+ else:
104
+ raise ValueError('Unknown unit: %s' % (self._unit,))
105
+
106
+
107
+ class SampledTotal(AbstractSampledStat):
108
+ __slots__ = ('_initial_value', '_samples', '_current')
109
+ def __init__(self, initial_value=None):
110
+ if initial_value is not None:
111
+ raise ValueError('initial_value cannot be set on SampledTotal')
112
+ super().__init__(0.0)
113
+
114
+ def update(self, sample, config, value, time_ms):
115
+ sample.value += value
116
+
117
+ def combine(self, samples, config, now):
118
+ return float(sum(sample.value for sample in samples))
@@ -0,0 +1,99 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from kafka.metrics.measurable_stat import AbstractMeasurableStat
4
+
5
+
6
+ class AbstractSampledStat(AbstractMeasurableStat, ABC):
7
+ """
8
+ An AbstractSampledStat records a single scalar value measured over
9
+ one or more samples. Each sample is recorded over a configurable
10
+ window. The window can be defined by number of events or elapsed
11
+ time (or both, if both are given the window is complete when
12
+ *either* the event count or elapsed time criterion is met).
13
+
14
+ All the samples are combined to produce the measurement. When a
15
+ window is complete the oldest sample is cleared and recycled to
16
+ begin recording the next sample.
17
+
18
+ Subclasses of this class define different statistics measured
19
+ using this basic pattern.
20
+ """
21
+ __slots__ = ('_initial_value', '_samples', '_current')
22
+
23
+ def __init__(self, initial_value):
24
+ self._initial_value = initial_value
25
+ self._samples = []
26
+ self._current = 0
27
+
28
+ @abstractmethod
29
+ def update(self, sample, config, value, time_ms):
30
+ pass
31
+
32
+ @abstractmethod
33
+ def combine(self, samples, config, now):
34
+ pass
35
+
36
+ def record(self, config, value, time_ms):
37
+ sample = self.current(time_ms)
38
+ if sample.is_complete(time_ms, config):
39
+ sample = self._advance(config, time_ms)
40
+ self.update(sample, config, float(value), time_ms)
41
+ sample.event_count += 1
42
+
43
+ def new_sample(self, time_ms):
44
+ return self.Sample(self._initial_value, time_ms)
45
+
46
+ def measure(self, config, now):
47
+ self.purge_obsolete_samples(config, now)
48
+ return float(self.combine(self._samples, config, now))
49
+
50
+ def current(self, time_ms):
51
+ if not self._samples:
52
+ self._samples.append(self.new_sample(time_ms))
53
+ return self._samples[self._current]
54
+
55
+ def oldest(self, now):
56
+ if not self._samples:
57
+ self._samples.append(self.new_sample(now))
58
+ oldest = self._samples[0]
59
+ for sample in self._samples[1:]:
60
+ if sample.last_window_ms < oldest.last_window_ms:
61
+ oldest = sample
62
+ return oldest
63
+
64
+ def purge_obsolete_samples(self, config, now):
65
+ """
66
+ Timeout any windows that have expired in the absence of any events
67
+ """
68
+ expire_age = config.samples * config.time_window_ms
69
+ for sample in self._samples:
70
+ if now - sample.last_window_ms >= expire_age:
71
+ sample.reset(now)
72
+
73
+ def _advance(self, config, time_ms):
74
+ self._current = (self._current + 1) % config.samples
75
+ if self._current >= len(self._samples):
76
+ sample = self.new_sample(time_ms)
77
+ self._samples.append(sample)
78
+ return sample
79
+ else:
80
+ sample = self.current(time_ms)
81
+ sample.reset(time_ms)
82
+ return sample
83
+
84
+ class Sample:
85
+
86
+ def __init__(self, initial_value, now):
87
+ self.initial_value = initial_value
88
+ self.event_count = 0
89
+ self.last_window_ms = now
90
+ self.value = initial_value
91
+
92
+ def reset(self, now):
93
+ self.event_count = 0
94
+ self.last_window_ms = now
95
+ self.value = self.initial_value
96
+
97
+ def is_complete(self, time_ms, config):
98
+ return (time_ms - self.last_window_ms >= config.time_window_ms or
99
+ self.event_count >= config.event_window)
@@ -0,0 +1,136 @@
1
+ import threading
2
+ import time
3
+
4
+ from kafka.errors import QuotaViolationError
5
+ from kafka.metrics import KafkaMetric
6
+
7
+
8
+ class Sensor:
9
+ """
10
+ A sensor applies a continuous sequence of numerical values
11
+ to a set of associated metrics. For example a sensor on
12
+ message size would record a sequence of message sizes using
13
+ the `record(double)` api and would maintain a set
14
+ of metrics about request sizes such as the average or max.
15
+ """
16
+ __slots__ = ('_lock', '_registry', '_name', '_parents', '_metrics',
17
+ '_stats', '_config', '_inactive_sensor_expiration_time_ms',
18
+ '_last_record_time')
19
+
20
+ def __init__(self, registry, name, parents, config,
21
+ inactive_sensor_expiration_time_seconds):
22
+ if not name:
23
+ raise ValueError('name must be non-empty')
24
+ self._lock = threading.RLock()
25
+ self._registry = registry
26
+ self._name = name
27
+ self._parents = parents or []
28
+ self._metrics = []
29
+ self._stats = []
30
+ self._config = config
31
+ self._inactive_sensor_expiration_time_ms = (
32
+ inactive_sensor_expiration_time_seconds * 1000)
33
+ self._last_record_time = time.monotonic() * 1000
34
+ self._check_forest(set())
35
+
36
+ def _check_forest(self, sensors):
37
+ """Validate that this sensor doesn't end up referencing itself."""
38
+ if self in sensors:
39
+ raise ValueError('Circular dependency in sensors: %s is its own'
40
+ 'parent.' % (self.name,))
41
+ sensors.add(self)
42
+ for parent in self._parents:
43
+ parent._check_forest(sensors)
44
+
45
+ @property
46
+ def name(self):
47
+ """
48
+ The name this sensor is registered with.
49
+ This name will be unique among all registered sensors.
50
+ """
51
+ return self._name
52
+
53
+ @property
54
+ def metrics(self):
55
+ return tuple(self._metrics)
56
+
57
+ def record(self, value=1.0, time_ms=None):
58
+ """
59
+ Record a value at a known time.
60
+ Arguments:
61
+ value (double): The value we are recording
62
+ time_ms (int): A POSIX timestamp in milliseconds.
63
+ Default: The time when record() is evaluated (now)
64
+
65
+ Raises:
66
+ QuotaViolationException: if recording this value moves a
67
+ metric beyond its configured maximum or minimum bound
68
+ """
69
+ if time_ms is None:
70
+ time_ms = time.monotonic() * 1000
71
+ self._last_record_time = time_ms
72
+ with self._lock: # XXX high volume, might be performance issue
73
+ # increment all the stats
74
+ for stat in self._stats:
75
+ stat.record(self._config, value, time_ms)
76
+ self._check_quotas(time_ms)
77
+ for parent in self._parents:
78
+ parent.record(value, time_ms)
79
+
80
+ def _check_quotas(self, time_ms):
81
+ """
82
+ Check if we have violated our quota for any metric that
83
+ has a configured quota
84
+ """
85
+ for metric in self._metrics:
86
+ if metric.config and metric.config.quota:
87
+ value = metric.value(time_ms)
88
+ if not metric.config.quota.is_acceptable(value):
89
+ raise QuotaViolationError("'%s' violated quota. Actual: "
90
+ "%d, Threshold: %d" %
91
+ (metric.metric_name,
92
+ value,
93
+ metric.config.quota.bound))
94
+
95
+ def add_compound(self, compound_stat, config=None):
96
+ """
97
+ Register a compound statistic with this sensor which
98
+ yields multiple measurable quantities (like a histogram)
99
+
100
+ Arguments:
101
+ stat (AbstractCompoundStat): The stat to register
102
+ config (MetricConfig): The configuration for this stat.
103
+ If None then the stat will use the default configuration
104
+ for this sensor.
105
+ """
106
+ if not compound_stat:
107
+ raise ValueError('compound stat must be non-empty')
108
+ self._stats.append(compound_stat)
109
+ for named_measurable in compound_stat.stats():
110
+ metric = KafkaMetric(named_measurable.name, named_measurable.stat,
111
+ config or self._config)
112
+ self._registry.register_metric(metric)
113
+ self._metrics.append(metric)
114
+
115
+ def add(self, metric_name, stat, config=None):
116
+ """
117
+ Register a metric with this sensor
118
+
119
+ Arguments:
120
+ metric_name (MetricName): The name of the metric
121
+ stat (AbstractMeasurableStat): The statistic to keep
122
+ config (MetricConfig): A special configuration for this metric.
123
+ If None use the sensor default configuration.
124
+ """
125
+ with self._lock:
126
+ metric = KafkaMetric(metric_name, stat, config or self._config)
127
+ self._registry.register_metric(metric)
128
+ self._metrics.append(metric)
129
+ self._stats.append(stat)
130
+
131
+ def has_expired(self):
132
+ """
133
+ Return True if the Sensor is eligible for removal due to inactivity.
134
+ """
135
+ return ((time.monotonic() * 1000 - self._last_record_time) >
136
+ self._inactive_sensor_expiration_time_ms)
@@ -0,0 +1,15 @@
1
+ from kafka.metrics.measurable_stat import AbstractMeasurableStat
2
+
3
+
4
+ class Total(AbstractMeasurableStat):
5
+ """An un-windowed cumulative total maintained over all time."""
6
+ __slots__ = ('_total',)
7
+
8
+ def __init__(self, value=0.0):
9
+ self._total = value
10
+
11
+ def record(self, config, value, now):
12
+ self._total += value
13
+
14
+ def measure(self, config, now):
15
+ return float(self._total)
kafka/net/__init__.py ADDED
@@ -0,0 +1,19 @@
1
+ from .connection import KafkaConnection
2
+ from .inet import create_connection, KafkaNetSocket
3
+ from .manager import KafkaConnectionManager
4
+ from .metrics import KafkaConnectionMetrics, KafkaManagerMetrics
5
+ from .selector import NetworkSelector
6
+ from .http_connect import HttpConnectProxy
7
+ from .socks5 import Socks5Proxy
8
+ from .transport import KafkaTCPTransport, KafkaSSLTransport
9
+ from .wakeup_notifier import WakeupNotifier
10
+
11
+ from .compat import KafkaNetClient
12
+
13
+
14
+ __all__ = [
15
+ 'KafkaConnection', 'create_connection', 'KafkaNetSocket',
16
+ 'KafkaConnectionManager', 'KafkaConnectionMetrics', 'KafkaManagerMetrics',
17
+ 'NetworkSelector', 'HttpConnectProxy', 'Socks5Proxy', 'KafkaTCPTransport', 'KafkaSSLTransport',
18
+ 'WakeupNotifier', 'KafkaNetClient',
19
+ ]
kafka/net/compat.py ADDED
@@ -0,0 +1,165 @@
1
+ import logging
2
+ import random
3
+ import threading
4
+ import time
5
+
6
+ import kafka.errors as Errors
7
+ from kafka.net.manager import KafkaConnectionManager
8
+ from kafka.net.selector import NetworkSelector
9
+
10
+
11
+ log = logging.getLogger(__name__)
12
+
13
+
14
+ class KafkaNetClient:
15
+ """Drop-in replacement for KafkaClient backed by KafkaConnectionManager.
16
+
17
+ Provides the KafkaClient API surface that existing consumer/producer/admin
18
+ code depends on. Goal: shrink over time as components transition to using
19
+ KafkaConnectionManager directly (fire-and-forget via _request_buffer).
20
+ """
21
+ def __init__(self, net=None, manager=None, **configs):
22
+ # _lock is still used by the legacy Coordinator (kafka/coordinator/base.py).
23
+ # Remove once Coordinator moves to the IO thread (Phase D).
24
+ self._lock = threading.RLock()
25
+ self._net = NetworkSelector(**configs) if net is None else net
26
+ self._manager = KafkaConnectionManager(self._net, **configs) if manager is None else manager
27
+
28
+ @property
29
+ def cluster(self):
30
+ return self._manager.cluster
31
+
32
+ # Connection state queries
33
+
34
+ def connected(self, node_id):
35
+ conn = self._manager._conns.get(node_id)
36
+ return conn is not None and conn.connected
37
+
38
+ def is_disconnected(self, node_id):
39
+ return not self.connected(node_id)
40
+
41
+ def is_ready(self, node_id):
42
+ conn = self._manager._conns.get(node_id)
43
+ return conn is not None and conn.connected and not conn.paused
44
+
45
+ def ready(self, node_id, **kwargs):
46
+ if self.is_ready(node_id):
47
+ return True
48
+ try:
49
+ self._manager.get_connection(node_id)
50
+ except Errors.NodeNotReadyError:
51
+ pass
52
+ return False
53
+
54
+ def maybe_connect(self, node_id, **kwargs):
55
+ try:
56
+ self._manager.get_connection(node_id)
57
+ except Errors.NodeNotReadyError:
58
+ pass
59
+
60
+ def await_ready(self, node_id, timeout_ms=30000):
61
+ if self.is_ready(node_id):
62
+ return True
63
+ self.maybe_connect(node_id)
64
+ conn = self._manager._conns.get(node_id)
65
+ if conn is not None and not conn.init_future.is_done:
66
+ self._net.poll(timeout_ms=timeout_ms, future=conn.init_future)
67
+ # Connection may be initialized but paused (e.g. max_in_flight reached).
68
+ # Poll briefly to drain in-flight responses and unpause.
69
+ if conn is not None and conn.connected and conn.paused:
70
+ self._net.poll(timeout_ms=min(timeout_ms, self._manager.config['request_timeout_ms']))
71
+ if not self.is_ready(node_id):
72
+ raise Errors.KafkaConnectionError('Node %s not ready after %s ms' % (node_id, timeout_ms))
73
+ return True
74
+
75
+ # In-flight request tracking
76
+
77
+ def in_flight_request_count(self, node_id=None):
78
+ if node_id is not None:
79
+ conn = self._manager._conns.get(node_id)
80
+ return len(conn.in_flight_requests) if conn is not None else 0
81
+ return sum(len(c.in_flight_requests) for c in self._manager._conns.values())
82
+
83
+ def throttle_delay(self, node_id):
84
+ conn = self._manager._conns.get(node_id)
85
+ if conn is None:
86
+ return 0
87
+ remaining = conn._throttle_time - time.monotonic()
88
+ return max(0, remaining) * 1000
89
+
90
+ # Bootstrap / version
91
+
92
+ def bootstrap_connected(self):
93
+ bootstrap_future = self._manager._bootstrap_future
94
+ return bootstrap_future is not None and not bootstrap_future.is_done
95
+
96
+ def get_broker_version(self, timeout_ms=None):
97
+ if self._manager.broker_version is None:
98
+ self._manager.bootstrap(timeout_ms)
99
+ return self._manager.broker_version
100
+
101
+ def check_version(self, node_id=None, timeout_ms=10000):
102
+ if not self._manager.bootstrapped:
103
+ self._manager.bootstrap(timeout_ms)
104
+ if node_id is None:
105
+ return self._manager.broker_version
106
+ async def _check_version(broker_id, timeout_ms):
107
+ conn = await self._manager.get_connection(broker_id, timeout_ms=timeout_ms)
108
+ return conn.broker_version
109
+ return self._net.run(_check_version, node_id, timeout_ms)
110
+
111
+ # Request sending
112
+
113
+ def send(self, node_id, request, **kwargs):
114
+ return self._manager.send(request, node_id=node_id)
115
+
116
+ def send_and_receive(self, node_id, request, timeout_ms=30000):
117
+ self.await_ready(node_id, timeout_ms=timeout_ms)
118
+ f = self.send(node_id, request)
119
+ self._net.poll(timeout_ms=timeout_ms, future=f)
120
+ if f.succeeded():
121
+ return f.value
122
+ elif f.failed():
123
+ raise f.exception
124
+ raise Errors.KafkaTimeoutError('Request timed out')
125
+
126
+ # Delegation
127
+
128
+ def poll(self, timeout_ms=None, future=None):
129
+ # _lock serializes with HeartbeatThread, which also drives poll()
130
+ # while holding this lock. Without it, both threads would call
131
+ # _net.poll() concurrently and race on selector / task state.
132
+ # The lock goes away once HeartbeatThread does (Phase D).
133
+ with self._lock:
134
+ return self._net.poll(timeout_ms=timeout_ms, future=future)
135
+
136
+ def close(self, node_id=None):
137
+ self._manager.close(node_id=node_id)
138
+ if node_id is None:
139
+ self._net.close()
140
+
141
+ def least_loaded_node(self, bootstrap_fallback=False):
142
+ node_id = self._manager.least_loaded_node()
143
+ if node_id is None and bootstrap_fallback:
144
+ node_id = random.choice(self._manager.cluster.bootstrap_brokers()).node_id
145
+ return node_id
146
+
147
+ def least_loaded_node_refresh_ms(self, bootstrap_fallback=False):
148
+ brokers = self._manager.cluster.brokers()
149
+ if not brokers and bootstrap_fallback:
150
+ brokers = self._manager.cluster.bootstrap_brokers()
151
+ if not brokers:
152
+ return self._manager.config['reconnect_backoff_ms']
153
+ delays = [self._manager.connection_delay(broker.node_id) for broker in brokers]
154
+ return min(delays) * 1000
155
+
156
+ def connection_delay(self, node_id):
157
+ return self._manager.connection_delay(node_id)
158
+
159
+ def wakeup(self):
160
+ self._net.wakeup()
161
+
162
+ def api_version(self, operation, max_version=None):
163
+ if self._manager.broker_version_data is None:
164
+ raise Errors.IllegalStateError('broker_version_data is not available: have we bootstrapped yet?')
165
+ return self._manager.broker_version_data.api_version(operation, max_version=max_version)