Skip to content

Commit 6cbbab9

Browse files
authored
Merge pull request confluentinc#160 from rolando-contrib/custom-schema-registry
ENH Allow to pass custom schema registry instance.
2 parents 421bf9e + 9208a18 commit 6cbbab9

File tree

4 files changed

+64
-23
lines changed

4 files changed

+64
-23
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ In order to run full test suite, simply execute:
183183

184184
**Run integration tests:**
185185

186-
To run the integration tests, uncomment the following line from `tox.ini` and add the paths to your Kafka and Confluent Schema Registry instances. If no Schema Registry path is provided then no AVRO tests will by run. You can also run the integration tests outside of `tox` by running this command from the source root.
186+
To run the integration tests, uncomment the following line from `tox.ini` and add the paths to your Kafka and Confluent Schema Registry instances. You can also run the integration tests outside of `tox` by running this command from the source root.
187187

188188
examples/integration_test.py <kafka-broker> [<test-topic>] [<schema-registry>]
189189

confluent_kafka/avro/__init__.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,17 @@ class AvroProducer(Producer):
7272
"""
7373

7474
def __init__(self, config, default_key_schema=None,
75-
default_value_schema=None):
76-
if ('schema.registry.url' not in config.keys()):
77-
raise ValueError("Missing parameter: schema.registry.url")
78-
schem_registry_url = config["schema.registry.url"]
79-
del config["schema.registry.url"]
75+
default_value_schema=None, schema_registry=None):
76+
schema_registry_url = config.pop("schema.registry.url", None)
77+
if schema_registry is None:
78+
if schema_registry_url is None:
79+
raise ValueError("Missing parameter: schema.registry.url")
80+
schema_registry = CachedSchemaRegistryClient(url=schema_registry_url)
81+
elif schema_registry_url is not None:
82+
raise ValueError("Cannot pass schema_registry along with schema.registry.url config")
8083

8184
super(AvroProducer, self).__init__(config)
82-
self._serializer = MessageSerializer(CachedSchemaRegistryClient(url=schem_registry_url))
85+
self._serializer = MessageSerializer(schema_registry)
8386
self._key_schema = default_key_schema
8487
self._value_schema = default_value_schema
8588

@@ -127,15 +130,17 @@ class AvroConsumer(Consumer):
127130
128131
@:param: config: dict object with config parameters containing url for schema registry (schema.registry.url).
129132
"""
130-
def __init__(self, config):
131-
132-
if ('schema.registry.url' not in config.keys()):
133-
raise ValueError("Missing parameter: schema.registry.url")
134-
schem_registry_url = config["schema.registry.url"]
135-
del config["schema.registry.url"]
133+
def __init__(self, config, schema_registry=None):
134+
schema_registry_url = config.pop("schema.registry.url", None)
135+
if schema_registry is None:
136+
if schema_registry_url is None:
137+
raise ValueError("Missing parameter: schema.registry.url")
138+
schema_registry = CachedSchemaRegistryClient(url=schema_registry_url)
139+
elif schema_registry_url is not None:
140+
raise ValueError("Cannot pass schema_registry along with schema.registry.url config")
136141

137142
super(AvroConsumer, self).__init__(config)
138-
self._serializer = MessageSerializer(CachedSchemaRegistryClient(url=schem_registry_url))
143+
self._serializer = MessageSerializer(schema_registry)
139144

140145
def poll(self, timeout=None):
141146
"""

examples/integration_test.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
bootstrap_servers = None
3939

4040
# Confluent schema-registry
41-
schema_registry = None
41+
schema_registry_url = None
4242

4343
# Topic to use
4444
topic = 'test'
@@ -56,6 +56,20 @@ def error_cb (err):
5656
print('Error: %s' % err)
5757

5858

59+
class InMemorySchemaRegistry(object):
60+
61+
schemas = {}
62+
next_idx = 0
63+
64+
def register(self, subject, schema):
65+
self.next_idx += 1
66+
self.schemas[self.next_idx] = schema
67+
return self.next_idx
68+
69+
def get_by_id(self, idx):
70+
return self.schemas.get(idx)
71+
72+
5973
class MyTestDr(object):
6074
""" Producer: Delivery report callback """
6175

@@ -218,13 +232,16 @@ def verify_avro():
218232

219233
# Producer config
220234
conf = {'bootstrap.servers': bootstrap_servers,
221-
'schema.registry.url': schema_registry,
222235
'error_cb': error_cb,
223236
'api.version.request': api_version_request,
224237
'default.topic.config': {'produce.offset.report': True}}
225238

226239
# Create producer
227-
p = avro.AvroProducer(conf)
240+
if schema_registry_url:
241+
conf['schema.registry.url'] = schema_registry_url
242+
p = avro.AvroProducer(conf)
243+
else:
244+
p = avro.AvroProducer(conf, schema_registry=InMemorySchemaRegistry())
228245

229246
prim_float = avro.load(os.path.join(avsc_dir, "primitive_float.avsc"))
230247
prim_string = avro.load(os.path.join(avsc_dir, "primitive_string.avsc"))
@@ -247,7 +264,6 @@ def verify_avro():
247264

248265
# Consumer config
249266
cons_conf = {'bootstrap.servers': bootstrap_servers,
250-
'schema.registry.url': schema_registry,
251267
'group.id': 'test.py',
252268
'session.timeout.ms': 6000,
253269
'enable.auto.commit': False,
@@ -265,7 +281,12 @@ def verify_avro():
265281
p.flush()
266282

267283
# Create consumer
268-
c = avro.AvroConsumer(copy(cons_conf))
284+
conf = copy(cons_conf)
285+
if schema_registry_url:
286+
conf['schema.registry.url'] = schema_registry_url
287+
c = avro.AvroConsumer(conf)
288+
else:
289+
c = avro.AvroConsumer(conf, schema_registry=InMemorySchemaRegistry())
269290
c.subscribe([combo['topic']])
270291

271292
while True:
@@ -628,7 +649,7 @@ def stats_cb(stats_json_str):
628649
if len(sys.argv) > 2:
629650
topic = sys.argv[2]
630651
if len(sys.argv) > 3:
631-
schema_registry = sys.argv[3]
652+
schema_registry_url = sys.argv[3]
632653
else:
633654
print('Usage: %s <broker> [<topic>] [<schema_registry>]' % sys.argv[0])
634655
sys.exit(1)
@@ -654,8 +675,7 @@ def stats_cb(stats_json_str):
654675
print('=' * 30, 'Verifying stats_cb', '=' * 30)
655676
verify_stats_cb()
656677

657-
if schema_registry:
658-
print('=' * 30, 'Verifying AVRO', '=' * 30)
659-
topics = verify_avro()
678+
print('=' * 30, 'Verifying AVRO', '=' * 30)
679+
topics = verify_avro()
660680

661681
print('=' * 30, 'Done', '=' * 30)

tests/avro/test_avro_producer.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
from confluent_kafka.avro import AvroProducer
3030
from confluent_kafka.avro.serializer import (KeySerializerError,
3131
ValueSerializerError)
32+
33+
from tests.avro.mock_schema_registry_client import MockSchemaRegistryClient
34+
35+
3236
avsc_dir = os.path.dirname(os.path.realpath(__file__))
3337

3438

@@ -82,3 +86,15 @@ def test_produce_primitive_key_and_value(self):
8286
producer = AvroProducer({'schema.registry.url': 'http://127.0.0.1:9001'})
8387
with self.assertRaises(ConnectionError): # Unexistent schema-registry
8488
producer.produce(topic='test', value=32., value_schema=value_schema, key='mykey', key_schema=key_schema)
89+
90+
def test_produce_with_custom_registry(self):
91+
schema_registry = MockSchemaRegistryClient()
92+
value_schema = avro.load(os.path.join(avsc_dir, "basic_schema.avsc"))
93+
key_schema = avro.load(os.path.join(avsc_dir, "primitive_string.avsc"))
94+
producer = AvroProducer({}, schema_registry=schema_registry)
95+
producer.produce(topic='test', value={"name": 'abc"'}, value_schema=value_schema, key='mykey', key_schema=key_schema)
96+
97+
def test_produce_with_custom_registry_and_registry_url(self):
98+
schema_registry = MockSchemaRegistryClient()
99+
with self.assertRaises(ValueError):
100+
producer = AvroProducer({'schema.registry.url': 'http://127.0.0.1:9001'}, schema_registry=schema_registry)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy