kafka-python 2.2.8__tar.gz → 2.2.10__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.
Files changed (168) hide show
  1. {kafka_python-2.2.8 → kafka_python-2.2.10}/CHANGES.md +14 -0
  2. {kafka_python-2.2.8 → kafka_python-2.2.10}/PKG-INFO +1 -1
  3. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/conn.py +1 -1
  4. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/consumer/fetcher.py +6 -1
  5. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/consumer/group.py +14 -14
  6. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/consumer.py +7 -1
  7. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/sasl/gssapi.py +12 -5
  8. kafka_python-2.2.10/kafka/version.py +1 -0
  9. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka_python.egg-info/PKG-INFO +1 -1
  10. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_conn.py +10 -0
  11. kafka_python-2.2.8/kafka/version.py +0 -1
  12. {kafka_python-2.2.8 → kafka_python-2.2.10}/AUTHORS.md +0 -0
  13. {kafka_python-2.2.8 → kafka_python-2.2.10}/LICENSE +0 -0
  14. {kafka_python-2.2.8 → kafka_python-2.2.10}/MANIFEST.in +0 -0
  15. {kafka_python-2.2.8 → kafka_python-2.2.10}/README.rst +0 -0
  16. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/__init__.py +0 -0
  17. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/admin/__init__.py +0 -0
  18. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/admin/acl_resource.py +0 -0
  19. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/admin/client.py +0 -0
  20. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/admin/config_resource.py +0 -0
  21. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/admin/new_partitions.py +0 -0
  22. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/admin/new_topic.py +0 -0
  23. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/benchmarks/__init__.py +0 -0
  24. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/benchmarks/consumer_performance.py +0 -0
  25. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/benchmarks/load_example.py +0 -0
  26. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/benchmarks/producer_performance.py +0 -0
  27. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/benchmarks/record_batch_compose.py +0 -0
  28. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/benchmarks/record_batch_read.py +0 -0
  29. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/benchmarks/varint_speed.py +0 -0
  30. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/client_async.py +0 -0
  31. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/cluster.py +0 -0
  32. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/codec.py +0 -0
  33. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/consumer/__init__.py +0 -0
  34. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/consumer/subscription_state.py +0 -0
  35. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/__init__.py +0 -0
  36. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/assignors/__init__.py +0 -0
  37. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/assignors/abstract.py +0 -0
  38. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/assignors/range.py +0 -0
  39. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/assignors/roundrobin.py +0 -0
  40. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/assignors/sticky/__init__.py +0 -0
  41. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/assignors/sticky/partition_movements.py +0 -0
  42. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/assignors/sticky/sorted_set.py +0 -0
  43. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/assignors/sticky/sticky_assignor.py +0 -0
  44. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/base.py +0 -0
  45. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/heartbeat.py +0 -0
  46. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/coordinator/protocol.py +0 -0
  47. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/errors.py +0 -0
  48. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/future.py +0 -0
  49. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/__init__.py +0 -0
  50. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/compound_stat.py +0 -0
  51. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/dict_reporter.py +0 -0
  52. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/kafka_metric.py +0 -0
  53. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/measurable.py +0 -0
  54. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/measurable_stat.py +0 -0
  55. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/metric_config.py +0 -0
  56. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/metric_name.py +0 -0
  57. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/metrics.py +0 -0
  58. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/metrics_reporter.py +0 -0
  59. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/quota.py +0 -0
  60. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stat.py +0 -0
  61. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/__init__.py +0 -0
  62. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/avg.py +0 -0
  63. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/count.py +0 -0
  64. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/histogram.py +0 -0
  65. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/max_stat.py +0 -0
  66. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/min_stat.py +0 -0
  67. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/percentile.py +0 -0
  68. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/percentiles.py +0 -0
  69. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/rate.py +0 -0
  70. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/sampled_stat.py +0 -0
  71. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/sensor.py +0 -0
  72. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/metrics/stats/total.py +0 -0
  73. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/partitioner/__init__.py +0 -0
  74. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/partitioner/default.py +0 -0
  75. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/producer/__init__.py +0 -0
  76. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/producer/future.py +0 -0
  77. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/producer/kafka.py +0 -0
  78. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/producer/record_accumulator.py +0 -0
  79. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/producer/sender.py +0 -0
  80. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/producer/transaction_manager.py +0 -0
  81. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/__init__.py +0 -0
  82. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/abstract.py +0 -0
  83. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/add_offsets_to_txn.py +0 -0
  84. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/add_partitions_to_txn.py +0 -0
  85. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/admin.py +0 -0
  86. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/api.py +0 -0
  87. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/api_versions.py +0 -0
  88. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/broker_api_versions.py +0 -0
  89. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/commit.py +0 -0
  90. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/end_txn.py +0 -0
  91. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/fetch.py +0 -0
  92. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/find_coordinator.py +0 -0
  93. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/frame.py +0 -0
  94. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/group.py +0 -0
  95. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/init_producer_id.py +0 -0
  96. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/list_offsets.py +0 -0
  97. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/message.py +0 -0
  98. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/metadata.py +0 -0
  99. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/offset_for_leader_epoch.py +0 -0
  100. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/parser.py +0 -0
  101. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/pickle.py +0 -0
  102. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/produce.py +0 -0
  103. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/sasl_authenticate.py +0 -0
  104. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/sasl_handshake.py +0 -0
  105. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/struct.py +0 -0
  106. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/txn_offset_commit.py +0 -0
  107. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/protocol/types.py +0 -0
  108. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/record/__init__.py +0 -0
  109. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/record/_crc32c.py +0 -0
  110. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/record/abc.py +0 -0
  111. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/record/default_records.py +0 -0
  112. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/record/legacy_records.py +0 -0
  113. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/record/memory_records.py +0 -0
  114. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/record/util.py +0 -0
  115. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/sasl/__init__.py +0 -0
  116. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/sasl/abc.py +0 -0
  117. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/sasl/msk.py +0 -0
  118. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/sasl/oauth.py +0 -0
  119. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/sasl/plain.py +0 -0
  120. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/sasl/scram.py +0 -0
  121. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/sasl/sspi.py +0 -0
  122. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/serializer/__init__.py +0 -0
  123. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/serializer/abstract.py +0 -0
  124. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/socks5_wrapper.py +0 -0
  125. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/structs.py +0 -0
  126. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/util.py +0 -0
  127. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/vendor/__init__.py +0 -0
  128. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/vendor/enum34.py +0 -0
  129. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/vendor/selectors34.py +0 -0
  130. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/vendor/six.py +0 -0
  131. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka/vendor/socketpair.py +0 -0
  132. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka_python.egg-info/SOURCES.txt +0 -0
  133. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka_python.egg-info/dependency_links.txt +0 -0
  134. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka_python.egg-info/requires.txt +0 -0
  135. {kafka_python-2.2.8 → kafka_python-2.2.10}/kafka_python.egg-info/top_level.txt +0 -0
  136. {kafka_python-2.2.8 → kafka_python-2.2.10}/pyproject.toml +0 -0
  137. {kafka_python-2.2.8 → kafka_python-2.2.10}/setup.cfg +0 -0
  138. {kafka_python-2.2.8 → kafka_python-2.2.10}/setup.py +0 -0
  139. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/integration/__init__.py +0 -0
  140. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/integration/conftest.py +0 -0
  141. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/integration/fixtures.py +0 -0
  142. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/integration/test_admin_integration.py +0 -0
  143. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/integration/test_consumer_group.py +0 -0
  144. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/integration/test_consumer_integration.py +0 -0
  145. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/integration/test_producer_integration.py +0 -0
  146. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/integration/test_sasl_integration.py +0 -0
  147. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_acl_comparisons.py +0 -0
  148. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_admin.py +0 -0
  149. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_api_object_implementation.py +0 -0
  150. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_assignors.py +0 -0
  151. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_client_async.py +0 -0
  152. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_cluster.py +0 -0
  153. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_codec.py +0 -0
  154. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_consumer.py +0 -0
  155. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_coordinator.py +0 -0
  156. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_fetcher.py +0 -0
  157. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_metrics.py +0 -0
  158. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_object_conversion.py +0 -0
  159. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_package.py +0 -0
  160. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_partition_movements.py +0 -0
  161. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_partitioner.py +0 -0
  162. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_producer.py +0 -0
  163. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_protocol.py +0 -0
  164. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_record_accumulator.py +0 -0
  165. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_sender.py +0 -0
  166. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_subscription_state.py +0 -0
  167. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/test_util.py +0 -0
  168. {kafka_python-2.2.8 → kafka_python-2.2.10}/test/testutil.py +0 -0
@@ -1,3 +1,17 @@
1
+ # 2.2.10 (May 22, 2025)
2
+
3
+ Fixes
4
+ * Set the current host in the SASL configs (#2633)
5
+ * Fix sasl gssapi plugin: do not rely on `client_ctx.complete` in `auth_bytes()` (#2631)
6
+
7
+ # 2.2.9 (May 21, 2025)
8
+
9
+ Fixes
10
+ * Do not reset fetch positions if offset commit fetch times out (#2629)
11
+
12
+ Logging / Error Messages
13
+ * More / updated debug logging for coordinator / consumer (#2630)
14
+
1
15
  # 2.2.8 (May 20, 2025)
2
16
 
3
17
  Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kafka-python
3
- Version: 2.2.8
3
+ Version: 2.2.10
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
@@ -313,7 +313,7 @@ class BrokerConnection(object):
313
313
 
314
314
  def _init_sasl_mechanism(self):
315
315
  if self.config['security_protocol'] in ('SASL_PLAINTEXT', 'SASL_SSL'):
316
- self._sasl_mechanism = get_sasl_mechanism(self.config['sasl_mechanism'])(**self.config)
316
+ self._sasl_mechanism = get_sasl_mechanism(self.config['sasl_mechanism'])(host=self.host, **self.config)
317
317
  else:
318
318
  self._sasl_mechanism = None
319
319
 
@@ -178,6 +178,9 @@ class Fetcher(six.Iterator):
178
178
  Arguments:
179
179
  partitions ([TopicPartition]): the partitions that need offsets reset
180
180
 
181
+ Returns:
182
+ bool: True if any partitions need reset; otherwise False (no reset pending)
183
+
181
184
  Raises:
182
185
  NoOffsetForPartitionError: if no offset reset strategy is defined
183
186
  KafkaTimeoutError if timeout_ms provided
@@ -189,7 +192,8 @@ class Fetcher(six.Iterator):
189
192
 
190
193
  partitions = self._subscriptions.partitions_needing_reset()
191
194
  if not partitions:
192
- return
195
+ return False
196
+ log.debug('Resetting offsets for %s', partitions)
193
197
 
194
198
  offset_resets = dict()
195
199
  for tp in partitions:
@@ -198,6 +202,7 @@ class Fetcher(six.Iterator):
198
202
  offset_resets[tp] = ts
199
203
 
200
204
  self._reset_offsets_async(offset_resets)
205
+ return True
201
206
 
202
207
  def offsets_by_times(self, timestamps, timeout_ms=None):
203
208
  """Fetch offset for each partition passed in ``timestamps`` map.
@@ -699,6 +699,7 @@ class KafkaConsumer(six.Iterator):
699
699
  dict: Map of topic to list of records (may be empty).
700
700
  """
701
701
  if not self._coordinator.poll(timeout_ms=timer.timeout_ms):
702
+ log.debug('poll: timeout during coordinator.poll(); returning early')
702
703
  return {}
703
704
 
704
705
  has_all_fetch_positions = self._update_fetch_positions(timeout_ms=timer.timeout_ms)
@@ -706,13 +707,13 @@ class KafkaConsumer(six.Iterator):
706
707
  # If data is available already, e.g. from a previous network client
707
708
  # poll() call to commit, then just return it immediately
708
709
  records, partial = self._fetcher.fetched_records(max_records, update_offsets=update_offsets)
709
- log.debug('Fetched records: %s, %s', records, partial)
710
+ log.debug('poll: fetched records: %s, %s', records, partial)
710
711
  # Before returning the fetched records, we can send off the
711
712
  # next round of fetches and avoid block waiting for their
712
713
  # responses to enable pipelining while the user is handling the
713
714
  # fetched records.
714
715
  if not partial:
715
- log.debug("Sending fetches")
716
+ log.debug("poll: Sending fetches")
716
717
  futures = self._fetcher.send_fetches()
717
718
  if len(futures):
718
719
  self._client.poll(timeout_ms=0)
@@ -724,12 +725,14 @@ class KafkaConsumer(six.Iterator):
724
725
  # since the offset lookup may be backing off after a failure
725
726
  poll_timeout_ms = min(timer.timeout_ms, self._coordinator.time_to_next_poll() * 1000)
726
727
  if not has_all_fetch_positions:
728
+ log.debug('poll: do not have all fetch positions...')
727
729
  poll_timeout_ms = min(poll_timeout_ms, self.config['retry_backoff_ms'])
728
730
 
729
731
  self._client.poll(timeout_ms=poll_timeout_ms)
730
732
  # after the long poll, we should check whether the group needs to rebalance
731
733
  # prior to returning data so that the group can stabilize faster
732
734
  if self._coordinator.need_rejoin():
735
+ log.debug('poll: coordinator needs rejoin; returning early')
733
736
  return {}
734
737
 
735
738
  records, _ = self._fetcher.fetched_records(max_records, update_offsets=update_offsets)
@@ -1124,7 +1127,7 @@ class KafkaConsumer(six.Iterator):
1124
1127
  partitions (List[TopicPartition]): The partitions that need
1125
1128
  updating fetch positions.
1126
1129
 
1127
- Returns True if fetch positions updated, False if timeout
1130
+ Returns True if fetch positions updated, False if timeout or async reset is pending
1128
1131
 
1129
1132
  Raises:
1130
1133
  NoOffsetForPartitionError: If no offset is stored for a given
@@ -1135,15 +1138,13 @@ class KafkaConsumer(six.Iterator):
1135
1138
 
1136
1139
  if (self.config['api_version'] >= (0, 8, 1) and
1137
1140
  self.config['group_id'] is not None):
1138
- try:
1139
- # If there are any partitions which do not have a valid position and are not
1140
- # awaiting reset, then we need to fetch committed offsets. We will only do a
1141
- # coordinator lookup if there are partitions which have missing positions, so
1142
- # a consumer with manually assigned partitions can avoid a coordinator dependence
1143
- # by always ensuring that assigned partitions have an initial position.
1144
- self._coordinator.refresh_committed_offsets_if_needed(timeout_ms=timeout_ms)
1145
- except KafkaTimeoutError:
1146
- pass
1141
+ # If there are any partitions which do not have a valid position and are not
1142
+ # awaiting reset, then we need to fetch committed offsets. We will only do a
1143
+ # coordinator lookup if there are partitions which have missing positions, so
1144
+ # a consumer with manually assigned partitions can avoid a coordinator dependence
1145
+ # by always ensuring that assigned partitions have an initial position.
1146
+ if not self._coordinator.refresh_committed_offsets_if_needed(timeout_ms=timeout_ms):
1147
+ return False
1147
1148
 
1148
1149
  # If there are partitions still needing a position and a reset policy is defined,
1149
1150
  # request reset using the default policy. If no reset strategy is defined and there
@@ -1152,8 +1153,7 @@ class KafkaConsumer(six.Iterator):
1152
1153
 
1153
1154
  # Finally send an asynchronous request to lookup and update the positions of any
1154
1155
  # partitions which are awaiting reset.
1155
- self._fetcher.reset_offsets_if_needed()
1156
- return False
1156
+ return not self._fetcher.reset_offsets_if_needed()
1157
1157
 
1158
1158
  def _message_generator_v2(self):
1159
1159
  timeout_ms = 1000 * max(0, self._consumer_timeout - time.time())
@@ -274,6 +274,7 @@ class ConsumerCoordinator(BaseCoordinator):
274
274
  try:
275
275
  self._invoke_completed_offset_commit_callbacks()
276
276
  if not self.ensure_coordinator_ready(timeout_ms=timer.timeout_ms):
277
+ log.debug('coordinator.poll: timeout in ensure_coordinator_ready; returning early')
277
278
  return False
278
279
 
279
280
  if self.config['api_version'] >= (0, 9) and self._subscription.partitions_auto_assigned():
@@ -293,9 +294,11 @@ class ConsumerCoordinator(BaseCoordinator):
293
294
  metadata_update = self._client.cluster.request_update()
294
295
  self._client.poll(future=metadata_update, timeout_ms=timer.timeout_ms)
295
296
  if not metadata_update.is_done:
297
+ log.debug('coordinator.poll: timeout updating metadata; returning early')
296
298
  return False
297
299
 
298
300
  if not self.ensure_active_group(timeout_ms=timer.timeout_ms):
301
+ log.debug('coordinator.poll: timeout in ensure_active_group; returning early')
299
302
  return False
300
303
 
301
304
  self.poll_heartbeat()
@@ -427,7 +430,8 @@ class ConsumerCoordinator(BaseCoordinator):
427
430
  future_key = frozenset(partitions)
428
431
  timer = Timer(timeout_ms)
429
432
  while True:
430
- self.ensure_coordinator_ready(timeout_ms=timer.timeout_ms)
433
+ if not self.ensure_coordinator_ready(timeout_ms=timer.timeout_ms):
434
+ timer.maybe_raise()
431
435
 
432
436
  # contact coordinator to fetch committed offsets
433
437
  if future_key in self._offset_fetch_futures:
@@ -722,6 +726,7 @@ class ConsumerCoordinator(BaseCoordinator):
722
726
  return future
723
727
 
724
728
  def _handle_offset_commit_response(self, offsets, future, send_time, response):
729
+ log.debug("Received OffsetCommitResponse: %s", response)
725
730
  # TODO look at adding request_latency_ms to response (like java kafka)
726
731
  if self._consumer_sensors:
727
732
  self._consumer_sensors.commit_latency.record((time.time() - send_time) * 1000)
@@ -848,6 +853,7 @@ class ConsumerCoordinator(BaseCoordinator):
848
853
  return future
849
854
 
850
855
  def _handle_offset_fetch_response(self, future, response):
856
+ log.debug("Received OffsetFetchResponse: %s", response)
851
857
  if response.API_VERSION >= 2 and response.error_code != Errors.NoError.errno:
852
858
  error_type = Errors.for_code(response.error_code)
853
859
  log.debug("Offset fetch failed: %s", error_type.__name__)
@@ -26,14 +26,15 @@ class SaslMechanismGSSAPI(SaslMechanism):
26
26
  raise ValueError('sasl_kerberos_service_name or sasl_kerberos_name required for GSSAPI sasl configuration')
27
27
  self._is_done = False
28
28
  self._is_authenticated = False
29
+ self.gssapi_name = None
29
30
  if config.get('sasl_kerberos_name', None) is not None:
30
31
  self.auth_id = str(config['sasl_kerberos_name'])
32
+ if isinstance(config['sasl_kerberos_name'], gssapi.Name):
33
+ self.gssapi_name = config['sasl_kerberos_name']
31
34
  else:
32
35
  kerberos_domain_name = config.get('sasl_kerberos_domain_name', '') or config.get('host', '')
33
36
  self.auth_id = config['sasl_kerberos_service_name'] + '@' + kerberos_domain_name
34
- if isinstance(config.get('sasl_kerberos_name', None), gssapi.Name):
35
- self.gssapi_name = config['sasl_kerberos_name']
36
- else:
37
+ if self.gssapi_name is None:
37
38
  self.gssapi_name = gssapi.Name(self.auth_id, name_type=gssapi.NameType.hostbased_service).canonicalize(gssapi.MechType.kerberos)
38
39
  self._client_ctx = gssapi.SecurityContext(name=self.gssapi_name, usage='initiate')
39
40
  self._next_token = self._client_ctx.step(None)
@@ -43,9 +44,8 @@ class SaslMechanismGSSAPI(SaslMechanism):
43
44
  # so mark is_done after the final auth_bytes are provided
44
45
  # in practice we'll still receive a response when using SaslAuthenticate
45
46
  # but not when using the prior unframed approach.
46
- if self._client_ctx.complete:
47
+ if self._is_authenticated:
47
48
  self._is_done = True
48
- self._is_authenticated = True
49
49
  return self._next_token or b''
50
50
 
51
51
  def receive(self, auth_bytes):
@@ -74,6 +74,13 @@ class SaslMechanismGSSAPI(SaslMechanism):
74
74
  ]
75
75
  # add authorization identity to the response, and GSS-wrap
76
76
  self._next_token = self._client_ctx.wrap(b''.join(message_parts), False).message
77
+ # We need to identify the last token in auth_bytes();
78
+ # we can't rely on client_ctx.complete because it becomes True after generating
79
+ # the second-to-last token (after calling .step(auth_bytes) for the final time)
80
+ # We could introduce an additional state variable (i.e., self._final_token),
81
+ # but instead we just set _is_authenticated. Since the plugin interface does
82
+ # not read is_authenticated() until after is_done() is True, this should be fine.
83
+ self._is_authenticated = True
77
84
 
78
85
  def is_done(self):
79
86
  return self._is_done
@@ -0,0 +1 @@
1
+ __version__ = '2.2.10'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kafka-python
3
- Version: 2.2.8
3
+ Version: 2.2.10
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
@@ -386,3 +386,13 @@ def test_maybe_throttle(conn):
386
386
 
387
387
  time.return_value = 3000
388
388
  assert not conn.throttled()
389
+
390
+
391
+ def test_host_in_sasl_config():
392
+ hostname = 'example.org'
393
+ port = 9092
394
+ for security_protocol in ('SASL_PLAINTEXT', 'SASL_SSL'):
395
+ with mock.patch("kafka.conn.get_sasl_mechanism") as get_sasl_mechanism:
396
+ BrokerConnection(hostname, port, socket.AF_UNSPEC, security_protocol=security_protocol)
397
+ call_config = get_sasl_mechanism.mock_calls[1].kwargs
398
+ assert call_config['host'] == hostname
@@ -1 +0,0 @@
1
- __version__ = '2.2.8'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes