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.
- kafka/__init__.py +34 -0
- kafka/__main__.py +5 -0
- kafka/admin/__init__.py +29 -0
- kafka/admin/__main__.py +5 -0
- kafka/admin/_acls.py +355 -0
- kafka/admin/_cluster.py +359 -0
- kafka/admin/_configs.py +479 -0
- kafka/admin/_groups.py +754 -0
- kafka/admin/_partitions.py +595 -0
- kafka/admin/_topics.py +281 -0
- kafka/admin/_transactions.py +450 -0
- kafka/admin/_users.py +194 -0
- kafka/admin/client.py +373 -0
- kafka/benchmarks/__init__.py +0 -0
- kafka/benchmarks/consumer_performance.py +138 -0
- kafka/benchmarks/load_example.py +109 -0
- kafka/benchmarks/producer_encode_path.py +201 -0
- kafka/benchmarks/producer_performance.py +161 -0
- kafka/benchmarks/profile_protocol.py +138 -0
- kafka/benchmarks/protocol_old_vs_new.py +447 -0
- kafka/benchmarks/record_batch_compose.py +77 -0
- kafka/benchmarks/record_batch_read.py +82 -0
- kafka/benchmarks/varint_speed.py +426 -0
- kafka/cli/__init__.py +36 -0
- kafka/cli/admin/__init__.py +117 -0
- kafka/cli/admin/acls/__init__.py +9 -0
- kafka/cli/admin/acls/common.py +76 -0
- kafka/cli/admin/acls/create.py +19 -0
- kafka/cli/admin/acls/delete.py +23 -0
- kafka/cli/admin/acls/describe.py +16 -0
- kafka/cli/admin/cluster/__init__.py +14 -0
- kafka/cli/admin/cluster/describe.py +11 -0
- kafka/cli/admin/cluster/describe_quorum.py +11 -0
- kafka/cli/admin/cluster/features.py +52 -0
- kafka/cli/admin/cluster/log_dirs.py +43 -0
- kafka/cli/admin/cluster/versions.py +33 -0
- kafka/cli/admin/configs/__init__.py +10 -0
- kafka/cli/admin/configs/alter.py +43 -0
- kafka/cli/admin/configs/common.py +17 -0
- kafka/cli/admin/configs/describe.py +30 -0
- kafka/cli/admin/configs/list.py +16 -0
- kafka/cli/admin/configs/reset.py +20 -0
- kafka/cli/admin/groups/__init__.py +16 -0
- kafka/cli/admin/groups/alter_offsets.py +30 -0
- kafka/cli/admin/groups/delete.py +11 -0
- kafka/cli/admin/groups/delete_offsets.py +29 -0
- kafka/cli/admin/groups/describe.py +11 -0
- kafka/cli/admin/groups/list.py +28 -0
- kafka/cli/admin/groups/list_offsets.py +29 -0
- kafka/cli/admin/groups/remove_members.py +40 -0
- kafka/cli/admin/groups/reset_offsets.py +139 -0
- kafka/cli/admin/partitions/__init__.py +21 -0
- kafka/cli/admin/partitions/alter_reassignments.py +37 -0
- kafka/cli/admin/partitions/create.py +27 -0
- kafka/cli/admin/partitions/delete_records.py +31 -0
- kafka/cli/admin/partitions/describe.py +36 -0
- kafka/cli/admin/partitions/elect_leaders.py +53 -0
- kafka/cli/admin/partitions/list_offsets.py +88 -0
- kafka/cli/admin/partitions/list_reassignments.py +35 -0
- kafka/cli/admin/topics/__init__.py +10 -0
- kafka/cli/admin/topics/create.py +13 -0
- kafka/cli/admin/topics/delete.py +19 -0
- kafka/cli/admin/topics/describe.py +18 -0
- kafka/cli/admin/topics/list.py +11 -0
- kafka/cli/admin/transactions/__init__.py +17 -0
- kafka/cli/admin/transactions/abort.py +38 -0
- kafka/cli/admin/transactions/describe.py +24 -0
- kafka/cli/admin/transactions/describe_producers.py +29 -0
- kafka/cli/admin/transactions/find_hanging.py +26 -0
- kafka/cli/admin/transactions/list.py +37 -0
- kafka/cli/admin/users/__init__.py +8 -0
- kafka/cli/admin/users/alter_user_scram_credentials.py +34 -0
- kafka/cli/admin/users/describe_user_scram_credentials.py +15 -0
- kafka/cli/common.py +95 -0
- kafka/cli/consumer/__init__.py +63 -0
- kafka/cli/producer/__init__.py +57 -0
- kafka/cluster.py +824 -0
- kafka/codec.py +325 -0
- kafka/consumer/__init__.py +5 -0
- kafka/consumer/__main__.py +5 -0
- kafka/consumer/fetcher.py +2012 -0
- kafka/consumer/group.py +1347 -0
- kafka/consumer/subscription_state.py +897 -0
- kafka/coordinator/__init__.py +0 -0
- kafka/coordinator/assignors/__init__.py +0 -0
- kafka/coordinator/assignors/abstract.py +90 -0
- kafka/coordinator/assignors/cooperative_sticky.py +167 -0
- kafka/coordinator/assignors/range.py +81 -0
- kafka/coordinator/assignors/roundrobin.py +101 -0
- kafka/coordinator/assignors/sticky/StickyAssignorUserData.json +37 -0
- kafka/coordinator/assignors/sticky/__init__.py +0 -0
- kafka/coordinator/assignors/sticky/partition_movements.py +149 -0
- kafka/coordinator/assignors/sticky/sorted_set.py +63 -0
- kafka/coordinator/assignors/sticky/sticky_assignor.py +665 -0
- kafka/coordinator/assignors/sticky/user_data.py +8 -0
- kafka/coordinator/base.py +1215 -0
- kafka/coordinator/consumer.py +1224 -0
- kafka/coordinator/heartbeat.py +82 -0
- kafka/coordinator/subscription.py +34 -0
- kafka/errors.py +1004 -0
- kafka/future.py +166 -0
- kafka/metrics/__init__.py +13 -0
- kafka/metrics/compound_stat.py +33 -0
- kafka/metrics/dict_reporter.py +81 -0
- kafka/metrics/kafka_metric.py +36 -0
- kafka/metrics/measurable.py +27 -0
- kafka/metrics/measurable_stat.py +13 -0
- kafka/metrics/metric_config.py +33 -0
- kafka/metrics/metric_name.py +105 -0
- kafka/metrics/metrics.py +261 -0
- kafka/metrics/metrics_reporter.py +53 -0
- kafka/metrics/quota.py +41 -0
- kafka/metrics/stat.py +19 -0
- kafka/metrics/stats/__init__.py +15 -0
- kafka/metrics/stats/avg.py +24 -0
- kafka/metrics/stats/count.py +17 -0
- kafka/metrics/stats/histogram.py +99 -0
- kafka/metrics/stats/max_stat.py +17 -0
- kafka/metrics/stats/min_stat.py +19 -0
- kafka/metrics/stats/percentile.py +14 -0
- kafka/metrics/stats/percentiles.py +75 -0
- kafka/metrics/stats/rate.py +118 -0
- kafka/metrics/stats/sampled_stat.py +99 -0
- kafka/metrics/stats/sensor.py +136 -0
- kafka/metrics/stats/total.py +15 -0
- kafka/net/__init__.py +19 -0
- kafka/net/compat.py +165 -0
- kafka/net/connection.py +593 -0
- kafka/net/http_connect.py +144 -0
- kafka/net/inet.py +122 -0
- kafka/net/manager.py +451 -0
- kafka/net/metrics.py +149 -0
- kafka/net/sasl/__init__.py +32 -0
- kafka/net/sasl/abc.py +28 -0
- kafka/net/sasl/gssapi.py +95 -0
- kafka/net/sasl/msk.py +245 -0
- kafka/net/sasl/oauth.py +98 -0
- kafka/net/sasl/plain.py +42 -0
- kafka/net/sasl/scram.py +135 -0
- kafka/net/sasl/sspi.py +111 -0
- kafka/net/selector.py +644 -0
- kafka/net/socks5.py +262 -0
- kafka/net/transport.py +415 -0
- kafka/net/wakeup_notifier.py +72 -0
- kafka/partitioner/__init__.py +8 -0
- kafka/partitioner/abc.py +8 -0
- kafka/partitioner/default.py +89 -0
- kafka/partitioner/sticky.py +109 -0
- kafka/producer/__init__.py +5 -0
- kafka/producer/__main__.py +5 -0
- kafka/producer/future.py +101 -0
- kafka/producer/kafka.py +1123 -0
- kafka/producer/producer_batch.py +192 -0
- kafka/producer/record_accumulator.py +647 -0
- kafka/producer/sender.py +884 -0
- kafka/producer/transaction_manager.py +1326 -0
- kafka/protocol/__init__.py +0 -0
- kafka/protocol/admin/__init__.py +29 -0
- kafka/protocol/admin/acl.py +83 -0
- kafka/protocol/admin/acl.pyi +375 -0
- kafka/protocol/admin/client_quotas.py +14 -0
- kafka/protocol/admin/client_quotas.pyi +265 -0
- kafka/protocol/admin/cluster.py +31 -0
- kafka/protocol/admin/cluster.pyi +620 -0
- kafka/protocol/admin/configs.py +22 -0
- kafka/protocol/admin/configs.pyi +437 -0
- kafka/protocol/admin/groups.py +24 -0
- kafka/protocol/admin/groups.pyi +261 -0
- kafka/protocol/admin/topics.py +53 -0
- kafka/protocol/admin/topics.pyi +982 -0
- kafka/protocol/admin/transactions.py +18 -0
- kafka/protocol/admin/transactions.pyi +311 -0
- kafka/protocol/admin/users.py +14 -0
- kafka/protocol/admin/users.pyi +223 -0
- kafka/protocol/api_data.py +125 -0
- kafka/protocol/api_header.py +55 -0
- kafka/protocol/api_key.py +97 -0
- kafka/protocol/api_message.py +277 -0
- kafka/protocol/broker_version_data.py +246 -0
- kafka/protocol/consumer/__init__.py +13 -0
- kafka/protocol/consumer/fetch.py +16 -0
- kafka/protocol/consumer/fetch.pyi +298 -0
- kafka/protocol/consumer/group.py +38 -0
- kafka/protocol/consumer/group.pyi +824 -0
- kafka/protocol/consumer/metadata.py +30 -0
- kafka/protocol/consumer/metadata.pyi +89 -0
- kafka/protocol/consumer/offsets.py +75 -0
- kafka/protocol/consumer/offsets.pyi +288 -0
- kafka/protocol/data_container.py +166 -0
- kafka/protocol/frame.py +30 -0
- kafka/protocol/generate_stubs.py +468 -0
- kafka/protocol/metadata/__init__.py +10 -0
- kafka/protocol/metadata/api_versions.py +41 -0
- kafka/protocol/metadata/api_versions.pyi +128 -0
- kafka/protocol/metadata/find_coordinator.py +19 -0
- kafka/protocol/metadata/find_coordinator.pyi +105 -0
- kafka/protocol/metadata/metadata.py +34 -0
- kafka/protocol/metadata/metadata.pyi +160 -0
- kafka/protocol/old/__init__.py +0 -0
- kafka/protocol/old/abstract.py +17 -0
- kafka/protocol/old/add_offsets_to_txn.py +54 -0
- kafka/protocol/old/add_partitions_to_txn.py +71 -0
- kafka/protocol/old/admin.py +1086 -0
- kafka/protocol/old/api.py +205 -0
- kafka/protocol/old/api_versions.py +133 -0
- kafka/protocol/old/commit.py +355 -0
- kafka/protocol/old/consumer_protocol.py +36 -0
- kafka/protocol/old/end_txn.py +53 -0
- kafka/protocol/old/fetch.py +408 -0
- kafka/protocol/old/find_coordinator.py +72 -0
- kafka/protocol/old/group.py +451 -0
- kafka/protocol/old/init_producer_id.py +42 -0
- kafka/protocol/old/list_offsets.py +186 -0
- kafka/protocol/old/metadata.py +290 -0
- kafka/protocol/old/offset_for_leader_epoch.py +133 -0
- kafka/protocol/old/produce.py +247 -0
- kafka/protocol/old/sasl_authenticate.py +38 -0
- kafka/protocol/old/sasl_handshake.py +39 -0
- kafka/protocol/old/struct.py +87 -0
- kafka/protocol/old/txn_offset_commit.py +73 -0
- kafka/protocol/old/types.py +440 -0
- kafka/protocol/parser.py +191 -0
- kafka/protocol/producer/__init__.py +7 -0
- kafka/protocol/producer/produce.py +17 -0
- kafka/protocol/producer/produce.pyi +197 -0
- kafka/protocol/producer/transaction.py +30 -0
- kafka/protocol/producer/transaction.pyi +663 -0
- kafka/protocol/sasl.py +52 -0
- kafka/protocol/sasl.pyi +126 -0
- kafka/protocol/schemas/__init__.py +7 -0
- kafka/protocol/schemas/fields/__init__.py +7 -0
- kafka/protocol/schemas/fields/array.py +127 -0
- kafka/protocol/schemas/fields/base.py +156 -0
- kafka/protocol/schemas/fields/codecs/__init__.py +12 -0
- kafka/protocol/schemas/fields/codecs/encode_buffer.py +82 -0
- kafka/protocol/schemas/fields/codecs/tagged_fields.py +109 -0
- kafka/protocol/schemas/fields/codecs/types.py +505 -0
- kafka/protocol/schemas/fields/codegen.py +40 -0
- kafka/protocol/schemas/fields/simple.py +127 -0
- kafka/protocol/schemas/fields/struct.py +357 -0
- kafka/protocol/schemas/fields/struct_array.py +142 -0
- kafka/protocol/schemas/load_json.py +42 -0
- kafka/protocol/schemas/resources/AddOffsetsToTxnRequest.json +40 -0
- kafka/protocol/schemas/resources/AddOffsetsToTxnResponse.json +35 -0
- kafka/protocol/schemas/resources/AddPartitionsToTxnRequest.json +65 -0
- kafka/protocol/schemas/resources/AddPartitionsToTxnResponse.json +60 -0
- kafka/protocol/schemas/resources/AlterClientQuotasRequest.json +47 -0
- kafka/protocol/schemas/resources/AlterClientQuotasResponse.json +41 -0
- kafka/protocol/schemas/resources/AlterConfigsRequest.json +43 -0
- kafka/protocol/schemas/resources/AlterConfigsResponse.json +39 -0
- kafka/protocol/schemas/resources/AlterPartitionReassignmentsRequest.json +42 -0
- kafka/protocol/schemas/resources/AlterPartitionReassignmentsResponse.json +47 -0
- kafka/protocol/schemas/resources/AlterReplicaLogDirsRequest.json +41 -0
- kafka/protocol/schemas/resources/AlterReplicaLogDirsResponse.json +41 -0
- kafka/protocol/schemas/resources/AlterUserScramCredentialsRequest.json +45 -0
- kafka/protocol/schemas/resources/AlterUserScramCredentialsResponse.json +35 -0
- kafka/protocol/schemas/resources/ApiVersionsRequest.json +34 -0
- kafka/protocol/schemas/resources/ApiVersionsResponse.json +79 -0
- kafka/protocol/schemas/resources/ConsumerProtocolAssignment.json +42 -0
- kafka/protocol/schemas/resources/ConsumerProtocolSubscription.json +49 -0
- kafka/protocol/schemas/resources/CreateAclsRequest.json +46 -0
- kafka/protocol/schemas/resources/CreateAclsResponse.json +37 -0
- kafka/protocol/schemas/resources/CreatePartitionsRequest.json +47 -0
- kafka/protocol/schemas/resources/CreatePartitionsResponse.json +41 -0
- kafka/protocol/schemas/resources/CreateTopicsRequest.json +65 -0
- kafka/protocol/schemas/resources/CreateTopicsResponse.json +72 -0
- kafka/protocol/schemas/resources/DeleteAclsRequest.json +46 -0
- kafka/protocol/schemas/resources/DeleteAclsResponse.json +59 -0
- kafka/protocol/schemas/resources/DeleteGroupsRequest.json +30 -0
- kafka/protocol/schemas/resources/DeleteGroupsResponse.json +36 -0
- kafka/protocol/schemas/resources/DeleteRecordsRequest.json +42 -0
- kafka/protocol/schemas/resources/DeleteRecordsResponse.json +43 -0
- kafka/protocol/schemas/resources/DeleteTopicsRequest.json +43 -0
- kafka/protocol/schemas/resources/DeleteTopicsResponse.json +52 -0
- kafka/protocol/schemas/resources/DescribeAclsRequest.json +43 -0
- kafka/protocol/schemas/resources/DescribeAclsResponse.json +55 -0
- kafka/protocol/schemas/resources/DescribeClientQuotasRequest.json +37 -0
- kafka/protocol/schemas/resources/DescribeClientQuotasResponse.json +47 -0
- kafka/protocol/schemas/resources/DescribeClusterRequest.json +35 -0
- kafka/protocol/schemas/resources/DescribeClusterResponse.json +56 -0
- kafka/protocol/schemas/resources/DescribeConfigsRequest.json +42 -0
- kafka/protocol/schemas/resources/DescribeConfigsResponse.json +69 -0
- kafka/protocol/schemas/resources/DescribeGroupsRequest.json +38 -0
- kafka/protocol/schemas/resources/DescribeGroupsResponse.json +74 -0
- kafka/protocol/schemas/resources/DescribeLogDirsRequest.json +38 -0
- kafka/protocol/schemas/resources/DescribeLogDirsResponse.json +65 -0
- kafka/protocol/schemas/resources/DescribeProducersRequest.json +32 -0
- kafka/protocol/schemas/resources/DescribeProducersResponse.json +55 -0
- kafka/protocol/schemas/resources/DescribeQuorumRequest.json +39 -0
- kafka/protocol/schemas/resources/DescribeQuorumResponse.json +82 -0
- kafka/protocol/schemas/resources/DescribeTopicPartitionsRequest.json +40 -0
- kafka/protocol/schemas/resources/DescribeTopicPartitionsResponse.json +66 -0
- kafka/protocol/schemas/resources/DescribeTransactionsRequest.json +27 -0
- kafka/protocol/schemas/resources/DescribeTransactionsResponse.json +52 -0
- kafka/protocol/schemas/resources/DescribeUserScramCredentialsRequest.json +30 -0
- kafka/protocol/schemas/resources/DescribeUserScramCredentialsResponse.json +45 -0
- kafka/protocol/schemas/resources/ElectLeadersRequest.json +41 -0
- kafka/protocol/schemas/resources/ElectLeadersResponse.json +45 -0
- kafka/protocol/schemas/resources/EndTxnRequest.json +43 -0
- kafka/protocol/schemas/resources/EndTxnResponse.json +41 -0
- kafka/protocol/schemas/resources/FetchRequest.json +125 -0
- kafka/protocol/schemas/resources/FetchResponse.json +124 -0
- kafka/protocol/schemas/resources/FindCoordinatorRequest.json +43 -0
- kafka/protocol/schemas/resources/FindCoordinatorResponse.json +58 -0
- kafka/protocol/schemas/resources/HeartbeatRequest.json +39 -0
- kafka/protocol/schemas/resources/HeartbeatResponse.json +35 -0
- kafka/protocol/schemas/resources/IncrementalAlterConfigsRequest.json +44 -0
- kafka/protocol/schemas/resources/IncrementalAlterConfigsResponse.json +38 -0
- kafka/protocol/schemas/resources/InitProducerIdRequest.json +50 -0
- kafka/protocol/schemas/resources/InitProducerIdResponse.json +47 -0
- kafka/protocol/schemas/resources/JoinGroupRequest.json +63 -0
- kafka/protocol/schemas/resources/JoinGroupResponse.json +69 -0
- kafka/protocol/schemas/resources/LeaveGroupRequest.json +47 -0
- kafka/protocol/schemas/resources/LeaveGroupResponse.json +47 -0
- kafka/protocol/schemas/resources/ListConfigResourcesRequest.json +31 -0
- kafka/protocol/schemas/resources/ListConfigResourcesResponse.json +37 -0
- kafka/protocol/schemas/resources/ListGroupsRequest.json +36 -0
- kafka/protocol/schemas/resources/ListGroupsResponse.json +49 -0
- kafka/protocol/schemas/resources/ListOffsetsRequest.json +72 -0
- kafka/protocol/schemas/resources/ListOffsetsResponse.json +71 -0
- kafka/protocol/schemas/resources/ListPartitionReassignmentsRequest.json +34 -0
- kafka/protocol/schemas/resources/ListPartitionReassignmentsResponse.json +46 -0
- kafka/protocol/schemas/resources/ListTransactionsRequest.json +40 -0
- kafka/protocol/schemas/resources/ListTransactionsResponse.json +42 -0
- kafka/protocol/schemas/resources/MetadataRequest.json +56 -0
- kafka/protocol/schemas/resources/MetadataResponse.json +101 -0
- kafka/protocol/schemas/resources/OffsetCommitRequest.json +76 -0
- kafka/protocol/schemas/resources/OffsetCommitResponse.json +71 -0
- kafka/protocol/schemas/resources/OffsetDeleteRequest.json +39 -0
- kafka/protocol/schemas/resources/OffsetDeleteResponse.json +42 -0
- kafka/protocol/schemas/resources/OffsetFetchRequest.json +76 -0
- kafka/protocol/schemas/resources/OffsetFetchResponse.json +107 -0
- kafka/protocol/schemas/resources/OffsetForLeaderEpochRequest.json +52 -0
- kafka/protocol/schemas/resources/OffsetForLeaderEpochResponse.json +51 -0
- kafka/protocol/schemas/resources/ProduceRequest.json +73 -0
- kafka/protocol/schemas/resources/ProduceResponse.json +96 -0
- kafka/protocol/schemas/resources/RequestHeader.json +44 -0
- kafka/protocol/schemas/resources/ResponseHeader.json +26 -0
- kafka/protocol/schemas/resources/SaslAuthenticateRequest.json +29 -0
- kafka/protocol/schemas/resources/SaslAuthenticateResponse.json +34 -0
- kafka/protocol/schemas/resources/SaslHandshakeRequest.json +31 -0
- kafka/protocol/schemas/resources/SaslHandshakeResponse.json +32 -0
- kafka/protocol/schemas/resources/SyncGroupRequest.json +56 -0
- kafka/protocol/schemas/resources/SyncGroupResponse.json +46 -0
- kafka/protocol/schemas/resources/TxnOffsetCommitRequest.json +68 -0
- kafka/protocol/schemas/resources/TxnOffsetCommitResponse.json +47 -0
- kafka/protocol/schemas/resources/UpdateFeaturesRequest.json +43 -0
- kafka/protocol/schemas/resources/UpdateFeaturesResponse.json +39 -0
- kafka/protocol/schemas/resources/WriteTxnMarkersRequest.json +49 -0
- kafka/protocol/schemas/resources/WriteTxnMarkersResponse.json +45 -0
- kafka/protocol/schemas/resources/__init__.py +0 -0
- kafka/record/__init__.py +3 -0
- kafka/record/_crc32c.py +161 -0
- kafka/record/abc.py +144 -0
- kafka/record/default_records.py +782 -0
- kafka/record/legacy_records.py +587 -0
- kafka/record/memory_records.py +255 -0
- kafka/record/util.py +135 -0
- kafka/serializer/__init__.py +4 -0
- kafka/serializer/abstract.py +20 -0
- kafka/serializer/default.py +16 -0
- kafka/serializer/json.py +17 -0
- kafka/serializer/wrapper.py +21 -0
- kafka/structs.py +69 -0
- kafka/util.py +159 -0
- kafka/vendor/__init__.py +0 -0
- kafka/version.py +1 -0
- kafka_python-3.0.0.dist-info/METADATA +319 -0
- kafka_python-3.0.0.dist-info/RECORD +373 -0
- kafka_python-3.0.0.dist-info/WHEEL +5 -0
- kafka_python-3.0.0.dist-info/entry_points.txt +2 -0
- kafka_python-3.0.0.dist-info/licenses/LICENSE +202 -0
- kafka_python-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from .api_data import JsonSchemaData
|
|
2
|
+
from .data_container import DataContainer, SlotsBuilder
|
|
3
|
+
from .schemas import BaseField, StructField, load_json
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ApiHeader(DataContainer, metaclass=JsonSchemaData, init=False):
|
|
7
|
+
__slots__ = ()
|
|
8
|
+
|
|
9
|
+
def __init_subclass__(cls, **kw):
|
|
10
|
+
super().__init_subclass__(**kw)
|
|
11
|
+
if kw.get('init', True):
|
|
12
|
+
# pylint: disable=E1101
|
|
13
|
+
assert cls._json['type'] == 'header'
|
|
14
|
+
cls._flexible_versions = BaseField.parse_versions(cls._json['flexibleVersions'])
|
|
15
|
+
cls._valid_versions = BaseField.parse_versions(cls._json['validVersions'])
|
|
16
|
+
|
|
17
|
+
def encode(self, flexible=False):
|
|
18
|
+
# Request versions are 1-2, Response versions are 0-1
|
|
19
|
+
version = self._flexible_versions[0] if flexible else self._valid_versions[0] # pylint: disable=E1136
|
|
20
|
+
# compact=False is probably wrong,
|
|
21
|
+
# but it works to make sure that the client_id request header field
|
|
22
|
+
# is never encoded as compact (required to support ApiVersionsRequest for unsupported version)
|
|
23
|
+
return super().encode(version=version, compact=False, tagged=flexible)
|
|
24
|
+
|
|
25
|
+
def encode_into(self, out, flexible=False):
|
|
26
|
+
version = self._flexible_versions[0] if flexible else self._valid_versions[0] # pylint: disable=E1136
|
|
27
|
+
super().encode_into(out, version=version, compact=False, tagged=flexible)
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def decode(cls, data, flexible=False):
|
|
31
|
+
# Request versions are 1-2, Response versions are 0-1
|
|
32
|
+
version = cls._flexible_versions[0] if flexible else cls._valid_versions[0] # pylint: disable=E1136
|
|
33
|
+
return cls._struct.decode(data, version=version, compact=False, tagged=flexible, data_class=cls)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ResponseClassRegistry:
|
|
37
|
+
_response_class_registry = {}
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def register_response_class(cls, response_class):
|
|
41
|
+
cls._response_class_registry[response_class.API_KEY] = response_class
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def get_response_class(cls, request_header):
|
|
45
|
+
response_class = cls._response_class_registry.get(request_header.request_api_key)
|
|
46
|
+
if response_class is not None:
|
|
47
|
+
return response_class[request_header.request_api_version]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class RequestHeader(ApiHeader):
|
|
51
|
+
def get_response_class(self):
|
|
52
|
+
return ResponseClassRegistry.get_response_class(self)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ResponseHeader(ApiHeader): pass
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from enum import IntEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ApiKey(IntEnum):
|
|
5
|
+
Produce = 0
|
|
6
|
+
Fetch = 1
|
|
7
|
+
ListOffsets = 2
|
|
8
|
+
Metadata = 3
|
|
9
|
+
LeaderAndIsr = 4
|
|
10
|
+
StopReplica = 5
|
|
11
|
+
UpdateMetadata = 6
|
|
12
|
+
ControlledShutdown = 7
|
|
13
|
+
OffsetCommit = 8
|
|
14
|
+
OffsetFetch = 9
|
|
15
|
+
FindCoordinator = 10
|
|
16
|
+
JoinGroup = 11
|
|
17
|
+
Heartbeat = 12
|
|
18
|
+
LeaveGroup = 13
|
|
19
|
+
SyncGroup = 14
|
|
20
|
+
DescribeGroups = 15
|
|
21
|
+
ListGroups = 16
|
|
22
|
+
SaslHandshake = 17
|
|
23
|
+
ApiVersions = 18
|
|
24
|
+
CreateTopics = 19
|
|
25
|
+
DeleteTopics = 20
|
|
26
|
+
DeleteRecords = 21
|
|
27
|
+
InitProducerId = 22
|
|
28
|
+
OffsetForLeaderEpoch = 23
|
|
29
|
+
AddPartitionsToTxn = 24
|
|
30
|
+
AddOffsetsToTxn = 25
|
|
31
|
+
EndTxn = 26
|
|
32
|
+
WriteTxnMarkers = 27
|
|
33
|
+
TxnOffsetCommit = 28
|
|
34
|
+
DescribeAcls = 29
|
|
35
|
+
CreateAcls = 30
|
|
36
|
+
DeleteAcls = 31
|
|
37
|
+
DescribeConfigs = 32
|
|
38
|
+
AlterConfigs = 33
|
|
39
|
+
AlterReplicaLogDirs = 34
|
|
40
|
+
DescribeLogDirs = 35
|
|
41
|
+
SaslAuthenticate = 36
|
|
42
|
+
CreatePartitions = 37
|
|
43
|
+
CreateDelegationToken = 38
|
|
44
|
+
RenewDelegationToken = 39
|
|
45
|
+
ExpireDelegationToken = 40
|
|
46
|
+
DescribeDelegationToken = 41
|
|
47
|
+
DeleteGroups = 42
|
|
48
|
+
ElectLeaders = 43
|
|
49
|
+
IncrementalAlterConfigs = 44
|
|
50
|
+
AlterPartitionReassignments = 45
|
|
51
|
+
ListPartitionReassignments = 46
|
|
52
|
+
OffsetDelete = 47
|
|
53
|
+
DescribeClientQuotas = 48
|
|
54
|
+
AlterClientQuotas = 49
|
|
55
|
+
DescribeUserScramCredentials = 50
|
|
56
|
+
AlterUserScramCredentials = 51
|
|
57
|
+
Vote = 52
|
|
58
|
+
BeginQuorumEpoch = 53
|
|
59
|
+
EndQuorumEpoch = 54
|
|
60
|
+
DescribeQuorum = 55
|
|
61
|
+
AlterPartition = 56
|
|
62
|
+
UpdateFeatures = 57
|
|
63
|
+
Envelope = 58
|
|
64
|
+
FetchSnapshot = 59
|
|
65
|
+
DescribeCluster = 60
|
|
66
|
+
DescribeProducers = 61
|
|
67
|
+
BrokerRegistration = 62
|
|
68
|
+
BrokerHeartbeat = 63
|
|
69
|
+
UnregisterBroker = 64
|
|
70
|
+
DescribeTransactions = 65
|
|
71
|
+
ListTransactions = 66
|
|
72
|
+
AllocateProducerIds = 67
|
|
73
|
+
ConsumerGroupHeartbeat = 68
|
|
74
|
+
ConsumerGroupDescribe = 69
|
|
75
|
+
ControllerRegistration = 70
|
|
76
|
+
GetTelemetrySubscriptions = 71
|
|
77
|
+
PushTelemetry = 72
|
|
78
|
+
AssignReplicasToDirs = 73
|
|
79
|
+
ListConfigResources = 74
|
|
80
|
+
DescribeTopicPartitions = 75
|
|
81
|
+
ShareGroupHeartbeat = 76
|
|
82
|
+
ShareGroupDescribe = 77
|
|
83
|
+
ShareFetch = 78
|
|
84
|
+
ShareAcknowledge = 79
|
|
85
|
+
AddRaftVoter = 80
|
|
86
|
+
RemoveRaftVoter = 81
|
|
87
|
+
UpdateRaftVoter = 82
|
|
88
|
+
InitializeShareGroupState = 83
|
|
89
|
+
ReadShareGroupState = 84
|
|
90
|
+
WriteShareGroupState = 85
|
|
91
|
+
DeleteShareGroupState = 86
|
|
92
|
+
ReadShareGroupStateSummary = 87
|
|
93
|
+
StreamsGroupHeartbeat = 88
|
|
94
|
+
StreamsGroupDescribe = 89
|
|
95
|
+
DescribeShareGroupOffsets = 90
|
|
96
|
+
AlterShareGroupOffsets = 91
|
|
97
|
+
DeleteShareGroupOffsets = 92
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import weakref
|
|
3
|
+
|
|
4
|
+
from .api_data import JsonSchemaData
|
|
5
|
+
from .api_header import RequestHeader, ResponseHeader, ResponseClassRegistry
|
|
6
|
+
from .data_container import DataContainer
|
|
7
|
+
from .schemas import BaseField, StructField, load_json
|
|
8
|
+
from .schemas.fields.codecs import Int32, EncodeBufferPool
|
|
9
|
+
from struct import pack_into
|
|
10
|
+
|
|
11
|
+
from kafka.util import classproperty
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class VersionSubscriptable(type):
|
|
15
|
+
def __init__(cls, name, bases, attrs, **kw):
|
|
16
|
+
super().__init__(name, bases, attrs, **kw)
|
|
17
|
+
if kw.get('init', True):
|
|
18
|
+
# The primary message class has _version = None
|
|
19
|
+
# and a _VERSIONS dict that provides access to version-specific wrappers
|
|
20
|
+
# We also include cls[None] -> primary class to "exit" a version class
|
|
21
|
+
if getattr(cls, '_class_version', None) is None:
|
|
22
|
+
cls._class_version = None
|
|
23
|
+
cls._VERSIONS = {}
|
|
24
|
+
|
|
25
|
+
def __getitem__(cls, version):
|
|
26
|
+
# Use [] lookups to move from primary class to "versioned" classes
|
|
27
|
+
# which are simple wrappers around the primary class but with a _version attr
|
|
28
|
+
if cls._class_version is not None:
|
|
29
|
+
primary_cls = cls.mro()[1]
|
|
30
|
+
if version is None:
|
|
31
|
+
return primary_cls
|
|
32
|
+
return primary_cls[version]
|
|
33
|
+
elif version is None:
|
|
34
|
+
return cls
|
|
35
|
+
if cls._valid_versions is not None:
|
|
36
|
+
if version < 0:
|
|
37
|
+
version += 1 + cls.max_version # support negative index, e.g., [-1]
|
|
38
|
+
if not cls.min_version <= version <= cls.max_version:
|
|
39
|
+
raise ValueError('Invalid version! min=%d, max=%d' % (cls.min_version, cls.max_version))
|
|
40
|
+
if version in cls._VERSIONS:
|
|
41
|
+
return cls._VERSIONS[version]
|
|
42
|
+
klass_name = cls.__name__ + '_v' + str(version)
|
|
43
|
+
cls._VERSIONS[version] = type(klass_name, tuple(cls.mro()), {'_class_version': version}, init=False)
|
|
44
|
+
return cls._VERSIONS[version]
|
|
45
|
+
|
|
46
|
+
def __len__(cls):
|
|
47
|
+
# Maintain compatibility
|
|
48
|
+
if cls._valid_versions is None:
|
|
49
|
+
raise RuntimeError('Unable to calculate __len__ for class without valid_versions')
|
|
50
|
+
elif cls._class_version is not None:
|
|
51
|
+
raise TypeError('len() only supported on primary message class (not versioned)')
|
|
52
|
+
return cls._valid_versions[1] + 1
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ApiMessageData(VersionSubscriptable, JsonSchemaData):
|
|
56
|
+
def __init__(cls, name, bases, attrs, **kw):
|
|
57
|
+
super().__init__(name, bases, attrs, **kw)
|
|
58
|
+
if kw.get('init', True):
|
|
59
|
+
# Ignore min valid version on request/response schemas
|
|
60
|
+
# We'll get the brokers supported versions via ApiVersionsRequest
|
|
61
|
+
if cls._struct._versions[0] > 0:
|
|
62
|
+
cls._struct._versions = (0, cls._struct._versions[1])
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ApiMessage(DataContainer, metaclass=ApiMessageData, init=False):
|
|
66
|
+
__slots__ = ('_header', '_min_version', '_max_version')
|
|
67
|
+
|
|
68
|
+
def __init_subclass__(cls, **kw):
|
|
69
|
+
super().__init_subclass__(**kw)
|
|
70
|
+
if kw.get('init', True):
|
|
71
|
+
# pylint: disable=E1101
|
|
72
|
+
assert cls._json is not None
|
|
73
|
+
assert cls._json['type'] in ('request', 'response')
|
|
74
|
+
cls._flexible_versions = BaseField.parse_versions(cls._json['flexibleVersions'])
|
|
75
|
+
cls._valid_versions = BaseField.parse_versions(cls._json['validVersions'])
|
|
76
|
+
if not cls.is_request():
|
|
77
|
+
ResponseClassRegistry.register_response_class(weakref.proxy(cls))
|
|
78
|
+
|
|
79
|
+
def __new__(cls, *args, **kwargs):
|
|
80
|
+
# Translate "versioned" classes back to primary w/ version= kwarg on construction
|
|
81
|
+
if cls._class_version is not None:
|
|
82
|
+
if kwargs.get('version', cls._class_version) != cls._class_version: # pylint: disable=E1101
|
|
83
|
+
raise ValueError("Version has already been set by class")
|
|
84
|
+
kwargs['version'] = cls._class_version
|
|
85
|
+
instance = super().__new__(cls[None])
|
|
86
|
+
instance.__init__(*args, **kwargs)
|
|
87
|
+
return instance
|
|
88
|
+
return super().__new__(cls)
|
|
89
|
+
|
|
90
|
+
def __init__(self, *args, **kwargs):
|
|
91
|
+
self._header = None
|
|
92
|
+
self._min_version = kwargs.pop('min_version', None)
|
|
93
|
+
self._max_version = kwargs.pop('max_version', None)
|
|
94
|
+
super().__init__(*args, **kwargs)
|
|
95
|
+
|
|
96
|
+
@classproperty
|
|
97
|
+
def name(cls): # pylint: disable=E0213
|
|
98
|
+
return cls._json['name'] # pylint: disable=E1101
|
|
99
|
+
|
|
100
|
+
@classproperty
|
|
101
|
+
def type(cls): # pylint: disable=E0213
|
|
102
|
+
return cls._json['type'] # pylint: disable=E1101
|
|
103
|
+
|
|
104
|
+
@classproperty
|
|
105
|
+
def API_KEY(cls): # pylint: disable=E0213
|
|
106
|
+
return cls._json['apiKey'] # pylint: disable=E1101
|
|
107
|
+
|
|
108
|
+
@classproperty
|
|
109
|
+
def json(cls): # pylint: disable=E0213
|
|
110
|
+
return cls._json # pylint: disable=E1101
|
|
111
|
+
|
|
112
|
+
@classproperty
|
|
113
|
+
def valid_versions(cls): # pylint: disable=E0213
|
|
114
|
+
return cls._valid_versions
|
|
115
|
+
|
|
116
|
+
@classproperty
|
|
117
|
+
def min_version(cls): # pylint: disable=E0213
|
|
118
|
+
return 0
|
|
119
|
+
|
|
120
|
+
@classproperty
|
|
121
|
+
def max_version(cls): # pylint: disable=E0213
|
|
122
|
+
if cls._valid_versions is not None:
|
|
123
|
+
return cls._valid_versions[1] # pylint: disable=E1136
|
|
124
|
+
return None
|
|
125
|
+
|
|
126
|
+
@classmethod
|
|
127
|
+
def flexible_version_q(cls, version):
|
|
128
|
+
if cls._flexible_versions is not None:
|
|
129
|
+
if cls._flexible_versions[0] <= version <= cls._flexible_versions[1]: # pylint: disable=E1136
|
|
130
|
+
return True
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
@classmethod
|
|
134
|
+
def is_request(cls):
|
|
135
|
+
return cls.type == 'request'
|
|
136
|
+
|
|
137
|
+
# allow override by api-specific classes (e.g., ProduceRequest)
|
|
138
|
+
def expect_response(self):
|
|
139
|
+
return True
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def API_VERSION(self):
|
|
143
|
+
return self._version if self._version is not None else self._class_version # pylint: disable=E1101
|
|
144
|
+
|
|
145
|
+
@API_VERSION.setter
|
|
146
|
+
def API_VERSION(self, version):
|
|
147
|
+
if not 0 <= version <= self.max_version:
|
|
148
|
+
raise ValueError('Invalid version %s (max version is %s).' % (version, self.max_version))
|
|
149
|
+
self._version = version
|
|
150
|
+
if self._header is not None:
|
|
151
|
+
self._header.request_api_version = version
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def header(self):
|
|
155
|
+
return self._header
|
|
156
|
+
|
|
157
|
+
@classproperty
|
|
158
|
+
def header_class(cls): # pylint: disable=E0213
|
|
159
|
+
if cls.type == 'response':
|
|
160
|
+
return ResponseHeader
|
|
161
|
+
elif cls.type == 'request':
|
|
162
|
+
return RequestHeader
|
|
163
|
+
elif cls.type is None:
|
|
164
|
+
return None
|
|
165
|
+
else:
|
|
166
|
+
raise ValueError('Expected request or response type: %s' % cls.type)
|
|
167
|
+
|
|
168
|
+
def with_header(self, correlation_id=0, client_id='kafka-python'):
|
|
169
|
+
if self.is_request():
|
|
170
|
+
kwargs = {
|
|
171
|
+
'request_api_key': self.API_KEY,
|
|
172
|
+
'request_api_version': self.API_VERSION,
|
|
173
|
+
'correlation_id': correlation_id,
|
|
174
|
+
'client_id': client_id,
|
|
175
|
+
}
|
|
176
|
+
else:
|
|
177
|
+
kwargs = {
|
|
178
|
+
'correlation_id': correlation_id,
|
|
179
|
+
}
|
|
180
|
+
self._header = self.header_class(**kwargs)
|
|
181
|
+
|
|
182
|
+
# allow override by api-specific classes (e.g., ApiVersionsResponse)
|
|
183
|
+
def encode_header(self, flexible=False):
|
|
184
|
+
return self._header.encode(flexible=flexible) # pylint: disable=E1120
|
|
185
|
+
|
|
186
|
+
def encode_header_into(self, out, flexible=False):
|
|
187
|
+
# Subclasses may override encode_header to change flexible flag
|
|
188
|
+
# (e.g., ApiVersionsResponse forces flexible=False).
|
|
189
|
+
# Fall back to bytes-based encode_header if not overridden at this level.
|
|
190
|
+
header_bytes = self.encode_header(flexible=flexible)
|
|
191
|
+
n = len(header_bytes)
|
|
192
|
+
out.buf[out.pos:out.pos+n] = header_bytes
|
|
193
|
+
out.pos += n
|
|
194
|
+
|
|
195
|
+
@classmethod
|
|
196
|
+
def parse_header(cls, data, version=None):
|
|
197
|
+
version = cls._class_version if version is None else version
|
|
198
|
+
if version is None:
|
|
199
|
+
raise ValueError('Version required to decode data')
|
|
200
|
+
elif not 0 <= version <= cls.max_version:
|
|
201
|
+
raise ValueError('Invalid version %s (max version is %s).' % (version, cls.max_version))
|
|
202
|
+
flexible = cls.flexible_version_q(version)
|
|
203
|
+
return cls.header_class.decode(data, flexible=flexible) # pylint: disable=E1101
|
|
204
|
+
|
|
205
|
+
@classmethod
|
|
206
|
+
def encode_into__optimized_context(cls, version=None):
|
|
207
|
+
if version is None:
|
|
208
|
+
version = cls._class_version
|
|
209
|
+
if version is None:
|
|
210
|
+
raise ValueError('Version required to encode data')
|
|
211
|
+
flexible = cls.flexible_version_q(version)
|
|
212
|
+
return cls._struct.encode_into__optimized_context(version, compact=flexible, tagged=flexible)
|
|
213
|
+
|
|
214
|
+
def encode(self, version=None, header=False, framed=False):
|
|
215
|
+
if version is not None:
|
|
216
|
+
self.API_VERSION = version
|
|
217
|
+
if self.API_VERSION is None:
|
|
218
|
+
raise ValueError('Version required to encode data')
|
|
219
|
+
if header and self._header is None:
|
|
220
|
+
raise ValueError('No header found')
|
|
221
|
+
|
|
222
|
+
flexible = self.flexible_version_q(self.API_VERSION)
|
|
223
|
+
with EncodeBufferPool.acquire() as out:
|
|
224
|
+
if framed:
|
|
225
|
+
out.pos += 4 # reserve space for frame size
|
|
226
|
+
if header:
|
|
227
|
+
self.encode_header_into(out, flexible=flexible)
|
|
228
|
+
fast_encode = self._struct.compiled_encode_into(self.API_VERSION, compact=flexible, tagged=flexible)
|
|
229
|
+
fast_encode(self, out)
|
|
230
|
+
if framed:
|
|
231
|
+
payload_size = out.pos - 4
|
|
232
|
+
pack_into('>i', out.buf, 0, payload_size)
|
|
233
|
+
return out.result()
|
|
234
|
+
|
|
235
|
+
@classmethod
|
|
236
|
+
def decode(cls, data, version=None, header=False, framed=False):
|
|
237
|
+
version = cls._class_version if version is None else version
|
|
238
|
+
if version is None:
|
|
239
|
+
raise ValueError('Version required to decode data')
|
|
240
|
+
elif not 0 <= version <= cls.max_version:
|
|
241
|
+
raise ValueError('Invalid version %s (max version is %s).' % (version, cls.max_version))
|
|
242
|
+
|
|
243
|
+
# Normalize input to memoryview
|
|
244
|
+
if isinstance(data, bytes):
|
|
245
|
+
data = memoryview(data)
|
|
246
|
+
elif not isinstance(data, memoryview):
|
|
247
|
+
if hasattr(data, 'read'):
|
|
248
|
+
data = memoryview(data.read())
|
|
249
|
+
else:
|
|
250
|
+
# else: assume buffer protocol compatible
|
|
251
|
+
data = memoryview(data)
|
|
252
|
+
pos = 0
|
|
253
|
+
|
|
254
|
+
if framed:
|
|
255
|
+
size, pos = Int32.decode_from(data, pos)
|
|
256
|
+
if header:
|
|
257
|
+
# Header decode uses BytesIO (variable-length fields)
|
|
258
|
+
hdr_data = io.BytesIO(bytes(data[pos:]))
|
|
259
|
+
hdr = cls.parse_header(hdr_data, version=version)
|
|
260
|
+
pos += hdr_data.tell()
|
|
261
|
+
else:
|
|
262
|
+
hdr = None
|
|
263
|
+
|
|
264
|
+
# Resolve versioned class to primary class (e.g., Response_v0 -> Response)
|
|
265
|
+
data_class = cls[None]
|
|
266
|
+
|
|
267
|
+
flexible = cls.flexible_version_q(version)
|
|
268
|
+
fast_decode = cls._struct.compiled_decode_from(version, compact=flexible, tagged=flexible, data_class=data_class)
|
|
269
|
+
ret, pos = fast_decode(data, pos)
|
|
270
|
+
if hdr is not None:
|
|
271
|
+
ret._header = hdr
|
|
272
|
+
return ret
|
|
273
|
+
|
|
274
|
+
def __eq__(self, other):
|
|
275
|
+
if self.version != other.version:
|
|
276
|
+
return False
|
|
277
|
+
return super().__eq__(other)
|