From 3f4b397741dd73e46508f6be6571cb9626641ff0 Mon Sep 17 00:00:00 2001 From: Yunze Xu Date: Tue, 21 Apr 2026 18:44:04 +0800 Subject: [PATCH 1/4] feat: implement ProtobufNative schema --- pulsar/schema/__init__.py | 1 + pulsar/schema/schema_protobuf.py | 127 +++++++++++++++++++++++++++++++ src/enums.cc | 3 +- tests/schema_test.py | 92 ++++++++++++++++++++++ tests/test_schema.proto | 37 +++++++++ tests/test_schema_pb2.py | 40 ++++++++++ 6 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 pulsar/schema/schema_protobuf.py create mode 100644 tests/test_schema.proto create mode 100644 tests/test_schema_pb2.py diff --git a/pulsar/schema/__init__.py b/pulsar/schema/__init__.py index efa68066..e3fa49e8 100644 --- a/pulsar/schema/__init__.py +++ b/pulsar/schema/__init__.py @@ -22,3 +22,4 @@ from .schema import Schema, BytesSchema, StringSchema, JsonSchema from .schema_avro import AvroSchema +from .schema_protobuf import ProtobufNativeSchema diff --git a/pulsar/schema/schema_protobuf.py b/pulsar/schema/schema_protobuf.py new file mode 100644 index 00000000..e691e777 --- /dev/null +++ b/pulsar/schema/schema_protobuf.py @@ -0,0 +1,127 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import base64 +import _pulsar + +from .schema import Schema + +try: + from google.protobuf import descriptor_pb2 + from google.protobuf.message import Message as ProtobufMessage + HAS_PROTOBUF = True +except ImportError: + HAS_PROTOBUF = False + + +def _collect_file_descriptors(file_descriptor, visited, file_descriptor_set): + """Recursively collect all FileDescriptorProto objects into file_descriptor_set.""" + if file_descriptor.name in visited: + return + for dep in file_descriptor.dependencies: + _collect_file_descriptors(dep, visited, file_descriptor_set) + visited.add(file_descriptor.name) + proto = descriptor_pb2.FileDescriptorProto() + file_descriptor.CopyToProto(proto) + file_descriptor_set.file.append(proto) + + +def _build_schema_definition(descriptor): + """ + Build the schema definition dict matching Java's ProtobufNativeSchemaData format: + { + "fileDescriptorSet": , + "rootMessageTypeName": , + "rootFileDescriptorName": + } + This mirrors ProtobufNativeSchemaUtils.serialize() in the Java client. + """ + file_descriptor_set = descriptor_pb2.FileDescriptorSet() + _collect_file_descriptors(descriptor.file, set(), file_descriptor_set) + file_descriptor_set_bytes = file_descriptor_set.SerializeToString() + return { + "fileDescriptorSet": base64.b64encode(file_descriptor_set_bytes).decode('utf-8'), + "rootMessageTypeName": descriptor.full_name, + "rootFileDescriptorName": descriptor.file.name, + } + + +if HAS_PROTOBUF: + class ProtobufNativeSchema(Schema): + """ + Schema for protobuf messages using the native protobuf binary encoding. + + The schema definition is stored as a JSON-encoded ProtobufNativeSchemaData + (fileDescriptorSet, rootMessageTypeName, rootFileDescriptorName), which is + compatible with the Java client's ProtobufNativeSchema. + + Parameters + ---------- + record_cls: + A generated protobuf message class (subclass of google.protobuf.message.Message). + + Example + ------- + .. code-block:: python + + import pulsar + from pulsar.schema import ProtobufNativeSchema + from my_proto_pb2 import MyMessage + + client = pulsar.Client('pulsar://localhost:6650') + producer = client.create_producer( + 'my-topic', + schema=ProtobufNativeSchema(MyMessage) + ) + producer.send(MyMessage(field='value')) + """ + + def __init__(self, record_cls): + if not (isinstance(record_cls, type) and issubclass(record_cls, ProtobufMessage)): + raise TypeError( + f'record_cls must be a protobuf Message subclass, got {record_cls!r}' + ) + schema_definition = _build_schema_definition(record_cls.DESCRIPTOR) + super(ProtobufNativeSchema, self).__init__( + record_cls, _pulsar.SchemaType.PROTOBUF_NATIVE, schema_definition, 'PROTOBUF_NATIVE' + ) + + def encode(self, obj): + self._validate_object_type(obj) + return obj.SerializeToString() + + def decode(self, data): + return self._record_cls.FromString(data) + + def __str__(self): + return f'ProtobufNativeSchema({self._record_cls.__name__})' + +else: + class ProtobufNativeSchema(Schema): + def __init__(self, _record_cls=None): + raise Exception( + "protobuf library support was not found. " + "Install it with: pip install protobuf" + ) + + def encode(self, obj): + pass + + def decode(self, data): + pass diff --git a/src/enums.cc b/src/enums.cc index 447d013c..7ee28ea1 100644 --- a/src/enums.cc +++ b/src/enums.cc @@ -115,7 +115,8 @@ void export_enums(py::module_& m) { .value("AVRO", pulsar::AVRO) .value("AUTO_CONSUME", pulsar::AUTO_CONSUME) .value("AUTO_PUBLISH", pulsar::AUTO_PUBLISH) - .value("KEY_VALUE", pulsar::KEY_VALUE); + .value("KEY_VALUE", pulsar::KEY_VALUE) + .value("PROTOBUF_NATIVE", pulsar::PROTOBUF_NATIVE); enum_(m, "InitialPosition", "Supported initial position") .value("Latest", InitialPositionLatest) diff --git a/tests/schema_test.py b/tests/schema_test.py index 9d031d15..575ec19c 100755 --- a/tests/schema_test.py +++ b/tests/schema_test.py @@ -18,7 +18,10 @@ # under the License. # +import base64 import math +import os +import sys import requests from typing import List from unittest import TestCase, main @@ -30,6 +33,10 @@ import json from fastavro.schema import load_schema +# Make generated protobuf test classes importable +sys.path.insert(0, os.path.dirname(__file__)) +from test_schema_pb2 import TestMessage, TestMessageWithNested, TestInner + class ExampleRecord(Record): str_field = String() int_field = Integer() @@ -1404,5 +1411,90 @@ def test_schema_type_promotion(self): client.close() +class ProtobufNativeSchemaTest(TestCase): + """Unit tests for ProtobufNativeSchema (no Pulsar broker required).""" + + def test_schema_type(self): + """Schema type must be PROTOBUF_NATIVE.""" + import _pulsar + schema = ProtobufNativeSchema(TestMessage) + self.assertEqual(schema.schema_info().schema_type(), _pulsar.SchemaType.PROTOBUF_NATIVE) + + def test_schema_definition_keys(self): + """Schema definition JSON must contain the three required keys.""" + schema = ProtobufNativeSchema(TestMessage) + schema_def = json.loads(schema.schema_info().schema()) + self.assertIn('fileDescriptorSet', schema_def) + self.assertIn('rootMessageTypeName', schema_def) + self.assertIn('rootFileDescriptorName', schema_def) + + def test_schema_definition_values(self): + """rootMessageTypeName and rootFileDescriptorName must match the descriptor.""" + schema = ProtobufNativeSchema(TestMessage) + schema_def = json.loads(schema.schema_info().schema()) + self.assertEqual(schema_def['rootMessageTypeName'], 'test.TestMessage') + self.assertEqual(schema_def['rootFileDescriptorName'], 'test_schema.proto') + + def test_file_descriptor_set_is_valid_base64_proto(self): + """fileDescriptorSet must be valid base64-encoded FileDescriptorSet bytes.""" + from google.protobuf import descriptor_pb2 + schema = ProtobufNativeSchema(TestMessage) + schema_def = json.loads(schema.schema_info().schema()) + raw = base64.b64decode(schema_def['fileDescriptorSet']) + fds = descriptor_pb2.FileDescriptorSet.FromString(raw) + file_names = [f.name for f in fds.file] + self.assertIn('test_schema.proto', file_names) + + def test_encode_decode_roundtrip(self): + """encode then decode must reproduce the original message.""" + schema = ProtobufNativeSchema(TestMessage) + original = TestMessage(name='hello', value=42) + encoded = schema.encode(original) + decoded = schema.decode(encoded) + self.assertEqual(decoded.name, 'hello') + self.assertEqual(decoded.value, 42) + + def test_encode_produces_protobuf_binary(self): + """Encoded bytes must be valid protobuf binary (parseable by the class directly).""" + schema = ProtobufNativeSchema(TestMessage) + msg = TestMessage(name='pulsar', value=100) + encoded = schema.encode(msg) + # Verify with protobuf's own parser + reparsed = TestMessage.FromString(encoded) + self.assertEqual(reparsed, msg) + + def test_encode_decode_nested_message(self): + """encode/decode round-trip works for messages containing nested message fields.""" + schema = ProtobufNativeSchema(TestMessageWithNested) + original = TestMessageWithNested( + str_field='test', + int_field=7, + double_field=3.14, + nested=TestInner(inner_str='inner', inner_int=999), + ) + decoded = schema.decode(schema.encode(original)) + self.assertEqual(decoded.str_field, 'test') + self.assertEqual(decoded.int_field, 7) + self.assertAlmostEqual(decoded.double_field, 3.14) + self.assertEqual(decoded.nested.inner_str, 'inner') + self.assertEqual(decoded.nested.inner_int, 999) + + def test_wrong_type_raises(self): + """Encoding an object of the wrong type must raise TypeError.""" + schema = ProtobufNativeSchema(TestMessage) + with self.assertRaises(TypeError): + schema.encode("not a protobuf message") + + def test_non_message_class_raises(self): + """Constructing with a non-Message class must raise TypeError.""" + with self.assertRaises(TypeError): + ProtobufNativeSchema(str) + + def test_schema_name(self): + """Schema name must be 'PROTOBUF_NATIVE'.""" + schema = ProtobufNativeSchema(TestMessage) + self.assertEqual(schema.schema_info().name(), 'PROTOBUF_NATIVE') + + if __name__ == '__main__': main() diff --git a/tests/test_schema.proto b/tests/test_schema.proto new file mode 100644 index 00000000..42ef6595 --- /dev/null +++ b/tests/test_schema.proto @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +syntax = "proto3"; + +package test; + +message TestMessage { + string name = 1; + int32 value = 2; +} + +message TestMessageWithNested { + string str_field = 1; + int32 int_field = 2; + double double_field = 3; + TestInner nested = 4; +} + +message TestInner { + string inner_str = 1; + int64 inner_int = 2; +} diff --git a/tests/test_schema_pb2.py b/tests/test_schema_pb2.py new file mode 100644 index 00000000..0434b193 --- /dev/null +++ b/tests/test_schema_pb2.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: test_schema.proto +# Protobuf Python Version: 6.32.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 32, + 0, + '', + 'test_schema.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11test_schema.proto\x12\x04test\"*\n\x0bTestMessage\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05\"t\n\x15TestMessageWithNested\x12\x11\n\tstr_field\x18\x01 \x01(\t\x12\x11\n\tint_field\x18\x02 \x01(\x05\x12\x14\n\x0c\x64ouble_field\x18\x03 \x01(\x01\x12\x1f\n\x06nested\x18\x04 \x01(\x0b\x32\x0f.test.TestInner\"1\n\tTestInner\x12\x11\n\tinner_str\x18\x01 \x01(\t\x12\x11\n\tinner_int\x18\x02 \x01(\x03\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'test_schema_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_TESTMESSAGE']._serialized_start=27 + _globals['_TESTMESSAGE']._serialized_end=69 + _globals['_TESTMESSAGEWITHNESTED']._serialized_start=71 + _globals['_TESTMESSAGEWITHNESTED']._serialized_end=187 + _globals['_TESTINNER']._serialized_start=189 + _globals['_TESTINNER']._serialized_end=238 +# @@protoc_insertion_point(module_scope) From ed304cc4fed0175d8791b6cedb3b83c91f96482e Mon Sep 17 00:00:00 2001 From: Yunze Xu Date: Mon, 11 May 2026 12:12:59 +0800 Subject: [PATCH 2/4] feat: add a protobuf extra --- .github/workflows/ci-pr-validation.yaml | 2 +- setup.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-pr-validation.yaml b/.github/workflows/ci-pr-validation.yaml index df2417de..dfe6d678 100644 --- a/.github/workflows/ci-pr-validation.yaml +++ b/.github/workflows/ci-pr-validation.yaml @@ -78,7 +78,7 @@ jobs: python3 -m pip install -U pip setuptools wheel requests python3 setup.py bdist_wheel WHEEL=$(find dist -name '*.whl') - pip3 install ${WHEEL}[avro] + pip3 install ${WHEEL}[avro,protobuf] - name: Run Oauth2 tests run: | diff --git a/setup.py b/setup.py index 76d929b2..d78b42e5 100755 --- a/setup.py +++ b/setup.py @@ -76,14 +76,21 @@ def build_extension(self, ext): extras_require = {} +# protobuf schema dependencies +extras_require["protobuf"] = sorted( + { + "protobuf>=3.6.1", + } +) + # functions dependencies extras_require["functions"] = sorted( { - "protobuf>=3.6.1", "grpcio>=1.59.3", "apache-bookkeeper-client>=4.16.1", "prometheus_client", - "ratelimit" + "ratelimit", + *extras_require["protobuf"], } ) From 1b4f04ad0672da8b506abf457cf673ef08e6d3ca Mon Sep 17 00:00:00 2001 From: Yunze Xu Date: Mon, 11 May 2026 12:47:13 +0800 Subject: [PATCH 3/4] fix: style check --- pulsar/schema/schema_protobuf.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/pulsar/schema/schema_protobuf.py b/pulsar/schema/schema_protobuf.py index e691e777..907f6202 100644 --- a/pulsar/schema/schema_protobuf.py +++ b/pulsar/schema/schema_protobuf.py @@ -44,13 +44,18 @@ def _collect_file_descriptors(file_descriptor, visited, file_descriptor_set): def _build_schema_definition(descriptor): """ - Build the schema definition dict matching Java's ProtobufNativeSchemaData format: - { - "fileDescriptorSet": , - "rootMessageTypeName": , - "rootFileDescriptorName": - } - This mirrors ProtobufNativeSchemaUtils.serialize() in the Java client. + Build the schema definition dict used by Java's ``ProtobufNativeSchemaData``. + + The returned mapping has these keys: + + .. code-block:: text + + fileDescriptorSet + rootMessageTypeName + rootFileDescriptorName + + ``fileDescriptorSet`` contains base64-encoded ``FileDescriptorSet`` bytes. + This mirrors ``ProtobufNativeSchemaUtils.serialize()`` in the Java client. """ file_descriptor_set = descriptor_pb2.FileDescriptorSet() _collect_file_descriptors(descriptor.file, set(), file_descriptor_set) From e1afd8efccddd9bb57e4bb087ddcd4b0415ebaf3 Mon Sep 17 00:00:00 2001 From: Yunze Xu Date: Mon, 11 May 2026 19:43:42 +0800 Subject: [PATCH 4/4] address comments --- pulsar/schema/schema_protobuf.py | 23 ++++++++--- setup.py | 2 +- tests/schema_test.py | 65 +++++++++++++++++++++++++++++--- tests/test_schema.proto | 37 ------------------ tests/test_schema_pb2.py | 40 -------------------- 5 files changed, 79 insertions(+), 88 deletions(-) delete mode 100644 tests/test_schema.proto delete mode 100644 tests/test_schema_pb2.py diff --git a/pulsar/schema/schema_protobuf.py b/pulsar/schema/schema_protobuf.py index 907f6202..1852cd97 100644 --- a/pulsar/schema/schema_protobuf.py +++ b/pulsar/schema/schema_protobuf.py @@ -90,11 +90,24 @@ class ProtobufNativeSchema(Schema): from my_proto_pb2 import MyMessage client = pulsar.Client('pulsar://localhost:6650') - producer = client.create_producer( - 'my-topic', - schema=ProtobufNativeSchema(MyMessage) - ) - producer.send(MyMessage(field='value')) + schema = ProtobufNativeSchema(MyMessage) + producer = client.create_producer('my-topic', schema=schema) + consumer = client.subscribe('my-topic', 'my-sub', schema=schema) + + message = MyMessage() + message.field = 'value' + producer.send(message) + + received = consumer.receive(timeout_millis=5000) + typed_value = received.value() + consumer.acknowledge(received) + + assert isinstance(typed_value, MyMessage) + assert typed_value.field == 'value' + + consumer.close() + producer.close() + client.close() """ def __init__(self, record_cls): diff --git a/setup.py b/setup.py index d78b42e5..370205df 100755 --- a/setup.py +++ b/setup.py @@ -79,7 +79,7 @@ def build_extension(self, ext): # protobuf schema dependencies extras_require["protobuf"] = sorted( { - "protobuf>=3.6.1", + "protobuf>=6.33.6", } ) diff --git a/tests/schema_test.py b/tests/schema_test.py index 575ec19c..42b65905 100755 --- a/tests/schema_test.py +++ b/tests/schema_test.py @@ -20,8 +20,6 @@ import base64 import math -import os -import sys import requests from typing import List from unittest import TestCase, main @@ -32,10 +30,67 @@ from enum import Enum import json from fastavro.schema import load_schema +from google.protobuf import descriptor_pb2, descriptor_pool, message_factory + + +def _add_protobuf_field(message, name, number, field_type, type_name=None): + field = message.field.add() + field.name = name + field.number = number + field.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + field.type = field_type + if type_name: + field.type_name = type_name + + +def _get_message_classes(pool, message_names): + if hasattr(message_factory, 'GetMessageClass'): + return tuple( + message_factory.GetMessageClass(pool.FindMessageTypeByName(message_name)) + for message_name in message_names + ) + factory = message_factory.MessageFactory(pool) + return tuple( + factory.GetPrototype(pool.FindMessageTypeByName(message_name)) + for message_name in message_names + ) + + +def _build_protobuf_test_messages(): + file_proto = descriptor_pb2.FileDescriptorProto() + file_proto.name = 'test_schema.proto' + file_proto.package = 'test' + file_proto.syntax = 'proto3' + + test_message = file_proto.message_type.add() + test_message.name = 'TestMessage' + _add_protobuf_field(test_message, 'name', 1, descriptor_pb2.FieldDescriptorProto.TYPE_STRING) + _add_protobuf_field(test_message, 'value', 2, descriptor_pb2.FieldDescriptorProto.TYPE_INT32) + + nested_message = file_proto.message_type.add() + nested_message.name = 'TestMessageWithNested' + _add_protobuf_field(nested_message, 'str_field', 1, descriptor_pb2.FieldDescriptorProto.TYPE_STRING) + _add_protobuf_field(nested_message, 'int_field', 2, descriptor_pb2.FieldDescriptorProto.TYPE_INT32) + _add_protobuf_field(nested_message, 'double_field', 3, descriptor_pb2.FieldDescriptorProto.TYPE_DOUBLE) + _add_protobuf_field( + nested_message, 'nested', 4, descriptor_pb2.FieldDescriptorProto.TYPE_MESSAGE, '.test.TestInner' + ) + + inner_message = file_proto.message_type.add() + inner_message.name = 'TestInner' + _add_protobuf_field(inner_message, 'inner_str', 1, descriptor_pb2.FieldDescriptorProto.TYPE_STRING) + _add_protobuf_field(inner_message, 'inner_int', 2, descriptor_pb2.FieldDescriptorProto.TYPE_INT64) + + pool = descriptor_pool.DescriptorPool() + pool.AddSerializedFile(file_proto.SerializeToString()) + return _get_message_classes( + pool, + ('test.TestMessage', 'test.TestMessageWithNested', 'test.TestInner'), + ) + + +TestMessage, TestMessageWithNested, TestInner = _build_protobuf_test_messages() -# Make generated protobuf test classes importable -sys.path.insert(0, os.path.dirname(__file__)) -from test_schema_pb2 import TestMessage, TestMessageWithNested, TestInner class ExampleRecord(Record): str_field = String() diff --git a/tests/test_schema.proto b/tests/test_schema.proto deleted file mode 100644 index 42ef6595..00000000 --- a/tests/test_schema.proto +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -syntax = "proto3"; - -package test; - -message TestMessage { - string name = 1; - int32 value = 2; -} - -message TestMessageWithNested { - string str_field = 1; - int32 int_field = 2; - double double_field = 3; - TestInner nested = 4; -} - -message TestInner { - string inner_str = 1; - int64 inner_int = 2; -} diff --git a/tests/test_schema_pb2.py b/tests/test_schema_pb2.py deleted file mode 100644 index 0434b193..00000000 --- a/tests/test_schema_pb2.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: test_schema.proto -# Protobuf Python Version: 6.32.0 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 32, - 0, - '', - 'test_schema.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11test_schema.proto\x12\x04test\"*\n\x0bTestMessage\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05\"t\n\x15TestMessageWithNested\x12\x11\n\tstr_field\x18\x01 \x01(\t\x12\x11\n\tint_field\x18\x02 \x01(\x05\x12\x14\n\x0c\x64ouble_field\x18\x03 \x01(\x01\x12\x1f\n\x06nested\x18\x04 \x01(\x0b\x32\x0f.test.TestInner\"1\n\tTestInner\x12\x11\n\tinner_str\x18\x01 \x01(\t\x12\x11\n\tinner_int\x18\x02 \x01(\x03\x62\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'test_schema_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_TESTMESSAGE']._serialized_start=27 - _globals['_TESTMESSAGE']._serialized_end=69 - _globals['_TESTMESSAGEWITHNESTED']._serialized_start=71 - _globals['_TESTMESSAGEWITHNESTED']._serialized_end=187 - _globals['_TESTINNER']._serialized_start=189 - _globals['_TESTINNER']._serialized_end=238 -# @@protoc_insertion_point(module_scope)