fix: support pydantic-version google pb (#568)
* feat: pydantic version of google pb * fix: patch pb Struct to support json, dict rountrip * fix: pydantic-version google pb, json, dict rntrip * chore: remove `@generated`, remove gen, code fmt * chore: test case for pydantic-version google pb
This commit is contained in:
parent
df1ba911b7
commit
c3c20556e0
@ -85,17 +85,19 @@ wrappers used to provide optional zero value support. Each of these has a specia
|
|||||||
representation and is handled a little differently from normal messages. The Python
|
representation and is handled a little differently from normal messages. The Python
|
||||||
mapping for these is as follows:
|
mapping for these is as follows:
|
||||||
|
|
||||||
+-------------------------------+-----------------------------------------------+--------------------------+
|
+-------------------------------+-------------------------------------------------+--------------------------+
|
||||||
| ``Google Message`` | ``Python Type`` | ``Default`` |
|
| ``Google Message`` | ``Python Type`` | ``Default`` |
|
||||||
+===============================+===============================================+==========================+
|
+===============================+=================================================+==========================+
|
||||||
| ``google.protobuf.duration`` | :class:`datetime.timedelta` | ``0`` |
|
| ``google.protobuf.duration`` | :class:`datetime.timedelta` | ``0`` |
|
||||||
+-------------------------------+-----------------------------------------------+--------------------------+
|
+-------------------------------+-------------------------------------------------+--------------------------+
|
||||||
| ``google.protobuf.timestamp`` | ``Timezone-aware`` :class:`datetime.datetime` | ``1970-01-01T00:00:00Z`` |
|
| ``google.protobuf.timestamp`` | ``Timezone-aware`` :class:`datetime.datetime` | ``1970-01-01T00:00:00Z`` |
|
||||||
+-------------------------------+-----------------------------------------------+--------------------------+
|
+-------------------------------+-------------------------------------------------+--------------------------+
|
||||||
| ``google.protobuf.*Value`` | ``Optional[...]``/``None`` | ``None`` |
|
| ``google.protobuf.*Value`` | ``Optional[...]``/``None`` | ``None`` |
|
||||||
+-------------------------------+-----------------------------------------------+--------------------------+
|
+-------------------------------+-------------------------------------------------+--------------------------+
|
||||||
| ``google.protobuf.*`` | ``betterproto.lib.google.protobuf.*`` | ``None`` |
|
| ``google.protobuf.*`` | ``betterproto.lib.std.google.protobuf.*`` | ``None`` |
|
||||||
+-------------------------------+-----------------------------------------------+--------------------------+
|
+-------------------------------+-------------------------------------------------+--------------------------+
|
||||||
|
| ``google.protobuf.*`` | ``betterproto.lib.pydantic.google.protobuf.*`` | ``None`` |
|
||||||
|
+-------------------------------+-------------------------------------------------+--------------------------+
|
||||||
|
|
||||||
|
|
||||||
For the wrapper types, the Python type corresponds to the wrapped type, e.g.
|
For the wrapper types, the Python type corresponds to the wrapped type, e.g.
|
||||||
|
@ -95,11 +95,11 @@ cmd = """
|
|||||||
protoc
|
protoc
|
||||||
--plugin=protoc-gen-custom=src/betterproto/plugin/main.py
|
--plugin=protoc-gen-custom=src/betterproto/plugin/main.py
|
||||||
--custom_opt=INCLUDE_GOOGLE
|
--custom_opt=INCLUDE_GOOGLE
|
||||||
--custom_out=src/betterproto/lib
|
--custom_out=src/betterproto/lib/std
|
||||||
-I /usr/local/include/
|
-I /usr/local/include/
|
||||||
/usr/local/include/google/protobuf/**/*.proto
|
/usr/local/include/google/protobuf/**/*.proto
|
||||||
"""
|
"""
|
||||||
help = "Regenerate the types in betterproto.lib.google"
|
help = "Regenerate the types in betterproto.lib.std.google"
|
||||||
|
|
||||||
# CI tasks
|
# CI tasks
|
||||||
|
|
||||||
|
@ -43,7 +43,12 @@ def parse_source_type_name(field_type_name: str) -> Tuple[str, str]:
|
|||||||
|
|
||||||
|
|
||||||
def get_type_reference(
|
def get_type_reference(
|
||||||
*, package: str, imports: set, source_type: str, unwrap: bool = True
|
*,
|
||||||
|
package: str,
|
||||||
|
imports: set,
|
||||||
|
source_type: str,
|
||||||
|
unwrap: bool = True,
|
||||||
|
pydantic: bool = False,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Return a Python type name for a proto type reference. Adds the import if
|
Return a Python type name for a proto type reference. Adds the import if
|
||||||
@ -69,7 +74,9 @@ def get_type_reference(
|
|||||||
compiling_google_protobuf = current_package == ["google", "protobuf"]
|
compiling_google_protobuf = current_package == ["google", "protobuf"]
|
||||||
importing_google_protobuf = py_package == ["google", "protobuf"]
|
importing_google_protobuf = py_package == ["google", "protobuf"]
|
||||||
if importing_google_protobuf and not compiling_google_protobuf:
|
if importing_google_protobuf and not compiling_google_protobuf:
|
||||||
py_package = ["betterproto", "lib"] + py_package
|
py_package = (
|
||||||
|
["betterproto", "lib"] + (["pydantic"] if pydantic else []) + py_package
|
||||||
|
)
|
||||||
|
|
||||||
if py_package[:1] == ["betterproto"]:
|
if py_package[:1] == ["betterproto"]:
|
||||||
return reference_absolute(imports, py_package, py_type)
|
return reference_absolute(imports, py_package, py_type)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,152 +1 @@
|
|||||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
from betterproto.lib.std.google.protobuf.compiler import *
|
||||||
# sources: google/protobuf/compiler/plugin.proto
|
|
||||||
# plugin: python-betterproto
|
|
||||||
# This file has been @generated
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
import betterproto
|
|
||||||
import betterproto.lib.google.protobuf as betterproto_lib_google_protobuf
|
|
||||||
|
|
||||||
|
|
||||||
class CodeGeneratorResponseFeature(betterproto.Enum):
|
|
||||||
"""Sync with code_generator.h."""
|
|
||||||
|
|
||||||
FEATURE_NONE = 0
|
|
||||||
FEATURE_PROTO3_OPTIONAL = 1
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(eq=False, repr=False)
|
|
||||||
class Version(betterproto.Message):
|
|
||||||
"""The version number of protocol compiler."""
|
|
||||||
|
|
||||||
major: int = betterproto.int32_field(1)
|
|
||||||
minor: int = betterproto.int32_field(2)
|
|
||||||
patch: int = betterproto.int32_field(3)
|
|
||||||
suffix: str = betterproto.string_field(4)
|
|
||||||
"""
|
|
||||||
A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
|
|
||||||
be empty for mainline stable releases.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(eq=False, repr=False)
|
|
||||||
class CodeGeneratorRequest(betterproto.Message):
|
|
||||||
"""An encoded CodeGeneratorRequest is written to the plugin's stdin."""
|
|
||||||
|
|
||||||
file_to_generate: List[str] = betterproto.string_field(1)
|
|
||||||
"""
|
|
||||||
The .proto files that were explicitly listed on the command-line. The code
|
|
||||||
generator should generate code only for these files. Each file's
|
|
||||||
descriptor will be included in proto_file, below.
|
|
||||||
"""
|
|
||||||
|
|
||||||
parameter: str = betterproto.string_field(2)
|
|
||||||
"""The generator parameter passed on the command-line."""
|
|
||||||
|
|
||||||
proto_file: List[
|
|
||||||
"betterproto_lib_google_protobuf.FileDescriptorProto"
|
|
||||||
] = betterproto.message_field(15)
|
|
||||||
"""
|
|
||||||
FileDescriptorProtos for all files in files_to_generate and everything they
|
|
||||||
import. The files will appear in topological order, so each file appears
|
|
||||||
before any file that imports it. protoc guarantees that all proto_files
|
|
||||||
will be written after the fields above, even though this is not technically
|
|
||||||
guaranteed by the protobuf wire format. This theoretically could allow a
|
|
||||||
plugin to stream in the FileDescriptorProtos and handle them one by one
|
|
||||||
rather than read the entire set into memory at once. However, as of this
|
|
||||||
writing, this is not similarly optimized on protoc's end -- it will store
|
|
||||||
all fields in memory at once before sending them to the plugin. Type names
|
|
||||||
of fields and extensions in the FileDescriptorProto are always fully
|
|
||||||
qualified.
|
|
||||||
"""
|
|
||||||
|
|
||||||
compiler_version: "Version" = betterproto.message_field(3)
|
|
||||||
"""The version number of protocol compiler."""
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(eq=False, repr=False)
|
|
||||||
class CodeGeneratorResponse(betterproto.Message):
|
|
||||||
"""The plugin writes an encoded CodeGeneratorResponse to stdout."""
|
|
||||||
|
|
||||||
error: str = betterproto.string_field(1)
|
|
||||||
"""
|
|
||||||
Error message. If non-empty, code generation failed. The plugin process
|
|
||||||
should exit with status code zero even if it reports an error in this way.
|
|
||||||
This should be used to indicate errors in .proto files which prevent the
|
|
||||||
code generator from generating correct code. Errors which indicate a
|
|
||||||
problem in protoc itself -- such as the input CodeGeneratorRequest being
|
|
||||||
unparseable -- should be reported by writing a message to stderr and
|
|
||||||
exiting with a non-zero status code.
|
|
||||||
"""
|
|
||||||
|
|
||||||
supported_features: int = betterproto.uint64_field(2)
|
|
||||||
"""
|
|
||||||
A bitmask of supported features that the code generator supports. This is a
|
|
||||||
bitwise "or" of values from the Feature enum.
|
|
||||||
"""
|
|
||||||
|
|
||||||
file: List["CodeGeneratorResponseFile"] = betterproto.message_field(15)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(eq=False, repr=False)
|
|
||||||
class CodeGeneratorResponseFile(betterproto.Message):
|
|
||||||
"""Represents a single generated file."""
|
|
||||||
|
|
||||||
name: str = betterproto.string_field(1)
|
|
||||||
"""
|
|
||||||
The file name, relative to the output directory. The name must not contain
|
|
||||||
"." or ".." components and must be relative, not be absolute (so, the file
|
|
||||||
cannot lie outside the output directory). "/" must be used as the path
|
|
||||||
separator, not "\". If the name is omitted, the content will be appended to
|
|
||||||
the previous file. This allows the generator to break large files into
|
|
||||||
small chunks, and allows the generated text to be streamed back to protoc
|
|
||||||
so that large files need not reside completely in memory at one time. Note
|
|
||||||
that as of this writing protoc does not optimize for this -- it will read
|
|
||||||
the entire CodeGeneratorResponse before writing files to disk.
|
|
||||||
"""
|
|
||||||
|
|
||||||
insertion_point: str = betterproto.string_field(2)
|
|
||||||
"""
|
|
||||||
If non-empty, indicates that the named file should already exist, and the
|
|
||||||
content here is to be inserted into that file at a defined insertion point.
|
|
||||||
This feature allows a code generator to extend the output produced by
|
|
||||||
another code generator. The original generator may provide insertion
|
|
||||||
points by placing special annotations in the file that look like:
|
|
||||||
@@protoc_insertion_point(NAME) The annotation can have arbitrary text
|
|
||||||
before and after it on the line, which allows it to be placed in a comment.
|
|
||||||
NAME should be replaced with an identifier naming the point -- this is what
|
|
||||||
other generators will use as the insertion_point. Code inserted at this
|
|
||||||
point will be placed immediately above the line containing the insertion
|
|
||||||
point (thus multiple insertions to the same point will come out in the
|
|
||||||
order they were added). The double-@ is intended to make it unlikely that
|
|
||||||
the generated code could contain things that look like insertion points by
|
|
||||||
accident. For example, the C++ code generator places the following line in
|
|
||||||
the .pb.h files that it generates: //
|
|
||||||
@@protoc_insertion_point(namespace_scope) This line appears within the
|
|
||||||
scope of the file's package namespace, but outside of any particular class.
|
|
||||||
Another plugin can then specify the insertion_point "namespace_scope" to
|
|
||||||
generate additional classes or other declarations that should be placed in
|
|
||||||
this scope. Note that if the line containing the insertion point begins
|
|
||||||
with whitespace, the same whitespace will be added to every line of the
|
|
||||||
inserted text. This is useful for languages like Python, where indentation
|
|
||||||
matters. In these languages, the insertion point comment should be
|
|
||||||
indented the same amount as any inserted code will need to be in order to
|
|
||||||
work correctly in that context. The code generator that generates the
|
|
||||||
initial file and the one which inserts into it must both run as part of a
|
|
||||||
single invocation of protoc. Code generators are executed in the order in
|
|
||||||
which they appear on the command line. If |insertion_point| is present,
|
|
||||||
|name| must also be present.
|
|
||||||
"""
|
|
||||||
|
|
||||||
content: str = betterproto.string_field(15)
|
|
||||||
"""The file contents."""
|
|
||||||
|
|
||||||
generated_code_info: "betterproto_lib_google_protobuf.GeneratedCodeInfo" = (
|
|
||||||
betterproto.message_field(16)
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
Information describing the file content being inserted. If an insertion
|
|
||||||
point is used, this information will be appropriately offset and inserted
|
|
||||||
into the code generation metadata for the generated files.
|
|
||||||
"""
|
|
||||||
|
0
src/betterproto/lib/pydantic/__init__.py
Normal file
0
src/betterproto/lib/pydantic/__init__.py
Normal file
0
src/betterproto/lib/pydantic/google/__init__.py
Normal file
0
src/betterproto/lib/pydantic/google/__init__.py
Normal file
2589
src/betterproto/lib/pydantic/google/protobuf/__init__.py
Normal file
2589
src/betterproto/lib/pydantic/google/protobuf/__init__.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,210 @@
|
|||||||
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
# sources: google/protobuf/compiler/plugin.proto
|
||||||
|
# plugin: python-betterproto
|
||||||
|
# This file has been @generated
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from dataclasses import dataclass
|
||||||
|
else:
|
||||||
|
from pydantic.dataclasses import dataclass
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
import betterproto
|
||||||
|
import betterproto.lib.pydantic.google.protobuf as betterproto_lib_pydantic_google_protobuf
|
||||||
|
|
||||||
|
|
||||||
|
class CodeGeneratorResponseFeature(betterproto.Enum):
|
||||||
|
"""Sync with code_generator.h."""
|
||||||
|
|
||||||
|
FEATURE_NONE = 0
|
||||||
|
FEATURE_PROTO3_OPTIONAL = 1
|
||||||
|
FEATURE_SUPPORTS_EDITIONS = 2
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(eq=False, repr=False)
|
||||||
|
class Version(betterproto.Message):
|
||||||
|
"""The version number of protocol compiler."""
|
||||||
|
|
||||||
|
major: int = betterproto.int32_field(1)
|
||||||
|
minor: int = betterproto.int32_field(2)
|
||||||
|
patch: int = betterproto.int32_field(3)
|
||||||
|
suffix: str = betterproto.string_field(4)
|
||||||
|
"""
|
||||||
|
A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
|
||||||
|
be empty for mainline stable releases.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(eq=False, repr=False)
|
||||||
|
class CodeGeneratorRequest(betterproto.Message):
|
||||||
|
"""An encoded CodeGeneratorRequest is written to the plugin's stdin."""
|
||||||
|
|
||||||
|
file_to_generate: List[str] = betterproto.string_field(1)
|
||||||
|
"""
|
||||||
|
The .proto files that were explicitly listed on the command-line. The
|
||||||
|
code generator should generate code only for these files. Each file's
|
||||||
|
descriptor will be included in proto_file, below.
|
||||||
|
"""
|
||||||
|
|
||||||
|
parameter: str = betterproto.string_field(2)
|
||||||
|
"""The generator parameter passed on the command-line."""
|
||||||
|
|
||||||
|
proto_file: List[
|
||||||
|
"betterproto_lib_pydantic_google_protobuf.FileDescriptorProto"
|
||||||
|
] = betterproto.message_field(15)
|
||||||
|
"""
|
||||||
|
FileDescriptorProtos for all files in files_to_generate and everything
|
||||||
|
they import. The files will appear in topological order, so each file
|
||||||
|
appears before any file that imports it.
|
||||||
|
|
||||||
|
Note: the files listed in files_to_generate will include runtime-retention
|
||||||
|
options only, but all other files will include source-retention options.
|
||||||
|
The source_file_descriptors field below is available in case you need
|
||||||
|
source-retention options for files_to_generate.
|
||||||
|
|
||||||
|
protoc guarantees that all proto_files will be written after
|
||||||
|
the fields above, even though this is not technically guaranteed by the
|
||||||
|
protobuf wire format. This theoretically could allow a plugin to stream
|
||||||
|
in the FileDescriptorProtos and handle them one by one rather than read
|
||||||
|
the entire set into memory at once. However, as of this writing, this
|
||||||
|
is not similarly optimized on protoc's end -- it will store all fields in
|
||||||
|
memory at once before sending them to the plugin.
|
||||||
|
|
||||||
|
Type names of fields and extensions in the FileDescriptorProto are always
|
||||||
|
fully qualified.
|
||||||
|
"""
|
||||||
|
|
||||||
|
source_file_descriptors: List[
|
||||||
|
"betterproto_lib_pydantic_google_protobuf.FileDescriptorProto"
|
||||||
|
] = betterproto.message_field(17)
|
||||||
|
"""
|
||||||
|
File descriptors with all options, including source-retention options.
|
||||||
|
These descriptors are only provided for the files listed in
|
||||||
|
files_to_generate.
|
||||||
|
"""
|
||||||
|
|
||||||
|
compiler_version: "Version" = betterproto.message_field(3)
|
||||||
|
"""The version number of protocol compiler."""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(eq=False, repr=False)
|
||||||
|
class CodeGeneratorResponse(betterproto.Message):
|
||||||
|
"""The plugin writes an encoded CodeGeneratorResponse to stdout."""
|
||||||
|
|
||||||
|
error: str = betterproto.string_field(1)
|
||||||
|
"""
|
||||||
|
Error message. If non-empty, code generation failed. The plugin process
|
||||||
|
should exit with status code zero even if it reports an error in this way.
|
||||||
|
|
||||||
|
This should be used to indicate errors in .proto files which prevent the
|
||||||
|
code generator from generating correct code. Errors which indicate a
|
||||||
|
problem in protoc itself -- such as the input CodeGeneratorRequest being
|
||||||
|
unparseable -- should be reported by writing a message to stderr and
|
||||||
|
exiting with a non-zero status code.
|
||||||
|
"""
|
||||||
|
|
||||||
|
supported_features: int = betterproto.uint64_field(2)
|
||||||
|
"""
|
||||||
|
A bitmask of supported features that the code generator supports.
|
||||||
|
This is a bitwise "or" of values from the Feature enum.
|
||||||
|
"""
|
||||||
|
|
||||||
|
minimum_edition: int = betterproto.int32_field(3)
|
||||||
|
"""
|
||||||
|
The minimum edition this plugin supports. This will be treated as an
|
||||||
|
Edition enum, but we want to allow unknown values. It should be specified
|
||||||
|
according the edition enum value, *not* the edition number. Only takes
|
||||||
|
effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
|
||||||
|
"""
|
||||||
|
|
||||||
|
maximum_edition: int = betterproto.int32_field(4)
|
||||||
|
"""
|
||||||
|
The maximum edition this plugin supports. This will be treated as an
|
||||||
|
Edition enum, but we want to allow unknown values. It should be specified
|
||||||
|
according the edition enum value, *not* the edition number. Only takes
|
||||||
|
effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
|
||||||
|
"""
|
||||||
|
|
||||||
|
file: List["CodeGeneratorResponseFile"] = betterproto.message_field(15)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(eq=False, repr=False)
|
||||||
|
class CodeGeneratorResponseFile(betterproto.Message):
|
||||||
|
"""Represents a single generated file."""
|
||||||
|
|
||||||
|
name: str = betterproto.string_field(1)
|
||||||
|
"""
|
||||||
|
The file name, relative to the output directory. The name must not
|
||||||
|
contain "." or ".." components and must be relative, not be absolute (so,
|
||||||
|
the file cannot lie outside the output directory). "/" must be used as
|
||||||
|
the path separator, not "\".
|
||||||
|
|
||||||
|
If the name is omitted, the content will be appended to the previous
|
||||||
|
file. This allows the generator to break large files into small chunks,
|
||||||
|
and allows the generated text to be streamed back to protoc so that large
|
||||||
|
files need not reside completely in memory at one time. Note that as of
|
||||||
|
this writing protoc does not optimize for this -- it will read the entire
|
||||||
|
CodeGeneratorResponse before writing files to disk.
|
||||||
|
"""
|
||||||
|
|
||||||
|
insertion_point: str = betterproto.string_field(2)
|
||||||
|
"""
|
||||||
|
If non-empty, indicates that the named file should already exist, and the
|
||||||
|
content here is to be inserted into that file at a defined insertion
|
||||||
|
point. This feature allows a code generator to extend the output
|
||||||
|
produced by another code generator. The original generator may provide
|
||||||
|
insertion points by placing special annotations in the file that look
|
||||||
|
like:
|
||||||
|
@@protoc_insertion_point(NAME)
|
||||||
|
The annotation can have arbitrary text before and after it on the line,
|
||||||
|
which allows it to be placed in a comment. NAME should be replaced with
|
||||||
|
an identifier naming the point -- this is what other generators will use
|
||||||
|
as the insertion_point. Code inserted at this point will be placed
|
||||||
|
immediately above the line containing the insertion point (thus multiple
|
||||||
|
insertions to the same point will come out in the order they were added).
|
||||||
|
The double-@ is intended to make it unlikely that the generated code
|
||||||
|
could contain things that look like insertion points by accident.
|
||||||
|
|
||||||
|
For example, the C++ code generator places the following line in the
|
||||||
|
.pb.h files that it generates:
|
||||||
|
// @@protoc_insertion_point(namespace_scope)
|
||||||
|
This line appears within the scope of the file's package namespace, but
|
||||||
|
outside of any particular class. Another plugin can then specify the
|
||||||
|
insertion_point "namespace_scope" to generate additional classes or
|
||||||
|
other declarations that should be placed in this scope.
|
||||||
|
|
||||||
|
Note that if the line containing the insertion point begins with
|
||||||
|
whitespace, the same whitespace will be added to every line of the
|
||||||
|
inserted text. This is useful for languages like Python, where
|
||||||
|
indentation matters. In these languages, the insertion point comment
|
||||||
|
should be indented the same amount as any inserted code will need to be
|
||||||
|
in order to work correctly in that context.
|
||||||
|
|
||||||
|
The code generator that generates the initial file and the one which
|
||||||
|
inserts into it must both run as part of a single invocation of protoc.
|
||||||
|
Code generators are executed in the order in which they appear on the
|
||||||
|
command line.
|
||||||
|
|
||||||
|
If |insertion_point| is present, |name| must also be present.
|
||||||
|
"""
|
||||||
|
|
||||||
|
content: str = betterproto.string_field(15)
|
||||||
|
"""The file contents."""
|
||||||
|
|
||||||
|
generated_code_info: (
|
||||||
|
"betterproto_lib_pydantic_google_protobuf.GeneratedCodeInfo"
|
||||||
|
) = betterproto.message_field(16)
|
||||||
|
"""
|
||||||
|
Information describing the file content being inserted. If an insertion
|
||||||
|
point is used, this information will be appropriately offset and inserted
|
||||||
|
into the code generation metadata for the generated files.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
CodeGeneratorRequest.__pydantic_model__.update_forward_refs() # type: ignore
|
||||||
|
CodeGeneratorResponse.__pydantic_model__.update_forward_refs() # type: ignore
|
||||||
|
CodeGeneratorResponseFile.__pydantic_model__.update_forward_refs() # type: ignore
|
0
src/betterproto/lib/std/__init__.py
Normal file
0
src/betterproto/lib/std/__init__.py
Normal file
0
src/betterproto/lib/std/google/__init__.py
Normal file
0
src/betterproto/lib/std/google/__init__.py
Normal file
2526
src/betterproto/lib/std/google/protobuf/__init__.py
Normal file
2526
src/betterproto/lib/std/google/protobuf/__init__.py
Normal file
File diff suppressed because it is too large
Load Diff
198
src/betterproto/lib/std/google/protobuf/compiler/__init__.py
Normal file
198
src/betterproto/lib/std/google/protobuf/compiler/__init__.py
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
# sources: google/protobuf/compiler/plugin.proto
|
||||||
|
# plugin: python-betterproto
|
||||||
|
# This file has been @generated
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
import betterproto
|
||||||
|
import betterproto.lib.google.protobuf as betterproto_lib_google_protobuf
|
||||||
|
|
||||||
|
|
||||||
|
class CodeGeneratorResponseFeature(betterproto.Enum):
|
||||||
|
"""Sync with code_generator.h."""
|
||||||
|
|
||||||
|
FEATURE_NONE = 0
|
||||||
|
FEATURE_PROTO3_OPTIONAL = 1
|
||||||
|
FEATURE_SUPPORTS_EDITIONS = 2
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(eq=False, repr=False)
|
||||||
|
class Version(betterproto.Message):
|
||||||
|
"""The version number of protocol compiler."""
|
||||||
|
|
||||||
|
major: int = betterproto.int32_field(1)
|
||||||
|
minor: int = betterproto.int32_field(2)
|
||||||
|
patch: int = betterproto.int32_field(3)
|
||||||
|
suffix: str = betterproto.string_field(4)
|
||||||
|
"""
|
||||||
|
A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
|
||||||
|
be empty for mainline stable releases.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(eq=False, repr=False)
|
||||||
|
class CodeGeneratorRequest(betterproto.Message):
|
||||||
|
"""An encoded CodeGeneratorRequest is written to the plugin's stdin."""
|
||||||
|
|
||||||
|
file_to_generate: List[str] = betterproto.string_field(1)
|
||||||
|
"""
|
||||||
|
The .proto files that were explicitly listed on the command-line. The
|
||||||
|
code generator should generate code only for these files. Each file's
|
||||||
|
descriptor will be included in proto_file, below.
|
||||||
|
"""
|
||||||
|
|
||||||
|
parameter: str = betterproto.string_field(2)
|
||||||
|
"""The generator parameter passed on the command-line."""
|
||||||
|
|
||||||
|
proto_file: List[
|
||||||
|
"betterproto_lib_google_protobuf.FileDescriptorProto"
|
||||||
|
] = betterproto.message_field(15)
|
||||||
|
"""
|
||||||
|
FileDescriptorProtos for all files in files_to_generate and everything
|
||||||
|
they import. The files will appear in topological order, so each file
|
||||||
|
appears before any file that imports it.
|
||||||
|
|
||||||
|
Note: the files listed in files_to_generate will include runtime-retention
|
||||||
|
options only, but all other files will include source-retention options.
|
||||||
|
The source_file_descriptors field below is available in case you need
|
||||||
|
source-retention options for files_to_generate.
|
||||||
|
|
||||||
|
protoc guarantees that all proto_files will be written after
|
||||||
|
the fields above, even though this is not technically guaranteed by the
|
||||||
|
protobuf wire format. This theoretically could allow a plugin to stream
|
||||||
|
in the FileDescriptorProtos and handle them one by one rather than read
|
||||||
|
the entire set into memory at once. However, as of this writing, this
|
||||||
|
is not similarly optimized on protoc's end -- it will store all fields in
|
||||||
|
memory at once before sending them to the plugin.
|
||||||
|
|
||||||
|
Type names of fields and extensions in the FileDescriptorProto are always
|
||||||
|
fully qualified.
|
||||||
|
"""
|
||||||
|
|
||||||
|
source_file_descriptors: List[
|
||||||
|
"betterproto_lib_google_protobuf.FileDescriptorProto"
|
||||||
|
] = betterproto.message_field(17)
|
||||||
|
"""
|
||||||
|
File descriptors with all options, including source-retention options.
|
||||||
|
These descriptors are only provided for the files listed in
|
||||||
|
files_to_generate.
|
||||||
|
"""
|
||||||
|
|
||||||
|
compiler_version: "Version" = betterproto.message_field(3)
|
||||||
|
"""The version number of protocol compiler."""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(eq=False, repr=False)
|
||||||
|
class CodeGeneratorResponse(betterproto.Message):
|
||||||
|
"""The plugin writes an encoded CodeGeneratorResponse to stdout."""
|
||||||
|
|
||||||
|
error: str = betterproto.string_field(1)
|
||||||
|
"""
|
||||||
|
Error message. If non-empty, code generation failed. The plugin process
|
||||||
|
should exit with status code zero even if it reports an error in this way.
|
||||||
|
|
||||||
|
This should be used to indicate errors in .proto files which prevent the
|
||||||
|
code generator from generating correct code. Errors which indicate a
|
||||||
|
problem in protoc itself -- such as the input CodeGeneratorRequest being
|
||||||
|
unparseable -- should be reported by writing a message to stderr and
|
||||||
|
exiting with a non-zero status code.
|
||||||
|
"""
|
||||||
|
|
||||||
|
supported_features: int = betterproto.uint64_field(2)
|
||||||
|
"""
|
||||||
|
A bitmask of supported features that the code generator supports.
|
||||||
|
This is a bitwise "or" of values from the Feature enum.
|
||||||
|
"""
|
||||||
|
|
||||||
|
minimum_edition: int = betterproto.int32_field(3)
|
||||||
|
"""
|
||||||
|
The minimum edition this plugin supports. This will be treated as an
|
||||||
|
Edition enum, but we want to allow unknown values. It should be specified
|
||||||
|
according the edition enum value, *not* the edition number. Only takes
|
||||||
|
effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
|
||||||
|
"""
|
||||||
|
|
||||||
|
maximum_edition: int = betterproto.int32_field(4)
|
||||||
|
"""
|
||||||
|
The maximum edition this plugin supports. This will be treated as an
|
||||||
|
Edition enum, but we want to allow unknown values. It should be specified
|
||||||
|
according the edition enum value, *not* the edition number. Only takes
|
||||||
|
effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
|
||||||
|
"""
|
||||||
|
|
||||||
|
file: List["CodeGeneratorResponseFile"] = betterproto.message_field(15)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(eq=False, repr=False)
|
||||||
|
class CodeGeneratorResponseFile(betterproto.Message):
|
||||||
|
"""Represents a single generated file."""
|
||||||
|
|
||||||
|
name: str = betterproto.string_field(1)
|
||||||
|
"""
|
||||||
|
The file name, relative to the output directory. The name must not
|
||||||
|
contain "." or ".." components and must be relative, not be absolute (so,
|
||||||
|
the file cannot lie outside the output directory). "/" must be used as
|
||||||
|
the path separator, not "\".
|
||||||
|
|
||||||
|
If the name is omitted, the content will be appended to the previous
|
||||||
|
file. This allows the generator to break large files into small chunks,
|
||||||
|
and allows the generated text to be streamed back to protoc so that large
|
||||||
|
files need not reside completely in memory at one time. Note that as of
|
||||||
|
this writing protoc does not optimize for this -- it will read the entire
|
||||||
|
CodeGeneratorResponse before writing files to disk.
|
||||||
|
"""
|
||||||
|
|
||||||
|
insertion_point: str = betterproto.string_field(2)
|
||||||
|
"""
|
||||||
|
If non-empty, indicates that the named file should already exist, and the
|
||||||
|
content here is to be inserted into that file at a defined insertion
|
||||||
|
point. This feature allows a code generator to extend the output
|
||||||
|
produced by another code generator. The original generator may provide
|
||||||
|
insertion points by placing special annotations in the file that look
|
||||||
|
like:
|
||||||
|
@@protoc_insertion_point(NAME)
|
||||||
|
The annotation can have arbitrary text before and after it on the line,
|
||||||
|
which allows it to be placed in a comment. NAME should be replaced with
|
||||||
|
an identifier naming the point -- this is what other generators will use
|
||||||
|
as the insertion_point. Code inserted at this point will be placed
|
||||||
|
immediately above the line containing the insertion point (thus multiple
|
||||||
|
insertions to the same point will come out in the order they were added).
|
||||||
|
The double-@ is intended to make it unlikely that the generated code
|
||||||
|
could contain things that look like insertion points by accident.
|
||||||
|
|
||||||
|
For example, the C++ code generator places the following line in the
|
||||||
|
.pb.h files that it generates:
|
||||||
|
// @@protoc_insertion_point(namespace_scope)
|
||||||
|
This line appears within the scope of the file's package namespace, but
|
||||||
|
outside of any particular class. Another plugin can then specify the
|
||||||
|
insertion_point "namespace_scope" to generate additional classes or
|
||||||
|
other declarations that should be placed in this scope.
|
||||||
|
|
||||||
|
Note that if the line containing the insertion point begins with
|
||||||
|
whitespace, the same whitespace will be added to every line of the
|
||||||
|
inserted text. This is useful for languages like Python, where
|
||||||
|
indentation matters. In these languages, the insertion point comment
|
||||||
|
should be indented the same amount as any inserted code will need to be
|
||||||
|
in order to work correctly in that context.
|
||||||
|
|
||||||
|
The code generator that generates the initial file and the one which
|
||||||
|
inserts into it must both run as part of a single invocation of protoc.
|
||||||
|
Code generators are executed in the order in which they appear on the
|
||||||
|
command line.
|
||||||
|
|
||||||
|
If |insertion_point| is present, |name| must also be present.
|
||||||
|
"""
|
||||||
|
|
||||||
|
content: str = betterproto.string_field(15)
|
||||||
|
"""The file contents."""
|
||||||
|
|
||||||
|
generated_code_info: "betterproto_lib_google_protobuf.GeneratedCodeInfo" = (
|
||||||
|
betterproto.message_field(16)
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
Information describing the file content being inserted. If an insertion
|
||||||
|
point is used, this information will be appropriately offset and inserted
|
||||||
|
into the code generation metadata for the generated files.
|
||||||
|
"""
|
@ -562,6 +562,7 @@ class FieldCompiler(MessageCompiler):
|
|||||||
package=self.output_file.package,
|
package=self.output_file.package,
|
||||||
imports=self.output_file.imports,
|
imports=self.output_file.imports,
|
||||||
source_type=self.proto_obj.type_name,
|
source_type=self.proto_obj.type_name,
|
||||||
|
pydantic=self.output_file.pydantic_dataclasses,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(f"Unknown type {self.proto_obj.type}")
|
raise NotImplementedError(f"Unknown type {self.proto_obj.type}")
|
||||||
@ -806,6 +807,7 @@ class ServiceMethodCompiler(ProtoContentBase):
|
|||||||
imports=self.output_file.imports,
|
imports=self.output_file.imports,
|
||||||
source_type=self.proto_obj.input_type,
|
source_type=self.proto_obj.input_type,
|
||||||
unwrap=False,
|
unwrap=False,
|
||||||
|
pydantic=self.output_file.pydantic_dataclasses,
|
||||||
).strip('"')
|
).strip('"')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -834,6 +836,7 @@ class ServiceMethodCompiler(ProtoContentBase):
|
|||||||
imports=self.output_file.imports,
|
imports=self.output_file.imports,
|
||||||
source_type=self.proto_obj.output_type,
|
source_type=self.proto_obj.output_type,
|
||||||
unwrap=False,
|
unwrap=False,
|
||||||
|
pydantic=self.output_file.pydantic_dataclasses,
|
||||||
).strip('"')
|
).strip('"')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -35,7 +35,48 @@ def test_reference_google_wellknown_types_non_wrappers(
|
|||||||
google_type: str, expected_name: str, expected_import: str
|
google_type: str, expected_name: str, expected_import: str
|
||||||
):
|
):
|
||||||
imports = set()
|
imports = set()
|
||||||
name = get_type_reference(package="", imports=imports, source_type=google_type)
|
name = get_type_reference(
|
||||||
|
package="", imports=imports, source_type=google_type, pydantic=False
|
||||||
|
)
|
||||||
|
|
||||||
|
assert name == expected_name
|
||||||
|
assert imports.__contains__(
|
||||||
|
expected_import
|
||||||
|
), f"{expected_import} not found in {imports}"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
["google_type", "expected_name", "expected_import"],
|
||||||
|
[
|
||||||
|
(
|
||||||
|
".google.protobuf.Empty",
|
||||||
|
'"betterproto_lib_pydantic_google_protobuf.Empty"',
|
||||||
|
"import betterproto.lib.pydantic.google.protobuf as betterproto_lib_pydantic_google_protobuf",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
".google.protobuf.Struct",
|
||||||
|
'"betterproto_lib_pydantic_google_protobuf.Struct"',
|
||||||
|
"import betterproto.lib.pydantic.google.protobuf as betterproto_lib_pydantic_google_protobuf",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
".google.protobuf.ListValue",
|
||||||
|
'"betterproto_lib_pydantic_google_protobuf.ListValue"',
|
||||||
|
"import betterproto.lib.pydantic.google.protobuf as betterproto_lib_pydantic_google_protobuf",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
".google.protobuf.Value",
|
||||||
|
'"betterproto_lib_pydantic_google_protobuf.Value"',
|
||||||
|
"import betterproto.lib.pydantic.google.protobuf as betterproto_lib_pydantic_google_protobuf",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_reference_google_wellknown_types_non_wrappers_pydantic(
|
||||||
|
google_type: str, expected_name: str, expected_import: str
|
||||||
|
):
|
||||||
|
imports = set()
|
||||||
|
name = get_type_reference(
|
||||||
|
package="", imports=imports, source_type=google_type, pydantic=True
|
||||||
|
)
|
||||||
|
|
||||||
assert name == expected_name
|
assert name == expected_name
|
||||||
assert imports.__contains__(
|
assert imports.__contains__(
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from betterproto.lib.google.protobuf import Struct
|
from betterproto.lib.google.protobuf import Struct
|
||||||
|
from betterproto.lib.pydantic.google.protobuf import Struct as StructPydantic
|
||||||
|
|
||||||
|
|
||||||
def test_struct_roundtrip():
|
def test_struct_roundtrip():
|
||||||
@ -22,3 +23,14 @@ def test_struct_roundtrip():
|
|||||||
assert struct_from_json.to_dict() == data
|
assert struct_from_json.to_dict() == data
|
||||||
assert struct_from_json == struct_from_dict
|
assert struct_from_json == struct_from_dict
|
||||||
assert struct_from_json.to_json() == data_json
|
assert struct_from_json.to_json() == data_json
|
||||||
|
|
||||||
|
struct_pyd_from_dict = StructPydantic(fields={}).from_dict(data)
|
||||||
|
assert struct_pyd_from_dict.fields == data
|
||||||
|
assert struct_pyd_from_dict.to_dict() == data
|
||||||
|
assert struct_pyd_from_dict.to_json() == data_json
|
||||||
|
|
||||||
|
struct_pyd_from_dict = StructPydantic(fields={}).from_json(data_json)
|
||||||
|
assert struct_pyd_from_dict.fields == data
|
||||||
|
assert struct_pyd_from_dict.to_dict() == data
|
||||||
|
assert struct_pyd_from_dict == struct_pyd_from_dict
|
||||||
|
assert struct_pyd_from_dict.to_json() == data_json
|
||||||
|
Loading…
x
Reference in New Issue
Block a user