kafka-python 2.0.4__py2.py3-none-any.whl → 2.0.6__py2.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/admin/client.py +30 -18
- kafka/client_async.py +72 -53
- kafka/conn.py +2 -2
- kafka/consumer/fetcher.py +12 -2
- kafka/coordinator/base.py +4 -3
- kafka/coordinator/consumer.py +4 -1
- kafka/record/default_records.py +45 -2
- kafka/version.py +1 -1
- {kafka_python-2.0.4.dist-info → kafka_python-2.0.6.dist-info}/METADATA +2 -2
- {kafka_python-2.0.4.dist-info → kafka_python-2.0.6.dist-info}/RECORD +12 -12
- {kafka_python-2.0.4.dist-info → kafka_python-2.0.6.dist-info}/WHEEL +1 -1
- {kafka_python-2.0.4.dist-info → kafka_python-2.0.6.dist-info}/top_level.txt +0 -0
kafka/admin/client.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
from __future__ import absolute_import
|
|
1
|
+
from __future__ import absolute_import, division
|
|
2
2
|
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
import copy
|
|
5
5
|
import logging
|
|
6
6
|
import socket
|
|
7
|
+
import time
|
|
7
8
|
|
|
8
9
|
from . import ConfigResourceType
|
|
9
10
|
from kafka.vendor import six
|
|
@@ -212,11 +213,13 @@ class KafkaAdminClient(object):
|
|
|
212
213
|
metric_group_prefix='admin',
|
|
213
214
|
**self.config
|
|
214
215
|
)
|
|
215
|
-
self._client.check_version(timeout=(self.config['api_version_auto_timeout_ms'] / 1000))
|
|
216
216
|
|
|
217
217
|
# Get auto-discovered version from client if necessary
|
|
218
218
|
if self.config['api_version'] is None:
|
|
219
219
|
self.config['api_version'] = self._client.config['api_version']
|
|
220
|
+
else:
|
|
221
|
+
# need to run check_version for get_api_versions()
|
|
222
|
+
self._client.check_version(timeout=(self.config['api_version_auto_timeout_ms'] / 1000))
|
|
220
223
|
|
|
221
224
|
self._closed = False
|
|
222
225
|
self._refresh_controller_id()
|
|
@@ -273,24 +276,33 @@ class KafkaAdminClient(object):
|
|
|
273
276
|
"""
|
|
274
277
|
return timeout_ms or self.config['request_timeout_ms']
|
|
275
278
|
|
|
276
|
-
def _refresh_controller_id(self):
|
|
279
|
+
def _refresh_controller_id(self, timeout_ms=30000):
|
|
277
280
|
"""Determine the Kafka cluster controller."""
|
|
278
281
|
version = self._matching_api_version(MetadataRequest)
|
|
279
282
|
if 1 <= version <= 6:
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
283
|
+
timeout_at = time.time() + timeout_ms / 1000
|
|
284
|
+
while time.time() < timeout_at:
|
|
285
|
+
request = MetadataRequest[version]()
|
|
286
|
+
future = self._send_request_to_node(self._client.least_loaded_node(), request)
|
|
287
|
+
|
|
288
|
+
self._wait_for_futures([future])
|
|
289
|
+
|
|
290
|
+
response = future.value
|
|
291
|
+
controller_id = response.controller_id
|
|
292
|
+
if controller_id == -1:
|
|
293
|
+
log.warning("Controller ID not available, got -1")
|
|
294
|
+
time.sleep(1)
|
|
295
|
+
continue
|
|
296
|
+
# verify the controller is new enough to support our requests
|
|
297
|
+
controller_version = self._client.check_version(node_id=controller_id)
|
|
298
|
+
if controller_version < (0, 10, 0):
|
|
299
|
+
raise IncompatibleBrokerVersion(
|
|
300
|
+
"The controller appears to be running Kafka {}. KafkaAdminClient requires brokers >= 0.10.0.0."
|
|
301
|
+
.format(controller_version))
|
|
302
|
+
self._controller_id = controller_id
|
|
303
|
+
return
|
|
304
|
+
else:
|
|
305
|
+
raise Errors.NodeNotAvailableError('controller')
|
|
294
306
|
else:
|
|
295
307
|
raise UnrecognizedBrokerVersion(
|
|
296
308
|
"Kafka Admin interface cannot determine the controller using MetadataRequest_v{}."
|
|
@@ -390,7 +402,7 @@ class KafkaAdminClient(object):
|
|
|
390
402
|
while not self._client.ready(node_id):
|
|
391
403
|
# poll until the connection to broker is ready, otherwise send()
|
|
392
404
|
# will fail with NodeNotReadyError
|
|
393
|
-
self._client.poll()
|
|
405
|
+
self._client.poll(timeout_ms=200)
|
|
394
406
|
return self._client.send(node_id, request, wakeup)
|
|
395
407
|
|
|
396
408
|
def _send_request_to_controller(self, request):
|
kafka/client_async.py
CHANGED
|
@@ -216,6 +216,8 @@ class KafkaClient(object):
|
|
|
216
216
|
self._connecting = set()
|
|
217
217
|
self._sending = set()
|
|
218
218
|
self._refresh_on_disconnects = True
|
|
219
|
+
|
|
220
|
+
# Not currently used, but data is collected internally
|
|
219
221
|
self._last_bootstrap = 0
|
|
220
222
|
self._bootstrap_fails = 0
|
|
221
223
|
|
|
@@ -233,12 +235,9 @@ class KafkaClient(object):
|
|
|
233
235
|
self.config['metric_group_prefix'],
|
|
234
236
|
weakref.proxy(self._conns))
|
|
235
237
|
|
|
236
|
-
self._num_bootstrap_hosts = len(collect_hosts(self.config['bootstrap_servers']))
|
|
237
|
-
|
|
238
238
|
# Check Broker Version if not set explicitly
|
|
239
239
|
if self.config['api_version'] is None:
|
|
240
|
-
|
|
241
|
-
self.config['api_version'] = self.check_version(timeout=check_timeout)
|
|
240
|
+
self.config['api_version'] = self.check_version()
|
|
242
241
|
|
|
243
242
|
def _init_wakeup_socketpair(self):
|
|
244
243
|
self._wake_r, self._wake_w = socket.socketpair()
|
|
@@ -259,20 +258,6 @@ class KafkaClient(object):
|
|
|
259
258
|
self._wake_r = None
|
|
260
259
|
self._wake_w = None
|
|
261
260
|
|
|
262
|
-
def _can_bootstrap(self):
|
|
263
|
-
effective_failures = self._bootstrap_fails // self._num_bootstrap_hosts
|
|
264
|
-
backoff_factor = 2 ** effective_failures
|
|
265
|
-
backoff_ms = min(self.config['reconnect_backoff_ms'] * backoff_factor,
|
|
266
|
-
self.config['reconnect_backoff_max_ms'])
|
|
267
|
-
|
|
268
|
-
backoff_ms *= random.uniform(0.8, 1.2)
|
|
269
|
-
|
|
270
|
-
next_at = self._last_bootstrap + backoff_ms / 1000.0
|
|
271
|
-
now = time.time()
|
|
272
|
-
if next_at > now:
|
|
273
|
-
return False
|
|
274
|
-
return True
|
|
275
|
-
|
|
276
261
|
def _can_connect(self, node_id):
|
|
277
262
|
if node_id not in self._conns:
|
|
278
263
|
if self.cluster.broker_metadata(node_id):
|
|
@@ -378,14 +363,24 @@ class KafkaClient(object):
|
|
|
378
363
|
|
|
379
364
|
return False
|
|
380
365
|
|
|
381
|
-
def
|
|
382
|
-
"""Idempotent non-blocking connection attempt to the given node id.
|
|
366
|
+
def _init_connect(self, node_id):
|
|
367
|
+
"""Idempotent non-blocking connection attempt to the given node id.
|
|
368
|
+
|
|
369
|
+
Returns True if connection object exists and is connected / connecting
|
|
370
|
+
"""
|
|
383
371
|
with self._lock:
|
|
384
372
|
conn = self._conns.get(node_id)
|
|
385
373
|
|
|
374
|
+
# Check if existing connection should be recreated because host/port changed
|
|
375
|
+
if conn is not None and self._should_recycle_connection(conn):
|
|
376
|
+
self._conns.pop(node_id).close()
|
|
377
|
+
conn = None
|
|
378
|
+
|
|
386
379
|
if conn is None:
|
|
387
380
|
broker = self.cluster.broker_metadata(node_id)
|
|
388
|
-
|
|
381
|
+
if broker is None:
|
|
382
|
+
log.debug('Broker id %s not in current metadata', node_id)
|
|
383
|
+
return False
|
|
389
384
|
|
|
390
385
|
log.debug("Initiating connection to node %s at %s:%s",
|
|
391
386
|
node_id, broker.host, broker.port)
|
|
@@ -397,16 +392,9 @@ class KafkaClient(object):
|
|
|
397
392
|
**self.config)
|
|
398
393
|
self._conns[node_id] = conn
|
|
399
394
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
return False
|
|
404
|
-
|
|
405
|
-
elif conn.connected():
|
|
406
|
-
return True
|
|
407
|
-
|
|
408
|
-
conn.connect()
|
|
409
|
-
return conn.connected()
|
|
395
|
+
if conn.disconnected():
|
|
396
|
+
conn.connect()
|
|
397
|
+
return not conn.disconnected()
|
|
410
398
|
|
|
411
399
|
def ready(self, node_id, metadata_priority=True):
|
|
412
400
|
"""Check whether a node is connected and ok to send more requests.
|
|
@@ -590,12 +578,18 @@ class KafkaClient(object):
|
|
|
590
578
|
if self._closed:
|
|
591
579
|
break
|
|
592
580
|
|
|
593
|
-
# Send a metadata request if needed (or initiate new connection)
|
|
594
|
-
metadata_timeout_ms = self._maybe_refresh_metadata()
|
|
595
|
-
|
|
596
581
|
# Attempt to complete pending connections
|
|
597
582
|
for node_id in list(self._connecting):
|
|
598
|
-
|
|
583
|
+
# False return means no more connection progress is possible
|
|
584
|
+
# Connected nodes will update _connecting via state_change callback
|
|
585
|
+
if not self._init_connect(node_id):
|
|
586
|
+
# It's possible that the connection attempt triggered a state change
|
|
587
|
+
# but if not, make sure to remove from _connecting list
|
|
588
|
+
if node_id in self._connecting:
|
|
589
|
+
self._connecting.remove(node_id)
|
|
590
|
+
|
|
591
|
+
# Send a metadata request if needed (or initiate new connection)
|
|
592
|
+
metadata_timeout_ms = self._maybe_refresh_metadata()
|
|
599
593
|
|
|
600
594
|
# If we got a future that is already done, don't block in _poll
|
|
601
595
|
if future is not None and future.is_done:
|
|
@@ -637,6 +631,11 @@ class KafkaClient(object):
|
|
|
637
631
|
self._selector.register(conn._sock, selectors.EVENT_WRITE, conn)
|
|
638
632
|
|
|
639
633
|
def _poll(self, timeout):
|
|
634
|
+
# Python throws OverflowError if timeout is > 2147483647 milliseconds
|
|
635
|
+
# (though the param to selector.select is in seconds)
|
|
636
|
+
# so convert any too-large timeout to blocking
|
|
637
|
+
if timeout > 2147483:
|
|
638
|
+
timeout = None
|
|
640
639
|
# This needs to be locked, but since it is only called from within the
|
|
641
640
|
# locked section of poll(), there is no additional lock acquisition here
|
|
642
641
|
processed = set()
|
|
@@ -857,6 +856,26 @@ class KafkaClient(object):
|
|
|
857
856
|
log.debug("Give up sending metadata request since no node is available. (reconnect delay %d ms)", next_connect_ms)
|
|
858
857
|
return next_connect_ms
|
|
859
858
|
|
|
859
|
+
if not self._can_send_request(node_id):
|
|
860
|
+
# If there's any connection establishment underway, wait until it completes. This prevents
|
|
861
|
+
# the client from unnecessarily connecting to additional nodes while a previous connection
|
|
862
|
+
# attempt has not been completed.
|
|
863
|
+
if self._connecting:
|
|
864
|
+
return float('inf')
|
|
865
|
+
|
|
866
|
+
elif self._can_connect(node_id):
|
|
867
|
+
log.debug("Initializing connection to node %s for metadata request", node_id)
|
|
868
|
+
self._connecting.add(node_id)
|
|
869
|
+
if not self._init_connect(node_id):
|
|
870
|
+
if node_id in self._connecting:
|
|
871
|
+
self._connecting.remove(node_id)
|
|
872
|
+
# Connection attempt failed immediately, need to retry with a different node
|
|
873
|
+
return self.config['reconnect_backoff_ms']
|
|
874
|
+
else:
|
|
875
|
+
# Existing connection with max in flight requests. Wait for request to complete.
|
|
876
|
+
return self.config['request_timeout_ms']
|
|
877
|
+
|
|
878
|
+
# Recheck node_id in case we were able to connect immediately above
|
|
860
879
|
if self._can_send_request(node_id):
|
|
861
880
|
topics = list(self._topics)
|
|
862
881
|
if not topics and self.cluster.is_bootstrap(node_id):
|
|
@@ -878,20 +897,11 @@ class KafkaClient(object):
|
|
|
878
897
|
future.add_errback(refresh_done)
|
|
879
898
|
return self.config['request_timeout_ms']
|
|
880
899
|
|
|
881
|
-
#
|
|
882
|
-
# the client from unnecessarily connecting to additional nodes while a previous connection
|
|
883
|
-
# attempt has not been completed.
|
|
900
|
+
# Should only get here if still connecting
|
|
884
901
|
if self._connecting:
|
|
885
902
|
return float('inf')
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
log.debug("Initializing connection to node %s for metadata request", node_id)
|
|
889
|
-
return float('inf')
|
|
890
|
-
|
|
891
|
-
# connected but can't send more, OR connecting
|
|
892
|
-
# In either case we just need to wait for a network event
|
|
893
|
-
# to let us know the selected connection might be usable again.
|
|
894
|
-
return float('inf')
|
|
903
|
+
else:
|
|
904
|
+
return self.config['reconnect_backoff_ms']
|
|
895
905
|
|
|
896
906
|
def get_api_versions(self):
|
|
897
907
|
"""Return the ApiVersions map, if available.
|
|
@@ -904,13 +914,16 @@ class KafkaClient(object):
|
|
|
904
914
|
"""
|
|
905
915
|
return self._api_versions
|
|
906
916
|
|
|
907
|
-
def check_version(self, node_id=None, timeout=
|
|
917
|
+
def check_version(self, node_id=None, timeout=None, strict=False):
|
|
908
918
|
"""Attempt to guess the version of a Kafka broker.
|
|
909
919
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
920
|
+
Keyword Arguments:
|
|
921
|
+
node_id (str, optional): Broker node id from cluster metadata. If None, attempts
|
|
922
|
+
to connect to any available broker until version is identified.
|
|
923
|
+
Default: None
|
|
924
|
+
timeout (num, optional): Maximum time in seconds to try to check broker version.
|
|
925
|
+
If unable to identify version before timeout, raise error (see below).
|
|
926
|
+
Default: api_version_auto_timeout_ms / 1000
|
|
914
927
|
|
|
915
928
|
Returns: version tuple, i.e. (0, 10), (0, 9), (0, 8, 2), ...
|
|
916
929
|
|
|
@@ -920,6 +933,7 @@ class KafkaClient(object):
|
|
|
920
933
|
UnrecognizedBrokerVersion: please file bug if seen!
|
|
921
934
|
AssertionError (if strict=True): please file bug if seen!
|
|
922
935
|
"""
|
|
936
|
+
timeout = timeout or (self.config['api_version_auto_timeout_ms'] / 1000)
|
|
923
937
|
self._lock.acquire()
|
|
924
938
|
end = time.time() + timeout
|
|
925
939
|
while time.time() < end:
|
|
@@ -930,7 +944,12 @@ class KafkaClient(object):
|
|
|
930
944
|
if try_node is None:
|
|
931
945
|
self._lock.release()
|
|
932
946
|
raise Errors.NoBrokersAvailable()
|
|
933
|
-
self.
|
|
947
|
+
if not self._init_connect(try_node):
|
|
948
|
+
if try_node == node_id:
|
|
949
|
+
raise Errors.NodeNotReadyError("Connection failed to %s" % node_id)
|
|
950
|
+
else:
|
|
951
|
+
continue
|
|
952
|
+
|
|
934
953
|
conn = self._conns[try_node]
|
|
935
954
|
|
|
936
955
|
# We will intentionally cause socket failures
|
kafka/conn.py
CHANGED
|
@@ -1315,8 +1315,8 @@ class BrokerConnection(object):
|
|
|
1315
1315
|
return version
|
|
1316
1316
|
|
|
1317
1317
|
def __str__(self):
|
|
1318
|
-
return "<BrokerConnection node_id=%s host=%s:%d %s [%s %s]>" % (
|
|
1319
|
-
self.node_id, self.host, self.port, self.state,
|
|
1318
|
+
return "<BrokerConnection client_id=%s, node_id=%s host=%s:%d %s [%s %s]>" % (
|
|
1319
|
+
self.config['client_id'], self.node_id, self.host, self.port, self.state,
|
|
1320
1320
|
AFI_NAMES[self._sock_afi], self._sock_addr)
|
|
1321
1321
|
|
|
1322
1322
|
|
kafka/consumer/fetcher.py
CHANGED
|
@@ -457,10 +457,20 @@ class Fetcher(six.Iterator):
|
|
|
457
457
|
batch = records.next_batch()
|
|
458
458
|
while batch is not None:
|
|
459
459
|
|
|
460
|
-
#
|
|
460
|
+
# Try DefaultsRecordBatch / message log format v2
|
|
461
|
+
# base_offset, last_offset_delta, and control batches
|
|
461
462
|
try:
|
|
462
463
|
self._subscriptions.assignment[tp].last_offset_from_message_batch = batch.base_offset + \
|
|
463
464
|
batch.last_offset_delta
|
|
465
|
+
# Control batches have a single record indicating whether a transaction
|
|
466
|
+
# was aborted or committed.
|
|
467
|
+
# When isolation_level is READ_COMMITTED (currently unsupported)
|
|
468
|
+
# we should also skip all messages from aborted transactions
|
|
469
|
+
# For now we only support READ_UNCOMMITTED and so we ignore the
|
|
470
|
+
# abort/commit signal.
|
|
471
|
+
if batch.is_control_batch:
|
|
472
|
+
batch = records.next_batch()
|
|
473
|
+
continue
|
|
464
474
|
except AttributeError:
|
|
465
475
|
pass
|
|
466
476
|
|
|
@@ -677,7 +687,7 @@ class Fetcher(six.Iterator):
|
|
|
677
687
|
if next_offset_from_batch_header > self._subscriptions.assignment[partition].position:
|
|
678
688
|
log.debug(
|
|
679
689
|
"Advance position for partition %s from %s to %s (last message batch location plus one)"
|
|
680
|
-
" to correct for deleted compacted messages",
|
|
690
|
+
" to correct for deleted compacted messages and/or transactional control records",
|
|
681
691
|
partition, self._subscriptions.assignment[partition].position, next_offset_from_batch_header)
|
|
682
692
|
self._subscriptions.assignment[partition].position = next_offset_from_batch_header
|
|
683
693
|
|
kafka/coordinator/base.py
CHANGED
|
@@ -371,7 +371,7 @@ class BaseCoordinator(object):
|
|
|
371
371
|
while not self.coordinator_unknown():
|
|
372
372
|
if not self._client.in_flight_request_count(self.coordinator_id):
|
|
373
373
|
break
|
|
374
|
-
self._client.poll()
|
|
374
|
+
self._client.poll(timeout_ms=200)
|
|
375
375
|
else:
|
|
376
376
|
continue
|
|
377
377
|
|
|
@@ -923,8 +923,6 @@ class HeartbeatThread(threading.Thread):
|
|
|
923
923
|
if self.closed:
|
|
924
924
|
return
|
|
925
925
|
self.closed = True
|
|
926
|
-
with self.coordinator._lock:
|
|
927
|
-
self.coordinator._lock.notify()
|
|
928
926
|
|
|
929
927
|
# Generally this should not happen - close() is triggered
|
|
930
928
|
# by the coordinator. But in some cases GC may close the coordinator
|
|
@@ -932,6 +930,9 @@ class HeartbeatThread(threading.Thread):
|
|
|
932
930
|
if threading.current_thread() == self:
|
|
933
931
|
return
|
|
934
932
|
|
|
933
|
+
with self.coordinator._lock:
|
|
934
|
+
self.coordinator._lock.notify()
|
|
935
|
+
|
|
935
936
|
if self.is_alive():
|
|
936
937
|
self.join(self.coordinator.config['heartbeat_interval_ms'] / 1000)
|
|
937
938
|
if self.is_alive():
|
kafka/coordinator/consumer.py
CHANGED
|
@@ -128,7 +128,10 @@ class ConsumerCoordinator(BaseCoordinator):
|
|
|
128
128
|
|
|
129
129
|
def __del__(self):
|
|
130
130
|
if hasattr(self, '_cluster') and self._cluster:
|
|
131
|
-
|
|
131
|
+
try:
|
|
132
|
+
self._cluster.remove_listener(WeakMethod(self._handle_metadata_update))
|
|
133
|
+
except TypeError:
|
|
134
|
+
pass
|
|
132
135
|
super(ConsumerCoordinator, self).__del__()
|
|
133
136
|
|
|
134
137
|
def protocol_type(self):
|
kafka/record/default_records.py
CHANGED
|
@@ -269,8 +269,12 @@ class DefaultRecordBatch(DefaultRecordBase, ABCRecordBatch):
|
|
|
269
269
|
"payload, but instead read {}".format(length, pos - start_pos))
|
|
270
270
|
self._pos = pos
|
|
271
271
|
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
if self.is_control_batch:
|
|
273
|
+
return ControlRecord(
|
|
274
|
+
offset, timestamp, self.timestamp_type, key, value, headers)
|
|
275
|
+
else:
|
|
276
|
+
return DefaultRecord(
|
|
277
|
+
offset, timestamp, self.timestamp_type, key, value, headers)
|
|
274
278
|
|
|
275
279
|
def __iter__(self):
|
|
276
280
|
self._maybe_uncompress()
|
|
@@ -362,6 +366,45 @@ class DefaultRecord(ABCRecord):
|
|
|
362
366
|
)
|
|
363
367
|
|
|
364
368
|
|
|
369
|
+
class ControlRecord(DefaultRecord):
|
|
370
|
+
__slots__ = ("_offset", "_timestamp", "_timestamp_type", "_key", "_value",
|
|
371
|
+
"_headers", "_version", "_type")
|
|
372
|
+
|
|
373
|
+
KEY_STRUCT = struct.Struct(
|
|
374
|
+
">h" # Current Version => Int16
|
|
375
|
+
"h" # Type => Int16 (0 indicates an abort marker, 1 indicates a commit)
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
def __init__(self, offset, timestamp, timestamp_type, key, value, headers):
|
|
379
|
+
super(ControlRecord, self).__init__(offset, timestamp, timestamp_type, key, value, headers)
|
|
380
|
+
(self._version, self._type) = self.KEY_STRUCT.unpack(self._key)
|
|
381
|
+
|
|
382
|
+
# see https://kafka.apache.org/documentation/#controlbatch
|
|
383
|
+
@property
|
|
384
|
+
def version(self):
|
|
385
|
+
return self._version
|
|
386
|
+
|
|
387
|
+
@property
|
|
388
|
+
def type(self):
|
|
389
|
+
return self._type
|
|
390
|
+
|
|
391
|
+
@property
|
|
392
|
+
def abort(self):
|
|
393
|
+
return self._type == 0
|
|
394
|
+
|
|
395
|
+
@property
|
|
396
|
+
def commit(self):
|
|
397
|
+
return self._type == 1
|
|
398
|
+
|
|
399
|
+
def __repr__(self):
|
|
400
|
+
return (
|
|
401
|
+
"ControlRecord(offset={!r}, timestamp={!r}, timestamp_type={!r},"
|
|
402
|
+
" version={!r}, type={!r} <{!s}>)".format(
|
|
403
|
+
self._offset, self._timestamp, self._timestamp_type,
|
|
404
|
+
self._version, self._type, "abort" if self.abort else "commit")
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
|
|
365
408
|
class DefaultRecordBatchBuilder(DefaultRecordBase, ABCRecordBatchBuilder):
|
|
366
409
|
|
|
367
410
|
# excluding key, value and headers:
|
kafka/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '2.0.
|
|
1
|
+
__version__ = '2.0.6'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: kafka-python
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.6
|
|
4
4
|
Summary: Pure Python client for Apache Kafka
|
|
5
5
|
Author-email: Dana Powers <dana.powers@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/dpkp/kafka-python
|
|
@@ -41,7 +41,7 @@ Requires-Dist: pytest-mock; extra == "testing"
|
|
|
41
41
|
Kafka Python client
|
|
42
42
|
------------------------
|
|
43
43
|
|
|
44
|
-
.. image:: https://img.shields.io/badge/kafka-
|
|
44
|
+
.. image:: https://img.shields.io/badge/kafka-3.9--0.8-brightgreen.svg
|
|
45
45
|
:target: https://kafka-python.readthedocs.io/en/master/compatibility.html
|
|
46
46
|
.. image:: https://img.shields.io/pypi/pyversions/kafka-python.svg
|
|
47
47
|
:target: https://pypi.python.org/pypi/kafka-python
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
kafka/__init__.py,sha256=4dvHKZAxmD_4tfJ5wGcRV2X78vPcm8vsUoqceULevjA,1077
|
|
2
|
-
kafka/client_async.py,sha256=
|
|
2
|
+
kafka/client_async.py,sha256=EpHEsKE9xYBNqY5VnKmGXXidEzzqN5jeXp9B-zGT0nQ,48391
|
|
3
3
|
kafka/cluster.py,sha256=LBSJGPO7wr1RQkMyTtAzVxPa5GCFl57u28-Q7oQ9Ieo,14841
|
|
4
4
|
kafka/codec.py,sha256=8NZpnehzNrhSBIjzbPVSvyFbSeLAqEntE7BfVHu-_9I,10036
|
|
5
|
-
kafka/conn.py,sha256=
|
|
5
|
+
kafka/conn.py,sha256=NciLcgGZpku8I1PtsUSShLmywRY8HE8a7YLBTaMht-U,69172
|
|
6
6
|
kafka/errors.py,sha256=yFzMajEiin_dwdlG7lQAOFKCSh80aIbsWBIiudp7k2I,34522
|
|
7
7
|
kafka/future.py,sha256=uJJLfKMFsdEHgHSyvCzQe_AXNrToiZE-MynZVNhk9qc,2474
|
|
8
8
|
kafka/scram.py,sha256=Ei9FPJ3ajfTQRRGaDs1RjDKTpplkoPQKvk-u6Dkbh_U,3034
|
|
9
9
|
kafka/structs.py,sha256=m2o20GOJBDJIiP7YUj1Lhk2bAXKLt9H48NloBJ39Om8,2927
|
|
10
10
|
kafka/util.py,sha256=nu0h9bXBv6Hl8v7MW07o8NFe4zoZNw6C6ehFBPazOpU,1856
|
|
11
|
-
kafka/version.py,sha256=
|
|
11
|
+
kafka/version.py,sha256=_rdDXO0eF8Rb-UlqwwfOrLeR0p4mNliGj-gv5nXgbms,22
|
|
12
12
|
kafka/admin/__init__.py,sha256=S_XxqyyV480_yXhttK79XZqNAmZyXRjspd3SoqYykE8,720
|
|
13
13
|
kafka/admin/acl_resource.py,sha256=ak_dUsSni4SyP0ORbSKenZpwTy0Ykxq3FSt_9XgLR8k,8265
|
|
14
|
-
kafka/admin/client.py,sha256=
|
|
14
|
+
kafka/admin/client.py,sha256=evnVHZspGWDOSxcggjexIczY_oMaXg5p_JSqpT3I-K0,71608
|
|
15
15
|
kafka/admin/config_resource.py,sha256=_JZWN_Q7jbuTtq2kdfHxWyTt_jI1LI-xnVGsf6oYGyY,1039
|
|
16
16
|
kafka/admin/new_partitions.py,sha256=rYSb7S6VL706ZauSmiN5J9GDsep0HYRmkkAZUgT2JIg,757
|
|
17
17
|
kafka/admin/new_topic.py,sha256=fvezLP9JXumqX-nU27Fgo0tj4d85ybcJgKluQImm3-0,1306
|
|
18
18
|
kafka/consumer/__init__.py,sha256=NDdvtyuJgFyQZahqL9i5sYXGP6rOMIXWwHQEaZ1fCcs,122
|
|
19
|
-
kafka/consumer/fetcher.py,sha256=
|
|
19
|
+
kafka/consumer/fetcher.py,sha256=Z7E4-1YQZwGTn1JnMuwgafqAl8nXWGYrQWhGo9GyIEw,48610
|
|
20
20
|
kafka/consumer/group.py,sha256=-q-TmdVlROumiHxJij960MA5qgBK9SuzjIv6AiyFCCw,58942
|
|
21
21
|
kafka/consumer/subscription_state.py,sha256=2SgH37QISlIZh-v0KnNJW0n1d_sMLOxxW7UxkhsC5R0,21665
|
|
22
22
|
kafka/coordinator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
-
kafka/coordinator/base.py,sha256=
|
|
24
|
-
kafka/coordinator/consumer.py,sha256=
|
|
23
|
+
kafka/coordinator/base.py,sha256=MIs_LDxQnJkFSITCgvMpu5sfUEdAp_5YNlwtJmsiHu8,46772
|
|
24
|
+
kafka/coordinator/consumer.py,sha256=IH6XGkR9AcFr-uAQdZLNOVSIFDqhL-sYlqlkFJtp0nc,38992
|
|
25
25
|
kafka/coordinator/heartbeat.py,sha256=WJqZGnXHG7TTq1Is3D0mKDis-bBwWVZlSgQiUoZv1jU,2304
|
|
26
26
|
kafka/coordinator/protocol.py,sha256=wTaIOnUVbj0CKXZ82FktZo-zMRvOCk3hdQAoHJ62e3I,1041
|
|
27
27
|
kafka/coordinator/assignors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -85,7 +85,7 @@ kafka/protocol/types.py,sha256=f-lwfCqsJulYnBT1loek_KbMnZZqItN4YRIONjg3kbE,10244
|
|
|
85
85
|
kafka/record/__init__.py,sha256=Q20hP_R5XX3AEnAlPkpoWzTLShESvxUT2OLXmI-JYEQ,129
|
|
86
86
|
kafka/record/_crc32c.py,sha256=Ok-P62Yvg6D6rMGM9Z56OMjZWQlnps4xBbakg-sdxvI,5761
|
|
87
87
|
kafka/record/abc.py,sha256=14m5X2BfXo1XUhEZh04gZXixhgC7ktGMzBzYsTnzaZY,3465
|
|
88
|
-
kafka/record/default_records.py,sha256=
|
|
88
|
+
kafka/record/default_records.py,sha256=aLvF8n7FrJ52wcamc6WFJV2-RqixzpUittHqtg7P6zk,22431
|
|
89
89
|
kafka/record/legacy_records.py,sha256=uFRdGC8W4NTFpiQyV5TZSaEwjw5AEbbm5G2W-pxvnkA,17820
|
|
90
90
|
kafka/record/memory_records.py,sha256=VjUsbLtIU0y5HM9eYlUjjpCFMwTej67uhrIL5CgtYq8,6344
|
|
91
91
|
kafka/record/util.py,sha256=LDajBWdYVetmXts_t9Q76CxEx7njgC9LnjMgz9yPEMM,3556
|
|
@@ -96,7 +96,7 @@ kafka/vendor/enum34.py,sha256=-u-lxAiJMt6ru4Do7NUDY9OpeWkYJMksb2xengJawFE,31204
|
|
|
96
96
|
kafka/vendor/selectors34.py,sha256=gxejLO4eXf8mRSGXaQiknPig3GdX1rtsZiYOQJVuAy8,20594
|
|
97
97
|
kafka/vendor/six.py,sha256=lLBa9_HrANP5BMZ7twEzg1M3wofwPmXyptuWmHX0brY,34826
|
|
98
98
|
kafka/vendor/socketpair.py,sha256=Fi3PoY1Okkppab720wFk1BhHXyjcw7hi5DwhqrYZH2Y,2737
|
|
99
|
-
kafka_python-2.0.
|
|
100
|
-
kafka_python-2.0.
|
|
101
|
-
kafka_python-2.0.
|
|
102
|
-
kafka_python-2.0.
|
|
99
|
+
kafka_python-2.0.6.dist-info/METADATA,sha256=eQALnAAZrmZeHVUoRQVAFofgOn-y2Cpu0GbPgceydts,8998
|
|
100
|
+
kafka_python-2.0.6.dist-info/WHEEL,sha256=rF4EZyR2XVS6irmOHQIJx2SUqXLZKRMUrjsg8UwN-XQ,109
|
|
101
|
+
kafka_python-2.0.6.dist-info/top_level.txt,sha256=IivJz7l5WHdLNDT6RIiVAlhjQzYRwGqBBmKHZ7WjPeM,6
|
|
102
|
+
kafka_python-2.0.6.dist-info/RECORD,,
|
|
File without changes
|