protobuf-to-pydantic


Nameprotobuf-to-pydantic JSON
Version 0.2.6.2 PyPI version JSON
download
home_pagehttps://github.com/so1n/protobuf_to_pydantic
SummaryGenerate the `pydantic.BaseModel` class (and the corresponding source code) with parameter verification function through the Protobuf file
upload_time2024-04-17 16:04:41
maintainerNone
docs_urlNone
authorSo1n
requires_python<4.0,>=3.7
licenseApache Software License
keywords
VCS
bugtrack_url
requirements annotated-types importlib-metadata protobuf pydantic-core pydantic toml typing-extensions zipp
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # protobuf_to_pydantic
Generate Pydantic Model or source code with parameter verification function based on Protobuf file (Proto3).


[中文文档](https://github.com/so1n/protobuf_to_pydantic/blob/master/README_ZH.md)

# Feature

Feature:
- [x] Generate source code through `Protobuf` plugin。
- [x] Generate `Pydantic Model` or source code by parsing `Protobuf Message` in `Python` runtime.
- [x] Compatible with `V1` and `V2` versions of `Pydantic`。
- [x] Supports multiple verification rules and is compatible with `proto-gen-validate` (subsequent versions will support the rules of `proto-gen-validate` 1.0)。
- [x] Support custom functionality through templates。
- [ ] Supports `protovalidate` verification rules(`proto-gen-validate` version >= 1.0)

The following is a functional overview diagram of `protobuf-to-pydantic`.
In the picture `P2P` represents `protobuf-to-pydantic`, `Protoc` represents the command for `Protobuf` to generate code, and `plugin` represents ` Plugin for Protoc`:
![protobuf-to-pydantic](https://github.com/so1n/protobuf_to_pydantic/blob/master/images/protobuf-to-pydantic_index.png?raw=true)

# Installation
By default, `protobuf-to-pydantic` can be installed directly via the following command:
```bash
pip install protobuf_to_pydantic
```
If want to use the full functionality of `protobuf-to-pydantic`, can install `protobuf-to-pydantic` with the following command:.
```bash
pip install protobuf_to_pydantic[all]
```
# Usage
## 1.code generation
`protobuf-to-pydantic` currently has two methods to generate `Pydantic Model` objects based on Protobuf files.:
- 1: Use the `Protoc` plug-in to generate the corresponding `Python` code file through the Protobuf file。
- 2: Generate the corresponding `Pydantic Model` object through the `Message` object in `Python` runtime。

### 1.1.Directly generate `Pydantic Model` code files through plug-ins
#### 1.1.0.Install dependencies
The `protobuf-to-pydantic` plug-in depends on `mypy-protobuf`, need to install `mypy-protobuf` through the following command first:
```bash
python -m pip install protobuf-to-pydantic[mypy-protobuf]
```
or
```bash
poetry add protobuf-to-pydantic -E mypy-protobuf
```
#### 1.1.1.Use plugins
Plug-in is the `Pydantic Model` source code generation method recommended by `protobuf-to-pydantic`.
It supports the most complete functions and is also very simple to use.

Assume that it is usually generated through the following command Code corresponding to Protobuf file:
```bash
python -m grpc_tools.protoc -I. example.proto
# or
protoc -I. --python_out=. example.proto
```
After installing `protobuf-to-pydantic`,can use the `protobuf-to-pydantic` plugin with the `--protobuf-to-pydantic_out` option with the following command:
```bash
python -m grpc_tools.protoc -I. --protobuf-to-pydantic_out=. example.proto
# or
protoc -I. --protobuf-to-pydantic_out=. example.proto
```

In this command, `--protobuf-to-pydantic_out=.` means using the `prorobuf-to-pydantic` plug-in,
And it is declared that the output location of the `protobuf-to-pydantic` plug-in is `.`

> `.` indicates the output path used by `grpc_tools.proto`.

After running the command, the `protobuf-to-pydantic` plugin writes the generated source code to a file with the filename suffix `p2p.py`, e.g., `example.proto` generates a file with the name `example_p2p.py`.


#### 1.1.2.Plug-in configuration
The `protobuf-to-pydantic` plugin supports loading configuration by reading a `Python` file。

> In order to ensure that the variables of the configuration file can be introduced normally, the configuration file must be stored in the current path of the running command.。

An example configuration that can be read by `protobuf-to-pydantic` is as follows:
```Python
import logging
from typing import List, Type

from google.protobuf.any_pb2 import Any  # type: ignore
from pydantic import confloat, conint
from pydantic.fields import FieldInfo

from protobuf_to_pydantic.desc_template import DescTemplate

# Configure the log output format and log level of the plugin, which is very useful when debugging
logging.basicConfig(format="[%(asctime)s %(levelname)s] %(message)s", datefmt="%y-%m-%d %H:%M:%S", level=logging.DEBUG)


class CustomerField(FieldInfo):
    pass


def customer_any() -> Any:
    return Any  # type: ignore


# For the configuration of the local template, see the use of the local template for details
local_dict = {
    "CustomerField": CustomerField,
    "confloat": confloat,
    "conint": conint,
    "customer_any": customer_any,
}
# Specifies the start of key comments
comment_prefix = "p2p"
# Specify the class of the template, can extend the template by inheriting this class, see the chapter on custom templates for details
desc_template: Type[DescTemplate] = DescTemplate
# Specify the protobuf files of which packages to ignore, and the messages of the ignored packages will not be parsed
ignore_pkg_list: List[str] = ["validate", "p2p_validate"]
# Specifies the generated file name suffix (without .py)
file_name_suffix = "_p2p"
```
Next, in order to be able to read this file, need to change the `--protobuf-to-pydantic_out=. ` to ` --protobuf-to-pydantic_out=config_path=plugin_config.py:. `.
where the left side of `:` indicates that the configuration file path to be read is `plugin_config.py`, and the right side of `:` declares that the output location of the `protobuf-to-pydantic` plugin is `. `
The final complete command is as follows:
```bash
python -m grpc_tools.protoc -I. --protobuf-to-pydantic_out=config_path=plugin_config.py:. example.proto
# or
protoc -I. --protobuf-to-pydantic_out=config_path=plugin_config.py:. example.proto
```
Through this command, can load the corresponding configuration and run the `protobuf-to-pydantic` plug-in。

In addition to the configuration options in the example configuration file,
the `protobuf-to-pydantic` plug-in also supports other configuration options.
The specific configuration instructions are as follows:

| Configuration name            | Functional module                      | Type                                            | Hidden meaning                                                                                                                                      |
|-------------------------------|----------------------------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| local_dict                    | Template                               | dict                                            | Holds variables for the `local` template                                                                                                            |
| desc_template                 | Template                               | protobuf_to_pydantic.desc_template.DescTemplate | Implementation of the template class                                                                                                                |
| comment_prefix                | Template                               | str                                             | Comment prefix.Only strings with a fixed prefix will be used by the template                                                                        |
| customer_import_set           | Code generation                        | `Set[str]`                                      | A collection of custom import statements, such as `from typing import Set`or `import typing`, that will write data in order to the source code file |
| customer_deque                | Code generation                        | `deque[str]`                                    | Custom source file content, used to add custom content                                                                                              |
| module_path                   | str                                    | str                                             | Used to define the root path of the project or module, which helps `protobuf-to-pydantic`to better automatically generate module import statements   |
| pyproject_file_path           | Code generation                        | str                                             | Define the pyproject file path, which defaults to the current project path                                                                          |
| code_indent                   | Code generation                        | int                                             | Defines the number of indentation Spaces in the code; the default is 4                                                                              |
| ignore_pkg_list               | Code generation(Limit plug-ins only)   | `list[str]`                                     | Definition ignores parsing of the specified package file                                                                                            |
| base_model_class              | Model Code generation, Code generation | `Type[BaseModel]`                               | Define the parent class of the generated Model                                                                                                      |
| file_name_suffix              | Code generation                        | str                                             | Define the generated file suffix, default `_p2p.py`                                                                                                 |
| file_descriptor_proto_to_code | Code generation(Limit plug-ins only)   | `Type[FileDescriptorProtoToCode]`               | Define the `FileDescriptorProtoToCode` to use                                                                                                       |


#### 1.1.3.buf-cli
If you are using `buf-cli` to manage Protobuf files,
then you can also use `protobuf-to-pydantic` in `buf-cli`, See [How to use `protobuf-to-pydantic` in `buf-cli`](https://github.com/so1n/protobuf_to_pydantic/blob/master/buf-plugin/README.md)

### 1.2.Generate a `Pydantic Model` object in Python runtime
`protobuf_to_pydantic` can generate the corresponding `PydanticModel` object based on the `Message` object at runtime。

For example, the `UserMessage` in the following Protobuf file named `demo.proto`:
```protobuf
// path: ./demo.proto
syntax = "proto3";
package user;

enum SexType {
  man = 0;
  women = 1;
}

message UserMessage {
  string uid=1;
  int32 age=2;
  float height=3;
  SexType sex=4;
  bool is_adult=5;
  string user_name=6;
}
```
`protoc` can be used to generate the Python code file corresponding to the `Protobuf` file (the file name is `demo_pb2.py`), and the code related to the `UserMessage` is stored in the code file.

At `Python` runtime, The func `msg_to_pydantic_model` can be called to read the `UserMessage` object from the `demo_pb2` module and generate the corresponding `Pydantic Model` object as follows:
```Python
from typing import Type
from protobuf_to_pydantic import msg_to_pydantic_model
from pydantic import BaseModel

# import protobuf gen python obj
from . import demo_pb2

UserModel: Type[BaseModel] = msg_to_pydantic_model(demo_pb2.UserMessage)
print(
    {
        k: v.field_info
        for k, v in UserModel.__fields__.items()
    }
)

# output
# {
#   `uid`: FieldInfo(default=``, extra={}),
#   `age`: FieldInfo(default=0, extra={}),
#   `height`: FieldInfo(default=0.0, extra={}),
#   `sex`: FieldInfo(default=0, extra={}),
#   `is_adult`: FieldInfo(default=False, extra={}),
#   `user_name`: FieldInfo(default=``, extra={})
#  }
```
Through the output results, it can be found that the generated `pydantic.BaseModel` object also contains `uid`, `age`, `height`, `sex`, `is adult` and `user name` fields,
and the `default` property matches the zero value of the Protobuf type。

The `msg_to_pydantic_model` func is customizable just like plugins, with the following extension parameters:

| Fields                                    | Meaning                                                   |
|-------------------------------------------|-----------------------------------------------------------|
| default_field                             | Generate a `Field` for each field in the `Pydantic Model` |
| comment_prefix                            | The prefix of a comment that can be parsed                |
| parse_msg_desc_method                     | Parsing rules to use                                      |
| local_dict                                | Variables used by the `local` template                    |
| pydantic_base                             | Generates the parent class of the `Pydantic Model` object |
| pydantic_module                           | Generate the `Module` of the `Pydantic Model` object      |
| desc_template                             | Template class to use                                     |
| message_type_dict_by_type_name            | Protobuf type mapping to `Python` type                    |
| message_default_factory_dict_by_type_name | Protobuf type mapping to the Python type factory          |


In addition to generating the corresponding `Pydantic Model` object at runtime,
`protobuf-to-pydantic` also supports converting `Pydantic Model` objects to Python code text at runtime (only compatible with `Pydantic Model` objects generated by `protobuf-to-pydantic`).
The `pydantic_model_to_py_code` func is used to generate the source code, and the `pydantic_model_to_py_file` func is used to generate the code file. The example code of the `pydantic_model_to_py_file` func is as follows:

```Python
from protobuf_to_pydantic import msg_to_pydantic_model, pydantic_model_to_py_file

# import protobuf gen python obj
from example.example_proto_python_code.example_proto.demo import demo_pb2

pydantic_model_to_py_file(
    "./demo_gen_code.py",
    msg_to_pydantic_model(demo_pb2.NestedMessage),
)
```
When the code runs, it converts`demo_pb2.NestedMessage`to a Pydantic Model object and passes it to the  `pydantic_model_to_py_file`. `pydantic_model_to_py_file` generates the source code and writes it to a `demo_gen_code.py` file.


## 2.Parameter validation
In the previous section, the `Pydantic Model` object generated by the Protobuf file is very simple because the Protobuf file does not have enough parameters to verify the relevant information.
In order for each field in the generated `Pydantic Model` object to have parameter validation capabilities, the corresponding parameter checking rules for the field need to be refined in the Protobuf file.

Currently, `protobuf-to-pydantic` supports three validation rules:
- 1.Text annotations
- 2.PGV(protoc-geb-validate)
- 3.P2P

With these rules, the `Pydantic Model` object generated by `protobuf-to-pydantic` will have parameter validation feature.
Among them, text annotations and P2P rules are consistent, they both support most of the parameters in `Pydantic Field`, some of the variations and new parameters are seen
[2.4.`P2P` and text annotation rule other parameter support](#24p2p-and-text-comment-rule-other-parameter-support)

> NOTE:
>  - 1.Text annotation rules are not the focus of subsequent functional iterative development, and it is recommended to use P2P verification rules.
>  - 2.`Protoc Plug-in` only support `PGV` and `P2P` rule.


### 2.1.Text annotations
In the Protobuf file, can write annotations for each field that meet the requirements of `protobuf-to-pydantic`,
so that `protobuf-to-pydantic` can obtain the validation information of the parameters when parsing the Protobuf file, such as the following example
```protobuf
syntax = "proto3";
package user;

enum SexType {
  man = 0;
  women = 1;
}

// user info
message UserMessage {
  // p2p: {"required": true, "example": "10086"}
  // p2p: {"title": "UID"}
  string uid=1; // p2p: {"description": "user union id"}
  // p2p: {"example": 18, "title": "use age", "ge": 0}
  int32 age=2;
  // p2p: {"ge": 0, "le": 2.5}
  float height=3;
  SexType sex=4;
  bool is_adult=5;
  // p2p: {"description": "user name"}
  // p2p: {"default": "", "min_length": 1, "max_length": "10", "example": "so1n"}
  string user_name=6;
}
```

In this example, each annotation that can be used by `protobuf_to_pydantic` starts with `p2p:` (supports customization) and is followed by a complete Json string. If are familiar with the usage of `pydantic`, can find This Json string contains the verification information corresponding to `pydantic.Field`. For example, the `uid` field in `UserMessage` contains a total of 4 pieces of information as follows:

| Column      | Meaning                                                                               |
|-------------|---------------------------------------------------------------------------------------|
| required    | Indicates that the generated field does not have a default value                      |
| example     | An example value representing the generated field is 10086                            |
| title       | Indicates that the schema name of the field is UID                                    |
 | description | The schema documentation for the representation field is described as `user_union_id` |

> Note:
>   - 1.Currently only single-line comments are supported and comments must be a complete Json data (no line breaks).
>   - 2.multi line comments are not supported。

When these annotations are written, `protobuf_to_pydantic` will bring the corresponding information for each field when converting the Message into the corresponding `Pydantic.BaseModel` object, as follows:

```python
# pydantic version V1
from typing import Type
from protobuf_to_pydantic import msg_to_pydantic_model
from pydantic import BaseModel

# import protobuf gen python obj
from example.example_proto_python_code.example_proto.demo import demo_pb2

UserModel: Type[BaseModel] = msg_to_pydantic_model(demo_pb2.UserMessage, parse_msg_desc_method=demo_pb2)
print(
    {
        k: v.field_info
        for k, v in UserModel.__fields__.items()
    }
)
# output
# {
#   `uid`: FieldInfo(default=PydanticUndefined, title=`UID`, description=`user union id`, extra={`example`: `10086`}),
#   `age`: FieldInfo(default=0, title=`use age`, ge=0, extra={`example`: 18}),
#   `height`: FieldInfo(default=0.0, ge=0, le=2, extra={}),
#   `sex`: FieldInfo(default=0, extra={}),
#   `is_adult`: FieldInfo(default=False, extra={}),
#   `user_name`: FieldInfo(default=``, description=`user name`, min_length=1, max_length=10, extra={`example`: `so1n`})
# }
```
It can be seen that the output fields carry the corresponding information, which is consistent with the comments of the Protobuf file.

In addition, this code differs from the previous section in that the `msg_to_pydantic_model` function has a keyword argument named `parse_msg_desc_method` and its value is the 'demo_pb2' module.
This parameter enables `protobuf-to-pydantic` to obtain additional information about each field in the Message object through comments in the `.pyi` file of the `demo_pb2` module.

> Note: This function needs to use the [mypy-protobuf](https://github.com/nipunn1313/mypy-protobuf) plugin when generating the corresponding `Python code through the Protobuf file, and the specified pyi file output path is the same as the generated `Python` code path to take effect.
> And need to install `protobuf-to-pydantic` via the `python -m pip install protobuf-to-pydantic[mypy-protobuf]` command

In addition to getting comments from the `.pyi` file, `protobuf-to-pydantic` also supports getting comment information for each field through comments on the Protobuf file to which the Message object belongs.
Using this feature is as simple as setting the value of `parse_msg_desc_method` to the root directory path specified when the Message object was generated.

> When using this method, make sure to install `protobuf-to-pydantic` via `python -m pip install protobuf-to-pydantic[lark]`, and also make sure that the Protobuf file exists in the project.

For example, the project structure of the `protobuf-to-pydantic` sample code is as follows:
```bash
./protobuf_to_pydantic/
├── example/
│ ├── python_example_proto_code/
│ └── example_proto/
├── protobuf_to_pydantic/
└── /
```

The Protobuf file is stored in the `example/example_proto` folder, and then run the following command in the `example` directory to generate the `Python` code file corresponding to Protobuf:
```bash
cd example

python -m grpc_tools.protoc
  --python_out=./python_example_proto_code \
  --grpc_python_out=./python_example_proto_code \
  -I. \
# or
protoc
  --python_out=./python_example_proto_code \
  --grpc_python_out=./python_example_proto_code \
  -I. \
```
Then the path that needs to be filled in for `parse_msg_desc_method` at this time is `./protobuf_to_pydantic/example`.
The following sample code:
```python
# pydantic Version v1
from typing import Type
from protobuf_to_pydantic import msg_to_pydantic_model
from pydantic import BaseModel

# import protobuf gen python obj
from example.proto_3_20_pydanticv1.example.example_proto.demo import demo_pb2

UserModel: Type[BaseModel] = msg_to_pydantic_model(
    demo_pb2.UserMessage, parse_msg_desc_method="./protobuf_to_pydantic/example"
)
print(
    {
        k: v.field_info
        for k, v in UserModel.__fields__.items()
    }
)
# output
# {
#   `uid`: FieldInfo(default=PydanticUndefined, title=`UID`, description=`user union id`, extra={`example`: `10086`}),
#   `age`: FieldInfo(default=0, title=`use age`, ge=0, extra={`example`: 18}),
#   `height`: FieldInfo(default=0.0, ge=0, le=2, extra={}),
#   `sex`: FieldInfo(default=0, extra={}),
#   `is_adult`: FieldInfo(default=False, extra={}),
#   `user_name`: FieldInfo(default=``, description=`user name`, min_length=1, max_length=10, extra={`example`: `so1n`})
# }
```
As you can see, the only difference in this code is the value of the `parse_msg_desc_method`, but through the output result, you can see that the field carries the same information as the result obtained through the module.

### 2.2.PGV(protoc-gen-validate)
At present, the commonly used parameter verification project in the Protobuf ecosystem is [protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate),
It has become a common standard in Protobuf because it supports multiple languages and requires only one writing of `PGV` rules to make the generated `Message` object support the corresponding validation rules.

> Currently `protobuf-to-pydantic` only supports rules that [protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate) is less than version 1.0.0

`protobuf-to-pydantic` supports parsing of `PGV` validation rules and generates `Pydantic Model` objects with validation logic functions.
Using `PGV` checksum rules in `protobuf-to-pydantic` is very simple, just write the corresponding `PGV` rules in the Protobuf file first,
and then specify the value of `parse_msg_desc_method` to be `PGV` when calling `msg_to_pydantic_model` as the code below:
```Python
# pydantic version V1
from typing import Type
from protobuf_to_pydantic import msg_to_pydantic_model
from pydantic import BaseModel

# import protobuf gen python obj
from example.proto_3_20_pydanticv1.example.example_proto.validate import demo_pb2

UserModel: Type[BaseModel] = msg_to_pydantic_model(
    demo_pb2.FloatTest, parse_msg_desc_method="PGV"
)
print(
    {
        k: v.field_info
        for k, v in UserModel.__fields__.items()
    }
)
# output
# {
#   `const_test`: FieldInfo(default=1.0, const=True, extra={}),
#   `range_e_test`: FieldInfo(default=0.0, ge=1, le=10, extra={}),
#   `range_test`: FieldInfo(default=0.0, gt=1, lt=10, extra={}),
#   `in_test`: FieldInfo(default=0.0, extra={`in`: [1.0, 2.0, 3.0]}),
#   `not_in_test`: FieldInfo(default=0.0, extra={`not_in`: [1.0, 2.0, 3.0]}),
#   `ignore_test`: FieldInfo(default=0.0, extra={})
# }
```

> Note:
>  - 1.For the usage of `PGV`, see: [protoc-gen-validate doc](https://github.com/bufbuild/protoc-gen-validate/blob/v0.10.2-SNAPSHOT.17/README.md)
>  - 2.Need to install `PGV` through `pip install protoc_gen_validate` or download [validate.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/common/validate.proto) to the protobuf directory in the project to write pgv rules in the Protobuf file.


### 2.3.P2P
The `PGV` verification rules are written in the Option attribute of each field of `Message` and have a better code specification,
so Protobuf that use `PGV` checksum rules will be more readable than Protobuf that use annotation .

At the same time, when writing `PGV` rules, can also experience the convenience of the IDE's auto-completion and the security of checksumming when generating the corresponding language objects from Protobuf files, but it only supports checksumming-related logic, which is not as rich as the file annotation mode.


The `P2P` verification rule that comes with `protobuf-to-pydantic` expands on the `PGV` verification rule by incorporating some of the functionality of the text annotation verification rule, which satisfies most of the customization of the properties of each `Field` in the `Pydantic Model`, such as the following Protobuf file.
```protobuf
syntax = "proto3";
package p2p_validate_test;

import "example_proto/common/p2p_validate.proto";


message FloatTest {
  float const_test = 1 [(p2p_validate.rules).float.const = 1];
  float range_e_test = 2 [(p2p_validate.rules).float = {ge: 1, le: 10}];
  float range_test = 3[(p2p_validate.rules).float = {gt: 1, lt: 10}];
  float in_test = 4[(p2p_validate.rules).float = {in: [1,2,3]}];
  float not_in_test = 5[(p2p_validate.rules).float = {not_in: [1,2,3]}];
  float default_test = 6[(p2p_validate.rules).float.default = 1.0];
  float not_enable_test = 7[(p2p_validate.rules).float.enable = false];
  float default_factory_test = 8[(p2p_validate.rules).float.default_factory = "p2p@builtin|float"];
  float miss_default_test = 9[(p2p_validate.rules).float.miss_default = true];
  float alias_test = 10 [(p2p_validate.rules).float.alias = "alias"];
  float desc_test = 11 [(p2p_validate.rules).float.description = "test desc"];
  float multiple_of_test = 12 [(p2p_validate.rules).float.multiple_of = 3.0];
  float example_test = 13 [(p2p_validate.rules).float.example = 1.0];
  float example_factory = 14 [(p2p_validate.rules).float.example_factory = "p2p@builtin|float"];
  float field_test = 15[(p2p_validate.rules).float.field = "p2p@local|CustomerField"];
  float type_test = 16[(p2p_validate.rules).float.type = "p2p@local|confloat"];
  float title_test = 17 [(p2p_validate.rules).float.title = "title_test"];
}
```
`protobuf-to-pydantic` can read the generated Message object at runtime and generate a `Pydantic Model` object with the corresponding information:

```python
# pydantic version V1
from typing import Type
from protobuf_to_pydantic import msg_to_pydantic_model
from pydantic import BaseModel, confloat
from pydantic.fields import FieldInfo

# import protobuf gen python obj
from example.proto_3_20_pydanticv1.example.example_proto.p2p_validate import demo_pb2


class CustomerField(FieldInfo):
    pass


DemoModel: Type[BaseModel] = msg_to_pydantic_model(
    demo_pb2.FloatTest,
    local_dict={"CustomerField": CustomerField, "confloat": confloat},
)
print(
    {
        k: v.field_info
        for k, v in DemoModel.__fields__.items()
    }
)
# output:
# {
#   'const_test': FieldInfo(default=1.0, const=True, extra={}),
#   'range_e_test': FieldInfo(default=0.0, ge=1, le=10, extra={}),
#   'range_test': FieldInfo(default=0.0, gt=1, lt=10, extra={}),
#   'in_test': FieldInfo(default=0.0, extra={'in': [1.0, 2.0, 3.0]}),
#   'not_in_test': FieldInfo(default=0.0, extra={'not_in': [1.0, 2.0, 3.0]}),
#   'default_test': FieldInfo(default=1.0, extra={}),
#   'default_factory_test': FieldInfo(default=PydanticUndefined, default_factory=<class 'float'>, extra={}),
#   'miss_default_test': FieldInfo(extra={}),
#   'alias_test': FieldInfo(default=0.0, alias='alias', alias_priority=2, extra={}),
#   'desc_test': FieldInfo(default=0.0, description='test desc', extra={}),
#   'multiple_of_test': FieldInfo(default=0.0, multiple_of=3, extra={}),
#   'example_test': FieldInfo(default=0.0, extra={'example': 1.0}),
#   'example_factory': FieldInfo(default=0.0, extra={'example': <class 'float'>}),
#   'field_test': CustomerField(default=0.0, extra={}),
#   'type_test': FieldInfo(default=0.0, extra={}),
#   'title_test': FieldInfo(default=0.0, title='title_test', extra={})
#   }
```

> Note:
>  - 1.See the [2.5.template](#25Template) for the usage of `local_dict`
>  - 2.If the reference to the Proto file fails, need to download [p2p_validate.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/protos/protobuf_to_pydantic/protos/p2p_validate.proto) in the project and use it in the Protobuf file。



### 2.4.`P2P` and text annotation rule other parameter support
The `protobuf-to-pydantic` text annotation rules and the `P2P` rules support most of the parameters in `FieldInfo`, as described in the [Pydantic Field doc](https://docs.pydantic.dev/latest/usage/fields/)。

> The new parameters added to `Pydantic V2` will be supported in version 2.1, for now `P2P` rule naming is still written on the basis of `Pydantic V1`, but automatic mapping to `Pydantic V2` naming is supported.

Other partial changes in meaning and new parameters are described as follows:

| Parameter        | Default value | Illustrate                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
|------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| required         | False         | By default, the default value of each field in the generated `Pydantic Model` object is the same as the zero value of its corresponding type. When `required` is `True`, no more default values are generated for the fields.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| enable           | True          | By default, `protobuf-to-pydantic` generates all fields for `Message`, if don't want the generated `Message` to have this field, can set `enable` to `False`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| const            | None          | Used to specify a constant value for a field, though different `Pydantic` versions behave differently<br/>  For `Pydantic V1`, the value of `default` in `Field` is set to the value specified by `const`, and `const` in `Field` is set to True.Note: `Pydantic Model`'s const only supports bool variables, when `const` is `True`, the accepted value can only be the value set by `default`, and the default value carried by the message generated by protobuf is the zero value of the corresponding type does not match with `Pydantic Model`, so ` protobuf-to-pydantic` makes some changes to the input of this value.<br/> For `Pydantic V2`, the value of `default` in `Field` remains the same, but the type annotation changes to `typing_extensions.Literal[xxx]` |
| type             | None          | By default, the default type of a field is the same as Protobuf's, but use the [2.5.template](#25Template) function to modify the type of a field.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| extra            | None          | The `extra` parameter accepted by `Pydantic` is of type `Python Dict`, which is not supported by Protobuf, and requires the use of either [2.5.Templates](#25Templates) or the corresponding Json structure `protobuf-to-pydantic` in the Protobuf file to parse it properly.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| field            | None          | By default, the `Field` of the parameter is `Pydantic FieldInfo`, although it can be customized using the [2.5.Templates](#25Templates) function                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| default_template | None          | Similar to `default`, default values can be customized in fields that are not of string type using the [2.5.Templates](#25Templates) feature.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |

In addition to the above parameters, also support for fast import of `Pydantic type` for string types. For example, if want to add a check for card numbers via the `pydantic.types.PaymentCardNumber` type, can specify the type of the `pydantic_type` parameter field to be `PaymentCardNumber`, which is similar to the use of template imports in the `type` rule, as follows:
- Text annotation rules:
  ```protobuf
  syntax = "proto3";
  package common_validate_test;

  // common example
  message UserPayMessage {
    string bank_number=1; // p2p: {"pydantic_type": "PaymentCardNumber"}
    string other_bank_number=2; // p2p: {"type": "p2p@import|pydantic.types|PaymentCardNumber"}
  }
  ```
- P2P rules:
  ```protobuf
  syntax = "proto3";
  package p2p_validate_test;

  import "example_proto/common/p2p_validate.proto";
  // p2p example
  message UserPayMessage {
    string bank_number=1[(p2p_validate.rules).string.pydantic_type = "PaymentCardNumber"];
    string other_bank_number=2[(p2p_validate.rules).string.type = "p2p@import|pydantic.types|PaymentCardNumber"];
  }
  ```

> See [Extra Types Overview](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) for supported `Pydantic Types'.
### 2.5.Template
When working with definition fields, will find that some fields are filled with values that are methods or functions of one of the libraries in `Python` (e.g., the values of the `type` parameter and the `default_factory` parameter), which can't be accomplished with the Json syntax.
At this point, templates can be used to solve the corresponding problem, and currently `protobuf-to-pydantic` supports a variety of template functi

> Note: The `p2p` string at the beginning of a template can be defined via the comment_prefix variable

#### 2.5.1.`p2p@import`Template
The `p2p@import` template is used to represent variables in other modules that need to be introduced before they can be used, as follows.
- Examples of text annotation rules:
  ```protobuf
  syntax = "proto3";
  package comment_validate_test;

  // comment example
  message UserPayMessage {
    string bank_number=1; // p2p: {"type": "p2p@import|pydantic.types|PaymentCardNumber"}
  }
  ```

- Examples of P2P rules (1):
  ```protobuf
  syntax = "proto3";
  package p2p_validate_test;
  import "example_proto/common/p2p_validate.proto";

  message UserPayMessage {
    string bank_number=1[(p2p_validate.rules).string.type = "p2p@import|pydantic.types|PaymentCardNumber"];
  }
  ```

- Examples of P2P rules (2):
  ```protobuf
  syntax = "proto3";
  package p2p_other_validate_test;
  import "example_proto/common/p2p_validate.proto";
  // p2p other example
  message UserPayMessage {
    string bank_number=1[(p2p_validate.rules).string.pydantic_type = "PaymentCardNumber"];
  }
  ```

The example Protobuf file uses a syntax in the format `p2p@{methods of the template}|{modules to be imported:A}|{variables in modules:B}`, indicating that a `B` object needs to be imported by `from A import B` and used by the corresponding rule.
With the definition of the template, `protobuf-to-pydantic` converts the corresponding Message into a `Pydantic Model`, as follows:
```python
from pydantic import BaseModel
from pydantic.fields import FieldInfo
# p2p@import|pydantic.types|PaymentCardNumber
from pydantic.types import PaymentCardNumber

class UserPayMessage(BaseModel):
    bank_number: PaymentCardNumber = FieldInfo(default="", extra={})
```

#### 2.5.2.`p2p@import_instance` Template
The `p2p@import_instance` template introduces the class of a library and then instantiates it in combination with the specified parameters before it is used by the corresponding rule, which is used as follows:
```protobuf
syntax = "proto3";
package p2p_validate_test;
import "google/protobuf/any.proto";
import "example_proto/common/p2p_validate.proto";
// p2p example
message AnyTest {
  google.protobuf.Any default_test = 23 [
    (p2p_validate.rules).any.default = 'p2p@import_instance|google.protobuf.any_pb2|Any|{"type_url": "type.googleapis.com/google.protobuf.Duration"}'
  ];
}
```
The syntax used here is `p2p@{methods of the template}|{modules to be introduced}|{classes to be introduced}|{initialization parameters}`, and the definition of `protobuf-to-pydantic` through the template will turn the corresponding Message into the following `Pydantic Model` object:
```python
from google.protobuf.any_pb2 import Any as AnyMessage
from pydantic import BaseModel
from pydantic.fields import FieldInfo


class AnyTest(BaseModel):
    default_test: AnyMessage = FieldInfo(
        default=AnyMessage(type_url="type.googleapis.com/google.protobuf.Duration")
    )
```

#### 2.5.3.`p2p@local` Template
This template is used to introduce user-defined variables, using a syntax in the format `{method of the template}|{local variable to be used}`, as follows:

- Example of text annotation:
  ```protobuf
  syntax = "proto3";
  package comment_validate_test;
  import "google/protobuf/timestamp.proto";
  import "example_proto/common/p2p_validate.proto";
  // comment example
  message UserPayMessage {
    google.protobuf.Timestamp exp=1; // p2p: {"default_factory": "p2p@local|exp_time"}
  }
  ```
- Examples of P2P rules:
  ```protobuf
  syntax = "proto3";
  package p2p_validate_test;
  import "google/protobuf/timestamp.proto";
  import "example_proto/common/p2p_validate.proto";
  // p2p example
  message UserPayMessage {
    google.protobuf.Timestamp exp=1[(p2p_validate.rules).timestamp.default_factory= "p2p@local|exp_time"];
  }
  ```
However, the `msg_to_pydantic_model` func needs to be called with the parameter `local_dict` to register the corresponding value, the pseudo-code is as follows:
```Python
# a.py
import time

from example.proto_3_20_pydanticv1.example.example_proto.p2p_validate import demo_pb2
from protobuf_to_pydantic import msg_to_pydantic_model


def exp_time() -> float:
  return time.time()

msg_to_pydantic_model(
    demo_pb2.NestedMessage,
    local_dict={"exp_time": exp_time},  # <----  use local_dict
)
```
In this way, `protobuf-to-pydantic` generates a conforming `Pydantic Model` object:
```python
# b.py
from datetime import datetime
from pydantic import BaseModel
from pydantic.fields import FieldInfo

from a import exp_time  # <-- exp_time in a.py

class UserPayMessage(BaseModel):
    exp: datetime = FieldInfo(default_factory=exp_time, extra={})
```


#### 2.5.4.`p2p@builtin` Template
This template (which can be thought of as a simplified version of the `p2p@local` template) can be used directly when the variables to be used come from `Python` built-in functions,the syntax is used as follows:
- Examples of text annotation rules:
  ```protobuf
  syntax = "proto3";
  package comment_validate_test;
  import "google/protobuf/timestamp.proto";
  import "example_proto/common/p2p_validate.proto";
  // comment example
  message UserPayMessage {
    google.protobuf.Timestamp exp=1; // p2p: {"type": "p2p@builtin|float"}
  }
  ```
- Examples of P2P rules:
  ```protobuf
  syntax = "proto3";
  package p2p_validate_test;
  import "google/protobuf/timestamp.proto";
  import "example_proto/common/p2p_validate.proto";
  // p2p example
  message UserPayMessage {
    google.protobuf.Timestamp exp=1[(p2p_validate.rules).timestamp.type= "p2p@builtin|float"];
  }
  ```
Then can directly generate a conforming `Pydantic Model` object by calling the `msg_to_pydantic_model` function, as follows:
```python
from pydantic import BaseModel
from pydantic.fields import FieldInfo


class UserPayMessage(BaseModel):
    exp: float = FieldInfo()
```
#### 2.5.5.Customized templates
Currently `protobuf-to-pydantic` only supports a few simple templates, if have more template needs, can extend the templates by inheriting the `DescTemplate` class.

For example, there is an odd feature that requires the default value of a field to be the timestamp of the time when the `Pydantic Model` object was generated, but the timestamps used are available in lengths of 10 and 13, so the following Protobuf file needs to be written to support defining the length of the timestamps:
```protobuf
syntax = "proto3";
package p2p_validate_test;
import "google/protobuf/timestamp.proto";
import "example_proto/common/p2p_validate.proto";

message TimestampTest{
  int32 timestamp_10 = 1[(p2p_validate.rules).int32.default_template = "p2p@timestamp|10"];
  int32 timestamp_13 = 2[(p2p_validate.rules).int32.default_template = "p2p@timestamp|13"];
}
```
As you can see, the Protobuf file customizes the syntax of `p2p@timestamp|{x}`, where `x` has only two values, 10 and 13. The next step is to write code based on this template behavior, which looks like this.
```python
import time
from protobuf_to_pydantic.gen_model import DescTemplate

class CustomDescTemplate(DescTemplate):
    def template_timestamp(self, length_str: str) -> int:
        timestamp: float = time.time()
        if length_str == "10":
            return int(timestamp)
        elif length_str == "13":
            return int(timestamp * 100)
        else:
            raise KeyError(f"timestamp template not support value:{length_str}")


from .demo_pb2 import TimestampTest # fake code
from protobuf_to_pydantic import msg_to_pydantic_model

msg_to_pydantic_model(
    TimestampTest,
    desc_template=CustomDescTemplate   # <-- Use a custom template class
)
```
This code first creates a class `CustomDescTemplate` that inherits from `DescTemplate`.
`DescTemplate` will forwards to the corresponding `template_{template name}` method based on the naming of the template, so this class needs to define the `template_timestamp` method to implement the `p2p@timestamp` template functionality.
In addition, the `length_str` variable received in this method is either 10 in `p2p@timestamp|10` or 13 in `p2p@timestamp|13`.

Then load the `CustomDescTemplate` through the `msg_to_pydantic_model` function, then the following code will be generated (assuming that the code is generated at a timestamp of 1600000000):
```python
from pydantic import BaseModel
from pydantic.fields import FieldInfo

class TimestampTest(BaseModel):
    timestamp_10: int = FieldInfo(default=1600000000)
    timestamp_13: int = FieldInfo(default=1600000000000)
```
## 3.Code format
The code generated directly through `protobuf-to-pydantic` is not perfect, but it is possible to indirectly generate code that conforms to the `Python` specification through different formatting tools.
Currently, `protobuf-to-pydantic` supports formatting tools such as `autoflake`, `black` and `isort`. If the corresponding formatting tool is installed in the current `Python` environment, then `protobuf-to-pydantic` will call the tool to format the generated code before outputting it to a file.

In addition, the decision to enable or disable a formatting tool can be made through the `pyproject.toml` configuration file, the `pyproject.toml` example of which reads as follows:
```toml
# Controls which formatting tools protobuf-to-pydantic uses,
# if false then no formatting tools are used (default is true)
[tool.protobuf-to-pydantic.format]
black = true
isort = true
autoflake = true

# black docc:https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#configuration-format
[tool.black]
line-length = 120
target-version = ['py37']

# isort doc:https://pycqa.github.io/isort/docs/configuration/config_files.html#pyprojecttoml-preferred-format
[tool.isort]
profile = "black"
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
ensure_newline_before_comments = true
line_length = 120

# autoflake doc:https://github.com/PyCQA/autoflake#configuration
[tool.autoflake]
in-place = true
remove-all-unused-imports = true
remove-unused-variables = true
```

## 4.example
`protobuf-to-pydantic` provides some simple example code for reference only.

### 4.1.Generate code directly
Protobuf file: [demo/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/demo/demo.proto)

Generate `Pydantic Model`(Pydantic V1): [proto_pydanticv1/demo_gen_code.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/demo_gen_code.py)

Generate `Pydantic Model`(Pydantic V2): [proto_pydanticv2/demo_gen_code.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/demo_gen_code.py)
### 4.2.Text annotation
Protobuf File: [demo/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/demo/demo.proto)

`Pydantic Model` generated based on `pyi` file(Pydantic V1): [proto_pydanticv1/demo_gen_code_by_text_comment_pyi.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/demo_gen_code_by_text_comment_pyi.py)

`Pydantic Model` generated based on `pyi` file(Pydantic V2): [proto_pydanticv2/demo_gen_code_by_text_comment_pyi.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/demo_gen_code_by_text_comment_pyi.py)

`Pydantic Model` generated based on protobuf file(Pydantic V1): [proto_pydanticv1/demo_gen_code_by_text_comment_protobuf_field.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/demo_gen_code_by_text_comment_protobuf_field.py)
`Pydantic Model` generated based on protobuf file(Pydantic V2): [proto_pydanticv2/demo_gen_code_by_text_comment_protobuf_field.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/demo_gen_code_by_text_comment_protobuf_field.py)
validate/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/validate/demo.proto)

Generate `Pydantic Model`(Pydantic V1): [proto_pydanticv1/demo_gen_code_by_pgv.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/demo_gen_code_by_pgv.py)

Generate `Pydantic Model`(Pydantic V2): [proto_pydanticv2/demo_gen_code_by_pgv.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/demo_gen_code_by_pgv.py)
### 4.4.P2P rule
Protobuf file: [p2p_validate/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/p2p_validate/demo.proto)

Generate `Pydantic Model`(Pydantic V1): [proto_pydanticv1/demo_gen_code_by_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/demo_gen_code_by_p2p.py)

Generate `Pydantic Model`(Pydantic V2): [proto_pydanticv2/demo_gen_code_by_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/demo_gen_code_by_p2p.py)
### 4.5.Protoc Plugin-in
Protobuf field: [demo/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/demo/demo.proto),[validate/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/validate/demo.proto),[p2p_validate/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/p2p_validate/demo.proto)

> Note: The Protoc plugin only supports P2P and PGV rules

`Pydantic Model` generated via `demo/demo.proto`(Pydantic V1):[example_proto/demo/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/example/example_proto/demo/demo_p2p.py)

`Pydantic Model` generated via `demo/demo.proto`(Pydantic V2):[example_proto/demo/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/example/example_proto/demo/demo_p2p.py)

`Pydantic Model` generated via `validate/demo.proto`(Pydantic V1):[example_proto/validate/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/example/example_proto/validate/demo_p2p.py)

`Pydantic Model` generated via `validate/demo.proto`(Pydantic V1):[example_proto/validate/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/example/example_proto/validate/demo_p2p.py)

`Pydantic Model` generated via `p2p_validate/demo.proto`(Pydantic V1):[example_proto/p2p_validate/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/example/example_proto/p2p_validate/demo_p2p.py)

`Pydantic Model` generated via `p2p_validate/demo.proto`(Pydantic V1):[example_proto/p2p_validate/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/example/example_proto/p2p_validate/demo_p2p.py)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/so1n/protobuf_to_pydantic",
    "name": "protobuf-to-pydantic",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.7",
    "maintainer_email": null,
    "keywords": null,
    "author": "So1n",
    "author_email": "so1n897046026@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/1d/18/58d7d9ee5bcbf64574e9e4371df004aafe2b69ec61e6d26fd19a5d2d1fb8/protobuf_to_pydantic-0.2.6.2.tar.gz",
    "platform": null,
    "description": "# protobuf_to_pydantic\nGenerate Pydantic Model or source code with parameter verification function based on Protobuf file (Proto3).\n\n\n[\u4e2d\u6587\u6587\u6863](https://github.com/so1n/protobuf_to_pydantic/blob/master/README_ZH.md)\n\n# Feature\n\nFeature\uff1a\n- [x] Generate source code through `Protobuf` plugin\u3002\n- [x] Generate `Pydantic Model` or source code by parsing `Protobuf Message` in `Python` runtime.\n- [x] Compatible with `V1` and `V2` versions of `Pydantic`\u3002\n- [x] Supports multiple verification rules and is compatible with `proto-gen-validate` (subsequent versions will support the rules of `proto-gen-validate` 1.0)\u3002\n- [x] Support custom functionality through templates\u3002\n- [ ] Supports `protovalidate` verification rules\uff08`proto-gen-validate` version >= 1.0\uff09\n\nThe following is a functional overview diagram of `protobuf-to-pydantic`.\nIn the picture `P2P` represents `protobuf-to-pydantic`, `Protoc` represents the command for `Protobuf` to generate code, and `plugin` represents ` Plugin for Protoc`:\n![protobuf-to-pydantic](https://github.com/so1n/protobuf_to_pydantic/blob/master/images/protobuf-to-pydantic_index.png?raw=true)\n\n# Installation\nBy default, `protobuf-to-pydantic` can be installed directly via the following command:\n```bash\npip install protobuf_to_pydantic\n```\nIf want to use the full functionality of `protobuf-to-pydantic`, can install `protobuf-to-pydantic` with the following command:.\n```bash\npip install protobuf_to_pydantic[all]\n```\n# Usage\n## 1.code generation\n`protobuf-to-pydantic` currently has two methods to generate `Pydantic Model` objects based on Protobuf files.\uff1a\n- 1: Use the `Protoc` plug-in to generate the corresponding `Python` code file through the Protobuf file\u3002\n- 2: Generate the corresponding `Pydantic Model` object through the `Message` object in `Python` runtime\u3002\n\n### 1.1.Directly generate `Pydantic Model` code files through plug-ins\n#### 1.1.0.Install dependencies\nThe `protobuf-to-pydantic` plug-in depends on `mypy-protobuf`, need to install `mypy-protobuf` through the following command first:\n```bash\npython -m pip install protobuf-to-pydantic[mypy-protobuf]\n```\nor\n```bash\npoetry add protobuf-to-pydantic -E mypy-protobuf\n```\n#### 1.1.1.Use plugins\nPlug-in is the `Pydantic Model` source code generation method recommended by `protobuf-to-pydantic`.\nIt supports the most complete functions and is also very simple to use.\n\nAssume that it is usually generated through the following command Code corresponding to Protobuf file:\n```bash\npython -m grpc_tools.protoc -I. example.proto\n# or\nprotoc -I. --python_out=. example.proto\n```\nAfter installing `protobuf-to-pydantic`,can use the `protobuf-to-pydantic` plugin with the `--protobuf-to-pydantic_out` option with the following command:\n```bash\npython -m grpc_tools.protoc -I. --protobuf-to-pydantic_out=. example.proto\n# or\nprotoc -I. --protobuf-to-pydantic_out=. example.proto\n```\n\nIn this command, `--protobuf-to-pydantic_out=.` means using the `prorobuf-to-pydantic` plug-in,\nAnd it is declared that the output location of the `protobuf-to-pydantic` plug-in is `.`\n\n> `.` indicates the output path used by `grpc_tools.proto`.\n\nAfter running the command, the `protobuf-to-pydantic` plugin writes the generated source code to a file with the filename suffix `p2p.py`, e.g., `example.proto` generates a file with the name `example_p2p.py`.\n\n\n#### 1.1.2.Plug-in configuration\nThe `protobuf-to-pydantic` plugin supports loading configuration by reading a `Python` file\u3002\n\n> In order to ensure that the variables of the configuration file can be introduced normally, the configuration file must be stored in the current path of the running command.\u3002\n\nAn example configuration that can be read by `protobuf-to-pydantic` is as follows:\n```Python\nimport logging\nfrom typing import List, Type\n\nfrom google.protobuf.any_pb2 import Any  # type: ignore\nfrom pydantic import confloat, conint\nfrom pydantic.fields import FieldInfo\n\nfrom protobuf_to_pydantic.desc_template import DescTemplate\n\n# Configure the log output format and log level of the plugin, which is very useful when debugging\nlogging.basicConfig(format=\"[%(asctime)s %(levelname)s] %(message)s\", datefmt=\"%y-%m-%d %H:%M:%S\", level=logging.DEBUG)\n\n\nclass CustomerField(FieldInfo):\n    pass\n\n\ndef customer_any() -> Any:\n    return Any  # type: ignore\n\n\n# For the configuration of the local template, see the use of the local template for details\nlocal_dict = {\n    \"CustomerField\": CustomerField,\n    \"confloat\": confloat,\n    \"conint\": conint,\n    \"customer_any\": customer_any,\n}\n# Specifies the start of key comments\ncomment_prefix = \"p2p\"\n# Specify the class of the template, can extend the template by inheriting this class, see the chapter on custom templates for details\ndesc_template: Type[DescTemplate] = DescTemplate\n# Specify the protobuf files of which packages to ignore, and the messages of the ignored packages will not be parsed\nignore_pkg_list: List[str] = [\"validate\", \"p2p_validate\"]\n# Specifies the generated file name suffix (without .py)\nfile_name_suffix = \"_p2p\"\n```\nNext, in order to be able to read this file, need to change the `--protobuf-to-pydantic_out=. ` to ` --protobuf-to-pydantic_out=config_path=plugin_config.py:. `.\nwhere the left side of `:` indicates that the configuration file path to be read is `plugin_config.py`, and the right side of `:` declares that the output location of the `protobuf-to-pydantic` plugin is `. `\nThe final complete command is as follows\uff1a\n```bash\npython -m grpc_tools.protoc -I. --protobuf-to-pydantic_out=config_path=plugin_config.py:. example.proto\n# or\nprotoc -I. --protobuf-to-pydantic_out=config_path=plugin_config.py:. example.proto\n```\nThrough this command, can load the corresponding configuration and run the `protobuf-to-pydantic` plug-in\u3002\n\nIn addition to the configuration options in the example configuration file,\nthe `protobuf-to-pydantic` plug-in also supports other configuration options.\nThe specific configuration instructions are as follows\uff1a\n\n| Configuration name            | Functional module                      | Type                                            | Hidden meaning                                                                                                                                      |\n|-------------------------------|----------------------------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|\n| local_dict                    | Template                               | dict                                            | Holds variables for the `local` template                                                                                                            |\n| desc_template                 | Template                               | protobuf_to_pydantic.desc_template.DescTemplate | Implementation of the template class                                                                                                                |\n| comment_prefix                | Template                               | str                                             | Comment prefix.Only strings with a fixed prefix will be used by the template                                                                        |\n| customer_import_set           | Code generation                        | `Set[str]`                                      | A collection of custom import statements, such as `from typing import Set`or `import typing`, that will write data in order to the source code file |\n| customer_deque                | Code generation                        | `deque[str]`                                    | Custom source file content, used to add custom content                                                                                              |\n| module_path                   | str                                    | str                                             | Used to define the root path of the project or module, which helps `protobuf-to-pydantic`to better automatically generate module import statements   |\n| pyproject_file_path           | Code generation                        | str                                             | Define the pyproject file path, which defaults to the current project path                                                                          |\n| code_indent                   | Code generation                        | int                                             | Defines the number of indentation Spaces in the code; the default is 4                                                                              |\n| ignore_pkg_list               | Code generation(Limit plug-ins only)   | `list[str]`                                     | Definition ignores parsing of the specified package file                                                                                            |\n| base_model_class              | Model Code generation, Code generation | `Type[BaseModel]`                               | Define the parent class of the generated Model                                                                                                      |\n| file_name_suffix              | Code generation                        | str                                             | Define the generated file suffix, default `_p2p.py`                                                                                                 |\n| file_descriptor_proto_to_code | Code generation(Limit plug-ins only)   | `Type[FileDescriptorProtoToCode]`               | Define the `FileDescriptorProtoToCode` to use                                                                                                       |\n\n\n#### 1.1.3.buf-cli\nIf you are using `buf-cli` to manage Protobuf files,\nthen you can also use `protobuf-to-pydantic` in `buf-cli`, See [How to use `protobuf-to-pydantic` in `buf-cli`](https://github.com/so1n/protobuf_to_pydantic/blob/master/buf-plugin/README.md)\n\n### 1.2.Generate a `Pydantic Model` object in Python runtime\n`protobuf_to_pydantic` can generate the corresponding `PydanticModel` object based on the `Message` object at runtime\u3002\n\nFor example, the `UserMessage` in the following Protobuf file named `demo.proto`:\n```protobuf\n// path: ./demo.proto\nsyntax = \"proto3\";\npackage user;\n\nenum SexType {\n  man = 0;\n  women = 1;\n}\n\nmessage UserMessage {\n  string uid=1;\n  int32 age=2;\n  float height=3;\n  SexType sex=4;\n  bool is_adult=5;\n  string user_name=6;\n}\n```\n`protoc` can be used to generate the Python code file corresponding to the `Protobuf` file (the file name is `demo_pb2.py`), and the code related to the `UserMessage` is stored in the code file.\n\nAt `Python` runtime, The func `msg_to_pydantic_model` can be called to read the `UserMessage` object from the `demo_pb2` module and generate the corresponding `Pydantic Model` object as follows:\n```Python\nfrom typing import Type\nfrom protobuf_to_pydantic import msg_to_pydantic_model\nfrom pydantic import BaseModel\n\n# import protobuf gen python obj\nfrom . import demo_pb2\n\nUserModel: Type[BaseModel] = msg_to_pydantic_model(demo_pb2.UserMessage)\nprint(\n    {\n        k: v.field_info\n        for k, v in UserModel.__fields__.items()\n    }\n)\n\n# output\n# {\n#   `uid`: FieldInfo(default=``, extra={}),\n#   `age`: FieldInfo(default=0, extra={}),\n#   `height`: FieldInfo(default=0.0, extra={}),\n#   `sex`: FieldInfo(default=0, extra={}),\n#   `is_adult`: FieldInfo(default=False, extra={}),\n#   `user_name`: FieldInfo(default=``, extra={})\n#  }\n```\nThrough the output results, it can be found that the generated `pydantic.BaseModel` object also contains `uid`, `age`, `height`, `sex`, `is adult` and `user name` fields,\nand the `default` property matches the zero value of the Protobuf type\u3002\n\nThe `msg_to_pydantic_model` func is customizable just like plugins, with the following extension parameters:\n\n| Fields                                    | Meaning                                                   |\n|-------------------------------------------|-----------------------------------------------------------|\n| default_field                             | Generate a `Field` for each field in the `Pydantic Model` |\n| comment_prefix                            | The prefix of a comment that can be parsed                |\n| parse_msg_desc_method                     | Parsing rules to use                                      |\n| local_dict                                | Variables used by the `local` template                    |\n| pydantic_base                             | Generates the parent class of the `Pydantic Model` object |\n| pydantic_module                           | Generate the `Module` of the `Pydantic Model` object      |\n| desc_template                             | Template class to use                                     |\n| message_type_dict_by_type_name            | Protobuf type mapping to `Python` type                    |\n| message_default_factory_dict_by_type_name | Protobuf type mapping to the Python type factory          |\n\n\nIn addition to generating the corresponding `Pydantic Model` object at runtime,\n`protobuf-to-pydantic` also supports converting `Pydantic Model` objects to Python code text at runtime (only compatible with `Pydantic Model` objects generated by `protobuf-to-pydantic`).\nThe `pydantic_model_to_py_code` func is used to generate the source code, and the `pydantic_model_to_py_file` func is used to generate the code file. The example code of the `pydantic_model_to_py_file` func is as follows:\n\n```Python\nfrom protobuf_to_pydantic import msg_to_pydantic_model, pydantic_model_to_py_file\n\n# import protobuf gen python obj\nfrom example.example_proto_python_code.example_proto.demo import demo_pb2\n\npydantic_model_to_py_file(\n    \"./demo_gen_code.py\",\n    msg_to_pydantic_model(demo_pb2.NestedMessage),\n)\n```\nWhen the code runs, it converts`demo_pb2.NestedMessage`to a Pydantic Model object and passes it to the  `pydantic_model_to_py_file`. `pydantic_model_to_py_file` generates the source code and writes it to a `demo_gen_code.py` file.\n\n\n## 2.Parameter validation\nIn the previous section, the `Pydantic Model` object generated by the Protobuf file is very simple because the Protobuf file does not have enough parameters to verify the relevant information.\nIn order for each field in the generated `Pydantic Model` object to have parameter validation capabilities, the corresponding parameter checking rules for the field need to be refined in the Protobuf file.\n\nCurrently, `protobuf-to-pydantic` supports three validation rules\uff1a\n- 1.Text annotations\n- 2.PGV(protoc-geb-validate)\n- 3.P2P\n\nWith these rules, the `Pydantic Model` object generated by `protobuf-to-pydantic` will have parameter validation feature.\nAmong them, text annotations and P2P rules are consistent, they both support most of the parameters in `Pydantic Field`, some of the variations and new parameters are seen\n[2.4.`P2P` and text annotation rule other parameter support](#24p2p-and-text-comment-rule-other-parameter-support)\n\n> NOTE:\n>  - 1.Text annotation rules are not the focus of subsequent functional iterative development, and it is recommended to use P2P verification rules.\n>  - 2.`Protoc Plug-in` only support `PGV` and `P2P` rule.\n\n\n### 2.1.Text annotations\nIn the Protobuf file, can write annotations for each field that meet the requirements of `protobuf-to-pydantic`,\nso that `protobuf-to-pydantic` can obtain the validation information of the parameters when parsing the Protobuf file, such as the following example\n```protobuf\nsyntax = \"proto3\";\npackage user;\n\nenum SexType {\n  man = 0;\n  women = 1;\n}\n\n// user info\nmessage UserMessage {\n  // p2p: {\"required\": true, \"example\": \"10086\"}\n  // p2p: {\"title\": \"UID\"}\n  string uid=1; // p2p: {\"description\": \"user union id\"}\n  // p2p: {\"example\": 18, \"title\": \"use age\", \"ge\": 0}\n  int32 age=2;\n  // p2p: {\"ge\": 0, \"le\": 2.5}\n  float height=3;\n  SexType sex=4;\n  bool is_adult=5;\n  // p2p: {\"description\": \"user name\"}\n  // p2p: {\"default\": \"\", \"min_length\": 1, \"max_length\": \"10\", \"example\": \"so1n\"}\n  string user_name=6;\n}\n```\n\nIn this example, each annotation that can be used by `protobuf_to_pydantic` starts with `p2p:` (supports customization) and is followed by a complete Json string. If are familiar with the usage of `pydantic`, can find This Json string contains the verification information corresponding to `pydantic.Field`. For example, the `uid` field in `UserMessage` contains a total of 4 pieces of information as follows\uff1a\n\n| Column      | Meaning                                                                               |\n|-------------|---------------------------------------------------------------------------------------|\n| required    | Indicates that the generated field does not have a default value                      |\n| example     | An example value representing the generated field is 10086                            |\n| title       | Indicates that the schema name of the field is UID                                    |\n | description | The schema documentation for the representation field is described as `user_union_id` |\n\n> Note:\n>   - 1.Currently only single-line comments are supported and comments must be a complete Json data (no line breaks).\n>   - 2.multi line comments are not supported\u3002\n\nWhen these annotations are written, `protobuf_to_pydantic` will bring the corresponding information for each field when converting the Message into the corresponding `Pydantic.BaseModel` object, as follows:\n\n```python\n# pydantic version V1\nfrom typing import Type\nfrom protobuf_to_pydantic import msg_to_pydantic_model\nfrom pydantic import BaseModel\n\n# import protobuf gen python obj\nfrom example.example_proto_python_code.example_proto.demo import demo_pb2\n\nUserModel: Type[BaseModel] = msg_to_pydantic_model(demo_pb2.UserMessage, parse_msg_desc_method=demo_pb2)\nprint(\n    {\n        k: v.field_info\n        for k, v in UserModel.__fields__.items()\n    }\n)\n# output\n# {\n#   `uid`: FieldInfo(default=PydanticUndefined, title=`UID`, description=`user union id`, extra={`example`: `10086`}),\n#   `age`: FieldInfo(default=0, title=`use age`, ge=0, extra={`example`: 18}),\n#   `height`: FieldInfo(default=0.0, ge=0, le=2, extra={}),\n#   `sex`: FieldInfo(default=0, extra={}),\n#   `is_adult`: FieldInfo(default=False, extra={}),\n#   `user_name`: FieldInfo(default=``, description=`user name`, min_length=1, max_length=10, extra={`example`: `so1n`})\n# }\n```\nIt can be seen that the output fields carry the corresponding information, which is consistent with the comments of the Protobuf file.\n\nIn addition, this code differs from the previous section in that the `msg_to_pydantic_model` function has a keyword argument named `parse_msg_desc_method` and its value is the 'demo_pb2' module.\nThis parameter enables `protobuf-to-pydantic` to obtain additional information about each field in the Message object through comments in the `.pyi` file of the `demo_pb2` module.\n\n> Note: This function needs to use the [mypy-protobuf](https://github.com/nipunn1313/mypy-protobuf) plugin when generating the corresponding `Python code through the Protobuf file, and the specified pyi file output path is the same as the generated `Python` code path to take effect.\n> And need to install `protobuf-to-pydantic` via the `python -m pip install protobuf-to-pydantic[mypy-protobuf]` command\n\nIn addition to getting comments from the `.pyi` file, `protobuf-to-pydantic` also supports getting comment information for each field through comments on the Protobuf file to which the Message object belongs.\nUsing this feature is as simple as setting the value of `parse_msg_desc_method` to the root directory path specified when the Message object was generated.\n\n> When using this method, make sure to install `protobuf-to-pydantic` via `python -m pip install protobuf-to-pydantic[lark]`, and also make sure that the Protobuf file exists in the project.\n\nFor example, the project structure of the `protobuf-to-pydantic` sample code is as follows:\n```bash\n./protobuf_to_pydantic/\n\u251c\u2500\u2500 example/\n\u2502 \u251c\u2500\u2500 python_example_proto_code/\n\u2502 \u2514\u2500\u2500 example_proto/\n\u251c\u2500\u2500 protobuf_to_pydantic/\n\u2514\u2500\u2500 /\n```\n\nThe Protobuf file is stored in the `example/example_proto` folder, and then run the following command in the `example` directory to generate the `Python` code file corresponding to Protobuf:\n```bash\ncd example\n\npython -m grpc_tools.protoc\n  --python_out=./python_example_proto_code \\\n  --grpc_python_out=./python_example_proto_code \\\n  -I. \\\n# or\nprotoc\n  --python_out=./python_example_proto_code \\\n  --grpc_python_out=./python_example_proto_code \\\n  -I. \\\n```\nThen the path that needs to be filled in for `parse_msg_desc_method` at this time is `./protobuf_to_pydantic/example`.\nThe following sample code:\n```python\n# pydantic Version v1\nfrom typing import Type\nfrom protobuf_to_pydantic import msg_to_pydantic_model\nfrom pydantic import BaseModel\n\n# import protobuf gen python obj\nfrom example.proto_3_20_pydanticv1.example.example_proto.demo import demo_pb2\n\nUserModel: Type[BaseModel] = msg_to_pydantic_model(\n    demo_pb2.UserMessage, parse_msg_desc_method=\"./protobuf_to_pydantic/example\"\n)\nprint(\n    {\n        k: v.field_info\n        for k, v in UserModel.__fields__.items()\n    }\n)\n# output\n# {\n#   `uid`: FieldInfo(default=PydanticUndefined, title=`UID`, description=`user union id`, extra={`example`: `10086`}),\n#   `age`: FieldInfo(default=0, title=`use age`, ge=0, extra={`example`: 18}),\n#   `height`: FieldInfo(default=0.0, ge=0, le=2, extra={}),\n#   `sex`: FieldInfo(default=0, extra={}),\n#   `is_adult`: FieldInfo(default=False, extra={}),\n#   `user_name`: FieldInfo(default=``, description=`user name`, min_length=1, max_length=10, extra={`example`: `so1n`})\n# }\n```\nAs you can see, the only difference in this code is the value of the `parse_msg_desc_method`, but through the output result, you can see that the field carries the same information as the result obtained through the module.\n\n### 2.2.PGV(protoc-gen-validate)\nAt present, the commonly used parameter verification project in the Protobuf ecosystem is [protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate)\uff0c\nIt has become a common standard in Protobuf because it supports multiple languages and requires only one writing of `PGV` rules to make the generated `Message` object support the corresponding validation rules.\n\n> Currently `protobuf-to-pydantic` only supports rules that [protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate) is less than version 1.0.0\n\n`protobuf-to-pydantic` supports parsing of `PGV` validation rules and generates `Pydantic Model` objects with validation logic functions.\nUsing `PGV` checksum rules in `protobuf-to-pydantic` is very simple, just write the corresponding `PGV` rules in the Protobuf file first,\nand then specify the value of `parse_msg_desc_method` to be `PGV` when calling `msg_to_pydantic_model` as the code below:\n```Python\n# pydantic version V1\nfrom typing import Type\nfrom protobuf_to_pydantic import msg_to_pydantic_model\nfrom pydantic import BaseModel\n\n# import protobuf gen python obj\nfrom example.proto_3_20_pydanticv1.example.example_proto.validate import demo_pb2\n\nUserModel: Type[BaseModel] = msg_to_pydantic_model(\n    demo_pb2.FloatTest, parse_msg_desc_method=\"PGV\"\n)\nprint(\n    {\n        k: v.field_info\n        for k, v in UserModel.__fields__.items()\n    }\n)\n# output\n# {\n#   `const_test`: FieldInfo(default=1.0, const=True, extra={}),\n#   `range_e_test`: FieldInfo(default=0.0, ge=1, le=10, extra={}),\n#   `range_test`: FieldInfo(default=0.0, gt=1, lt=10, extra={}),\n#   `in_test`: FieldInfo(default=0.0, extra={`in`: [1.0, 2.0, 3.0]}),\n#   `not_in_test`: FieldInfo(default=0.0, extra={`not_in`: [1.0, 2.0, 3.0]}),\n#   `ignore_test`: FieldInfo(default=0.0, extra={})\n# }\n```\n\n> Note:\n>  - 1.For the usage of `PGV`, see: [protoc-gen-validate doc](https://github.com/bufbuild/protoc-gen-validate/blob/v0.10.2-SNAPSHOT.17/README.md)\n>  - 2.Need to install `PGV` through `pip install protoc_gen_validate` or download [validate.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/common/validate.proto) to the protobuf directory in the project to write pgv rules in the Protobuf file.\n\n\n### 2.3.P2P\nThe `PGV` verification rules are written in the Option attribute of each field of `Message` and have a better code specification,\nso Protobuf that use `PGV` checksum rules will be more readable than Protobuf that use annotation .\n\nAt the same time, when writing `PGV` rules, can also experience the convenience of the IDE's auto-completion and the security of checksumming when generating the corresponding language objects from Protobuf files, but it only supports checksumming-related logic, which is not as rich as the file annotation mode.\n\n\nThe `P2P` verification rule that comes with `protobuf-to-pydantic` expands on the `PGV` verification rule by incorporating some of the functionality of the text annotation verification rule, which satisfies most of the customization of the properties of each `Field` in the `Pydantic Model`, such as the following Protobuf file.\n```protobuf\nsyntax = \"proto3\";\npackage p2p_validate_test;\n\nimport \"example_proto/common/p2p_validate.proto\";\n\n\nmessage FloatTest {\n  float const_test = 1 [(p2p_validate.rules).float.const = 1];\n  float range_e_test = 2 [(p2p_validate.rules).float = {ge: 1, le: 10}];\n  float range_test = 3[(p2p_validate.rules).float = {gt: 1, lt: 10}];\n  float in_test = 4[(p2p_validate.rules).float = {in: [1,2,3]}];\n  float not_in_test = 5[(p2p_validate.rules).float = {not_in: [1,2,3]}];\n  float default_test = 6[(p2p_validate.rules).float.default = 1.0];\n  float not_enable_test = 7[(p2p_validate.rules).float.enable = false];\n  float default_factory_test = 8[(p2p_validate.rules).float.default_factory = \"p2p@builtin|float\"];\n  float miss_default_test = 9[(p2p_validate.rules).float.miss_default = true];\n  float alias_test = 10 [(p2p_validate.rules).float.alias = \"alias\"];\n  float desc_test = 11 [(p2p_validate.rules).float.description = \"test desc\"];\n  float multiple_of_test = 12 [(p2p_validate.rules).float.multiple_of = 3.0];\n  float example_test = 13 [(p2p_validate.rules).float.example = 1.0];\n  float example_factory = 14 [(p2p_validate.rules).float.example_factory = \"p2p@builtin|float\"];\n  float field_test = 15[(p2p_validate.rules).float.field = \"p2p@local|CustomerField\"];\n  float type_test = 16[(p2p_validate.rules).float.type = \"p2p@local|confloat\"];\n  float title_test = 17 [(p2p_validate.rules).float.title = \"title_test\"];\n}\n```\n`protobuf-to-pydantic` can read the generated Message object at runtime and generate a `Pydantic Model` object with the corresponding information:\n\n```python\n# pydantic version V1\nfrom typing import Type\nfrom protobuf_to_pydantic import msg_to_pydantic_model\nfrom pydantic import BaseModel, confloat\nfrom pydantic.fields import FieldInfo\n\n# import protobuf gen python obj\nfrom example.proto_3_20_pydanticv1.example.example_proto.p2p_validate import demo_pb2\n\n\nclass CustomerField(FieldInfo):\n    pass\n\n\nDemoModel: Type[BaseModel] = msg_to_pydantic_model(\n    demo_pb2.FloatTest,\n    local_dict={\"CustomerField\": CustomerField, \"confloat\": confloat},\n)\nprint(\n    {\n        k: v.field_info\n        for k, v in DemoModel.__fields__.items()\n    }\n)\n# output:\n# {\n#   'const_test': FieldInfo(default=1.0, const=True, extra={}),\n#   'range_e_test': FieldInfo(default=0.0, ge=1, le=10, extra={}),\n#   'range_test': FieldInfo(default=0.0, gt=1, lt=10, extra={}),\n#   'in_test': FieldInfo(default=0.0, extra={'in': [1.0, 2.0, 3.0]}),\n#   'not_in_test': FieldInfo(default=0.0, extra={'not_in': [1.0, 2.0, 3.0]}),\n#   'default_test': FieldInfo(default=1.0, extra={}),\n#   'default_factory_test': FieldInfo(default=PydanticUndefined, default_factory=<class 'float'>, extra={}),\n#   'miss_default_test': FieldInfo(extra={}),\n#   'alias_test': FieldInfo(default=0.0, alias='alias', alias_priority=2, extra={}),\n#   'desc_test': FieldInfo(default=0.0, description='test desc', extra={}),\n#   'multiple_of_test': FieldInfo(default=0.0, multiple_of=3, extra={}),\n#   'example_test': FieldInfo(default=0.0, extra={'example': 1.0}),\n#   'example_factory': FieldInfo(default=0.0, extra={'example': <class 'float'>}),\n#   'field_test': CustomerField(default=0.0, extra={}),\n#   'type_test': FieldInfo(default=0.0, extra={}),\n#   'title_test': FieldInfo(default=0.0, title='title_test', extra={})\n#   }\n```\n\n> Note:\n>  - 1.See the [2.5.template](#25Template) for the usage of `local_dict`\n>  - 2.If the reference to the Proto file fails, need to download [p2p_validate.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/protos/protobuf_to_pydantic/protos/p2p_validate.proto) in the project and use it in the Protobuf file\u3002\n\n\n\n### 2.4.`P2P` and text annotation rule other parameter support\nThe `protobuf-to-pydantic` text annotation rules and the `P2P` rules support most of the parameters in `FieldInfo`, as described in the [Pydantic Field doc](https://docs.pydantic.dev/latest/usage/fields/)\u3002\n\n> The new parameters added to `Pydantic V2` will be supported in version 2.1, for now `P2P` rule naming is still written on the basis of `Pydantic V1`, but automatic mapping to `Pydantic V2` naming is supported.\n\nOther partial changes in meaning and new parameters are described as follows:\n\n| Parameter        | Default value | Illustrate                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n|------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| required         | False         | By default, the default value of each field in the generated `Pydantic Model` object is the same as the zero value of its corresponding type. When `required` is `True`, no more default values are generated for the fields.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |\n| enable           | True          | By default, `protobuf-to-pydantic` generates all fields for `Message`, if don't want the generated `Message` to have this field, can set `enable` to `False`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| const            | None          | Used to specify a constant value for a field, though different `Pydantic` versions behave differently<br/>  For `Pydantic V1`, the value of `default` in `Field` is set to the value specified by `const`, and `const` in `Field` is set to True.Note: `Pydantic Model`'s const only supports bool variables, when `const` is `True`, the accepted value can only be the value set by `default`, and the default value carried by the message generated by protobuf is the zero value of the corresponding type does not match with `Pydantic Model`, so ` protobuf-to-pydantic` makes some changes to the input of this value.<br/> For `Pydantic V2`, the value of `default` in `Field` remains the same, but the type annotation changes to `typing_extensions.Literal[xxx]` |\n| type             | None          | By default, the default type of a field is the same as Protobuf's, but use the [2.5.template](#25Template) function to modify the type of a field.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |\n| extra            | None          | The `extra` parameter accepted by `Pydantic` is of type `Python Dict`, which is not supported by Protobuf, and requires the use of either [2.5.Templates](#25Templates) or the corresponding Json structure `protobuf-to-pydantic` in the Protobuf file to parse it properly.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |\n| field            | None          | By default, the `Field` of the parameter is `Pydantic FieldInfo`, although it can be customized using the [2.5.Templates](#25Templates) function                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |\n| default_template | None          | Similar to `default`, default values can be customized in fields that are not of string type using the [2.5.Templates](#25Templates) feature.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |\n\nIn addition to the above parameters, also support for fast import of `Pydantic type` for string types. For example, if want to add a check for card numbers via the `pydantic.types.PaymentCardNumber` type, can specify the type of the `pydantic_type` parameter field to be `PaymentCardNumber`, which is similar to the use of template imports in the `type` rule, as follows:\n- Text annotation rules\uff1a\n  ```protobuf\n  syntax = \"proto3\";\n  package common_validate_test;\n\n  // common example\n  message UserPayMessage {\n    string bank_number=1; // p2p: {\"pydantic_type\": \"PaymentCardNumber\"}\n    string other_bank_number=2; // p2p: {\"type\": \"p2p@import|pydantic.types|PaymentCardNumber\"}\n  }\n  ```\n- P2P rules\uff1a\n  ```protobuf\n  syntax = \"proto3\";\n  package p2p_validate_test;\n\n  import \"example_proto/common/p2p_validate.proto\";\n  // p2p example\n  message UserPayMessage {\n    string bank_number=1[(p2p_validate.rules).string.pydantic_type = \"PaymentCardNumber\"];\n    string other_bank_number=2[(p2p_validate.rules).string.type = \"p2p@import|pydantic.types|PaymentCardNumber\"];\n  }\n  ```\n\n> See [Extra Types Overview](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) for supported `Pydantic Types'.\n### 2.5.Template\nWhen working with definition fields, will find that some fields are filled with values that are methods or functions of one of the libraries in `Python` (e.g., the values of the `type` parameter and the `default_factory` parameter), which can't be accomplished with the Json syntax.\nAt this point, templates can be used to solve the corresponding problem, and currently `protobuf-to-pydantic` supports a variety of template functi\n\n> Note: The `p2p` string at the beginning of a template can be defined via the comment_prefix variable\n\n#### 2.5.1.`p2p@import`Template\nThe `p2p@import` template is used to represent variables in other modules that need to be introduced before they can be used, as follows.\n- Examples of text annotation rules\uff1a\n  ```protobuf\n  syntax = \"proto3\";\n  package comment_validate_test;\n\n  // comment example\n  message UserPayMessage {\n    string bank_number=1; // p2p: {\"type\": \"p2p@import|pydantic.types|PaymentCardNumber\"}\n  }\n  ```\n\n- Examples of P2P rules (1)\uff1a\n  ```protobuf\n  syntax = \"proto3\";\n  package p2p_validate_test;\n  import \"example_proto/common/p2p_validate.proto\";\n\n  message UserPayMessage {\n    string bank_number=1[(p2p_validate.rules).string.type = \"p2p@import|pydantic.types|PaymentCardNumber\"];\n  }\n  ```\n\n- Examples of P2P rules (2)\uff1a\n  ```protobuf\n  syntax = \"proto3\";\n  package p2p_other_validate_test;\n  import \"example_proto/common/p2p_validate.proto\";\n  // p2p other example\n  message UserPayMessage {\n    string bank_number=1[(p2p_validate.rules).string.pydantic_type = \"PaymentCardNumber\"];\n  }\n  ```\n\nThe example Protobuf file uses a syntax in the format `p2p@{methods of the template}|{modules to be imported:A}|{variables in modules:B}`, indicating that a `B` object needs to be imported by `from A import B` and used by the corresponding rule.\nWith the definition of the template, `protobuf-to-pydantic` converts the corresponding Message into a `Pydantic Model`, as follows:\n```python\nfrom pydantic import BaseModel\nfrom pydantic.fields import FieldInfo\n# p2p@import|pydantic.types|PaymentCardNumber\nfrom pydantic.types import PaymentCardNumber\n\nclass UserPayMessage(BaseModel):\n    bank_number: PaymentCardNumber = FieldInfo(default=\"\", extra={})\n```\n\n#### 2.5.2.`p2p@import_instance` Template\nThe `p2p@import_instance` template introduces the class of a library and then instantiates it in combination with the specified parameters before it is used by the corresponding rule, which is used as follows:\n```protobuf\nsyntax = \"proto3\";\npackage p2p_validate_test;\nimport \"google/protobuf/any.proto\";\nimport \"example_proto/common/p2p_validate.proto\";\n// p2p example\nmessage AnyTest {\n  google.protobuf.Any default_test = 23 [\n    (p2p_validate.rules).any.default = 'p2p@import_instance|google.protobuf.any_pb2|Any|{\"type_url\": \"type.googleapis.com/google.protobuf.Duration\"}'\n  ];\n}\n```\nThe syntax used here is `p2p@{methods of the template}|{modules to be introduced}|{classes to be introduced}|{initialization parameters}`, and the definition of `protobuf-to-pydantic` through the template will turn the corresponding Message into the following `Pydantic Model` object:\n```python\nfrom google.protobuf.any_pb2 import Any as AnyMessage\nfrom pydantic import BaseModel\nfrom pydantic.fields import FieldInfo\n\n\nclass AnyTest(BaseModel):\n    default_test: AnyMessage = FieldInfo(\n        default=AnyMessage(type_url=\"type.googleapis.com/google.protobuf.Duration\")\n    )\n```\n\n#### 2.5.3.`p2p@local` Template\nThis template is used to introduce user-defined variables, using a syntax in the format `{method of the template}|{local variable to be used}`, as follows:\n\n- Example of text annotation:\n  ```protobuf\n  syntax = \"proto3\";\n  package comment_validate_test;\n  import \"google/protobuf/timestamp.proto\";\n  import \"example_proto/common/p2p_validate.proto\";\n  // comment example\n  message UserPayMessage {\n    google.protobuf.Timestamp exp=1; // p2p: {\"default_factory\": \"p2p@local|exp_time\"}\n  }\n  ```\n- Examples of P2P rules\uff1a\n  ```protobuf\n  syntax = \"proto3\";\n  package p2p_validate_test;\n  import \"google/protobuf/timestamp.proto\";\n  import \"example_proto/common/p2p_validate.proto\";\n  // p2p example\n  message UserPayMessage {\n    google.protobuf.Timestamp exp=1[(p2p_validate.rules).timestamp.default_factory= \"p2p@local|exp_time\"];\n  }\n  ```\nHowever, the `msg_to_pydantic_model` func needs to be called with the parameter `local_dict` to register the corresponding value, the pseudo-code is as follows:\n```Python\n# a.py\nimport time\n\nfrom example.proto_3_20_pydanticv1.example.example_proto.p2p_validate import demo_pb2\nfrom protobuf_to_pydantic import msg_to_pydantic_model\n\n\ndef exp_time() -> float:\n  return time.time()\n\nmsg_to_pydantic_model(\n    demo_pb2.NestedMessage,\n    local_dict={\"exp_time\": exp_time},  # <----  use local_dict\n)\n```\nIn this way, `protobuf-to-pydantic` generates a conforming `Pydantic Model` object:\n```python\n# b.py\nfrom datetime import datetime\nfrom pydantic import BaseModel\nfrom pydantic.fields import FieldInfo\n\nfrom a import exp_time  # <-- exp_time in a.py\n\nclass UserPayMessage(BaseModel):\n    exp: datetime = FieldInfo(default_factory=exp_time, extra={})\n```\n\n\n#### 2.5.4.`p2p@builtin` Template\nThis template (which can be thought of as a simplified version of the `p2p@local` template) can be used directly when the variables to be used come from `Python` built-in functions,the syntax is used as follows:\n- Examples of text annotation rules:\n  ```protobuf\n  syntax = \"proto3\";\n  package comment_validate_test;\n  import \"google/protobuf/timestamp.proto\";\n  import \"example_proto/common/p2p_validate.proto\";\n  // comment example\n  message UserPayMessage {\n    google.protobuf.Timestamp exp=1; // p2p: {\"type\": \"p2p@builtin|float\"}\n  }\n  ```\n- Examples of P2P rules\uff1a\n  ```protobuf\n  syntax = \"proto3\";\n  package p2p_validate_test;\n  import \"google/protobuf/timestamp.proto\";\n  import \"example_proto/common/p2p_validate.proto\";\n  // p2p example\n  message UserPayMessage {\n    google.protobuf.Timestamp exp=1[(p2p_validate.rules).timestamp.type= \"p2p@builtin|float\"];\n  }\n  ```\nThen can directly generate a conforming `Pydantic Model` object by calling the `msg_to_pydantic_model` function, as follows:\n```python\nfrom pydantic import BaseModel\nfrom pydantic.fields import FieldInfo\n\n\nclass UserPayMessage(BaseModel):\n    exp: float = FieldInfo()\n```\n#### 2.5.5.Customized templates\nCurrently `protobuf-to-pydantic` only supports a few simple templates, if have more template needs, can extend the templates by inheriting the `DescTemplate` class.\n\nFor example, there is an odd feature that requires the default value of a field to be the timestamp of the time when the `Pydantic Model` object was generated, but the timestamps used are available in lengths of 10 and 13, so the following Protobuf file needs to be written to support defining the length of the timestamps:\n```protobuf\nsyntax = \"proto3\";\npackage p2p_validate_test;\nimport \"google/protobuf/timestamp.proto\";\nimport \"example_proto/common/p2p_validate.proto\";\n\nmessage TimestampTest{\n  int32 timestamp_10 = 1[(p2p_validate.rules).int32.default_template = \"p2p@timestamp|10\"];\n  int32 timestamp_13 = 2[(p2p_validate.rules).int32.default_template = \"p2p@timestamp|13\"];\n}\n```\nAs you can see, the Protobuf file customizes the syntax of `p2p@timestamp|{x}`, where `x` has only two values, 10 and 13. The next step is to write code based on this template behavior, which looks like this.\n```python\nimport time\nfrom protobuf_to_pydantic.gen_model import DescTemplate\n\nclass CustomDescTemplate(DescTemplate):\n    def template_timestamp(self, length_str: str) -> int:\n        timestamp: float = time.time()\n        if length_str == \"10\":\n            return int(timestamp)\n        elif length_str == \"13\":\n            return int(timestamp * 100)\n        else:\n            raise KeyError(f\"timestamp template not support value:{length_str}\")\n\n\nfrom .demo_pb2 import TimestampTest # fake code\nfrom protobuf_to_pydantic import msg_to_pydantic_model\n\nmsg_to_pydantic_model(\n    TimestampTest,\n    desc_template=CustomDescTemplate   # <-- Use a custom template class\n)\n```\nThis code first creates a class `CustomDescTemplate` that inherits from `DescTemplate`.\n`DescTemplate` will forwards to the corresponding `template_{template name}` method based on the naming of the template, so this class needs to define the `template_timestamp` method to implement the `p2p@timestamp` template functionality.\nIn addition, the `length_str` variable received in this method is either 10 in `p2p@timestamp|10` or 13 in `p2p@timestamp|13`.\n\nThen load the `CustomDescTemplate` through the `msg_to_pydantic_model` function, then the following code will be generated (assuming that the code is generated at a timestamp of 1600000000):\n```python\nfrom pydantic import BaseModel\nfrom pydantic.fields import FieldInfo\n\nclass TimestampTest(BaseModel):\n    timestamp_10: int = FieldInfo(default=1600000000)\n    timestamp_13: int = FieldInfo(default=1600000000000)\n```\n## 3.Code format\nThe code generated directly through `protobuf-to-pydantic` is not perfect, but it is possible to indirectly generate code that conforms to the `Python` specification through different formatting tools.\nCurrently, `protobuf-to-pydantic` supports formatting tools such as `autoflake`, `black` and `isort`. If the corresponding formatting tool is installed in the current `Python` environment, then `protobuf-to-pydantic` will call the tool to format the generated code before outputting it to a file.\n\nIn addition, the decision to enable or disable a formatting tool can be made through the `pyproject.toml` configuration file, the `pyproject.toml` example of which reads as follows:\n```toml\n# Controls which formatting tools protobuf-to-pydantic uses,\n# if false then no formatting tools are used (default is true)\n[tool.protobuf-to-pydantic.format]\nblack = true\nisort = true\nautoflake = true\n\n# black docc:https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#configuration-format\n[tool.black]\nline-length = 120\ntarget-version = ['py37']\n\n# isort doc:https://pycqa.github.io/isort/docs/configuration/config_files.html#pyprojecttoml-preferred-format\n[tool.isort]\nprofile = \"black\"\nmulti_line_output = 3\ninclude_trailing_comma = true\nforce_grid_wrap = 0\nuse_parentheses = true\nensure_newline_before_comments = true\nline_length = 120\n\n# autoflake doc:https://github.com/PyCQA/autoflake#configuration\n[tool.autoflake]\nin-place = true\nremove-all-unused-imports = true\nremove-unused-variables = true\n```\n\n## 4.example\n`protobuf-to-pydantic` provides some simple example code for reference only.\n\n### 4.1.Generate code directly\nProtobuf file: [demo/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/demo/demo.proto)\n\nGenerate `Pydantic Model`(Pydantic V1): [proto_pydanticv1/demo_gen_code.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/demo_gen_code.py)\n\nGenerate `Pydantic Model`(Pydantic V2): [proto_pydanticv2/demo_gen_code.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/demo_gen_code.py)\n### 4.2.Text annotation\nProtobuf File: [demo/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/demo/demo.proto)\n\n`Pydantic Model` generated based on `pyi` file(Pydantic V1): [proto_pydanticv1/demo_gen_code_by_text_comment_pyi.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/demo_gen_code_by_text_comment_pyi.py)\n\n`Pydantic Model` generated based on `pyi` file(Pydantic V2): [proto_pydanticv2/demo_gen_code_by_text_comment_pyi.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/demo_gen_code_by_text_comment_pyi.py)\n\n`Pydantic Model` generated based on protobuf file(Pydantic V1): [proto_pydanticv1/demo_gen_code_by_text_comment_protobuf_field.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/demo_gen_code_by_text_comment_protobuf_field.py)\n`Pydantic Model` generated based on protobuf file(Pydantic V2): [proto_pydanticv2/demo_gen_code_by_text_comment_protobuf_field.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/demo_gen_code_by_text_comment_protobuf_field.py)\nvalidate/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/validate/demo.proto)\n\nGenerate `Pydantic Model`(Pydantic V1): [proto_pydanticv1/demo_gen_code_by_pgv.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/demo_gen_code_by_pgv.py)\n\nGenerate `Pydantic Model`(Pydantic V2): [proto_pydanticv2/demo_gen_code_by_pgv.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/demo_gen_code_by_pgv.py)\n### 4.4.P2P rule\nProtobuf file: [p2p_validate/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/p2p_validate/demo.proto)\n\nGenerate `Pydantic Model`(Pydantic V1): [proto_pydanticv1/demo_gen_code_by_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/demo_gen_code_by_p2p.py)\n\nGenerate `Pydantic Model`(Pydantic V2): [proto_pydanticv2/demo_gen_code_by_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/demo_gen_code_by_p2p.py)\n### 4.5.Protoc Plugin-in\nProtobuf field: [demo/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/demo/demo.proto)\uff0c[validate/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/validate/demo.proto)\uff0c[p2p_validate/demo.proto](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/example_proto/p2p_validate/demo.proto)\n\n> Note: The Protoc plugin only supports P2P and PGV rules\n\n`Pydantic Model` generated via `demo/demo.proto`(Pydantic V1):[example_proto/demo/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/example/example_proto/demo/demo_p2p.py)\n\n`Pydantic Model` generated via `demo/demo.proto`(Pydantic V2):[example_proto/demo/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/example/example_proto/demo/demo_p2p.py)\n\n`Pydantic Model` generated via `validate/demo.proto`(Pydantic V1):[example_proto/validate/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/example/example_proto/validate/demo_p2p.py)\n\n`Pydantic Model` generated via `validate/demo.proto`(Pydantic V1):[example_proto/validate/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/example/example_proto/validate/demo_p2p.py)\n\n`Pydantic Model` generated via `p2p_validate/demo.proto`(Pydantic V1):[example_proto/p2p_validate/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv1/example/example_proto/p2p_validate/demo_p2p.py)\n\n`Pydantic Model` generated via `p2p_validate/demo.proto`(Pydantic V1):[example_proto/p2p_validate/demo_p2p.py](https://github.com/so1n/protobuf_to_pydantic/blob/master/example/proto_pydanticv2/example/example_proto/p2p_validate/demo_p2p.py)\n",
    "bugtrack_url": null,
    "license": "Apache Software License",
    "summary": "Generate the `pydantic.BaseModel` class (and the corresponding source code) with parameter verification function through the Protobuf file",
    "version": "0.2.6.2",
    "project_urls": {
        "Homepage": "https://github.com/so1n/protobuf_to_pydantic",
        "Repository": "https://github.com/so1n/protobuf_to_pydantic"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "dba376df378817c818ffb4711fa9a90a06dce9b9947ddb85cfc08181ce8ca94d",
                "md5": "1882640583da10b66c33ef46c550d9df",
                "sha256": "8c254f56af983e54e9b3a40f78bb957171935d47a4924bacea9d84f25819ea23"
            },
            "downloads": -1,
            "filename": "protobuf_to_pydantic-0.2.6.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "1882640583da10b66c33ef46c550d9df",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.7",
            "size": 145014,
            "upload_time": "2024-04-17T16:04:39",
            "upload_time_iso_8601": "2024-04-17T16:04:39.234810Z",
            "url": "https://files.pythonhosted.org/packages/db/a3/76df378817c818ffb4711fa9a90a06dce9b9947ddb85cfc08181ce8ca94d/protobuf_to_pydantic-0.2.6.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1d1858d7d9ee5bcbf64574e9e4371df004aafe2b69ec61e6d26fd19a5d2d1fb8",
                "md5": "dbd6d7e58ddd408ac16b6290222ba43c",
                "sha256": "23f62e785a202b1d81f9e17ca3a3d48f31602e77e88c6ea56a95b563aca8591f"
            },
            "downloads": -1,
            "filename": "protobuf_to_pydantic-0.2.6.2.tar.gz",
            "has_sig": false,
            "md5_digest": "dbd6d7e58ddd408ac16b6290222ba43c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.7",
            "size": 149919,
            "upload_time": "2024-04-17T16:04:41",
            "upload_time_iso_8601": "2024-04-17T16:04:41.408239Z",
            "url": "https://files.pythonhosted.org/packages/1d/18/58d7d9ee5bcbf64574e9e4371df004aafe2b69ec61e6d26fd19a5d2d1fb8/protobuf_to_pydantic-0.2.6.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-17 16:04:41",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "so1n",
    "github_project": "protobuf_to_pydantic",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "annotated-types",
            "specs": [
                [
                    "==",
                    "0.5.0"
                ]
            ]
        },
        {
            "name": "importlib-metadata",
            "specs": [
                [
                    "==",
                    "4.11.4"
                ]
            ]
        },
        {
            "name": "protobuf",
            "specs": [
                [
                    "==",
                    "4.24.4"
                ]
            ]
        },
        {
            "name": "pydantic-core",
            "specs": [
                [
                    "==",
                    "2.14.5"
                ]
            ]
        },
        {
            "name": "pydantic",
            "specs": [
                [
                    "==",
                    "2.5.2"
                ]
            ]
        },
        {
            "name": "toml",
            "specs": [
                [
                    "==",
                    "0.10.2"
                ]
            ]
        },
        {
            "name": "typing-extensions",
            "specs": [
                [
                    "==",
                    "4.7.1"
                ]
            ]
        },
        {
            "name": "zipp",
            "specs": [
                [
                    "==",
                    "3.15.0"
                ]
            ]
        }
    ],
    "tox": true,
    "lcname": "protobuf-to-pydantic"
}
        
Elapsed time: 0.24485s