kafka-python 2.0.4__tar.gz → 2.0.5__tar.gz
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_python-2.0.4 → kafka_python-2.0.5}/CHANGES.md +26 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/PKG-INFO +2 -2
- {kafka_python-2.0.4 → kafka_python-2.0.5}/README.rst +1 -1
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/admin/client.py +30 -18
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/client_async.py +2 -16
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/conn.py +2 -2
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/base.py +4 -3
- kafka_python-2.0.5/kafka/version.py +1 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka_python.egg-info/PKG-INFO +2 -2
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_admin_integration.py +6 -3
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_consumer_integration.py +1 -1
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_sasl_integration.py +13 -7
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/testutil.py +2 -2
- kafka_python-2.0.4/kafka/version.py +0 -1
- {kafka_python-2.0.4 → kafka_python-2.0.5}/AUTHORS.md +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/LICENSE +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/MANIFEST.in +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/admin/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/admin/acl_resource.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/admin/config_resource.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/admin/new_partitions.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/admin/new_topic.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/cluster.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/codec.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/consumer/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/consumer/fetcher.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/consumer/group.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/consumer/subscription_state.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/assignors/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/assignors/abstract.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/assignors/range.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/assignors/roundrobin.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/assignors/sticky/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/assignors/sticky/partition_movements.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/assignors/sticky/sorted_set.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/assignors/sticky/sticky_assignor.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/consumer.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/heartbeat.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/protocol.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/errors.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/future.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/compound_stat.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/dict_reporter.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/kafka_metric.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/measurable.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/measurable_stat.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/metric_config.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/metric_name.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/metrics.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/metrics_reporter.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/quota.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stat.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/avg.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/count.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/histogram.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/max_stat.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/min_stat.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/percentile.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/percentiles.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/rate.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/sampled_stat.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/sensor.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/metrics/stats/total.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/oauth/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/oauth/abstract.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/partitioner/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/partitioner/default.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/producer/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/producer/buffer.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/producer/future.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/producer/kafka.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/producer/record_accumulator.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/producer/sender.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/abstract.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/admin.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/api.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/commit.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/fetch.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/frame.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/group.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/message.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/metadata.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/offset.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/parser.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/pickle.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/produce.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/struct.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/protocol/types.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/record/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/record/_crc32c.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/record/abc.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/record/default_records.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/record/legacy_records.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/record/memory_records.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/record/util.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/scram.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/serializer/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/serializer/abstract.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/structs.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/util.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/vendor/__init__.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/vendor/enum34.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/vendor/selectors34.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/vendor/six.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/vendor/socketpair.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka_python.egg-info/SOURCES.txt +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka_python.egg-info/dependency_links.txt +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka_python.egg-info/requires.txt +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/kafka_python.egg-info/top_level.txt +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/pyproject.toml +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/setup.cfg +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/setup.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_acl_comparisons.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_admin.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_api_object_implementation.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_assignors.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_client_async.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_cluster.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_codec.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_conn.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_consumer.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_consumer_group.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_coordinator.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_fetcher.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_metrics.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_object_conversion.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_package.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_partition_movements.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_partitioner.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_producer.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_protocol.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_sender.py +0 -0
- {kafka_python-2.0.4 → kafka_python-2.0.5}/test/test_subscription_state.py +0 -0
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
# 2.0.5 (Feb 25, 2025)
|
|
2
|
+
|
|
3
|
+
Networking
|
|
4
|
+
* Remove unused client bootstrap backoff code
|
|
5
|
+
* 200ms timeout for client.poll in ensure_active_group and admin client
|
|
6
|
+
|
|
7
|
+
Fixes
|
|
8
|
+
* Admin client: check_version only if needed, use node_id kwarg for controller
|
|
9
|
+
* Check for -1 controller_id in admin client
|
|
10
|
+
* Only acquire coordinator lock in heartbeat thread close if not self thread
|
|
11
|
+
|
|
12
|
+
Testing
|
|
13
|
+
* Also sleep when waiting for consumers in test_describe_consumer_group_exists
|
|
14
|
+
* Refactor sasl_integration test_client - wait for node ready; use send future
|
|
15
|
+
* Add timeout to test_kafka_consumer
|
|
16
|
+
* Add error str to assert_message_count checks
|
|
17
|
+
* Retry on error in test fixture create_topic_via_metadata
|
|
18
|
+
* Fixup variable interpolation in test fixture error
|
|
19
|
+
|
|
20
|
+
Documentation
|
|
21
|
+
* Update compatibility docs
|
|
22
|
+
* Include client_id in BrokerConnection __str__ output
|
|
23
|
+
|
|
24
|
+
Project Maintenance
|
|
25
|
+
* Add make targets `servers/*/api_versions` and `servers/*/messages`
|
|
26
|
+
|
|
1
27
|
# 2.0.4 (Feb 21, 2025)
|
|
2
28
|
|
|
3
29
|
Networking
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: kafka-python
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
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,7 +1,7 @@
|
|
|
1
1
|
Kafka Python client
|
|
2
2
|
------------------------
|
|
3
3
|
|
|
4
|
-
.. image:: https://img.shields.io/badge/kafka-
|
|
4
|
+
.. image:: https://img.shields.io/badge/kafka-3.9--0.8-brightgreen.svg
|
|
5
5
|
:target: https://kafka-python.readthedocs.io/en/master/compatibility.html
|
|
6
6
|
.. image:: https://img.shields.io/pypi/pyversions/kafka-python.svg
|
|
7
7
|
:target: https://pypi.python.org/pypi/kafka-python
|
|
@@ -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, timeout=(self.config['api_version_auto_timeout_ms'] / 1000))
|
|
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):
|
|
@@ -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,8 +235,6 @@ 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
240
|
check_timeout = self.config['api_version_auto_timeout_ms'] / 1000
|
|
@@ -259,20 +259,6 @@ class KafkaClient(object):
|
|
|
259
259
|
self._wake_r = None
|
|
260
260
|
self._wake_w = None
|
|
261
261
|
|
|
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
262
|
def _can_connect(self, node_id):
|
|
277
263
|
if node_id not in self._conns:
|
|
278
264
|
if self.cluster.broker_metadata(node_id):
|
|
@@ -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
|
|
|
@@ -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():
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.0.5'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: kafka-python
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
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
|
|
@@ -168,7 +168,7 @@ def test_describe_consumer_group_exists(kafka_admin_client, kafka_consumer_facto
|
|
|
168
168
|
stop[i] = Event()
|
|
169
169
|
consumers[i] = kafka_consumer_factory(group_id=group_id)
|
|
170
170
|
while not stop[i].is_set():
|
|
171
|
-
consumers[i].poll(
|
|
171
|
+
consumers[i].poll(timeout_ms=200)
|
|
172
172
|
consumers[i].close()
|
|
173
173
|
consumers[i] = None
|
|
174
174
|
stop[i] = None
|
|
@@ -183,6 +183,7 @@ def test_describe_consumer_group_exists(kafka_admin_client, kafka_consumer_facto
|
|
|
183
183
|
try:
|
|
184
184
|
timeout = time() + 35
|
|
185
185
|
while True:
|
|
186
|
+
info('Checking consumers...')
|
|
186
187
|
for c in range(num_consumers):
|
|
187
188
|
|
|
188
189
|
# Verify all consumers have been created
|
|
@@ -212,9 +213,9 @@ def test_describe_consumer_group_exists(kafka_admin_client, kafka_consumer_facto
|
|
|
212
213
|
|
|
213
214
|
if not rejoining and is_same_generation:
|
|
214
215
|
break
|
|
215
|
-
else:
|
|
216
|
-
sleep(1)
|
|
217
216
|
assert time() < timeout, "timeout waiting for assignments"
|
|
217
|
+
info('sleeping...')
|
|
218
|
+
sleep(1)
|
|
218
219
|
|
|
219
220
|
info('Group stabilized; verifying assignment')
|
|
220
221
|
output = kafka_admin_client.describe_consumer_groups(group_id_list)
|
|
@@ -236,6 +237,8 @@ def test_describe_consumer_group_exists(kafka_admin_client, kafka_consumer_facto
|
|
|
236
237
|
for c in range(num_consumers):
|
|
237
238
|
info('Stopping consumer %s', c)
|
|
238
239
|
stop[c].set()
|
|
240
|
+
for c in range(num_consumers):
|
|
241
|
+
info('Waiting for consumer thread %s', c)
|
|
239
242
|
threads[c].join()
|
|
240
243
|
threads[c] = None
|
|
241
244
|
|
|
@@ -27,7 +27,7 @@ def test_kafka_version_infer(kafka_consumer_factory):
|
|
|
27
27
|
@pytest.mark.skipif(not env_kafka_version(), reason="No KAFKA_VERSION set")
|
|
28
28
|
def test_kafka_consumer(kafka_consumer_factory, send_messages):
|
|
29
29
|
"""Test KafkaConsumer"""
|
|
30
|
-
consumer = kafka_consumer_factory(auto_offset_reset='earliest')
|
|
30
|
+
consumer = kafka_consumer_factory(auto_offset_reset='earliest', consumer_timeout_ms=2000)
|
|
31
31
|
send_messages(range(0, 100), partition=0)
|
|
32
32
|
send_messages(range(0, 100), partition=1)
|
|
33
33
|
cnt = 0
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import uuid
|
|
3
|
+
import time
|
|
3
4
|
|
|
4
5
|
import pytest
|
|
5
6
|
|
|
@@ -69,12 +70,17 @@ def test_client(request, sasl_kafka):
|
|
|
69
70
|
|
|
70
71
|
client, = sasl_kafka.get_clients(1)
|
|
71
72
|
request = MetadataRequest_v1(None)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
timeout_at = time.time() + 1
|
|
74
|
+
while not client.is_ready(0):
|
|
75
|
+
client.maybe_connect(0)
|
|
76
|
+
client.poll(timeout_ms=100)
|
|
77
|
+
if time.time() > timeout_at:
|
|
78
|
+
raise RuntimeError("Couldn't connect to node 0")
|
|
79
|
+
future = client.send(0, request)
|
|
80
|
+
client.poll(future=future, timeout_ms=10000)
|
|
81
|
+
if not future.is_done:
|
|
78
82
|
raise RuntimeError("Couldn't fetch topic response from Broker.")
|
|
79
|
-
|
|
83
|
+
elif future.failed():
|
|
84
|
+
raise future.exception
|
|
85
|
+
result = future.value
|
|
80
86
|
assert topic_name in [t[1] for t in result.topics]
|
|
@@ -28,12 +28,12 @@ def env_kafka_version():
|
|
|
28
28
|
def assert_message_count(messages, num_messages):
|
|
29
29
|
"""Check that we received the expected number of messages with no duplicates."""
|
|
30
30
|
# Make sure we got them all
|
|
31
|
-
assert len(messages) == num_messages
|
|
31
|
+
assert len(messages) == num_messages, 'Expected %d messages, got %d' % (num_messages, len(messages))
|
|
32
32
|
# Make sure there are no duplicates
|
|
33
33
|
# Note: Currently duplicates are identified only using key/value. Other attributes like topic, partition, headers,
|
|
34
34
|
# timestamp, etc are ignored... this could be changed if necessary, but will be more tolerant of dupes.
|
|
35
35
|
unique_messages = {(m.key, m.value) for m in messages}
|
|
36
|
-
assert len(unique_messages) == num_messages
|
|
36
|
+
assert len(unique_messages) == num_messages, 'Expected %d unique messages, got %d' % (num_messages, len(unique_messages))
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
class Timer(object):
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '2.0.4'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/assignors/sticky/partition_movements.py
RENAMED
|
File without changes
|
|
File without changes
|
{kafka_python-2.0.4 → kafka_python-2.0.5}/kafka/coordinator/assignors/sticky/sticky_assignor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|