adc-streaming 2.4.0__tar.gz → 2.6.0__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 (36) hide show
  1. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/.github/workflows/build.yml +1 -1
  2. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/PKG-INFO +30 -3
  3. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc/auth.py +6 -0
  4. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc/consumer.py +4 -5
  5. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc/producer.py +25 -10
  6. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc_streaming.egg-info/PKG-INFO +30 -3
  7. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc_streaming.egg-info/SOURCES.txt +0 -1
  8. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc_streaming.egg-info/requires.txt +1 -3
  9. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/setup.py +1 -3
  10. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/tests/test_auth.py +1 -1
  11. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/tests/test_kafka_integration.py +79 -12
  12. adc-streaming-2.4.0/adc/oidc.py +0 -27
  13. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/.gitignore +0 -0
  14. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/LICENSE +0 -0
  15. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/Makefile +0 -0
  16. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/README.md +0 -0
  17. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc/__init__.py +0 -0
  18. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc/errors.py +0 -0
  19. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc/io.py +0 -0
  20. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc/kafka.py +0 -0
  21. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc_streaming.egg-info/dependency_links.txt +0 -0
  22. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc_streaming.egg-info/not-zip-safe +0 -0
  23. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/adc_streaming.egg-info/top_level.txt +0 -0
  24. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/doc/Makefile +0 -0
  25. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/doc/_static/css/my_theme.css +0 -0
  26. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/doc/_templates/layout.html +0 -0
  27. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/doc/api/api.rst +0 -0
  28. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/doc/api/streaming.rst +0 -0
  29. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/doc/conf.py +0 -0
  30. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/doc/index.rst +0 -0
  31. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/doc/user/installation.rst +0 -0
  32. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/doc/user/quickstart.rst +0 -0
  33. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/pyproject.toml +0 -0
  34. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/recipe/meta.yaml +0 -0
  35. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/setup.cfg +0 -0
  36. {adc-streaming-2.4.0 → adc_streaming-2.6.0}/tests/test_kafka.py +0 -0
@@ -7,7 +7,7 @@ jobs:
7
7
  runs-on: ubuntu-latest
8
8
  strategy:
9
9
  matrix:
10
- python-version: [3.7, 3.8, 3.9]
10
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
11
11
 
12
12
  steps:
13
13
  - name: Check out the code
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: adc-streaming
3
- Version: 2.4.0
3
+ Version: 2.6.0
4
4
  Summary: Astronomy Data Commons streaming client libraries
5
5
  Home-page: https://github.com/astronomy-commons/adc-streaming
6
6
  Author: Astronomy Data Commons Team
@@ -12,8 +12,35 @@ Classifier: Development Status :: 3 - Alpha
12
12
  Classifier: Operating System :: POSIX :: Linux
13
13
  Classifier: Operating System :: MacOS :: MacOS X
14
14
  Description-Content-Type: text/markdown
15
- Provides-Extra: dev
16
15
  License-File: LICENSE
16
+ Requires-Dist: confluent-kafka>=2.11.0
17
+ Requires-Dist: dataclasses; python_version < "3.7"
18
+ Requires-Dist: importlib-metadata; python_version < "3.8"
19
+ Requires-Dist: tqdm
20
+ Requires-Dist: certifi>=2020.04.05.1
21
+ Requires-Dist: typing-extensions; python_version < "3.8"
22
+ Provides-Extra: dev
23
+ Requires-Dist: autopep8; extra == "dev"
24
+ Requires-Dist: docker; extra == "dev"
25
+ Requires-Dist: flake8; extra == "dev"
26
+ Requires-Dist: isort; extra == "dev"
27
+ Requires-Dist: pytest; extra == "dev"
28
+ Requires-Dist: pytest-timeout; extra == "dev"
29
+ Requires-Dist: pytest-integration; extra == "dev"
30
+ Requires-Dist: sphinx; extra == "dev"
31
+ Requires-Dist: sphinx_rtd_theme; extra == "dev"
32
+ Requires-Dist: twine; extra == "dev"
33
+ Dynamic: author
34
+ Dynamic: author-email
35
+ Dynamic: classifier
36
+ Dynamic: description
37
+ Dynamic: description-content-type
38
+ Dynamic: home-page
39
+ Dynamic: license
40
+ Dynamic: license-file
41
+ Dynamic: provides-extra
42
+ Dynamic: requires-dist
43
+ Dynamic: summary
17
44
 
18
45
  # Astronomy Data Commons Streaming Client Libraries
19
46
 
@@ -38,6 +38,8 @@ class SASLAuth(object):
38
38
  ssl_ca_location : `str`, optional
39
39
  If using SSL via a self-signed cert, a path/location
40
40
  to the certificate.
41
+ ssl_endpoint_identification_algorithm : `str`, optional
42
+ If using SSL, the algorithm used to verify that certificate is valid for the endpoint.
41
43
  token_endpoint : `str`, optional
42
44
  The OpenID Connect token endpoint URL.
43
45
  Required for OAUTHBEARER / OpenID Connect, otherwise ignored.
@@ -62,7 +64,11 @@ class SASLAuth(object):
62
64
  self._config = {
63
65
  "security.protocol": "SASL_SSL",
64
66
  "ssl.ca.location": ssl_cert,
67
+ "https.ca.location": ssl_cert,
65
68
  }
69
+ if "ssl_endpoint_identification_algorithm" in kwargs:
70
+ self._config["ssl.endpoint.identification.algorithm"] = \
71
+ kwargs["ssl_endpoint_identification_algorithm"]
66
72
  else:
67
73
  self._config = {"security.protocol": "SASL_PLAINTEXT"}
68
74
 
@@ -14,7 +14,6 @@ import confluent_kafka.admin # type: ignore
14
14
 
15
15
  from .auth import SASLAuth
16
16
  from .errors import ErrorCallback, log_client_errors
17
- from .oidc import set_oauth_cb
18
17
 
19
18
 
20
19
  class LogicalOffset(enum.IntEnum):
@@ -38,7 +37,8 @@ class Consumer:
38
37
  self.logger = logging.getLogger("adc-streaming.consumer")
39
38
  self.conf = conf
40
39
  self._consumer = confluent_kafka.Consumer(conf._to_confluent_kafka())
41
- # Workaround for https://github.com/confluentinc/librdkafka/issues/3753#issuecomment-1058272987.
40
+ # Workaround for
41
+ # https://github.com/confluentinc/librdkafka/issues/3753#issuecomment-1058272987.
42
42
  # FIXME: Remove once fixed upstream, or on removal of oauth_cb.
43
43
  self._consumer.poll(0)
44
44
  self._stop_event = threading.Event()
@@ -196,7 +196,7 @@ class Consumer:
196
196
  self.mark_done(m, asynchronous=True)
197
197
  yield m
198
198
  else:
199
- raise(confluent_kafka.KafkaException(err))
199
+ raise (confluent_kafka.KafkaException(err))
200
200
  finally:
201
201
  if autocommit:
202
202
  self._consumer.commit(asynchronous=True)
@@ -242,7 +242,7 @@ class Consumer:
242
242
  # Done with all partitions for the topic, remove it
243
243
  del active_partitions[m.topic()]
244
244
  else:
245
- raise(confluent_kafka.KafkaException(err))
245
+ raise (confluent_kafka.KafkaException(err))
246
246
  finally:
247
247
  if autocommit:
248
248
  self._consumer.commit(asynchronous=True)
@@ -359,5 +359,4 @@ class ConsumerConfig:
359
359
 
360
360
  if self.auth is not None:
361
361
  config.update(self.auth())
362
- set_oauth_cb(config)
363
362
  return config
@@ -14,7 +14,6 @@ import confluent_kafka # type: ignore
14
14
  from .auth import SASLAuth
15
15
  from .errors import (DeliveryCallback, ErrorCallback, log_client_errors,
16
16
  log_delivery_errors)
17
- from .oidc import set_oauth_cb
18
17
 
19
18
 
20
19
  class Producer:
@@ -27,7 +26,8 @@ class Producer:
27
26
  self.conf = conf
28
27
  self.logger.debug(f"connecting to producer with config {conf._to_confluent_kafka()}")
29
28
  self._producer = confluent_kafka.Producer(conf._to_confluent_kafka())
30
- # Workaround for https://github.com/confluentinc/librdkafka/issues/3753#issuecomment-1058272987.
29
+ # Workaround for
30
+ # https://github.com/confluentinc/librdkafka/issues/3753#issuecomment-1058272987.
31
31
  # FIXME: Remove once fixed upstream, or on removal of oauth_cb.
32
32
  self._producer.poll(0)
33
33
 
@@ -35,7 +35,8 @@ class Producer:
35
35
  msg: Union[bytes, 'Serializable'],
36
36
  headers: Optional[Union[dict, list]] = None,
37
37
  delivery_callback: Optional[DeliveryCallback] = log_delivery_errors,
38
- topic: Optional[str] = None) -> None:
38
+ topic: Optional[str] = None,
39
+ key: Optional[Union[str, bytes]] = None) -> None:
39
40
  if isinstance(msg, Serializable):
40
41
  msg = msg.serialize()
41
42
  if topic is None:
@@ -46,11 +47,26 @@ class Producer:
46
47
  "Either configure a topic when constructing the Producer, "
47
48
  "or specify the topic argument to write()")
48
49
  self.logger.debug("writing message to %s", topic)
50
+ produce_kwargs = {"headers": headers, "key": key}
49
51
  if delivery_callback is not None:
50
- self._producer.produce(topic, msg, headers=headers,
51
- on_delivery=delivery_callback)
52
- else:
53
- self._producer.produce(topic, msg, headers=headers)
52
+ produce_kwargs["on_delivery"] = delivery_callback
53
+ while True:
54
+ try:
55
+ self._producer.produce(topic, msg, **produce_kwargs)
56
+ break
57
+ except BufferError:
58
+ # It's hard to know what the size limit on the buffer is, so we will try to
59
+ # wait until the number of items in it decreases (or it is empty, in case all
60
+ # messages were successfully sent in the time it took to handle the error).
61
+ buffer_len = len(self._producer)
62
+ self.logger.debug(f"Blocking due to BufferError, buffer size: {buffer_len}")
63
+ while buffer_len > 0 and len(self._producer) == buffer_len:
64
+ self._producer.poll(0.01)
65
+
66
+ def queued_message_count(self):
67
+ """Get the number of messages waiting to be sent to the broker.
68
+ """
69
+ return len(self._producer)
54
70
 
55
71
  def flush(self, timeout: timedelta = timedelta(seconds=10)) -> int:
56
72
  """Attempt to flush enqueued messages. Return the number of messages still
@@ -64,9 +80,9 @@ class Producer:
64
80
  self.logger.debug("flushed all messages")
65
81
  return n
66
82
 
67
- def close(self) -> int:
83
+ def close(self, timeout: timedelta = timedelta(seconds=10)) -> int:
68
84
  self.logger.debug("shutting down producer")
69
- return self.flush()
85
+ return self.flush(timeout)
70
86
 
71
87
  def __enter__(self) -> 'Producer':
72
88
  return self
@@ -140,7 +156,6 @@ class ProducerConfig:
140
156
  config["error_cb"] = self.error_callback
141
157
  if self.auth is not None:
142
158
  config.update(self.auth())
143
- set_oauth_cb(config)
144
159
  return config
145
160
 
146
161
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: adc-streaming
3
- Version: 2.4.0
3
+ Version: 2.6.0
4
4
  Summary: Astronomy Data Commons streaming client libraries
5
5
  Home-page: https://github.com/astronomy-commons/adc-streaming
6
6
  Author: Astronomy Data Commons Team
@@ -12,8 +12,35 @@ Classifier: Development Status :: 3 - Alpha
12
12
  Classifier: Operating System :: POSIX :: Linux
13
13
  Classifier: Operating System :: MacOS :: MacOS X
14
14
  Description-Content-Type: text/markdown
15
- Provides-Extra: dev
16
15
  License-File: LICENSE
16
+ Requires-Dist: confluent-kafka>=2.11.0
17
+ Requires-Dist: dataclasses; python_version < "3.7"
18
+ Requires-Dist: importlib-metadata; python_version < "3.8"
19
+ Requires-Dist: tqdm
20
+ Requires-Dist: certifi>=2020.04.05.1
21
+ Requires-Dist: typing-extensions; python_version < "3.8"
22
+ Provides-Extra: dev
23
+ Requires-Dist: autopep8; extra == "dev"
24
+ Requires-Dist: docker; extra == "dev"
25
+ Requires-Dist: flake8; extra == "dev"
26
+ Requires-Dist: isort; extra == "dev"
27
+ Requires-Dist: pytest; extra == "dev"
28
+ Requires-Dist: pytest-timeout; extra == "dev"
29
+ Requires-Dist: pytest-integration; extra == "dev"
30
+ Requires-Dist: sphinx; extra == "dev"
31
+ Requires-Dist: sphinx_rtd_theme; extra == "dev"
32
+ Requires-Dist: twine; extra == "dev"
33
+ Dynamic: author
34
+ Dynamic: author-email
35
+ Dynamic: classifier
36
+ Dynamic: description
37
+ Dynamic: description-content-type
38
+ Dynamic: home-page
39
+ Dynamic: license
40
+ Dynamic: license-file
41
+ Dynamic: provides-extra
42
+ Dynamic: requires-dist
43
+ Dynamic: summary
17
44
 
18
45
  # Astronomy Data Commons Streaming Client Libraries
19
46
 
@@ -12,7 +12,6 @@ adc/consumer.py
12
12
  adc/errors.py
13
13
  adc/io.py
14
14
  adc/kafka.py
15
- adc/oidc.py
16
15
  adc/producer.py
17
16
  adc_streaming.egg-info/PKG-INFO
18
17
  adc_streaming.egg-info/SOURCES.txt
@@ -1,6 +1,4 @@
1
- authlib
2
- confluent-kafka!=2.1.0,!=2.1.1,>=1.6.1
3
- requests
1
+ confluent-kafka>=2.11.0
4
2
  tqdm
5
3
  certifi>=2020.04.05.1
6
4
 
@@ -3,11 +3,9 @@ from setuptools import setup
3
3
 
4
4
  # requirements
5
5
  install_requires = [
6
- "authlib", # FIXME: drop after next release of confluent-kafka with OIDC support
7
- "confluent-kafka >= 1.6.1, != 2.1.0, != 2.1.1",
6
+ "confluent-kafka >= 2.11.0",
8
7
  "dataclasses ; python_version < '3.7'",
9
8
  "importlib-metadata ; python_version < '3.8'",
10
- "requests", # FIXME: drop after next release of confluent-kafka with OIDC support
11
9
  "tqdm",
12
10
  "certifi>=2020.04.05.1",
13
11
  "typing-extensions ; python_version < '3.8'",
@@ -1,6 +1,6 @@
1
1
  import pytest
2
2
 
3
- from adc.auth import SASLAuth, SASLMethod
3
+ from adc.auth import SASLAuth
4
4
 
5
5
 
6
6
  @pytest.mark.parametrize('auth,expected_config', [
@@ -2,8 +2,8 @@ import logging
2
2
  import tempfile
3
3
  import time
4
4
  import unittest
5
- from datetime import datetime, timedelta, timezone
6
- from typing import List
5
+ from datetime import datetime, timedelta
6
+ from typing import List, Optional
7
7
 
8
8
  import docker
9
9
  import pytest
@@ -59,6 +59,69 @@ class KafkaIntegrationTestCase(unittest.TestCase):
59
59
  self.assertEqual(msg.topic(), topic)
60
60
  self.assertEqual(msg.value(), b"can you hear me?")
61
61
 
62
+ def test_message_with_key(self):
63
+ """Try writing a message into the Kafka broker, and try pulling the same
64
+ message back out.
65
+
66
+ """
67
+ topic = "test_message_with_key"
68
+ # Push one message in...
69
+ simple_write_msg(self.kafka, topic, "can you hear me?", key="test_msg")
70
+ # ... and pull it back out.
71
+ consumer = adc.consumer.Consumer(adc.consumer.ConsumerConfig(
72
+ broker_urls=[self.kafka.address],
73
+ group_id="test_consumer",
74
+ auth=self.kafka.auth,
75
+ ))
76
+ consumer.subscribe(topic)
77
+ stream = consumer.stream()
78
+
79
+ msg = next(stream)
80
+ if msg.error() is not None:
81
+ raise Exception(msg.error())
82
+
83
+ self.assertEqual(msg.topic(), topic)
84
+ self.assertEqual(msg.value(), b"can you hear me?")
85
+ self.assertEqual(msg.key(), b"test_msg")
86
+
87
+ def test_message_with_callback(self):
88
+ """Try writing a message into the Kafka broker, with a delivery callback.
89
+ """
90
+ topic = "test_message_with_callback"
91
+ callback_called = False
92
+ callback_error = False
93
+
94
+ def callback(err, msg):
95
+ nonlocal callback_called
96
+ nonlocal callback_error
97
+ callback_called = True
98
+ callback_error = err is not None
99
+
100
+ ap = adc.producer
101
+ with ap.Producer(ap.ProducerConfig(broker_urls=[self.kafka.address],
102
+ topic=topic, auth=self.kafka.auth)) as producer:
103
+ producer.write("message data", delivery_callback=callback)
104
+ producer.flush()
105
+ consumer = adc.consumer.Consumer(adc.consumer.ConsumerConfig(
106
+ broker_urls=[self.kafka.address],
107
+ group_id="test_consumer",
108
+ auth=self.kafka.auth,
109
+ ))
110
+ consumer.subscribe(topic)
111
+ stream = consumer.stream()
112
+
113
+ msg = next(stream)
114
+ if msg.error() is not None:
115
+ raise Exception(msg.error())
116
+ # give the producer's background thread time to notice the ack from the broker and
117
+ # fire the callback
118
+ producer._producer.poll(0.1)
119
+
120
+ self.assertEqual(msg.topic(), topic)
121
+ self.assertEqual(msg.value(), b"message data")
122
+ self.assertEqual(callback_called, True)
123
+ self.assertEqual(callback_error, False)
124
+
62
125
  def test_reset_to_end(self):
63
126
  # Write a few messages.
64
127
  topic = "test_reset_to_end"
@@ -283,7 +346,7 @@ class KafkaIntegrationTestCase(unittest.TestCase):
283
346
  "message 1",
284
347
  "message 2",
285
348
  "message 3",
286
- ])
349
+ ])
287
350
  # Wait a while, write, and wait some more
288
351
  time.sleep(2)
289
352
  client_middle_time = datetime.now()
@@ -390,8 +453,8 @@ class KafkaIntegrationTestCase(unittest.TestCase):
390
453
  topic=None,
391
454
  auth=self.kafka.auth,
392
455
  ))
393
- for i in range(0,8):
394
- producer.write(str(i), topic=topics[i%2])
456
+ for i in range(0, 8):
457
+ producer.write(str(i), topic=topics[i % 2])
395
458
  producer.flush()
396
459
  logger.info("messages sent")
397
460
 
@@ -403,12 +466,12 @@ class KafkaIntegrationTestCase(unittest.TestCase):
403
466
  ))
404
467
  consumer.subscribe(topics)
405
468
  stream = consumer.stream()
406
- total_messages = 0;
469
+ total_messages = 0
407
470
  for msg in stream:
408
471
  if msg.error() is not None:
409
472
  raise Exception(msg.error())
410
473
  idx = int(msg.value())
411
- self.assertEqual(msg.topic(), topics[idx%2])
474
+ self.assertEqual(msg.topic(), topics[idx % 2])
412
475
  total_messages += 1
413
476
  if total_messages == 8:
414
477
  break
@@ -451,13 +514,17 @@ class KafkaDockerConnection:
451
514
  self.auth = adc.auth.SASLAuth(
452
515
  user="test", password="test-pass",
453
516
  ssl_ca_location=self.certfile.name,
517
+ # disable endpoint verification because the docker service generates a certificate with
518
+ # a useless subject (the container ID) which can never match the hostname used to
519
+ # connect (typically 0.0.0.0)
520
+ ssl_endpoint_identification_algorithm="none",
454
521
  )
455
522
 
456
523
  def poll_for_kafka_broker_address(self, maxiter=20, sleep=timedelta(milliseconds=500)):
457
524
  """Block until the Docker daemon tells us the IP and Port of the Kafa broker.
458
525
 
459
526
  Returns the ip and port as a string in the form "ip:port."
460
- """
527
+ """
461
528
  i = 0
462
529
  while (not self.query_kafka_broker_address()) and i < maxiter:
463
530
  logger.info("polling to wait for container to acquire port...")
@@ -479,7 +546,7 @@ class KafkaDockerConnection:
479
546
  port = addrs[0]['HostPort']
480
547
  return f"{ip}:{port}"
481
548
 
482
- def poll_for_kafka_active(self, maxiter=20, sleep=timedelta(milliseconds=500)):
549
+ def poll_for_kafka_active(self, maxiter=40, sleep=timedelta(milliseconds=500)):
483
550
  """Block until Kafka's network listener is accepting connections."""
484
551
  i = 0
485
552
  while (not self.query_kafka_active()) and i < maxiter:
@@ -550,7 +617,7 @@ class KafkaDockerConnection:
550
617
  # these tests cannot run if there is already an instance of Kafka running on
551
618
  # the same host.
552
619
  ports={"9092/tcp": 9092},
553
- command=["/root/runServer","--advertisedListener","SASL_SSL://localhost:9092"],
620
+ command=["/root/runServer", "--advertisedListener", "SASL_SSL://localhost:9092"],
554
621
  )
555
622
 
556
623
  def get_or_create_docker_network(self):
@@ -565,13 +632,13 @@ class KafkaDockerConnection:
565
632
  return self.docker_client.networks.create(name="adc-integration-test")
566
633
 
567
634
 
568
- def simple_write_msg(conn: KafkaDockerConnection, topic: str, msg: str):
635
+ def simple_write_msg(conn: KafkaDockerConnection, topic: str, msg: str, key: Optional[str] = None):
569
636
  producer = adc.producer.Producer(adc.producer.ProducerConfig(
570
637
  broker_urls=[conn.address],
571
638
  topic=topic,
572
639
  auth=conn.auth,
573
640
  ))
574
- producer.write(msg)
641
+ producer.write(msg, key=key)
575
642
  producer.flush()
576
643
 
577
644
 
@@ -1,27 +0,0 @@
1
- def set_oauth_cb(config):
2
- """Implement client support for KIP-768 OpenID Connect.
3
-
4
- Apache Kafka 3.1.0 supports authentication using OpenID Client Credentials.
5
- Native support for Python is still incomplete due to this issue:
6
- https://github.com/confluentinc/librdkafka/issues/3751
7
-
8
- Meanwhile, this is a pure Python implementation of the refresh token
9
- callback.
10
- """
11
- if config.pop('sasl.oauthbearer.method', None) != 'oidc':
12
- return
13
-
14
- client_id = config.pop('sasl.oauthbearer.client.id')
15
- client_secret = config.pop('sasl.oauthbearer.client.secret')
16
- scope = config.pop('sasl.oauthbearer.scope', None)
17
- token_endpoint = config.pop('sasl.oauthbearer.token.endpoint.url')
18
-
19
- from authlib.integrations.requests_client import OAuth2Session
20
- session = OAuth2Session(client_id, client_secret, scope=scope)
21
-
22
- def oauth_cb(*_, **__):
23
- token = session.fetch_token(
24
- token_endpoint, grant_type='client_credentials')
25
- return token['access_token'], token['expires_at']
26
-
27
- config['oauth_cb'] = oauth_cb
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes