├── .coveragerc ├── .editorconfig ├── .github └── workflows │ ├── codeql.yml │ └── release_to_pypi.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── protobuf2pydantic ├── __init__.py ├── biz.py └── main.py ├── pytest.ini ├── requirements.txt ├── setup.py ├── tests ├── __init__.py ├── celery_task_pb2.py ├── test___init__.py ├── test_biz.py ├── test_main.py ├── test_map_pb2.py └── test_pb2.py └── version /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | source = protobuf2pydantic 4 | 5 | [report] 6 | exclude_lines = 7 | if self.debug: 8 | pragma: no cover 9 | raise NotImplementedError 10 | if __name__ == .__main__.: 11 | pass 12 | raise 13 | ignore_errors = False 14 | omit = 15 | tests/* 16 | protobuf2pydantic/__init__.py 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # Matches multiple files with brace expansion notation 12 | # Set default charset 13 | [*.{js,html,css}] 14 | charset = utf-8 15 | indent_style = space 16 | tab_width = 2 17 | 18 | [*.py] 19 | max_line_length = 100 20 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | schedule: 9 | - cron: "4 13 * * 2" 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | language: [ python ] 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v2 31 | with: 32 | languages: ${{ matrix.language }} 33 | queries: +security-and-quality 34 | 35 | - name: Autobuild 36 | uses: github/codeql-action/autobuild@v2 37 | 38 | - name: Perform CodeQL Analysis 39 | uses: github/codeql-action/analyze@v2 40 | with: 41 | category: "/language:${{ matrix.language }}" 42 | -------------------------------------------------------------------------------- /.github/workflows/release_to_pypi.yml: -------------------------------------------------------------------------------- 1 | # This workflows will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Release to PyPI 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | pypi-publish: 12 | name: upload release to PyPI 13 | runs-on: ubuntu-latest 14 | # Specifying a GitHub environment is optional, but strongly encouraged 15 | environment: release 16 | permissions: 17 | # IMPORTANT: this permission is mandatory for trusted publishing 18 | id-token: write 19 | steps: 20 | - name: Checkout code 21 | uses: actions/checkout@v2 22 | with: 23 | fetch-depth: 1 24 | - name: Set up Python 25 | uses: actions/setup-python@v2 26 | - name: Install dependencies 27 | run: | 28 | make release 29 | pip install setuptools wheel twine 30 | - name: Get version 31 | run: | 32 | echo $GITHUB_REF | awk -F '/' '{print $3}' >> version 33 | make build 34 | - name: Publish package distributions to PyPI 35 | uses: pypa/gh-action-pypi-publish@release/v1 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | .DS_Store 131 | .idea/ 132 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.6" 4 | - "3.7" 5 | branches: 6 | only: 7 | - main 8 | cache: pip 9 | install: make init 10 | script: make test 11 | after_success: 12 | - bash <(curl -s https://codecov.io/bash) 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 The Python Packaging Authority 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | init: 2 | python3 -m venv venv 3 | . venv/bin/activate \ 4 | && pip3 install -r requirements.txt \ 5 | && pip3 install wheel \ 6 | && pip3 install coverage pytest 7 | test: 8 | coverage run -m pytest -v 9 | release: 10 | pip3 install -r requirements.txt 11 | build: 12 | python3 setup.py sdist bdist_wheel 13 | pypi: 14 | twine upload dist/* 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # protobuf2pydantic 2 | 3 | ![GitHub](https://img.shields.io/github/license/Ed-XCF/protobuf2pydantic) 4 | [![Build Status](https://www.travis-ci.org/Ed-XCF/protobuf2pydantic.svg?branch=main)](https://www.travis-ci.org/Ed-XCF/protobuf2pydantic) 5 | [![codecov](https://codecov.io/gh/Ed-XCF/protobuf2pydantic/branch/main/graph/badge.svg?token=4YYBSTLS5F)](https://codecov.io/gh/Ed-XCF/protobuf2pydantic) 6 | ![PyPI](https://img.shields.io/pypi/v/protobuf2pydantic) 7 | [![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/Ed-XCF/protobuf2pydantic.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Ed-XCF/protobuf2pydantic/context:python) 8 | 9 | ### Generate a file which include pydantic models by using protobuf.pb2 file 10 | ## Installation 11 | ```shell 12 | pip3 install protobuf2pydantic 13 | ``` 14 | 15 | ## Getting Started 16 | ### in CLI 17 | ```shell 18 | pb2py ../test_pb2.py > wow.py 19 | ``` 20 | 21 | ### in Python 22 | ```python 23 | from protobuf2pydantic import msg2py 24 | from pydantic import validator 25 | 26 | import transaction_pb2 27 | 28 | 29 | class AmountResponse(msg2py(transaction_pb2.AmountResponse)): 30 | @validator("amount") 31 | def non_negative(cls, v): 32 | assert v >= 0 33 | return v 34 | ``` 35 | 36 | ### * Required proto file syntax = "proto3"; 37 | -------------------------------------------------------------------------------- /protobuf2pydantic/__init__.py: -------------------------------------------------------------------------------- 1 | from os import linesep 2 | from typing import * # noqa 3 | from enum import IntEnum # noqa 4 | 5 | from google.protobuf.reflection import GeneratedProtocolMessageType 6 | from google.protobuf.struct_pb2 import Struct # noqa 7 | from google.protobuf.timestamp_pb2 import Timestamp # noqa 8 | from google.protobuf.duration_pb2 import Duration # noqa 9 | from pydantic import BaseModel, Field # noqa 10 | 11 | from protobuf2pydantic.biz import msg2pydantic 12 | 13 | 14 | def message2pydantic(message: GeneratedProtocolMessageType) -> Type[BaseModel]: 15 | """ convert a protobuf message object to pydantic model object """ 16 | descriptor = message.DESCRIPTOR 17 | model_string = msg2pydantic(0, descriptor) 18 | getter_key = "getter" 19 | getter_string = f"def {getter_key}(): return {descriptor.name}" 20 | compile_string = model_string + linesep + getter_string 21 | compile_code = compile(compile_string, "", "exec") 22 | sub_namespace = {k: v for k, v in globals().items() if not k.startswith("__")} 23 | exec(compile_code, sub_namespace) 24 | return sub_namespace[getter_key]() 25 | 26 | 27 | msg2py = message2pydantic 28 | -------------------------------------------------------------------------------- /protobuf2pydantic/biz.py: -------------------------------------------------------------------------------- 1 | from os import linesep 2 | from typing import List, Optional 3 | from functools import partial 4 | 5 | from google.protobuf.reflection import GeneratedProtocolMessageType 6 | from google.protobuf.descriptor import Descriptor, FieldDescriptor, EnumDescriptor 7 | 8 | message_metaclasses = [GeneratedProtocolMessageType] 9 | try: 10 | from google._upb._message import MessageMeta 11 | 12 | message_metaclasses.append(MessageMeta) 13 | except ImportError: 14 | pass 15 | 16 | tab = " " * 4 17 | one_line, two_lines = linesep * 2, linesep * 3 18 | type_mapping = { 19 | FieldDescriptor.TYPE_DOUBLE: float, 20 | FieldDescriptor.TYPE_FLOAT: float, 21 | FieldDescriptor.TYPE_INT64: int, 22 | FieldDescriptor.TYPE_UINT64: int, 23 | FieldDescriptor.TYPE_INT32: int, 24 | FieldDescriptor.TYPE_FIXED64: float, 25 | FieldDescriptor.TYPE_FIXED32: float, 26 | FieldDescriptor.TYPE_BOOL: bool, 27 | FieldDescriptor.TYPE_STRING: str, 28 | FieldDescriptor.TYPE_BYTES: str, 29 | FieldDescriptor.TYPE_UINT32: int, 30 | FieldDescriptor.TYPE_SFIXED32: float, 31 | FieldDescriptor.TYPE_SFIXED64: float, 32 | FieldDescriptor.TYPE_SINT32: int, 33 | FieldDescriptor.TYPE_SINT64: int, 34 | } 35 | 36 | # maintain map of level to list of created class names 37 | defined_classes :dict[int, list[str]] = {} 38 | 39 | 40 | def m(field: FieldDescriptor) -> str: 41 | return type_mapping[field.type].__name__ 42 | 43 | 44 | def class_already_defined(level: int, field: FieldDescriptor) -> bool: 45 | try: 46 | already_defined = defined_classes[level] 47 | except KeyError: 48 | return False 49 | if field.type == FieldDescriptor.TYPE_ENUM: 50 | return field.enum_type.name in already_defined 51 | elif field.type == FieldDescriptor.TYPE_MESSAGE: 52 | return field.message_type.name in already_defined 53 | return False 54 | 55 | 56 | def add_defined_class(level: int, class_name: str): 57 | try: 58 | defined_classes[level] 59 | except KeyError: 60 | defined_classes[level] = [] 61 | defined_classes[level].append(class_name) 62 | 63 | 64 | def convert_field(level: int, field: FieldDescriptor) -> Optional[str]: 65 | level += 1 66 | field_type = field.type 67 | field_label = field.label 68 | was_mapping = False 69 | extra = None 70 | 71 | if class_already_defined(level, field): 72 | return 73 | 74 | if field_type == FieldDescriptor.TYPE_ENUM: 75 | enum_type: EnumDescriptor = field.enum_type 76 | type_statement = enum_type.name 77 | class_statement = f"{tab * level}class {enum_type.name}(IntEnum):" 78 | field_statements = map( 79 | lambda value: f"{tab * (level + 1)}{value.name} = {value.index}", 80 | enum_type.values, 81 | ) 82 | add_defined_class(level, enum_type.name) 83 | extra = linesep.join([class_statement, *field_statements]) 84 | factory = "int" 85 | 86 | elif field_type == FieldDescriptor.TYPE_MESSAGE: 87 | type_statement: str = field.message_type.name 88 | if type_statement.endswith("Entry"): 89 | key, value = field.message_type.fields # type: FieldDescriptor 90 | if value.type != 11: 91 | type_statement = f"Dict[{m(key)}, {m(value)}]" 92 | else: 93 | was_mapping = True 94 | type_statement = f"Dict[{m(key)}, {value.message_type.name}]" 95 | factory = "dict" 96 | elif type_statement == "Struct": 97 | type_statement = "Dict[str, Any]" 98 | factory = "dict" 99 | else: 100 | extra = msg2pydantic(level, field.message_type) 101 | factory = type_statement 102 | else: 103 | type_statement = m(field) 104 | factory = type_statement 105 | 106 | if field_label == FieldDescriptor.LABEL_REPEATED and not was_mapping: 107 | type_statement = f"List[{type_statement}]" 108 | factory = "list" 109 | 110 | default_statement = f" = Field(default_factory={factory})" 111 | if field_label == FieldDescriptor.LABEL_REQUIRED: 112 | default_statement = "" 113 | 114 | field_statement = f"{tab * level}{field.name}: {type_statement}{default_statement}" 115 | if not extra: 116 | return field_statement 117 | return linesep + extra + one_line + field_statement 118 | 119 | 120 | def msg2pydantic(level: int, msg: Descriptor) -> str: 121 | class_statement = f"{tab * level}class {msg.name}(BaseModel):" 122 | add_defined_class(level, msg.name) 123 | if msg.fields: 124 | field_statements = map(partial(convert_field, level), msg.fields) 125 | else: 126 | field_statements = [f"{tab * (level + 1)}pass"] 127 | return linesep.join([class_statement, *[fs for fs in field_statements if fs]]) 128 | 129 | 130 | def get_config(level: int): 131 | level += 1 132 | class_statement = f"{tab * level}class Config:" 133 | attribute_statement = f"{tab * (level + 1)}arbitrary_types_allowed = True" 134 | return linesep + class_statement + linesep + attribute_statement 135 | 136 | 137 | def pb2_to_pydantic(module) -> str: 138 | pydantic_models: List[str] = [] 139 | for i in dir(module): 140 | obj = getattr(module, i) 141 | if not any(isinstance(obj, metacls) for metacls in message_metaclasses): 142 | continue 143 | model_string = msg2pydantic(0, obj.DESCRIPTOR) 144 | pydantic_models.append(model_string) 145 | 146 | header = """from typing import List, Dict, Any 147 | from enum import IntEnum 148 | 149 | from pydantic import BaseModel, Field 150 | 151 | 152 | """ 153 | return header + two_lines.join(pydantic_models) 154 | -------------------------------------------------------------------------------- /protobuf2pydantic/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pathlib import Path 3 | from importlib import import_module 4 | 5 | from typer import Typer, echo, Argument 6 | 7 | from protobuf2pydantic import biz 8 | 9 | app = Typer() 10 | 11 | 12 | @app.command() 13 | def pydantic( 14 | pb2: Path = Argument( 15 | ..., 16 | exists=True, 17 | dir_okay=False, 18 | resolve_path=True, 19 | ) 20 | ): 21 | sys.path.append(str(pb2.parent)) 22 | module = import_module(pb2.stem) 23 | echo(biz.pb2_to_pydantic(module)) 24 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = -p no:warnings --doctest-modules 3 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | grpcio>=1.32.0 2 | grpcio-tools>=1.32.0 3 | typer>=0.3.2 4 | pydantic>=1.7.3 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open("README.md", "r") as fh: 4 | long_description = fh.read() 5 | 6 | with open("requirements.txt", "r") as fh: 7 | install_requires = fh.read().splitlines() 8 | 9 | with open("version", "r") as fh: 10 | version = fh.read() 11 | 12 | setuptools.setup( 13 | name="protobuf2pydantic", 14 | version=version, 15 | author="Ed__xu__Ed", 16 | author_email="m.tofu@qq.com", 17 | description="Generate a file which include pydantic models by protobuf.pb2 file", 18 | long_description=long_description, 19 | long_description_content_type="text/markdown", 20 | url="https://github.com/Ed-XCF/protobuf2pydantic", 21 | packages=setuptools.find_packages(), 22 | classifiers=[ 23 | "Programming Language :: Python :: 3", 24 | "License :: OSI Approved :: MIT License", 25 | "Operating System :: OS Independent", 26 | ], 27 | python_requires='>=3.6', 28 | install_requires=install_requires, 29 | entry_points={"console_scripts": ["pb2py = protobuf2pydantic.main:app"]} 30 | ) 31 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ed-XCF/protobuf2pydantic/a455c06a804bb6e14564e37a9f62bf37b2496ace/tests/__init__.py -------------------------------------------------------------------------------- /tests/celery_task_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: celery_task.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='celery_task.proto', 19 | package='celery_task', 20 | syntax='proto3', 21 | serialized_options=None, 22 | create_key=_descriptor._internal_create_key, 23 | serialized_pb=b'\n\x11\x63\x65lery_task.proto\x12\x0b\x63\x65lery_task\x1a\x1cgoogle/protobuf/struct.proto\"\x8b\x01\n\x0bTaskRequest\x12\x0c\n\x04task\x18\x01 \x01(\t\x12%\n\x04\x61rgs\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\'\n\x06kwargs\x18\x03 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x11\n\tcountdown\x18\x04 \x01(\x05\x12\x0b\n\x03\x65ta\x18\x05 \x01(\x05\"\x17\n\tTaskReply\x12\n\n\x02id\x18\x01 \x01(\t2Q\n\x11\x43\x65leryTaskService\x12<\n\x06\x43reate\x12\x18.celery_task.TaskRequest\x1a\x16.celery_task.TaskReply\"\x00\x62\x06proto3' 24 | , 25 | dependencies=[google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,]) 26 | 27 | 28 | 29 | 30 | _TASKREQUEST = _descriptor.Descriptor( 31 | name='TaskRequest', 32 | full_name='celery_task.TaskRequest', 33 | filename=None, 34 | file=DESCRIPTOR, 35 | containing_type=None, 36 | create_key=_descriptor._internal_create_key, 37 | fields=[ 38 | _descriptor.FieldDescriptor( 39 | name='task', full_name='celery_task.TaskRequest.task', index=0, 40 | number=1, type=9, cpp_type=9, label=1, 41 | has_default_value=False, default_value=b"".decode('utf-8'), 42 | message_type=None, enum_type=None, containing_type=None, 43 | is_extension=False, extension_scope=None, 44 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 45 | _descriptor.FieldDescriptor( 46 | name='args', full_name='celery_task.TaskRequest.args', index=1, 47 | number=2, type=11, cpp_type=10, label=1, 48 | has_default_value=False, default_value=None, 49 | message_type=None, enum_type=None, containing_type=None, 50 | is_extension=False, extension_scope=None, 51 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 52 | _descriptor.FieldDescriptor( 53 | name='kwargs', full_name='celery_task.TaskRequest.kwargs', index=2, 54 | number=3, type=11, cpp_type=10, label=1, 55 | has_default_value=False, default_value=None, 56 | message_type=None, enum_type=None, containing_type=None, 57 | is_extension=False, extension_scope=None, 58 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 59 | _descriptor.FieldDescriptor( 60 | name='countdown', full_name='celery_task.TaskRequest.countdown', index=3, 61 | number=4, type=5, cpp_type=1, label=1, 62 | has_default_value=False, default_value=0, 63 | message_type=None, enum_type=None, containing_type=None, 64 | is_extension=False, extension_scope=None, 65 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 66 | _descriptor.FieldDescriptor( 67 | name='eta', full_name='celery_task.TaskRequest.eta', index=4, 68 | number=5, type=5, cpp_type=1, label=1, 69 | has_default_value=False, default_value=0, 70 | message_type=None, enum_type=None, containing_type=None, 71 | is_extension=False, extension_scope=None, 72 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 73 | ], 74 | extensions=[ 75 | ], 76 | nested_types=[], 77 | enum_types=[ 78 | ], 79 | serialized_options=None, 80 | is_extendable=False, 81 | syntax='proto3', 82 | extension_ranges=[], 83 | oneofs=[ 84 | ], 85 | serialized_start=65, 86 | serialized_end=204, 87 | ) 88 | 89 | 90 | _TASKREPLY = _descriptor.Descriptor( 91 | name='TaskReply', 92 | full_name='celery_task.TaskReply', 93 | filename=None, 94 | file=DESCRIPTOR, 95 | containing_type=None, 96 | create_key=_descriptor._internal_create_key, 97 | fields=[ 98 | _descriptor.FieldDescriptor( 99 | name='id', full_name='celery_task.TaskReply.id', index=0, 100 | number=1, type=9, cpp_type=9, label=1, 101 | has_default_value=False, default_value=b"".decode('utf-8'), 102 | message_type=None, enum_type=None, containing_type=None, 103 | is_extension=False, extension_scope=None, 104 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 105 | ], 106 | extensions=[ 107 | ], 108 | nested_types=[], 109 | enum_types=[ 110 | ], 111 | serialized_options=None, 112 | is_extendable=False, 113 | syntax='proto3', 114 | extension_ranges=[], 115 | oneofs=[ 116 | ], 117 | serialized_start=206, 118 | serialized_end=229, 119 | ) 120 | 121 | _TASKREQUEST.fields_by_name['args'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT 122 | _TASKREQUEST.fields_by_name['kwargs'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT 123 | DESCRIPTOR.message_types_by_name['TaskRequest'] = _TASKREQUEST 124 | DESCRIPTOR.message_types_by_name['TaskReply'] = _TASKREPLY 125 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 126 | 127 | TaskRequest = _reflection.GeneratedProtocolMessageType('TaskRequest', (_message.Message,), { 128 | 'DESCRIPTOR' : _TASKREQUEST, 129 | '__module__' : 'celery_task_pb2' 130 | # @@protoc_insertion_point(class_scope:celery_task.TaskRequest) 131 | }) 132 | _sym_db.RegisterMessage(TaskRequest) 133 | 134 | TaskReply = _reflection.GeneratedProtocolMessageType('TaskReply', (_message.Message,), { 135 | 'DESCRIPTOR' : _TASKREPLY, 136 | '__module__' : 'celery_task_pb2' 137 | # @@protoc_insertion_point(class_scope:celery_task.TaskReply) 138 | }) 139 | _sym_db.RegisterMessage(TaskReply) 140 | 141 | 142 | 143 | _CELERYTASKSERVICE = _descriptor.ServiceDescriptor( 144 | name='CeleryTaskService', 145 | full_name='celery_task.CeleryTaskService', 146 | file=DESCRIPTOR, 147 | index=0, 148 | serialized_options=None, 149 | create_key=_descriptor._internal_create_key, 150 | serialized_start=231, 151 | serialized_end=312, 152 | methods=[ 153 | _descriptor.MethodDescriptor( 154 | name='Create', 155 | full_name='celery_task.CeleryTaskService.Create', 156 | index=0, 157 | containing_service=None, 158 | input_type=_TASKREQUEST, 159 | output_type=_TASKREPLY, 160 | serialized_options=None, 161 | create_key=_descriptor._internal_create_key, 162 | ), 163 | ]) 164 | _sym_db.RegisterServiceDescriptor(_CELERYTASKSERVICE) 165 | 166 | DESCRIPTOR.services_by_name['CeleryTaskService'] = _CELERYTASKSERVICE 167 | 168 | # @@protoc_insertion_point(module_scope) 169 | -------------------------------------------------------------------------------- /tests/test___init__.py: -------------------------------------------------------------------------------- 1 | from pydantic.main import ModelMetaclass # noqa 2 | 3 | from protobuf2pydantic import message2pydantic 4 | from tests.test_pb2 import TestMessage 5 | 6 | 7 | def test_message2pydantic(): 8 | klass = message2pydantic(TestMessage) 9 | assert isinstance(klass, ModelMetaclass) 10 | assert klass.__name__ == TestMessage.__name__ 11 | 12 | 13 | test_msg2py = test_message2pydantic 14 | -------------------------------------------------------------------------------- /tests/test_biz.py: -------------------------------------------------------------------------------- 1 | from protobuf2pydantic.biz import pb2_to_pydantic 2 | 3 | 4 | class TestPb2ToPydantic: 5 | def test_with_celery_task(self): 6 | from . import celery_task_pb2 7 | pb2_to_pydantic(celery_task_pb2) 8 | 9 | def test_with_test(self): 10 | from . import test_pb2 11 | pb2_to_pydantic(test_pb2) 12 | 13 | def test_with_map(self): 14 | from . import test_map_pb2 15 | pb2_to_pydantic(test_map_pb2) 16 | -------------------------------------------------------------------------------- /tests/test_main.py: -------------------------------------------------------------------------------- 1 | from typer.testing import CliRunner 2 | 3 | from protobuf2pydantic.main import app 4 | 5 | runner = CliRunner() 6 | 7 | 8 | def test_app(): 9 | r = runner.invoke(app, ["./tests/test_pb2.py"]) 10 | assert r.exit_code == 0 11 | -------------------------------------------------------------------------------- /tests/test_map_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: ssss.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 15 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor.FileDescriptor( 19 | name='ssss.proto', 20 | package='', 21 | syntax='proto3', 22 | serialized_options=None, 23 | create_key=_descriptor._internal_create_key, 24 | serialized_pb=b'\n\nssss.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xf2\x02\n\x07Payload\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\t\n\x01\x62\x18\x02 \x01(\t\x12\x1a\n\x01\x63\x18\x03 \x03(\x0b\x32\x0f.Payload.CEntry\x12\x17\n\x01\x64\x18\x04 \x01(\x0b\x32\x0c.Payload.wow\x12\x1a\n\x01\x65\x18\x05 \x03(\x0b\x32\x0f.Payload.EEntry\x12\"\n\x01\x66\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x18\n\x01g\x18\x07 \x03(\x0b\x32\r.Payload.wows\x12\"\n\x01h\x18\x08 \x03(\x0b\x32\x17.google.protobuf.Struct\x12%\n\x01i\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a(\n\x06\x43\x45ntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x10\n\x03wow\x12\t\n\x01z\x18\x01 \x01(\t\x1a(\n\x06\x45\x45ntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x11\n\x04wows\x12\t\n\x01z\x18\x01 \x01(\t\" \n\x08Response\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\t\n\x01\x62\x18\x02 \x01(\t2F\n\x04Test\x12\x1e\n\x03One\x12\x08.Payload\x1a\t.Response\"\x00(\x01\x12\x1e\n\x03Two\x12\x08.Payload\x1a\t.Response\"\x00(\x01\x62\x06proto3' 25 | , 26 | dependencies=[google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,]) 27 | 28 | 29 | 30 | 31 | _PAYLOAD_CENTRY = _descriptor.Descriptor( 32 | name='CEntry', 33 | full_name='Payload.CEntry', 34 | filename=None, 35 | file=DESCRIPTOR, 36 | containing_type=None, 37 | create_key=_descriptor._internal_create_key, 38 | fields=[ 39 | _descriptor.FieldDescriptor( 40 | name='key', full_name='Payload.CEntry.key', index=0, 41 | number=1, type=9, cpp_type=9, label=1, 42 | has_default_value=False, default_value=b"".decode('utf-8'), 43 | message_type=None, enum_type=None, containing_type=None, 44 | is_extension=False, extension_scope=None, 45 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 46 | _descriptor.FieldDescriptor( 47 | name='value', full_name='Payload.CEntry.value', index=1, 48 | number=2, type=5, cpp_type=1, label=1, 49 | has_default_value=False, default_value=0, 50 | message_type=None, enum_type=None, containing_type=None, 51 | is_extension=False, extension_scope=None, 52 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 53 | ], 54 | extensions=[ 55 | ], 56 | nested_types=[], 57 | enum_types=[ 58 | ], 59 | serialized_options=b'8\001', 60 | is_extendable=False, 61 | syntax='proto3', 62 | extension_ranges=[], 63 | oneofs=[ 64 | ], 65 | serialized_start=329, 66 | serialized_end=369, 67 | ) 68 | 69 | _PAYLOAD_WOW = _descriptor.Descriptor( 70 | name='wow', 71 | full_name='Payload.wow', 72 | filename=None, 73 | file=DESCRIPTOR, 74 | containing_type=None, 75 | create_key=_descriptor._internal_create_key, 76 | fields=[ 77 | _descriptor.FieldDescriptor( 78 | name='z', full_name='Payload.wow.z', index=0, 79 | number=1, type=9, cpp_type=9, label=1, 80 | has_default_value=False, default_value=b"".decode('utf-8'), 81 | message_type=None, enum_type=None, containing_type=None, 82 | is_extension=False, extension_scope=None, 83 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 84 | ], 85 | extensions=[ 86 | ], 87 | nested_types=[], 88 | enum_types=[ 89 | ], 90 | serialized_options=None, 91 | is_extendable=False, 92 | syntax='proto3', 93 | extension_ranges=[], 94 | oneofs=[ 95 | ], 96 | serialized_start=371, 97 | serialized_end=387, 98 | ) 99 | 100 | _PAYLOAD_EENTRY = _descriptor.Descriptor( 101 | name='EEntry', 102 | full_name='Payload.EEntry', 103 | filename=None, 104 | file=DESCRIPTOR, 105 | containing_type=None, 106 | create_key=_descriptor._internal_create_key, 107 | fields=[ 108 | _descriptor.FieldDescriptor( 109 | name='key', full_name='Payload.EEntry.key', index=0, 110 | number=1, type=9, cpp_type=9, label=1, 111 | has_default_value=False, default_value=b"".decode('utf-8'), 112 | message_type=None, enum_type=None, containing_type=None, 113 | is_extension=False, extension_scope=None, 114 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 115 | _descriptor.FieldDescriptor( 116 | name='value', full_name='Payload.EEntry.value', index=1, 117 | number=2, type=9, cpp_type=9, label=1, 118 | has_default_value=False, default_value=b"".decode('utf-8'), 119 | message_type=None, enum_type=None, containing_type=None, 120 | is_extension=False, extension_scope=None, 121 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 122 | ], 123 | extensions=[ 124 | ], 125 | nested_types=[], 126 | enum_types=[ 127 | ], 128 | serialized_options=b'8\001', 129 | is_extendable=False, 130 | syntax='proto3', 131 | extension_ranges=[], 132 | oneofs=[ 133 | ], 134 | serialized_start=389, 135 | serialized_end=429, 136 | ) 137 | 138 | _PAYLOAD_WOWS = _descriptor.Descriptor( 139 | name='wows', 140 | full_name='Payload.wows', 141 | filename=None, 142 | file=DESCRIPTOR, 143 | containing_type=None, 144 | create_key=_descriptor._internal_create_key, 145 | fields=[ 146 | _descriptor.FieldDescriptor( 147 | name='z', full_name='Payload.wows.z', index=0, 148 | number=1, type=9, cpp_type=9, label=1, 149 | has_default_value=False, default_value=b"".decode('utf-8'), 150 | message_type=None, enum_type=None, containing_type=None, 151 | is_extension=False, extension_scope=None, 152 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 153 | ], 154 | extensions=[ 155 | ], 156 | nested_types=[], 157 | enum_types=[ 158 | ], 159 | serialized_options=None, 160 | is_extendable=False, 161 | syntax='proto3', 162 | extension_ranges=[], 163 | oneofs=[ 164 | ], 165 | serialized_start=431, 166 | serialized_end=448, 167 | ) 168 | 169 | _PAYLOAD = _descriptor.Descriptor( 170 | name='Payload', 171 | full_name='Payload', 172 | filename=None, 173 | file=DESCRIPTOR, 174 | containing_type=None, 175 | create_key=_descriptor._internal_create_key, 176 | fields=[ 177 | _descriptor.FieldDescriptor( 178 | name='a', full_name='Payload.a', index=0, 179 | number=1, type=5, cpp_type=1, label=1, 180 | has_default_value=False, default_value=0, 181 | message_type=None, enum_type=None, containing_type=None, 182 | is_extension=False, extension_scope=None, 183 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 184 | _descriptor.FieldDescriptor( 185 | name='b', full_name='Payload.b', index=1, 186 | number=2, type=9, cpp_type=9, label=1, 187 | has_default_value=False, default_value=b"".decode('utf-8'), 188 | message_type=None, enum_type=None, containing_type=None, 189 | is_extension=False, extension_scope=None, 190 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 191 | _descriptor.FieldDescriptor( 192 | name='c', full_name='Payload.c', index=2, 193 | number=3, type=11, cpp_type=10, label=3, 194 | has_default_value=False, default_value=[], 195 | message_type=None, enum_type=None, containing_type=None, 196 | is_extension=False, extension_scope=None, 197 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 198 | _descriptor.FieldDescriptor( 199 | name='d', full_name='Payload.d', index=3, 200 | number=4, type=11, cpp_type=10, label=1, 201 | has_default_value=False, default_value=None, 202 | message_type=None, enum_type=None, containing_type=None, 203 | is_extension=False, extension_scope=None, 204 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 205 | _descriptor.FieldDescriptor( 206 | name='e', full_name='Payload.e', index=4, 207 | number=5, type=11, cpp_type=10, label=3, 208 | has_default_value=False, default_value=[], 209 | message_type=None, enum_type=None, containing_type=None, 210 | is_extension=False, extension_scope=None, 211 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 212 | _descriptor.FieldDescriptor( 213 | name='f', full_name='Payload.f', index=5, 214 | number=6, type=11, cpp_type=10, label=1, 215 | has_default_value=False, default_value=None, 216 | message_type=None, enum_type=None, containing_type=None, 217 | is_extension=False, extension_scope=None, 218 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 219 | _descriptor.FieldDescriptor( 220 | name='g', full_name='Payload.g', index=6, 221 | number=7, type=11, cpp_type=10, label=3, 222 | has_default_value=False, default_value=[], 223 | message_type=None, enum_type=None, containing_type=None, 224 | is_extension=False, extension_scope=None, 225 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 226 | _descriptor.FieldDescriptor( 227 | name='h', full_name='Payload.h', index=7, 228 | number=8, type=11, cpp_type=10, label=3, 229 | has_default_value=False, default_value=[], 230 | message_type=None, enum_type=None, containing_type=None, 231 | is_extension=False, extension_scope=None, 232 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 233 | _descriptor.FieldDescriptor( 234 | name='i', full_name='Payload.i', index=8, 235 | number=9, type=11, cpp_type=10, label=1, 236 | has_default_value=False, default_value=None, 237 | message_type=None, enum_type=None, containing_type=None, 238 | is_extension=False, extension_scope=None, 239 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 240 | ], 241 | extensions=[ 242 | ], 243 | nested_types=[_PAYLOAD_CENTRY, _PAYLOAD_WOW, _PAYLOAD_EENTRY, _PAYLOAD_WOWS, ], 244 | enum_types=[ 245 | ], 246 | serialized_options=None, 247 | is_extendable=False, 248 | syntax='proto3', 249 | extension_ranges=[], 250 | oneofs=[ 251 | ], 252 | serialized_start=78, 253 | serialized_end=448, 254 | ) 255 | 256 | 257 | _RESPONSE = _descriptor.Descriptor( 258 | name='Response', 259 | full_name='Response', 260 | filename=None, 261 | file=DESCRIPTOR, 262 | containing_type=None, 263 | create_key=_descriptor._internal_create_key, 264 | fields=[ 265 | _descriptor.FieldDescriptor( 266 | name='a', full_name='Response.a', index=0, 267 | number=1, type=5, cpp_type=1, label=1, 268 | has_default_value=False, default_value=0, 269 | message_type=None, enum_type=None, containing_type=None, 270 | is_extension=False, extension_scope=None, 271 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 272 | _descriptor.FieldDescriptor( 273 | name='b', full_name='Response.b', index=1, 274 | number=2, type=9, cpp_type=9, label=1, 275 | has_default_value=False, default_value=b"".decode('utf-8'), 276 | message_type=None, enum_type=None, containing_type=None, 277 | is_extension=False, extension_scope=None, 278 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 279 | ], 280 | extensions=[ 281 | ], 282 | nested_types=[], 283 | enum_types=[ 284 | ], 285 | serialized_options=None, 286 | is_extendable=False, 287 | syntax='proto3', 288 | extension_ranges=[], 289 | oneofs=[ 290 | ], 291 | serialized_start=450, 292 | serialized_end=482, 293 | ) 294 | 295 | _PAYLOAD_CENTRY.containing_type = _PAYLOAD 296 | _PAYLOAD_WOW.containing_type = _PAYLOAD 297 | _PAYLOAD_EENTRY.containing_type = _PAYLOAD 298 | _PAYLOAD_WOWS.containing_type = _PAYLOAD 299 | _PAYLOAD.fields_by_name['c'].message_type = _PAYLOAD_CENTRY 300 | _PAYLOAD.fields_by_name['d'].message_type = _PAYLOAD_WOW 301 | _PAYLOAD.fields_by_name['e'].message_type = _PAYLOAD_EENTRY 302 | _PAYLOAD.fields_by_name['f'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT 303 | _PAYLOAD.fields_by_name['g'].message_type = _PAYLOAD_WOWS 304 | _PAYLOAD.fields_by_name['h'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT 305 | _PAYLOAD.fields_by_name['i'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP 306 | DESCRIPTOR.message_types_by_name['Payload'] = _PAYLOAD 307 | DESCRIPTOR.message_types_by_name['Response'] = _RESPONSE 308 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 309 | 310 | Payload = _reflection.GeneratedProtocolMessageType('Payload', (_message.Message,), { 311 | 312 | 'CEntry' : _reflection.GeneratedProtocolMessageType('CEntry', (_message.Message,), { 313 | 'DESCRIPTOR' : _PAYLOAD_CENTRY, 314 | '__module__' : 'ssss_pb2' 315 | # @@protoc_insertion_point(class_scope:Payload.CEntry) 316 | }) 317 | , 318 | 319 | 'wow' : _reflection.GeneratedProtocolMessageType('wow', (_message.Message,), { 320 | 'DESCRIPTOR' : _PAYLOAD_WOW, 321 | '__module__' : 'ssss_pb2' 322 | # @@protoc_insertion_point(class_scope:Payload.wow) 323 | }) 324 | , 325 | 326 | 'EEntry' : _reflection.GeneratedProtocolMessageType('EEntry', (_message.Message,), { 327 | 'DESCRIPTOR' : _PAYLOAD_EENTRY, 328 | '__module__' : 'ssss_pb2' 329 | # @@protoc_insertion_point(class_scope:Payload.EEntry) 330 | }) 331 | , 332 | 333 | 'wows' : _reflection.GeneratedProtocolMessageType('wows', (_message.Message,), { 334 | 'DESCRIPTOR' : _PAYLOAD_WOWS, 335 | '__module__' : 'ssss_pb2' 336 | # @@protoc_insertion_point(class_scope:Payload.wows) 337 | }) 338 | , 339 | 'DESCRIPTOR' : _PAYLOAD, 340 | '__module__' : 'ssss_pb2' 341 | # @@protoc_insertion_point(class_scope:Payload) 342 | }) 343 | _sym_db.RegisterMessage(Payload) 344 | _sym_db.RegisterMessage(Payload.CEntry) 345 | _sym_db.RegisterMessage(Payload.wow) 346 | _sym_db.RegisterMessage(Payload.EEntry) 347 | _sym_db.RegisterMessage(Payload.wows) 348 | 349 | Response = _reflection.GeneratedProtocolMessageType('Response', (_message.Message,), { 350 | 'DESCRIPTOR' : _RESPONSE, 351 | '__module__' : 'ssss_pb2' 352 | # @@protoc_insertion_point(class_scope:Response) 353 | }) 354 | _sym_db.RegisterMessage(Response) 355 | 356 | 357 | _PAYLOAD_CENTRY._options = None 358 | _PAYLOAD_EENTRY._options = None 359 | 360 | _TEST = _descriptor.ServiceDescriptor( 361 | name='Test', 362 | full_name='Test', 363 | file=DESCRIPTOR, 364 | index=0, 365 | serialized_options=None, 366 | create_key=_descriptor._internal_create_key, 367 | serialized_start=484, 368 | serialized_end=554, 369 | methods=[ 370 | _descriptor.MethodDescriptor( 371 | name='One', 372 | full_name='Test.One', 373 | index=0, 374 | containing_service=None, 375 | input_type=_PAYLOAD, 376 | output_type=_RESPONSE, 377 | serialized_options=None, 378 | create_key=_descriptor._internal_create_key, 379 | ), 380 | _descriptor.MethodDescriptor( 381 | name='Two', 382 | full_name='Test.Two', 383 | index=1, 384 | containing_service=None, 385 | input_type=_PAYLOAD, 386 | output_type=_RESPONSE, 387 | serialized_options=None, 388 | create_key=_descriptor._internal_create_key, 389 | ), 390 | ]) 391 | _sym_db.RegisterServiceDescriptor(_TEST) 392 | 393 | DESCRIPTOR.services_by_name['Test'] = _TEST 394 | 395 | # @@protoc_insertion_point(module_scope) 396 | -------------------------------------------------------------------------------- /tests/test_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: test.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor.FileDescriptor( 17 | name='test.proto', 18 | package='protobuf_json_test', 19 | syntax='proto2', 20 | serialized_options=None, 21 | create_key=_descriptor._internal_create_key, 22 | serialized_pb=b'\n\ntest.proto\x12\x12protobuf_json_test\"\xfc\x02\n\x0bTestMessage\x12\n\n\x02id\x18\x01 \x02(\x05\x12\x13\n\x05query\x18\x02 \x01(\t:\x04test\x12\x0c\n\x04\x66lag\x18\x03 \x01(\x08\x12?\n\ttest_enum\x18\x04 \x01(\x0e\x32(.protobuf_json_test.TestMessage.TestEnum:\x02V1\x12=\n\nnested_msg\x18\x05 \x02(\x0b\x32).protobuf_json_test.TestMessage.NestedMsg\x12>\n\x0bnested_msgs\x18\x06 \x03(\x0b\x32).protobuf_json_test.TestMessage.NestedMsg\x12\x0f\n\x07rep_int\x18\x07 \x03(\x05\x12\t\n\x01\x62\x18\x08 \x01(\x0c\x12\n\n\x02\x62s\x18\t \x03(\x0c\x1a\x33\n\tNestedMsg\x12\n\n\x02id\x18\x01 \x02(\x05\x12\r\n\x05title\x18\x02 \x01(\t\x12\x0b\n\x03url\x18\x03 \x01(\t\"\x1a\n\x08TestEnum\x12\x06\n\x02V1\x10\x01\x12\x06\n\x02V2\x10\x02*\x05\x08\x64\x10\xc8\x01:8\n\x05query\x12\x1f.protobuf_json_test.TestMessage\x18\x64 \x01(\t:\x08test ext:-\n\x04long\x12\x1f.protobuf_json_test.TestMessage\x18\x65 \x01(\x04' 23 | ) 24 | 25 | 26 | QUERY_FIELD_NUMBER = 100 27 | query = _descriptor.FieldDescriptor( 28 | name='query', full_name='protobuf_json_test.query', index=0, 29 | number=100, type=9, cpp_type=9, label=1, 30 | has_default_value=True, default_value=b"test ext".decode('utf-8'), 31 | message_type=None, enum_type=None, containing_type=None, 32 | is_extension=True, extension_scope=None, 33 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) 34 | LONG_FIELD_NUMBER = 101 35 | long = _descriptor.FieldDescriptor( 36 | name='long', full_name='protobuf_json_test.long', index=1, 37 | number=101, type=4, cpp_type=4, label=1, 38 | has_default_value=False, default_value=0, 39 | message_type=None, enum_type=None, containing_type=None, 40 | is_extension=True, extension_scope=None, 41 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) 42 | 43 | _TESTMESSAGE_TESTENUM = _descriptor.EnumDescriptor( 44 | name='TestEnum', 45 | full_name='protobuf_json_test.TestMessage.TestEnum', 46 | filename=None, 47 | file=DESCRIPTOR, 48 | create_key=_descriptor._internal_create_key, 49 | values=[ 50 | _descriptor.EnumValueDescriptor( 51 | name='V1', index=0, number=1, 52 | serialized_options=None, 53 | type=None, 54 | create_key=_descriptor._internal_create_key), 55 | _descriptor.EnumValueDescriptor( 56 | name='V2', index=1, number=2, 57 | serialized_options=None, 58 | type=None, 59 | create_key=_descriptor._internal_create_key), 60 | ], 61 | containing_type=None, 62 | serialized_options=None, 63 | serialized_start=382, 64 | serialized_end=408, 65 | ) 66 | _sym_db.RegisterEnumDescriptor(_TESTMESSAGE_TESTENUM) 67 | 68 | 69 | _TESTMESSAGE_NESTEDMSG = _descriptor.Descriptor( 70 | name='NestedMsg', 71 | full_name='protobuf_json_test.TestMessage.NestedMsg', 72 | filename=None, 73 | file=DESCRIPTOR, 74 | containing_type=None, 75 | create_key=_descriptor._internal_create_key, 76 | fields=[ 77 | _descriptor.FieldDescriptor( 78 | name='id', full_name='protobuf_json_test.TestMessage.NestedMsg.id', index=0, 79 | number=1, type=5, cpp_type=1, label=2, 80 | has_default_value=False, default_value=0, 81 | message_type=None, enum_type=None, containing_type=None, 82 | is_extension=False, extension_scope=None, 83 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 84 | _descriptor.FieldDescriptor( 85 | name='title', full_name='protobuf_json_test.TestMessage.NestedMsg.title', index=1, 86 | number=2, type=9, cpp_type=9, label=1, 87 | has_default_value=False, default_value=b"".decode('utf-8'), 88 | message_type=None, enum_type=None, containing_type=None, 89 | is_extension=False, extension_scope=None, 90 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 91 | _descriptor.FieldDescriptor( 92 | name='url', full_name='protobuf_json_test.TestMessage.NestedMsg.url', index=2, 93 | number=3, type=9, cpp_type=9, label=1, 94 | has_default_value=False, default_value=b"".decode('utf-8'), 95 | message_type=None, enum_type=None, containing_type=None, 96 | is_extension=False, extension_scope=None, 97 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 98 | ], 99 | extensions=[ 100 | ], 101 | nested_types=[], 102 | enum_types=[ 103 | ], 104 | serialized_options=None, 105 | is_extendable=False, 106 | syntax='proto2', 107 | extension_ranges=[], 108 | oneofs=[ 109 | ], 110 | serialized_start=329, 111 | serialized_end=380, 112 | ) 113 | 114 | _TESTMESSAGE = _descriptor.Descriptor( 115 | name='TestMessage', 116 | full_name='protobuf_json_test.TestMessage', 117 | filename=None, 118 | file=DESCRIPTOR, 119 | containing_type=None, 120 | create_key=_descriptor._internal_create_key, 121 | fields=[ 122 | _descriptor.FieldDescriptor( 123 | name='id', full_name='protobuf_json_test.TestMessage.id', index=0, 124 | number=1, type=5, cpp_type=1, label=2, 125 | has_default_value=False, default_value=0, 126 | message_type=None, enum_type=None, containing_type=None, 127 | is_extension=False, extension_scope=None, 128 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 129 | _descriptor.FieldDescriptor( 130 | name='query', full_name='protobuf_json_test.TestMessage.query', index=1, 131 | number=2, type=9, cpp_type=9, label=1, 132 | has_default_value=True, default_value=b"test".decode('utf-8'), 133 | message_type=None, enum_type=None, containing_type=None, 134 | is_extension=False, extension_scope=None, 135 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 136 | _descriptor.FieldDescriptor( 137 | name='flag', full_name='protobuf_json_test.TestMessage.flag', index=2, 138 | number=3, type=8, cpp_type=7, label=1, 139 | has_default_value=False, default_value=False, 140 | message_type=None, enum_type=None, containing_type=None, 141 | is_extension=False, extension_scope=None, 142 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 143 | _descriptor.FieldDescriptor( 144 | name='test_enum', full_name='protobuf_json_test.TestMessage.test_enum', index=3, 145 | number=4, type=14, cpp_type=8, label=1, 146 | has_default_value=True, default_value=1, 147 | message_type=None, enum_type=None, containing_type=None, 148 | is_extension=False, extension_scope=None, 149 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 150 | _descriptor.FieldDescriptor( 151 | name='nested_msg', full_name='protobuf_json_test.TestMessage.nested_msg', index=4, 152 | number=5, type=11, cpp_type=10, label=2, 153 | has_default_value=False, default_value=None, 154 | message_type=None, enum_type=None, containing_type=None, 155 | is_extension=False, extension_scope=None, 156 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 157 | _descriptor.FieldDescriptor( 158 | name='nested_msgs', full_name='protobuf_json_test.TestMessage.nested_msgs', index=5, 159 | number=6, type=11, cpp_type=10, label=3, 160 | has_default_value=False, default_value=[], 161 | message_type=None, enum_type=None, containing_type=None, 162 | is_extension=False, extension_scope=None, 163 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 164 | _descriptor.FieldDescriptor( 165 | name='rep_int', full_name='protobuf_json_test.TestMessage.rep_int', index=6, 166 | number=7, type=5, cpp_type=1, label=3, 167 | has_default_value=False, default_value=[], 168 | message_type=None, enum_type=None, containing_type=None, 169 | is_extension=False, extension_scope=None, 170 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 171 | _descriptor.FieldDescriptor( 172 | name='b', full_name='protobuf_json_test.TestMessage.b', index=7, 173 | number=8, type=12, cpp_type=9, label=1, 174 | has_default_value=False, default_value=b"", 175 | message_type=None, enum_type=None, containing_type=None, 176 | is_extension=False, extension_scope=None, 177 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 178 | _descriptor.FieldDescriptor( 179 | name='bs', full_name='protobuf_json_test.TestMessage.bs', index=8, 180 | number=9, type=12, cpp_type=9, label=3, 181 | has_default_value=False, default_value=[], 182 | message_type=None, enum_type=None, containing_type=None, 183 | is_extension=False, extension_scope=None, 184 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 185 | ], 186 | extensions=[ 187 | ], 188 | nested_types=[_TESTMESSAGE_NESTEDMSG, ], 189 | enum_types=[ 190 | _TESTMESSAGE_TESTENUM, 191 | ], 192 | serialized_options=None, 193 | is_extendable=True, 194 | syntax='proto2', 195 | extension_ranges=[(100, 200), ], 196 | oneofs=[ 197 | ], 198 | serialized_start=35, 199 | serialized_end=415, 200 | ) 201 | 202 | _TESTMESSAGE_NESTEDMSG.containing_type = _TESTMESSAGE 203 | _TESTMESSAGE.fields_by_name['test_enum'].enum_type = _TESTMESSAGE_TESTENUM 204 | _TESTMESSAGE.fields_by_name['nested_msg'].message_type = _TESTMESSAGE_NESTEDMSG 205 | _TESTMESSAGE.fields_by_name['nested_msgs'].message_type = _TESTMESSAGE_NESTEDMSG 206 | _TESTMESSAGE_TESTENUM.containing_type = _TESTMESSAGE 207 | DESCRIPTOR.message_types_by_name['TestMessage'] = _TESTMESSAGE 208 | DESCRIPTOR.extensions_by_name['query'] = query 209 | DESCRIPTOR.extensions_by_name['long'] = long 210 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 211 | 212 | TestMessage = _reflection.GeneratedProtocolMessageType('TestMessage', (_message.Message,), { 213 | 214 | 'NestedMsg' : _reflection.GeneratedProtocolMessageType('NestedMsg', (_message.Message,), { 215 | 'DESCRIPTOR' : _TESTMESSAGE_NESTEDMSG, 216 | '__module__' : 'test_pb2' 217 | # @@protoc_insertion_point(class_scope:protobuf_json_test.TestMessage.NestedMsg) 218 | }) 219 | , 220 | 'DESCRIPTOR' : _TESTMESSAGE, 221 | '__module__' : 'test_pb2' 222 | # @@protoc_insertion_point(class_scope:protobuf_json_test.TestMessage) 223 | }) 224 | _sym_db.RegisterMessage(TestMessage) 225 | _sym_db.RegisterMessage(TestMessage.NestedMsg) 226 | 227 | TestMessage.RegisterExtension(query) 228 | TestMessage.RegisterExtension(long) 229 | 230 | # @@protoc_insertion_point(module_scope) 231 | -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ed-XCF/protobuf2pydantic/a455c06a804bb6e14564e37a9f62bf37b2496ace/version --------------------------------------------------------------------------------