diff --git a/README.md b/README.md index b025cbb..09ee883 100644 --- a/README.md +++ b/README.md @@ -443,9 +443,9 @@ Assuming your `google.protobuf` source files (included with all releases of `pro ```sh protoc \ - --plugin=protoc-gen-custom=betterproto/plugin.py \ + --plugin=protoc-gen-custom=src/betterproto/plugin/main.py \ --custom_opt=INCLUDE_GOOGLE \ - --custom_out=betterproto/lib \ + --custom_out=src/betterproto/lib \ -I /usr/local/include/ \ /usr/local/include/google/protobuf/*.proto ``` diff --git a/src/betterproto/__init__.py b/src/betterproto/__init__.py index 6ebe2bc..61d9fc2 100644 --- a/src/betterproto/__init__.py +++ b/src/betterproto/__init__.py @@ -1172,6 +1172,7 @@ from .lib.google.protobuf import ( # noqa BytesValue, DoubleValue, Duration, + EnumValue, FloatValue, Int32Value, Int64Value, @@ -1238,14 +1239,17 @@ class _WrappedMessage(Message): def _get_wrapper(proto_type: str) -> Type: """Get the wrapper message class for a wrapped type.""" + + # TODO: include ListValue and NullValue? return { TYPE_BOOL: BoolValue, - TYPE_INT32: Int32Value, - TYPE_UINT32: UInt32Value, - TYPE_INT64: Int64Value, - TYPE_UINT64: UInt64Value, - TYPE_FLOAT: FloatValue, - TYPE_DOUBLE: DoubleValue, - TYPE_STRING: StringValue, TYPE_BYTES: BytesValue, + TYPE_DOUBLE: DoubleValue, + TYPE_FLOAT: FloatValue, + TYPE_ENUM: EnumValue, + TYPE_INT32: Int32Value, + TYPE_INT64: Int64Value, + TYPE_STRING: StringValue, + TYPE_UINT32: UInt32Value, + TYPE_UINT64: UInt64Value, }[proto_type] diff --git a/src/betterproto/lib/google/protobuf/__init__.py b/src/betterproto/lib/google/protobuf/__init__.py index 936d175..d1f21f9 100644 --- a/src/betterproto/lib/google/protobuf/__init__.py +++ b/src/betterproto/lib/google/protobuf/__init__.py @@ -1,6 +1,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: google/protobuf/any.proto, google/protobuf/source_context.proto, google/protobuf/type.proto, google/protobuf/api.proto, google/protobuf/descriptor.proto, google/protobuf/duration.proto, google/protobuf/empty.proto, google/protobuf/field_mask.proto, google/protobuf/struct.proto, google/protobuf/timestamp.proto, google/protobuf/wrappers.proto +# sources: google/protobuf/timestamp.proto, google/protobuf/field_mask.proto, google/protobuf/source_context.proto, google/protobuf/any.proto, google/protobuf/type.proto, google/protobuf/api.proto, google/protobuf/duration.proto, google/protobuf/struct.proto, google/protobuf/wrappers.proto, google/protobuf/empty.proto, google/protobuf/descriptor.proto # plugin: python-betterproto +import warnings from dataclasses import dataclass from typing import Dict, List @@ -45,6 +46,17 @@ class FieldCardinality(betterproto.Enum): CARDINALITY_REPEATED = 3 +class NullValue(betterproto.Enum): + """ + `NullValue` is a singleton enumeration to represent the null value for the + `Value` type union. The JSON representation for `NullValue` is JSON + `null`. + """ + + # Null value. + NULL_VALUE = 0 + + class FieldDescriptorProtoType(betterproto.Enum): TYPE_DOUBLE = 1 TYPE_FLOAT = 2 @@ -96,923 +108,75 @@ class MethodOptionsIdempotencyLevel(betterproto.Enum): IDEMPOTENT = 2 -class NullValue(betterproto.Enum): +@dataclass(eq=False, repr=False) +class Timestamp(betterproto.Message): """ - `NullValue` is a singleton enumeration to represent the null value for the - `Value` type union. The JSON representation for `NullValue` is JSON - `null`. + A Timestamp represents a point in time independent of any time zone or + local calendar, encoded as a count of seconds and fractions of seconds at + nanosecond resolution. The count is relative to an epoch at UTC midnight on + January 1, 1970, in the proleptic Gregorian calendar which extends the + Gregorian calendar backwards to year one. All minutes are 60 seconds long. + Leap seconds are "smeared" so that no leap second table is needed for + interpretation, using a [24-hour linear + smear](https://developers.google.com/time/smear). The range is from + 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By restricting to + that range, we ensure that we can convert to and from [RFC + 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. # Examples + Example 1: Compute Timestamp from POSIX `time()`. Timestamp timestamp; + timestamp.set_seconds(time(NULL)); timestamp.set_nanos(0); Example 2: + Compute Timestamp from POSIX `gettimeofday()`. struct timeval tv; + gettimeofday(&tv, NULL); Timestamp timestamp; + timestamp.set_seconds(tv.tv_sec); timestamp.set_nanos(tv.tv_usec * + 1000); Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + FILETIME ft; GetSystemTimeAsFileTime(&ft); UINT64 ticks = + (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; // A Windows + tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z // is + 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. Timestamp + timestamp; timestamp.set_seconds((INT64) ((ticks / 10000000) - + 11644473600LL)); timestamp.set_nanos((INT32) ((ticks % 10000000) * + 100)); Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + long millis = System.currentTimeMillis(); Timestamp timestamp = + Timestamp.newBuilder().setSeconds(millis / 1000) .setNanos((int) + ((millis % 1000) * 1000000)).build(); Example 5: Compute Timestamp from + current time in Python. timestamp = Timestamp() + timestamp.GetCurrentTime() # JSON Mapping In JSON format, the Timestamp + type is encoded as a string in the [RFC + 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the format is + "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" where {year} is + always expressed using four digits while {month}, {day}, {hour}, {min}, and + {sec} are zero-padded to two digits each. The fractional seconds, which can + go up to 9 digits (i.e. up to 1 nanosecond resolution), are optional. The + "Z" suffix indicates the timezone ("UTC"); the timezone is required. A + proto3 JSON serializer should always use UTC (as indicated by "Z") when + printing the Timestamp type and a proto3 JSON parser should be able to + accept both UTC and other timezones (as indicated by an offset). For + example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past 01:30 UTC on + January 15, 2017. In JavaScript, one can convert a Date object to this + format using the standard [toISOString()](https://developer.mozilla.org/en- + US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) method. + In Python, a standard `datetime.datetime` object can be converted to this + format using + [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) + with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one + can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( + http://www.joda.org/joda- + time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D ) + to obtain a formatter capable of generating timestamps in this format. """ - # Null value. - NULL_VALUE = 0 - - -@dataclass -class Any(betterproto.Message): - """ - `Any` contains an arbitrary serialized protocol buffer message along with a - URL that describes the type of the serialized message. Protobuf library - provides support to pack/unpack Any values in the form of utility functions - or additional generated methods of the Any type. Example 1: Pack and unpack - a message in C++. Foo foo = ...; Any any; any.PackFrom(foo); - ... if (any.UnpackTo(&foo)) { ... } Example 2: Pack and - unpack a message in Java. Foo foo = ...; Any any = Any.pack(foo); - ... if (any.is(Foo.class)) { foo = any.unpack(Foo.class); } - Example 3: Pack and unpack a message in Python. foo = Foo(...) any - = Any() any.Pack(foo) ... if any.Is(Foo.DESCRIPTOR): - any.Unpack(foo) ... Example 4: Pack and unpack a message in Go - foo := &pb.Foo{...} any, err := ptypes.MarshalAny(foo) ... - foo := &pb.Foo{} if err := ptypes.UnmarshalAny(any, foo); err != nil { - ... } The pack methods provided by protobuf library will by default - use 'type.googleapis.com/full.type.name' as the type URL and the unpack - methods only use the fully qualified type name after the last '/' in the - type URL, for example "foo.bar.com/x/y.z" will yield type name "y.z". JSON - ==== The JSON representation of an `Any` value uses the regular - representation of the deserialized, embedded message, with an additional - field `@type` which contains the type URL. Example: package - google.profile; message Person { string first_name = 1; - string last_name = 2; } { "@type": - "type.googleapis.com/google.profile.Person", "firstName": , - "lastName": } If the embedded message type is well-known and - has a custom JSON representation, that representation will be embedded - adding a field `value` which holds the custom JSON in addition to the - `@type` field. Example (for message [google.protobuf.Duration][]): { - "@type": "type.googleapis.com/google.protobuf.Duration", "value": - "1.212s" } - """ - - # A URL/resource name that uniquely identifies the type of the serialized - # protocol buffer message. This string must contain at least one "/" - # character. The last segment of the URL's path must represent the fully - # qualified name of the type (as in `path/google.protobuf.Duration`). The - # name should be in a canonical form (e.g., leading "." is not accepted). In - # practice, teams usually precompile into the binary all types that they - # expect it to use in the context of Any. However, for URLs which use the - # scheme `http`, `https`, or no scheme, one can optionally set up a type - # server that maps type URLs to message definitions as follows: * If no - # scheme is provided, `https` is assumed. * An HTTP GET on the URL must yield - # a [google.protobuf.Type][] value in binary format, or produce an error. * - # Applications are allowed to cache lookup results based on the URL, or - # have them precompiled into a binary to avoid any lookup. Therefore, - # binary compatibility needs to be preserved on changes to types. (Use - # versioned type names to manage breaking changes.) Note: this - # functionality is not currently available in the official protobuf release, - # and it is not used for type URLs beginning with type.googleapis.com. - # Schemes other than `http`, `https` (or the empty scheme) might be used with - # implementation specific semantics. - type_url: str = betterproto.string_field(1) - # Must be a valid serialized protocol buffer of the above specified type. - value: bytes = betterproto.bytes_field(2) - - -@dataclass -class SourceContext(betterproto.Message): - """ - `SourceContext` represents information about the source of a protobuf - element, like the file in which it is defined. - """ - - # The path-qualified name of the .proto file that contained the associated - # protobuf element. For example: `"google/protobuf/source_context.proto"`. - file_name: str = betterproto.string_field(1) - - -@dataclass -class Type(betterproto.Message): - """A protocol buffer message type.""" - - # The fully qualified message name. - name: str = betterproto.string_field(1) - # The list of fields. - fields: List["Field"] = betterproto.message_field(2) - # The list of types appearing in `oneof` definitions in this type. - oneofs: List[str] = betterproto.string_field(3) - # The protocol buffer options. - options: List["Option"] = betterproto.message_field(4) - # The source context. - source_context: "SourceContext" = betterproto.message_field(5) - # The source syntax. - syntax: "Syntax" = betterproto.enum_field(6) - - -@dataclass -class Field(betterproto.Message): - """A single field of a message type.""" - - # The field type. - kind: "FieldKind" = betterproto.enum_field(1) - # The field cardinality. - cardinality: "FieldCardinality" = betterproto.enum_field(2) - # The field number. - number: int = betterproto.int32_field(3) - # The field name. - name: str = betterproto.string_field(4) - # The field type URL, without the scheme, for message or enumeration types. - # Example: `"type.googleapis.com/google.protobuf.Timestamp"`. - type_url: str = betterproto.string_field(6) - # The index of the field type in `Type.oneofs`, for message or enumeration - # types. The first type has index 1; zero means the type is not in the list. - oneof_index: int = betterproto.int32_field(7) - # Whether to use alternative packed wire representation. - packed: bool = betterproto.bool_field(8) - # The protocol buffer options. - options: List["Option"] = betterproto.message_field(9) - # The field JSON name. - json_name: str = betterproto.string_field(10) - # The string value of the default value of this field. Proto2 syntax only. - default_value: str = betterproto.string_field(11) - - -@dataclass -class Enum(betterproto.Message): - """Enum type definition.""" - - # Enum type name. - name: str = betterproto.string_field(1) - # Enum value definitions. - enumvalue: List["EnumValue"] = betterproto.message_field( - 2, wraps=betterproto.TYPE_ENUM - ) - # Protocol buffer options. - options: List["Option"] = betterproto.message_field(3) - # The source context. - source_context: "SourceContext" = betterproto.message_field(4) - # The source syntax. - syntax: "Syntax" = betterproto.enum_field(5) - - -@dataclass -class EnumValue(betterproto.Message): - """Enum value definition.""" - - # Enum value name. - name: str = betterproto.string_field(1) - # Enum value number. - number: int = betterproto.int32_field(2) - # Protocol buffer options. - options: List["Option"] = betterproto.message_field(3) - - -@dataclass -class Option(betterproto.Message): - """ - A protocol buffer option, which can be attached to a message, field, - enumeration, etc. - """ - - # The option's name. For protobuf built-in options (options defined in - # descriptor.proto), this is the short name. For example, `"map_entry"`. For - # custom options, it should be the fully-qualified name. For example, - # `"google.api.http"`. - name: str = betterproto.string_field(1) - # The option's value packed in an Any message. If the value is a primitive, - # the corresponding wrapper type defined in google/protobuf/wrappers.proto - # should be used. If the value is an enum, it should be stored as an int32 - # value using the google.protobuf.Int32Value type. - value: "Any" = betterproto.message_field(2) - - -@dataclass -class Api(betterproto.Message): - """ - Api is a light-weight descriptor for an API Interface. Interfaces are also - described as "protocol buffer services" in some contexts, such as by the - "service" keyword in a .proto file, but they are different from API - Services, which represent a concrete implementation of an interface as - opposed to simply a description of methods and bindings. They are also - sometimes simply referred to as "APIs" in other contexts, such as the name - of this message itself. See https://cloud.google.com/apis/design/glossary - for detailed terminology. - """ - - # The fully qualified name of this interface, including package name followed - # by the interface's simple name. - name: str = betterproto.string_field(1) - # The methods of this interface, in unspecified order. - methods: List["Method"] = betterproto.message_field(2) - # Any metadata attached to the interface. - options: List["Option"] = betterproto.message_field(3) - # A version string for this interface. If specified, must have the form - # `major-version.minor-version`, as in `1.10`. If the minor version is - # omitted, it defaults to zero. If the entire version field is empty, the - # major version is derived from the package name, as outlined below. If the - # field is not empty, the version in the package name will be verified to be - # consistent with what is provided here. The versioning schema uses [semantic - # versioning](http://semver.org) where the major version number indicates a - # breaking change and the minor version an additive, non-breaking change. - # Both version numbers are signals to users what to expect from different - # versions, and should be carefully chosen based on the product plan. The - # major version is also reflected in the package name of the interface, which - # must end in `v`, as in `google.feature.v1`. For major - # versions 0 and 1, the suffix can be omitted. Zero major versions must only - # be used for experimental, non-GA interfaces. - version: str = betterproto.string_field(4) - # Source context for the protocol buffer service represented by this message. - source_context: "SourceContext" = betterproto.message_field(5) - # Included interfaces. See [Mixin][]. - mixins: List["Mixin"] = betterproto.message_field(6) - # The source syntax of the service. - syntax: "Syntax" = betterproto.enum_field(7) - - -@dataclass -class Method(betterproto.Message): - """Method represents a method of an API interface.""" - - # The simple name of this method. - name: str = betterproto.string_field(1) - # A URL of the input message type. - request_type_url: str = betterproto.string_field(2) - # If true, the request is streamed. - request_streaming: bool = betterproto.bool_field(3) - # The URL of the output message type. - response_type_url: str = betterproto.string_field(4) - # If true, the response is streamed. - response_streaming: bool = betterproto.bool_field(5) - # Any metadata attached to the method. - options: List["Option"] = betterproto.message_field(6) - # The source syntax of this method. - syntax: "Syntax" = betterproto.enum_field(7) - - -@dataclass -class Mixin(betterproto.Message): - """ - Declares an API Interface to be included in this interface. The including - interface must redeclare all the methods from the included interface, but - documentation and options are inherited as follows: - If after comment and - whitespace stripping, the documentation string of the redeclared method - is empty, it will be inherited from the original method. - Each - annotation belonging to the service config (http, visibility) which is - not set in the redeclared method will be inherited. - If an http - annotation is inherited, the path pattern will be modified as follows. - Any version prefix will be replaced by the version of the including - interface plus the [root][] path if specified. Example of a simple mixin: - package google.acl.v1; service AccessControl { // Get the - underlying ACL object. rpc GetAcl(GetAclRequest) returns (Acl) { - option (google.api.http).get = "/v1/{resource=**}:getAcl"; } } - package google.storage.v2; service Storage { rpc - GetAcl(GetAclRequest) returns (Acl); // Get a data record. rpc - GetData(GetDataRequest) returns (Data) { option - (google.api.http).get = "/v2/{resource=**}"; } } Example of a - mixin configuration: apis: - name: google.storage.v2.Storage - mixins: - name: google.acl.v1.AccessControl The mixin construct - implies that all methods in `AccessControl` are also declared with same - name and request/response types in `Storage`. A documentation generator or - annotation processor will see the effective `Storage.GetAcl` method after - inherting documentation and annotations as follows: service Storage { - // Get the underlying ACL object. rpc GetAcl(GetAclRequest) returns - (Acl) { option (google.api.http).get = "/v2/{resource=**}:getAcl"; - } ... } Note how the version in the path pattern changed from - `v1` to `v2`. If the `root` field in the mixin is specified, it should be a - relative path under which inherited HTTP paths are placed. Example: - apis: - name: google.storage.v2.Storage mixins: - name: - google.acl.v1.AccessControl root: acls This implies the following - inherited HTTP annotation: service Storage { // Get the - underlying ACL object. rpc GetAcl(GetAclRequest) returns (Acl) { - option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; } - ... } - """ - - # The fully qualified name of the interface which is included. - name: str = betterproto.string_field(1) - # If non-empty specifies a path under which inherited HTTP paths are rooted. - root: str = betterproto.string_field(2) - - -@dataclass -class FileDescriptorSet(betterproto.Message): - """ - The protocol compiler can output a FileDescriptorSet containing the .proto - files it parses. - """ - - file: List["FileDescriptorProto"] = betterproto.message_field(1) - - -@dataclass -class FileDescriptorProto(betterproto.Message): - """Describes a complete .proto file.""" - - name: str = betterproto.string_field(1) - package: str = betterproto.string_field(2) - # Names of files imported by this file. - dependency: List[str] = betterproto.string_field(3) - # Indexes of the public imported files in the dependency list above. - public_dependency: List[int] = betterproto.int32_field(10) - # Indexes of the weak imported files in the dependency list. For Google- - # internal migration only. Do not use. - weak_dependency: List[int] = betterproto.int32_field(11) - # All top-level definitions in this file. - message_type: List["DescriptorProto"] = betterproto.message_field(4) - enum_type: List["EnumDescriptorProto"] = betterproto.message_field(5) - service: List["ServiceDescriptorProto"] = betterproto.message_field(6) - extension: List["FieldDescriptorProto"] = betterproto.message_field(7) - options: "FileOptions" = betterproto.message_field(8) - # This field contains optional information about the original source code. - # You may safely remove this entire field without harming runtime - # functionality of the descriptors -- the information is needed only by - # development tools. - source_code_info: "SourceCodeInfo" = betterproto.message_field(9) - # The syntax of the proto file. The supported values are "proto2" and - # "proto3". - syntax: str = betterproto.string_field(12) - - -@dataclass -class DescriptorProto(betterproto.Message): - """Describes a message type.""" - - name: str = betterproto.string_field(1) - field: List["FieldDescriptorProto"] = betterproto.message_field(2) - extension: List["FieldDescriptorProto"] = betterproto.message_field(6) - nested_type: List["DescriptorProto"] = betterproto.message_field(3) - enum_type: List["EnumDescriptorProto"] = betterproto.message_field(4) - extension_range: List["DescriptorProtoExtensionRange"] = betterproto.message_field( - 5 - ) - oneof_decl: List["OneofDescriptorProto"] = betterproto.message_field(8) - options: "MessageOptions" = betterproto.message_field(7) - reserved_range: List["DescriptorProtoReservedRange"] = betterproto.message_field(9) - # Reserved field names, which may not be used by fields in the same message. - # A given name may only be reserved once. - reserved_name: List[str] = betterproto.string_field(10) - - -@dataclass -class DescriptorProtoExtensionRange(betterproto.Message): - start: int = betterproto.int32_field(1) - end: int = betterproto.int32_field(2) - options: "ExtensionRangeOptions" = betterproto.message_field(3) - - -@dataclass -class DescriptorProtoReservedRange(betterproto.Message): - """ - Range of reserved tag numbers. Reserved tag numbers may not be used by - fields or extension ranges in the same message. Reserved ranges may not - overlap. - """ - - start: int = betterproto.int32_field(1) - end: int = betterproto.int32_field(2) - - -@dataclass -class ExtensionRangeOptions(betterproto.Message): - # The parser stores options it doesn't recognize here. See above. - uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) - - -@dataclass -class FieldDescriptorProto(betterproto.Message): - """Describes a field within a message.""" - - name: str = betterproto.string_field(1) - number: int = betterproto.int32_field(3) - label: "FieldDescriptorProtoLabel" = betterproto.enum_field(4) - # If type_name is set, this need not be set. If both this and type_name are - # set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. - type: "FieldDescriptorProtoType" = betterproto.enum_field(5) - # For message and enum types, this is the name of the type. If the name - # starts with a '.', it is fully-qualified. Otherwise, C++-like scoping - # rules are used to find the type (i.e. first the nested types within this - # message are searched, then within the parent, on up to the root namespace). - type_name: str = betterproto.string_field(6) - # For extensions, this is the name of the type being extended. It is - # resolved in the same manner as type_name. - extendee: str = betterproto.string_field(2) - # For numeric types, contains the original text representation of the value. - # For booleans, "true" or "false". For strings, contains the default text - # contents (not escaped in any way). For bytes, contains the C escaped value. - # All bytes >= 128 are escaped. TODO(kenton): Base-64 encode? - default_value: str = betterproto.string_field(7) - # If set, gives the index of a oneof in the containing type's oneof_decl - # list. This field is a member of that oneof. - oneof_index: int = betterproto.int32_field(9) - # JSON name of this field. The value is set by protocol compiler. If the user - # has set a "json_name" option on this field, that option's value will be - # used. Otherwise, it's deduced from the field's name by converting it to - # camelCase. - json_name: str = betterproto.string_field(10) - options: "FieldOptions" = betterproto.message_field(8) - - -@dataclass -class OneofDescriptorProto(betterproto.Message): - """Describes a oneof.""" - - name: str = betterproto.string_field(1) - options: "OneofOptions" = betterproto.message_field(2) - - -@dataclass -class EnumDescriptorProto(betterproto.Message): - """Describes an enum type.""" - - name: str = betterproto.string_field(1) - value: List["EnumValueDescriptorProto"] = betterproto.message_field( - 2, wraps=betterproto.TYPE_ENUM - ) - options: "EnumOptions" = betterproto.message_field(3) - # Range of reserved numeric values. Reserved numeric values may not be used - # by enum values in the same enum declaration. Reserved ranges may not - # overlap. - reserved_range: List[ - "EnumDescriptorProtoEnumReservedRange" - ] = betterproto.message_field(4) - # Reserved enum value names, which may not be reused. A given name may only - # be reserved once. - reserved_name: List[str] = betterproto.string_field(5) - - -@dataclass -class EnumDescriptorProtoEnumReservedRange(betterproto.Message): - """ - Range of reserved numeric values. Reserved values may not be used by - entries in the same enum. Reserved ranges may not overlap. Note that this - is distinct from DescriptorProto.ReservedRange in that it is inclusive such - that it can appropriately represent the entire int32 domain. - """ - - start: int = betterproto.int32_field(1) - end: int = betterproto.int32_field(2) - - -@dataclass -class EnumValueDescriptorProto(betterproto.Message): - """Describes a value within an enum.""" - - name: str = betterproto.string_field(1) - number: int = betterproto.int32_field(2) - options: "EnumValueOptions" = betterproto.message_field( - 3, wraps=betterproto.TYPE_ENUM - ) - - -@dataclass -class ServiceDescriptorProto(betterproto.Message): - """Describes a service.""" - - name: str = betterproto.string_field(1) - method: List["MethodDescriptorProto"] = betterproto.message_field(2) - options: "ServiceOptions" = betterproto.message_field(3) - - -@dataclass -class MethodDescriptorProto(betterproto.Message): - """Describes a method of a service.""" - - name: str = betterproto.string_field(1) - # Input and output type names. These are resolved in the same way as - # FieldDescriptorProto.type_name, but must refer to a message type. - input_type: str = betterproto.string_field(2) - output_type: str = betterproto.string_field(3) - options: "MethodOptions" = betterproto.message_field(4) - # Identifies if client streams multiple client messages - client_streaming: bool = betterproto.bool_field(5) - # Identifies if server streams multiple server messages - server_streaming: bool = betterproto.bool_field(6) - - -@dataclass -class FileOptions(betterproto.Message): - # Sets the Java package where classes generated from this .proto will be - # placed. By default, the proto package is used, but this is often - # inappropriate because proto packages do not normally start with backwards - # domain names. - java_package: str = betterproto.string_field(1) - # If set, all the classes from the .proto file are wrapped in a single outer - # class with the given name. This applies to both Proto1 (equivalent to the - # old "--one_java_file" option) and Proto2 (where a .proto always translates - # to a single class, but you may want to explicitly choose the class name). - java_outer_classname: str = betterproto.string_field(8) - # If set true, then the Java code generator will generate a separate .java - # file for each top-level message, enum, and service defined in the .proto - # file. Thus, these types will *not* be nested inside the outer class named - # by java_outer_classname. However, the outer class will still be generated - # to contain the file's getDescriptor() method as well as any top-level - # extensions defined in the file. - java_multiple_files: bool = betterproto.bool_field(10) - # This option does nothing. - java_generate_equals_and_hash: bool = betterproto.bool_field(20) - # If set true, then the Java2 code generator will generate code that throws - # an exception whenever an attempt is made to assign a non-UTF-8 byte - # sequence to a string field. Message reflection will do the same. However, - # an extension field still accepts non-UTF-8 byte sequences. This option has - # no effect on when used with the lite runtime. - java_string_check_utf8: bool = betterproto.bool_field(27) - optimize_for: "FileOptionsOptimizeMode" = betterproto.enum_field(9) - # Sets the Go package where structs generated from this .proto will be - # placed. If omitted, the Go package will be derived from the following: - - # The basename of the package import path, if provided. - Otherwise, the - # package statement in the .proto file, if present. - Otherwise, the - # basename of the .proto file, without extension. - go_package: str = betterproto.string_field(11) - # Should generic services be generated in each language? "Generic" services - # are not specific to any particular RPC system. They are generated by the - # main code generators in each language (without additional plugins). Generic - # services were the only kind of service generation supported by early - # versions of google.protobuf. Generic services are now considered deprecated - # in favor of using plugins that generate code specific to your particular - # RPC system. Therefore, these default to false. Old code which depends on - # generic services should explicitly set them to true. - cc_generic_services: bool = betterproto.bool_field(16) - java_generic_services: bool = betterproto.bool_field(17) - py_generic_services: bool = betterproto.bool_field(18) - php_generic_services: bool = betterproto.bool_field(42) - # Is this file deprecated? Depending on the target platform, this can emit - # Deprecated annotations for everything in the file, or it will be completely - # ignored; in the very least, this is a formalization for deprecating files. - deprecated: bool = betterproto.bool_field(23) - # Enables the use of arenas for the proto messages in this file. This applies - # only to generated classes for C++. - cc_enable_arenas: bool = betterproto.bool_field(31) - # Sets the objective c class prefix which is prepended to all objective c - # generated classes from this .proto. There is no default. - objc_class_prefix: str = betterproto.string_field(36) - # Namespace for generated classes; defaults to the package. - csharp_namespace: str = betterproto.string_field(37) - # By default Swift generators will take the proto package and CamelCase it - # replacing '.' with underscore and use that to prefix the types/symbols - # defined. When this options is provided, they will use this value instead to - # prefix the types/symbols defined. - swift_prefix: str = betterproto.string_field(39) - # Sets the php class prefix which is prepended to all php generated classes - # from this .proto. Default is empty. - php_class_prefix: str = betterproto.string_field(40) - # Use this option to change the namespace of php generated classes. Default - # is empty. When this option is empty, the package name will be used for - # determining the namespace. - php_namespace: str = betterproto.string_field(41) - # Use this option to change the namespace of php generated metadata classes. - # Default is empty. When this option is empty, the proto file name will be - # used for determining the namespace. - php_metadata_namespace: str = betterproto.string_field(44) - # Use this option to change the package of ruby generated classes. Default is - # empty. When this option is not set, the package name will be used for - # determining the ruby package. - ruby_package: str = betterproto.string_field(45) - # The parser stores options it doesn't recognize here. See the documentation - # for the "Options" section above. - uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) - - -@dataclass -class MessageOptions(betterproto.Message): - # Set true to use the old proto1 MessageSet wire format for extensions. This - # is provided for backwards-compatibility with the MessageSet wire format. - # You should not use this for any other reason: It's less efficient, has - # fewer features, and is more complicated. The message must be defined - # exactly as follows: message Foo { option message_set_wire_format = - # true; extensions 4 to max; } Note that the message cannot have any - # defined fields; MessageSets only have extensions. All extensions of your - # type must be singular messages; e.g. they cannot be int32s, enums, or - # repeated messages. Because this is an option, the above two restrictions - # are not enforced by the protocol compiler. - message_set_wire_format: bool = betterproto.bool_field(1) - # Disables the generation of the standard "descriptor()" accessor, which can - # conflict with a field of the same name. This is meant to make migration - # from proto1 easier; new code should avoid fields named "descriptor". - no_standard_descriptor_accessor: bool = betterproto.bool_field(2) - # Is this message deprecated? Depending on the target platform, this can emit - # Deprecated annotations for the message, or it will be completely ignored; - # in the very least, this is a formalization for deprecating messages. - deprecated: bool = betterproto.bool_field(3) - # Whether the message is an automatically generated map entry type for the - # maps field. For maps fields: map map_field = 1; The - # parsed descriptor looks like: message MapFieldEntry { option - # map_entry = true; optional KeyType key = 1; optional - # ValueType value = 2; } repeated MapFieldEntry map_field = 1; - # Implementations may choose not to generate the map_entry=true message, but - # use a native map in the target language to hold the keys and values. The - # reflection APIs in such implementations still need to work as if the field - # is a repeated message field. NOTE: Do not set the option in .proto files. - # Always use the maps syntax instead. The option should only be implicitly - # set by the proto compiler parser. - map_entry: bool = betterproto.bool_field(7) - # The parser stores options it doesn't recognize here. See above. - uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) - - -@dataclass -class FieldOptions(betterproto.Message): - # The ctype option instructs the C++ code generator to use a different - # representation of the field than it normally would. See the specific - # options below. This option is not yet implemented in the open source - # release -- sorry, we'll try to include it in a future version! - ctype: "FieldOptionsCType" = betterproto.enum_field(1) - # The packed option can be enabled for repeated primitive fields to enable a - # more efficient representation on the wire. Rather than repeatedly writing - # the tag and type for each element, the entire array is encoded as a single - # length-delimited blob. In proto3, only explicit setting it to false will - # avoid using packed encoding. - packed: bool = betterproto.bool_field(2) - # The jstype option determines the JavaScript type used for values of the - # field. The option is permitted only for 64 bit integral and fixed types - # (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING - # is represented as JavaScript string, which avoids loss of precision that - # can happen when a large value is converted to a floating point JavaScript. - # Specifying JS_NUMBER for the jstype causes the generated JavaScript code to - # use the JavaScript "number" type. The behavior of the default option - # JS_NORMAL is implementation dependent. This option is an enum to permit - # additional types to be added, e.g. goog.math.Integer. - jstype: "FieldOptionsJsType" = betterproto.enum_field(6) - # Should this field be parsed lazily? Lazy applies only to message-type - # fields. It means that when the outer message is initially parsed, the - # inner message's contents will not be parsed but instead stored in encoded - # form. The inner message will actually be parsed when it is first accessed. - # This is only a hint. Implementations are free to choose whether to use - # eager or lazy parsing regardless of the value of this option. However, - # setting this option true suggests that the protocol author believes that - # using lazy parsing on this field is worth the additional bookkeeping - # overhead typically needed to implement it. This option does not affect the - # public interface of any generated code; all method signatures remain the - # same. Furthermore, thread-safety of the interface is not affected by this - # option; const methods remain safe to call from multiple threads - # concurrently, while non-const methods continue to require exclusive access. - # Note that implementations may choose not to check required fields within a - # lazy sub-message. That is, calling IsInitialized() on the outer message - # may return true even if the inner message has missing required fields. This - # is necessary because otherwise the inner message would have to be parsed in - # order to perform the check, defeating the purpose of lazy parsing. An - # implementation which chooses not to check required fields must be - # consistent about it. That is, for any particular sub-message, the - # implementation must either *always* check its required fields, or *never* - # check its required fields, regardless of whether or not the message has - # been parsed. - lazy: bool = betterproto.bool_field(5) - # Is this field deprecated? Depending on the target platform, this can emit - # Deprecated annotations for accessors, or it will be completely ignored; in - # the very least, this is a formalization for deprecating fields. - deprecated: bool = betterproto.bool_field(3) - # For Google-internal migration only. Do not use. - weak: bool = betterproto.bool_field(10) - # The parser stores options it doesn't recognize here. See above. - uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) - - -@dataclass -class OneofOptions(betterproto.Message): - # The parser stores options it doesn't recognize here. See above. - uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) - - -@dataclass -class EnumOptions(betterproto.Message): - # Set this option to true to allow mapping different tag names to the same - # value. - allow_alias: bool = betterproto.bool_field(2) - # Is this enum deprecated? Depending on the target platform, this can emit - # Deprecated annotations for the enum, or it will be completely ignored; in - # the very least, this is a formalization for deprecating enums. - deprecated: bool = betterproto.bool_field(3) - # The parser stores options it doesn't recognize here. See above. - uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) - - -@dataclass -class EnumValueOptions(betterproto.Message): - # Is this enum value deprecated? Depending on the target platform, this can - # emit Deprecated annotations for the enum value, or it will be completely - # ignored; in the very least, this is a formalization for deprecating enum - # values. - deprecated: bool = betterproto.bool_field(1) - # The parser stores options it doesn't recognize here. See above. - uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) - - -@dataclass -class ServiceOptions(betterproto.Message): - # Is this service deprecated? Depending on the target platform, this can emit - # Deprecated annotations for the service, or it will be completely ignored; - # in the very least, this is a formalization for deprecating services. - deprecated: bool = betterproto.bool_field(33) - # The parser stores options it doesn't recognize here. See above. - uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) - - -@dataclass -class MethodOptions(betterproto.Message): - # Is this method deprecated? Depending on the target platform, this can emit - # Deprecated annotations for the method, or it will be completely ignored; in - # the very least, this is a formalization for deprecating methods. - deprecated: bool = betterproto.bool_field(33) - idempotency_level: "MethodOptionsIdempotencyLevel" = betterproto.enum_field(34) - # The parser stores options it doesn't recognize here. See above. - uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) - - -@dataclass -class UninterpretedOption(betterproto.Message): - """ - A message representing a option the parser does not recognize. This only - appears in options protos created by the compiler::Parser class. - DescriptorPool resolves these when building Descriptor objects. Therefore, - options protos in descriptor objects (e.g. returned by - Descriptor::options(), or produced by Descriptor::CopyTo()) will never have - UninterpretedOptions in them. - """ - - name: List["UninterpretedOptionNamePart"] = betterproto.message_field(2) - # The value of the uninterpreted option, in whatever type the tokenizer - # identified it as during parsing. Exactly one of these should be set. - identifier_value: str = betterproto.string_field(3) - positive_int_value: int = betterproto.uint64_field(4) - negative_int_value: int = betterproto.int64_field(5) - double_value: float = betterproto.double_field(6) - string_value: bytes = betterproto.bytes_field(7) - aggregate_value: str = betterproto.string_field(8) - - -@dataclass -class UninterpretedOptionNamePart(betterproto.Message): - """ - The name of the uninterpreted option. Each string represents a segment in - a dot-separated name. is_extension is true iff a segment represents an - extension (denoted with parentheses in options specs in .proto files). - E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents - "foo.(bar.baz).qux". - """ - - name_part: str = betterproto.string_field(1) - is_extension: bool = betterproto.bool_field(2) - - -@dataclass -class SourceCodeInfo(betterproto.Message): - """ - Encapsulates information about the original source file from which a - FileDescriptorProto was generated. - """ - - # A Location identifies a piece of source code in a .proto file which - # corresponds to a particular definition. This information is intended to be - # useful to IDEs, code indexers, documentation generators, and similar tools. - # For example, say we have a file like: message Foo { optional string - # foo = 1; } Let's look at just the field definition: optional string foo - # = 1; ^ ^^ ^^ ^ ^^^ a bc de f ghi We have the - # following locations: span path represents [a,i) [ 4, - # 0, 2, 0 ] The whole field definition. [a,b) [ 4, 0, 2, 0, 4 ] The - # label (optional). [c,d) [ 4, 0, 2, 0, 5 ] The type (string). [e,f) [ - # 4, 0, 2, 0, 1 ] The name (foo). [g,h) [ 4, 0, 2, 0, 3 ] The number - # (1). Notes: - A location may refer to a repeated field itself (i.e. not to - # any particular index within it). This is used whenever a set of elements - # are logically enclosed in a single code segment. For example, an entire - # extend block (possibly containing multiple extension definitions) will - # have an outer location whose path refers to the "extensions" repeated - # field without an index. - Multiple locations may have the same path. This - # happens when a single logical declaration is spread out across multiple - # places. The most obvious example is the "extend" block again -- there - # may be multiple extend blocks in the same scope, each of which will have - # the same path. - A location's span is not always a subset of its parent's - # span. For example, the "extendee" of an extension declaration appears at - # the beginning of the "extend" block and is shared by all extensions - # within the block. - Just because a location's span is a subset of some - # other location's span does not mean that it is a descendant. For - # example, a "group" defines both a type and a field in a single - # declaration. Thus, the locations corresponding to the type and field and - # their components will overlap. - Code which tries to interpret locations - # should probably be designed to ignore those that it doesn't understand, - # as more types of locations could be recorded in the future. - location: List["SourceCodeInfoLocation"] = betterproto.message_field(1) - - -@dataclass -class SourceCodeInfoLocation(betterproto.Message): - # Identifies which part of the FileDescriptorProto was defined at this - # location. Each element is a field number or an index. They form a path - # from the root FileDescriptorProto to the place where the definition. For - # example, this path: [ 4, 3, 2, 7, 1 ] refers to: file.message_type(3) - # // 4, 3 .field(7) // 2, 7 .name() // 1 This - # is because FileDescriptorProto.message_type has field number 4: repeated - # DescriptorProto message_type = 4; and DescriptorProto.field has field - # number 2: repeated FieldDescriptorProto field = 2; and - # FieldDescriptorProto.name has field number 1: optional string name = 1; - # Thus, the above path gives the location of a field name. If we removed the - # last element: [ 4, 3, 2, 7 ] this path refers to the whole field - # declaration (from the beginning of the label to the terminating semicolon). - path: List[int] = betterproto.int32_field(1) - # Always has exactly three or four elements: start line, start column, end - # line (optional, otherwise assumed same as start line), end column. These - # are packed into a single field for efficiency. Note that line and column - # numbers are zero-based -- typically you will want to add 1 to each before - # displaying to a user. - span: List[int] = betterproto.int32_field(2) - # If this SourceCodeInfo represents a complete declaration, these are any - # comments appearing before and after the declaration which appear to be - # attached to the declaration. A series of line comments appearing on - # consecutive lines, with no other tokens appearing on those lines, will be - # treated as a single comment. leading_detached_comments will keep paragraphs - # of comments that appear before (but not connected to) the current element. - # Each paragraph, separated by empty lines, will be one comment element in - # the repeated field. Only the comment content is provided; comment markers - # (e.g. //) are stripped out. For block comments, leading whitespace and an - # asterisk will be stripped from the beginning of each line other than the - # first. Newlines are included in the output. Examples: optional int32 foo - # = 1; // Comment attached to foo. // Comment attached to bar. optional - # int32 bar = 2; optional string baz = 3; // Comment attached to baz. - # // Another line attached to baz. // Comment attached to qux. // // - # Another line attached to qux. optional double qux = 4; // Detached - # comment for corge. This is not leading or trailing comments // to qux or - # corge because there are blank lines separating it from // both. // - # Detached comment for corge paragraph 2. optional string corge = 5; /* - # Block comment attached * to corge. Leading asterisks * will be - # removed. */ /* Block comment attached to * grault. */ optional int32 - # grault = 6; // ignored detached comments. - leading_comments: str = betterproto.string_field(3) - trailing_comments: str = betterproto.string_field(4) - leading_detached_comments: List[str] = betterproto.string_field(6) - - -@dataclass -class GeneratedCodeInfo(betterproto.Message): - """ - Describes the relationship between generated code and its original source - file. A GeneratedCodeInfo message is associated with only one generated - source file, but may contain references to different source .proto files. - """ - - # An Annotation connects some span of text in generated code to an element of - # its generating .proto file. - annotation: List["GeneratedCodeInfoAnnotation"] = betterproto.message_field(1) - - -@dataclass -class GeneratedCodeInfoAnnotation(betterproto.Message): - # Identifies the element in the original source .proto file. This field is - # formatted the same as SourceCodeInfo.Location.path. - path: List[int] = betterproto.int32_field(1) - # Identifies the filesystem path to the original source .proto. - source_file: str = betterproto.string_field(2) - # Identifies the starting offset in bytes in the generated code that relates - # to the identified object. - begin: int = betterproto.int32_field(3) - # Identifies the ending offset in bytes in the generated code that relates to - # the identified offset. The end offset should be one past the last relevant - # byte (so the length of the text = end - begin). - end: int = betterproto.int32_field(4) - - -@dataclass -class Duration(betterproto.Message): - """ - A Duration represents a signed, fixed-length span of time represented as a - count of seconds and fractions of seconds at nanosecond resolution. It is - independent of any calendar and concepts like "day" or "month". It is - related to Timestamp in that the difference between two Timestamp values is - a Duration and it can be added or subtracted from a Timestamp. Range is - approximately +-10,000 years. # Examples Example 1: Compute Duration from - two Timestamps in pseudo code. Timestamp start = ...; Timestamp end - = ...; Duration duration = ...; duration.seconds = end.seconds - - start.seconds; duration.nanos = end.nanos - start.nanos; if - (duration.seconds < 0 && duration.nanos > 0) { duration.seconds += 1; - duration.nanos -= 1000000000; } else if (duration.seconds > 0 && - duration.nanos < 0) { duration.seconds -= 1; duration.nanos += - 1000000000; } Example 2: Compute Timestamp from Timestamp + Duration in - pseudo code. Timestamp start = ...; Duration duration = ...; - Timestamp end = ...; end.seconds = start.seconds + duration.seconds; - end.nanos = start.nanos + duration.nanos; if (end.nanos < 0) { - end.seconds -= 1; end.nanos += 1000000000; } else if (end.nanos - >= 1000000000) { end.seconds += 1; end.nanos -= 1000000000; - } Example 3: Compute Duration from datetime.timedelta in Python. td = - datetime.timedelta(days=3, minutes=10) duration = Duration() - duration.FromTimedelta(td) # JSON Mapping In JSON format, the Duration type - is encoded as a string rather than an object, where the string ends in the - suffix "s" (indicating seconds) and is preceded by the number of seconds, - with nanoseconds expressed as fractional seconds. For example, 3 seconds - with 0 nanoseconds should be encoded in JSON format as "3s", while 3 - seconds and 1 nanosecond should be expressed in JSON format as - "3.000000001s", and 3 seconds and 1 microsecond should be expressed in JSON - format as "3.000001s". - """ - - # Signed seconds of the span of time. Must be from -315,576,000,000 to - # +315,576,000,000 inclusive. Note: these bounds are computed from: 60 - # sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + # Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must + # be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive. seconds: int = betterproto.int64_field(1) - # Signed fractions of a second at nanosecond resolution of the span of time. - # Durations less than one second are represented with a 0 `seconds` field and - # a positive or negative `nanos` field. For durations of one second or more, - # a non-zero value for the `nanos` field must be of the same sign as the - # `seconds` field. Must be from -999,999,999 to +999,999,999 inclusive. + # Non-negative fractions of a second at nanosecond resolution. Negative + # second values with fractions must still have non-negative nanos values that + # count forward in time. Must be from 0 to 999,999,999 inclusive. nanos: int = betterproto.int32_field(2) - -@dataclass -class Empty(betterproto.Message): - """ - A generic empty message that you can re-use to avoid defining duplicated - empty messages in your APIs. A typical example is to use it as the request - or the response type of an API method. For instance: service Foo { - rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); } The - JSON representation for `Empty` is empty JSON object `{}`. - """ - - pass + def __post_init__(self) -> None: + super().__post_init__() -@dataclass +@dataclass(eq=False, repr=False) class FieldMask(betterproto.Message): """ `FieldMask` represents a set of symbolic field paths, for example: @@ -1095,8 +259,362 @@ class FieldMask(betterproto.Message): # The set of field mask paths. paths: List[str] = betterproto.string_field(1) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) +class SourceContext(betterproto.Message): + """ + `SourceContext` represents information about the source of a protobuf + element, like the file in which it is defined. + """ + + # The path-qualified name of the .proto file that contained the associated + # protobuf element. For example: `"google/protobuf/source_context.proto"`. + file_name: str = betterproto.string_field(1) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class Any(betterproto.Message): + """ + `Any` contains an arbitrary serialized protocol buffer message along with a + URL that describes the type of the serialized message. Protobuf library + provides support to pack/unpack Any values in the form of utility functions + or additional generated methods of the Any type. Example 1: Pack and unpack + a message in C++. Foo foo = ...; Any any; any.PackFrom(foo); + ... if (any.UnpackTo(&foo)) { ... } Example 2: Pack and + unpack a message in Java. Foo foo = ...; Any any = Any.pack(foo); + ... if (any.is(Foo.class)) { foo = any.unpack(Foo.class); } + Example 3: Pack and unpack a message in Python. foo = Foo(...) any + = Any() any.Pack(foo) ... if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) ... Example 4: Pack and unpack a message in Go + foo := &pb.Foo{...} any, err := ptypes.MarshalAny(foo) ... + foo := &pb.Foo{} if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... } The pack methods provided by protobuf library will by default + use 'type.googleapis.com/full.type.name' as the type URL and the unpack + methods only use the fully qualified type name after the last '/' in the + type URL, for example "foo.bar.com/x/y.z" will yield type name "y.z". JSON + ==== The JSON representation of an `Any` value uses the regular + representation of the deserialized, embedded message, with an additional + field `@type` which contains the type URL. Example: package + google.profile; message Person { string first_name = 1; + string last_name = 2; } { "@type": + "type.googleapis.com/google.profile.Person", "firstName": , + "lastName": } If the embedded message type is well-known and + has a custom JSON representation, that representation will be embedded + adding a field `value` which holds the custom JSON in addition to the + `@type` field. Example (for message [google.protobuf.Duration][]): { + "@type": "type.googleapis.com/google.protobuf.Duration", "value": + "1.212s" } + """ + + # A URL/resource name that uniquely identifies the type of the serialized + # protocol buffer message. This string must contain at least one "/" + # character. The last segment of the URL's path must represent the fully + # qualified name of the type (as in `path/google.protobuf.Duration`). The + # name should be in a canonical form (e.g., leading "." is not accepted). In + # practice, teams usually precompile into the binary all types that they + # expect it to use in the context of Any. However, for URLs which use the + # scheme `http`, `https`, or no scheme, one can optionally set up a type + # server that maps type URLs to message definitions as follows: * If no + # scheme is provided, `https` is assumed. * An HTTP GET on the URL must yield + # a [google.protobuf.Type][] value in binary format, or produce an error. * + # Applications are allowed to cache lookup results based on the URL, or + # have them precompiled into a binary to avoid any lookup. Therefore, + # binary compatibility needs to be preserved on changes to types. (Use + # versioned type names to manage breaking changes.) Note: this + # functionality is not currently available in the official protobuf release, + # and it is not used for type URLs beginning with type.googleapis.com. + # Schemes other than `http`, `https` (or the empty scheme) might be used with + # implementation specific semantics. + type_url: str = betterproto.string_field(1) + # Must be a valid serialized protocol buffer of the above specified type. + value: bytes = betterproto.bytes_field(2) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class Type(betterproto.Message): + """A protocol buffer message type.""" + + # The fully qualified message name. + name: str = betterproto.string_field(1) + # The list of fields. + fields: List["Field"] = betterproto.message_field(2) + # The list of types appearing in `oneof` definitions in this type. + oneofs: List[str] = betterproto.string_field(3) + # The protocol buffer options. + options: List["Option"] = betterproto.message_field(4) + # The source context. + source_context: "SourceContext" = betterproto.message_field(5) + # The source syntax. + syntax: "Syntax" = betterproto.enum_field(6) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class Field(betterproto.Message): + """A single field of a message type.""" + + # The field type. + kind: "FieldKind" = betterproto.enum_field(1) + # The field cardinality. + cardinality: "FieldCardinality" = betterproto.enum_field(2) + # The field number. + number: int = betterproto.int32_field(3) + # The field name. + name: str = betterproto.string_field(4) + # The field type URL, without the scheme, for message or enumeration types. + # Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + type_url: str = betterproto.string_field(6) + # The index of the field type in `Type.oneofs`, for message or enumeration + # types. The first type has index 1; zero means the type is not in the list. + oneof_index: int = betterproto.int32_field(7) + # Whether to use alternative packed wire representation. + packed: bool = betterproto.bool_field(8) + # The protocol buffer options. + options: List["Option"] = betterproto.message_field(9) + # The field JSON name. + json_name: str = betterproto.string_field(10) + # The string value of the default value of this field. Proto2 syntax only. + default_value: str = betterproto.string_field(11) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class Enum(betterproto.Message): + """Enum type definition.""" + + # Enum type name. + name: str = betterproto.string_field(1) + # Enum value definitions. + enumvalue: List["EnumValue"] = betterproto.message_field( + 2, wraps=betterproto.TYPE_ENUM + ) + # Protocol buffer options. + options: List["Option"] = betterproto.message_field(3) + # The source context. + source_context: "SourceContext" = betterproto.message_field(4) + # The source syntax. + syntax: "Syntax" = betterproto.enum_field(5) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class EnumValue(betterproto.Message): + """Enum value definition.""" + + # Enum value name. + name: str = betterproto.string_field(1) + # Enum value number. + number: int = betterproto.int32_field(2) + # Protocol buffer options. + options: List["Option"] = betterproto.message_field(3) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class Option(betterproto.Message): + """ + A protocol buffer option, which can be attached to a message, field, + enumeration, etc. + """ + + # The option's name. For protobuf built-in options (options defined in + # descriptor.proto), this is the short name. For example, `"map_entry"`. For + # custom options, it should be the fully-qualified name. For example, + # `"google.api.http"`. + name: str = betterproto.string_field(1) + # The option's value packed in an Any message. If the value is a primitive, + # the corresponding wrapper type defined in google/protobuf/wrappers.proto + # should be used. If the value is an enum, it should be stored as an int32 + # value using the google.protobuf.Int32Value type. + value: "Any" = betterproto.message_field(2) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class Api(betterproto.Message): + """ + Api is a light-weight descriptor for an API Interface. Interfaces are also + described as "protocol buffer services" in some contexts, such as by the + "service" keyword in a .proto file, but they are different from API + Services, which represent a concrete implementation of an interface as + opposed to simply a description of methods and bindings. They are also + sometimes simply referred to as "APIs" in other contexts, such as the name + of this message itself. See https://cloud.google.com/apis/design/glossary + for detailed terminology. + """ + + # The fully qualified name of this interface, including package name followed + # by the interface's simple name. + name: str = betterproto.string_field(1) + # The methods of this interface, in unspecified order. + methods: List["Method"] = betterproto.message_field(2) + # Any metadata attached to the interface. + options: List["Option"] = betterproto.message_field(3) + # A version string for this interface. If specified, must have the form + # `major-version.minor-version`, as in `1.10`. If the minor version is + # omitted, it defaults to zero. If the entire version field is empty, the + # major version is derived from the package name, as outlined below. If the + # field is not empty, the version in the package name will be verified to be + # consistent with what is provided here. The versioning schema uses [semantic + # versioning](http://semver.org) where the major version number indicates a + # breaking change and the minor version an additive, non-breaking change. + # Both version numbers are signals to users what to expect from different + # versions, and should be carefully chosen based on the product plan. The + # major version is also reflected in the package name of the interface, which + # must end in `v`, as in `google.feature.v1`. For major + # versions 0 and 1, the suffix can be omitted. Zero major versions must only + # be used for experimental, non-GA interfaces. + version: str = betterproto.string_field(4) + # Source context for the protocol buffer service represented by this message. + source_context: "SourceContext" = betterproto.message_field(5) + # Included interfaces. See [Mixin][]. + mixins: List["Mixin"] = betterproto.message_field(6) + # The source syntax of the service. + syntax: "Syntax" = betterproto.enum_field(7) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class Method(betterproto.Message): + """Method represents a method of an API interface.""" + + # The simple name of this method. + name: str = betterproto.string_field(1) + # A URL of the input message type. + request_type_url: str = betterproto.string_field(2) + # If true, the request is streamed. + request_streaming: bool = betterproto.bool_field(3) + # The URL of the output message type. + response_type_url: str = betterproto.string_field(4) + # If true, the response is streamed. + response_streaming: bool = betterproto.bool_field(5) + # Any metadata attached to the method. + options: List["Option"] = betterproto.message_field(6) + # The source syntax of this method. + syntax: "Syntax" = betterproto.enum_field(7) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class Mixin(betterproto.Message): + """ + Declares an API Interface to be included in this interface. The including + interface must redeclare all the methods from the included interface, but + documentation and options are inherited as follows: - If after comment and + whitespace stripping, the documentation string of the redeclared method + is empty, it will be inherited from the original method. - Each + annotation belonging to the service config (http, visibility) which is + not set in the redeclared method will be inherited. - If an http + annotation is inherited, the path pattern will be modified as follows. + Any version prefix will be replaced by the version of the including + interface plus the [root][] path if specified. Example of a simple mixin: + package google.acl.v1; service AccessControl { // Get the + underlying ACL object. rpc GetAcl(GetAclRequest) returns (Acl) { + option (google.api.http).get = "/v1/{resource=**}:getAcl"; } } + package google.storage.v2; service Storage { rpc + GetAcl(GetAclRequest) returns (Acl); // Get a data record. rpc + GetData(GetDataRequest) returns (Data) { option + (google.api.http).get = "/v2/{resource=**}"; } } Example of a + mixin configuration: apis: - name: google.storage.v2.Storage + mixins: - name: google.acl.v1.AccessControl The mixin construct + implies that all methods in `AccessControl` are also declared with same + name and request/response types in `Storage`. A documentation generator or + annotation processor will see the effective `Storage.GetAcl` method after + inherting documentation and annotations as follows: service Storage { + // Get the underlying ACL object. rpc GetAcl(GetAclRequest) returns + (Acl) { option (google.api.http).get = "/v2/{resource=**}:getAcl"; + } ... } Note how the version in the path pattern changed from + `v1` to `v2`. If the `root` field in the mixin is specified, it should be a + relative path under which inherited HTTP paths are placed. Example: + apis: - name: google.storage.v2.Storage mixins: - name: + google.acl.v1.AccessControl root: acls This implies the following + inherited HTTP annotation: service Storage { // Get the + underlying ACL object. rpc GetAcl(GetAclRequest) returns (Acl) { + option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; } + ... } + """ + + # The fully qualified name of the interface which is included. + name: str = betterproto.string_field(1) + # If non-empty specifies a path under which inherited HTTP paths are rooted. + root: str = betterproto.string_field(2) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class Duration(betterproto.Message): + """ + A Duration represents a signed, fixed-length span of time represented as a + count of seconds and fractions of seconds at nanosecond resolution. It is + independent of any calendar and concepts like "day" or "month". It is + related to Timestamp in that the difference between two Timestamp values is + a Duration and it can be added or subtracted from a Timestamp. Range is + approximately +-10,000 years. # Examples Example 1: Compute Duration from + two Timestamps in pseudo code. Timestamp start = ...; Timestamp end + = ...; Duration duration = ...; duration.seconds = end.seconds - + start.seconds; duration.nanos = end.nanos - start.nanos; if + (duration.seconds < 0 && duration.nanos > 0) { duration.seconds += 1; + duration.nanos -= 1000000000; } else if (duration.seconds > 0 && + duration.nanos < 0) { duration.seconds -= 1; duration.nanos += + 1000000000; } Example 2: Compute Timestamp from Timestamp + Duration in + pseudo code. Timestamp start = ...; Duration duration = ...; + Timestamp end = ...; end.seconds = start.seconds + duration.seconds; + end.nanos = start.nanos + duration.nanos; if (end.nanos < 0) { + end.seconds -= 1; end.nanos += 1000000000; } else if (end.nanos + >= 1000000000) { end.seconds += 1; end.nanos -= 1000000000; + } Example 3: Compute Duration from datetime.timedelta in Python. td = + datetime.timedelta(days=3, minutes=10) duration = Duration() + duration.FromTimedelta(td) # JSON Mapping In JSON format, the Duration type + is encoded as a string rather than an object, where the string ends in the + suffix "s" (indicating seconds) and is preceded by the number of seconds, + with nanoseconds expressed as fractional seconds. For example, 3 seconds + with 0 nanoseconds should be encoded in JSON format as "3s", while 3 + seconds and 1 nanosecond should be expressed in JSON format as + "3.000000001s", and 3 seconds and 1 microsecond should be expressed in JSON + format as "3.000001s". + """ + + # Signed seconds of the span of time. Must be from -315,576,000,000 to + # +315,576,000,000 inclusive. Note: these bounds are computed from: 60 + # sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + seconds: int = betterproto.int64_field(1) + # Signed fractions of a second at nanosecond resolution of the span of time. + # Durations less than one second are represented with a 0 `seconds` field and + # a positive or negative `nanos` field. For durations of one second or more, + # a non-zero value for the `nanos` field must be of the same sign as the + # `seconds` field. Must be from -999,999,999 to +999,999,999 inclusive. + nanos: int = betterproto.int32_field(2) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) class Struct(betterproto.Message): """ `Struct` represents a structured data value, consisting of fields which map @@ -1112,8 +630,11 @@ class Struct(betterproto.Message): 1, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE ) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) class Value(betterproto.Message): """ `Value` represents a dynamically typed value which can be either null, a @@ -1136,8 +657,11 @@ class Value(betterproto.Message): # Represents a repeated `Value`. list_value: "ListValue" = betterproto.message_field(6, group="kind") + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) class ListValue(betterproto.Message): """ `ListValue` is a wrapper around a repeated field of values. The JSON @@ -1147,73 +671,11 @@ class ListValue(betterproto.Message): # Repeated field of dynamically typed values. values: List["Value"] = betterproto.message_field(1) - -@dataclass -class Timestamp(betterproto.Message): - """ - A Timestamp represents a point in time independent of any time zone or - local calendar, encoded as a count of seconds and fractions of seconds at - nanosecond resolution. The count is relative to an epoch at UTC midnight on - January 1, 1970, in the proleptic Gregorian calendar which extends the - Gregorian calendar backwards to year one. All minutes are 60 seconds long. - Leap seconds are "smeared" so that no leap second table is needed for - interpretation, using a [24-hour linear - smear](https://developers.google.com/time/smear). The range is from - 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By restricting to - that range, we ensure that we can convert to and from [RFC - 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. # Examples - Example 1: Compute Timestamp from POSIX `time()`. Timestamp timestamp; - timestamp.set_seconds(time(NULL)); timestamp.set_nanos(0); Example 2: - Compute Timestamp from POSIX `gettimeofday()`. struct timeval tv; - gettimeofday(&tv, NULL); Timestamp timestamp; - timestamp.set_seconds(tv.tv_sec); timestamp.set_nanos(tv.tv_usec * - 1000); Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. - FILETIME ft; GetSystemTimeAsFileTime(&ft); UINT64 ticks = - (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; // A Windows - tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z // is - 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. Timestamp - timestamp; timestamp.set_seconds((INT64) ((ticks / 10000000) - - 11644473600LL)); timestamp.set_nanos((INT32) ((ticks % 10000000) * - 100)); Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. - long millis = System.currentTimeMillis(); Timestamp timestamp = - Timestamp.newBuilder().setSeconds(millis / 1000) .setNanos((int) - ((millis % 1000) * 1000000)).build(); Example 5: Compute Timestamp from - current time in Python. timestamp = Timestamp() - timestamp.GetCurrentTime() # JSON Mapping In JSON format, the Timestamp - type is encoded as a string in the [RFC - 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the format is - "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" where {year} is - always expressed using four digits while {month}, {day}, {hour}, {min}, and - {sec} are zero-padded to two digits each. The fractional seconds, which can - go up to 9 digits (i.e. up to 1 nanosecond resolution), are optional. The - "Z" suffix indicates the timezone ("UTC"); the timezone is required. A - proto3 JSON serializer should always use UTC (as indicated by "Z") when - printing the Timestamp type and a proto3 JSON parser should be able to - accept both UTC and other timezones (as indicated by an offset). For - example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past 01:30 UTC on - January 15, 2017. In JavaScript, one can convert a Date object to this - format using the standard [toISOString()](https://developer.mozilla.org/en- - US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) method. - In Python, a standard `datetime.datetime` object can be converted to this - format using - [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) - with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one - can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( - http://www.joda.org/joda- - time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D ) - to obtain a formatter capable of generating timestamps in this format. - """ - - # Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must - # be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive. - seconds: int = betterproto.int64_field(1) - # Non-negative fractions of a second at nanosecond resolution. Negative - # second values with fractions must still have non-negative nanos values that - # count forward in time. Must be from 0 to 999,999,999 inclusive. - nanos: int = betterproto.int32_field(2) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass +@dataclass(eq=False, repr=False) class DoubleValue(betterproto.Message): """ Wrapper message for `double`. The JSON representation for `DoubleValue` is @@ -1223,8 +685,11 @@ class DoubleValue(betterproto.Message): # The double value. value: float = betterproto.double_field(1) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) class FloatValue(betterproto.Message): """ Wrapper message for `float`. The JSON representation for `FloatValue` is @@ -1234,8 +699,11 @@ class FloatValue(betterproto.Message): # The float value. value: float = betterproto.float_field(1) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) class Int64Value(betterproto.Message): """ Wrapper message for `int64`. The JSON representation for `Int64Value` is @@ -1245,8 +713,11 @@ class Int64Value(betterproto.Message): # The int64 value. value: int = betterproto.int64_field(1) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) class UInt64Value(betterproto.Message): """ Wrapper message for `uint64`. The JSON representation for `UInt64Value` is @@ -1256,8 +727,11 @@ class UInt64Value(betterproto.Message): # The uint64 value. value: int = betterproto.uint64_field(1) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) class Int32Value(betterproto.Message): """ Wrapper message for `int32`. The JSON representation for `Int32Value` is @@ -1267,8 +741,11 @@ class Int32Value(betterproto.Message): # The int32 value. value: int = betterproto.int32_field(1) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) class UInt32Value(betterproto.Message): """ Wrapper message for `uint32`. The JSON representation for `UInt32Value` is @@ -1278,8 +755,11 @@ class UInt32Value(betterproto.Message): # The uint32 value. value: int = betterproto.uint32_field(1) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) class BoolValue(betterproto.Message): """ Wrapper message for `bool`. The JSON representation for `BoolValue` is JSON @@ -1289,8 +769,11 @@ class BoolValue(betterproto.Message): # The bool value. value: bool = betterproto.bool_field(1) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) class StringValue(betterproto.Message): """ Wrapper message for `string`. The JSON representation for `StringValue` is @@ -1300,8 +783,11 @@ class StringValue(betterproto.Message): # The string value. value: str = betterproto.string_field(1) + def __post_init__(self) -> None: + super().__post_init__() -@dataclass + +@dataclass(eq=False, repr=False) class BytesValue(betterproto.Message): """ Wrapper message for `bytes`. The JSON representation for `BytesValue` is @@ -1310,3 +796,678 @@ class BytesValue(betterproto.Message): # The bytes value. value: bytes = betterproto.bytes_field(1) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class Empty(betterproto.Message): + """ + A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to use it as the request + or the response type of an API method. For instance: service Foo { + rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); } The + JSON representation for `Empty` is empty JSON object `{}`. + """ + + pass + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class FileDescriptorSet(betterproto.Message): + """ + The protocol compiler can output a FileDescriptorSet containing the .proto + files it parses. + """ + + file: List["FileDescriptorProto"] = betterproto.message_field(1) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class FileDescriptorProto(betterproto.Message): + """Describes a complete .proto file.""" + + name: str = betterproto.string_field(1) + package: str = betterproto.string_field(2) + # Names of files imported by this file. + dependency: List[str] = betterproto.string_field(3) + # Indexes of the public imported files in the dependency list above. + public_dependency: List[int] = betterproto.int32_field(10) + # Indexes of the weak imported files in the dependency list. For Google- + # internal migration only. Do not use. + weak_dependency: List[int] = betterproto.int32_field(11) + # All top-level definitions in this file. + message_type: List["DescriptorProto"] = betterproto.message_field(4) + enum_type: List["EnumDescriptorProto"] = betterproto.message_field(5) + service: List["ServiceDescriptorProto"] = betterproto.message_field(6) + extension: List["FieldDescriptorProto"] = betterproto.message_field(7) + options: "FileOptions" = betterproto.message_field(8) + # This field contains optional information about the original source code. + # You may safely remove this entire field without harming runtime + # functionality of the descriptors -- the information is needed only by + # development tools. + source_code_info: "SourceCodeInfo" = betterproto.message_field(9) + # The syntax of the proto file. The supported values are "proto2" and + # "proto3". + syntax: str = betterproto.string_field(12) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class DescriptorProto(betterproto.Message): + """Describes a message type.""" + + name: str = betterproto.string_field(1) + field: List["FieldDescriptorProto"] = betterproto.message_field(2) + extension: List["FieldDescriptorProto"] = betterproto.message_field(6) + nested_type: List["DescriptorProto"] = betterproto.message_field(3) + enum_type: List["EnumDescriptorProto"] = betterproto.message_field(4) + extension_range: List["DescriptorProtoExtensionRange"] = betterproto.message_field( + 5 + ) + oneof_decl: List["OneofDescriptorProto"] = betterproto.message_field(8) + options: "MessageOptions" = betterproto.message_field(7) + reserved_range: List["DescriptorProtoReservedRange"] = betterproto.message_field(9) + # Reserved field names, which may not be used by fields in the same message. + # A given name may only be reserved once. + reserved_name: List[str] = betterproto.string_field(10) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class DescriptorProtoExtensionRange(betterproto.Message): + start: int = betterproto.int32_field(1) + end: int = betterproto.int32_field(2) + options: "ExtensionRangeOptions" = betterproto.message_field(3) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class DescriptorProtoReservedRange(betterproto.Message): + """ + Range of reserved tag numbers. Reserved tag numbers may not be used by + fields or extension ranges in the same message. Reserved ranges may not + overlap. + """ + + start: int = betterproto.int32_field(1) + end: int = betterproto.int32_field(2) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class ExtensionRangeOptions(betterproto.Message): + # The parser stores options it doesn't recognize here. See above. + uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class FieldDescriptorProto(betterproto.Message): + """Describes a field within a message.""" + + name: str = betterproto.string_field(1) + number: int = betterproto.int32_field(3) + label: "FieldDescriptorProtoLabel" = betterproto.enum_field(4) + # If type_name is set, this need not be set. If both this and type_name are + # set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + type: "FieldDescriptorProtoType" = betterproto.enum_field(5) + # For message and enum types, this is the name of the type. If the name + # starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + # rules are used to find the type (i.e. first the nested types within this + # message are searched, then within the parent, on up to the root namespace). + type_name: str = betterproto.string_field(6) + # For extensions, this is the name of the type being extended. It is + # resolved in the same manner as type_name. + extendee: str = betterproto.string_field(2) + # For numeric types, contains the original text representation of the value. + # For booleans, "true" or "false". For strings, contains the default text + # contents (not escaped in any way). For bytes, contains the C escaped value. + # All bytes >= 128 are escaped. TODO(kenton): Base-64 encode? + default_value: str = betterproto.string_field(7) + # If set, gives the index of a oneof in the containing type's oneof_decl + # list. This field is a member of that oneof. + oneof_index: int = betterproto.int32_field(9) + # JSON name of this field. The value is set by protocol compiler. If the user + # has set a "json_name" option on this field, that option's value will be + # used. Otherwise, it's deduced from the field's name by converting it to + # camelCase. + json_name: str = betterproto.string_field(10) + options: "FieldOptions" = betterproto.message_field(8) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class OneofDescriptorProto(betterproto.Message): + """Describes a oneof.""" + + name: str = betterproto.string_field(1) + options: "OneofOptions" = betterproto.message_field(2) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class EnumDescriptorProto(betterproto.Message): + """Describes an enum type.""" + + name: str = betterproto.string_field(1) + value: List["EnumValueDescriptorProto"] = betterproto.message_field(2) + options: "EnumOptions" = betterproto.message_field(3) + # Range of reserved numeric values. Reserved numeric values may not be used + # by enum values in the same enum declaration. Reserved ranges may not + # overlap. + reserved_range: List[ + "EnumDescriptorProtoEnumReservedRange" + ] = betterproto.message_field(4) + # Reserved enum value names, which may not be reused. A given name may only + # be reserved once. + reserved_name: List[str] = betterproto.string_field(5) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class EnumDescriptorProtoEnumReservedRange(betterproto.Message): + """ + Range of reserved numeric values. Reserved values may not be used by + entries in the same enum. Reserved ranges may not overlap. Note that this + is distinct from DescriptorProto.ReservedRange in that it is inclusive such + that it can appropriately represent the entire int32 domain. + """ + + start: int = betterproto.int32_field(1) + end: int = betterproto.int32_field(2) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class EnumValueDescriptorProto(betterproto.Message): + """Describes a value within an enum.""" + + name: str = betterproto.string_field(1) + number: int = betterproto.int32_field(2) + options: "EnumValueOptions" = betterproto.message_field(3) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class ServiceDescriptorProto(betterproto.Message): + """Describes a service.""" + + name: str = betterproto.string_field(1) + method: List["MethodDescriptorProto"] = betterproto.message_field(2) + options: "ServiceOptions" = betterproto.message_field(3) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class MethodDescriptorProto(betterproto.Message): + """Describes a method of a service.""" + + name: str = betterproto.string_field(1) + # Input and output type names. These are resolved in the same way as + # FieldDescriptorProto.type_name, but must refer to a message type. + input_type: str = betterproto.string_field(2) + output_type: str = betterproto.string_field(3) + options: "MethodOptions" = betterproto.message_field(4) + # Identifies if client streams multiple client messages + client_streaming: bool = betterproto.bool_field(5) + # Identifies if server streams multiple server messages + server_streaming: bool = betterproto.bool_field(6) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class FileOptions(betterproto.Message): + # Sets the Java package where classes generated from this .proto will be + # placed. By default, the proto package is used, but this is often + # inappropriate because proto packages do not normally start with backwards + # domain names. + java_package: str = betterproto.string_field(1) + # If set, all the classes from the .proto file are wrapped in a single outer + # class with the given name. This applies to both Proto1 (equivalent to the + # old "--one_java_file" option) and Proto2 (where a .proto always translates + # to a single class, but you may want to explicitly choose the class name). + java_outer_classname: str = betterproto.string_field(8) + # If set true, then the Java code generator will generate a separate .java + # file for each top-level message, enum, and service defined in the .proto + # file. Thus, these types will *not* be nested inside the outer class named + # by java_outer_classname. However, the outer class will still be generated + # to contain the file's getDescriptor() method as well as any top-level + # extensions defined in the file. + java_multiple_files: bool = betterproto.bool_field(10) + # This option does nothing. + java_generate_equals_and_hash: bool = betterproto.bool_field(20) + # If set true, then the Java2 code generator will generate code that throws + # an exception whenever an attempt is made to assign a non-UTF-8 byte + # sequence to a string field. Message reflection will do the same. However, + # an extension field still accepts non-UTF-8 byte sequences. This option has + # no effect on when used with the lite runtime. + java_string_check_utf8: bool = betterproto.bool_field(27) + optimize_for: "FileOptionsOptimizeMode" = betterproto.enum_field(9) + # Sets the Go package where structs generated from this .proto will be + # placed. If omitted, the Go package will be derived from the following: - + # The basename of the package import path, if provided. - Otherwise, the + # package statement in the .proto file, if present. - Otherwise, the + # basename of the .proto file, without extension. + go_package: str = betterproto.string_field(11) + # Should generic services be generated in each language? "Generic" services + # are not specific to any particular RPC system. They are generated by the + # main code generators in each language (without additional plugins). Generic + # services were the only kind of service generation supported by early + # versions of google.protobuf. Generic services are now considered deprecated + # in favor of using plugins that generate code specific to your particular + # RPC system. Therefore, these default to false. Old code which depends on + # generic services should explicitly set them to true. + cc_generic_services: bool = betterproto.bool_field(16) + java_generic_services: bool = betterproto.bool_field(17) + py_generic_services: bool = betterproto.bool_field(18) + php_generic_services: bool = betterproto.bool_field(42) + # Is this file deprecated? Depending on the target platform, this can emit + # Deprecated annotations for everything in the file, or it will be completely + # ignored; in the very least, this is a formalization for deprecating files. + deprecated: bool = betterproto.bool_field(23) + # Enables the use of arenas for the proto messages in this file. This applies + # only to generated classes for C++. + cc_enable_arenas: bool = betterproto.bool_field(31) + # Sets the objective c class prefix which is prepended to all objective c + # generated classes from this .proto. There is no default. + objc_class_prefix: str = betterproto.string_field(36) + # Namespace for generated classes; defaults to the package. + csharp_namespace: str = betterproto.string_field(37) + # By default Swift generators will take the proto package and CamelCase it + # replacing '.' with underscore and use that to prefix the types/symbols + # defined. When this options is provided, they will use this value instead to + # prefix the types/symbols defined. + swift_prefix: str = betterproto.string_field(39) + # Sets the php class prefix which is prepended to all php generated classes + # from this .proto. Default is empty. + php_class_prefix: str = betterproto.string_field(40) + # Use this option to change the namespace of php generated classes. Default + # is empty. When this option is empty, the package name will be used for + # determining the namespace. + php_namespace: str = betterproto.string_field(41) + # Use this option to change the namespace of php generated metadata classes. + # Default is empty. When this option is empty, the proto file name will be + # used for determining the namespace. + php_metadata_namespace: str = betterproto.string_field(44) + # Use this option to change the package of ruby generated classes. Default is + # empty. When this option is not set, the package name will be used for + # determining the ruby package. + ruby_package: str = betterproto.string_field(45) + # The parser stores options it doesn't recognize here. See the documentation + # for the "Options" section above. + uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) + + def __post_init__(self) -> None: + super().__post_init__() + if self.java_generate_equals_and_hash: + warnings.warn( + "FileOptions.java_generate_equals_and_hash is deprecated", + DeprecationWarning, + ) + + +@dataclass(eq=False, repr=False) +class MessageOptions(betterproto.Message): + # Set true to use the old proto1 MessageSet wire format for extensions. This + # is provided for backwards-compatibility with the MessageSet wire format. + # You should not use this for any other reason: It's less efficient, has + # fewer features, and is more complicated. The message must be defined + # exactly as follows: message Foo { option message_set_wire_format = + # true; extensions 4 to max; } Note that the message cannot have any + # defined fields; MessageSets only have extensions. All extensions of your + # type must be singular messages; e.g. they cannot be int32s, enums, or + # repeated messages. Because this is an option, the above two restrictions + # are not enforced by the protocol compiler. + message_set_wire_format: bool = betterproto.bool_field(1) + # Disables the generation of the standard "descriptor()" accessor, which can + # conflict with a field of the same name. This is meant to make migration + # from proto1 easier; new code should avoid fields named "descriptor". + no_standard_descriptor_accessor: bool = betterproto.bool_field(2) + # Is this message deprecated? Depending on the target platform, this can emit + # Deprecated annotations for the message, or it will be completely ignored; + # in the very least, this is a formalization for deprecating messages. + deprecated: bool = betterproto.bool_field(3) + # Whether the message is an automatically generated map entry type for the + # maps field. For maps fields: map map_field = 1; The + # parsed descriptor looks like: message MapFieldEntry { option + # map_entry = true; optional KeyType key = 1; optional + # ValueType value = 2; } repeated MapFieldEntry map_field = 1; + # Implementations may choose not to generate the map_entry=true message, but + # use a native map in the target language to hold the keys and values. The + # reflection APIs in such implementations still need to work as if the field + # is a repeated message field. NOTE: Do not set the option in .proto files. + # Always use the maps syntax instead. The option should only be implicitly + # set by the proto compiler parser. + map_entry: bool = betterproto.bool_field(7) + # The parser stores options it doesn't recognize here. See above. + uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class FieldOptions(betterproto.Message): + # The ctype option instructs the C++ code generator to use a different + # representation of the field than it normally would. See the specific + # options below. This option is not yet implemented in the open source + # release -- sorry, we'll try to include it in a future version! + ctype: "FieldOptionsCType" = betterproto.enum_field(1) + # The packed option can be enabled for repeated primitive fields to enable a + # more efficient representation on the wire. Rather than repeatedly writing + # the tag and type for each element, the entire array is encoded as a single + # length-delimited blob. In proto3, only explicit setting it to false will + # avoid using packed encoding. + packed: bool = betterproto.bool_field(2) + # The jstype option determines the JavaScript type used for values of the + # field. The option is permitted only for 64 bit integral and fixed types + # (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + # is represented as JavaScript string, which avoids loss of precision that + # can happen when a large value is converted to a floating point JavaScript. + # Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + # use the JavaScript "number" type. The behavior of the default option + # JS_NORMAL is implementation dependent. This option is an enum to permit + # additional types to be added, e.g. goog.math.Integer. + jstype: "FieldOptionsJsType" = betterproto.enum_field(6) + # Should this field be parsed lazily? Lazy applies only to message-type + # fields. It means that when the outer message is initially parsed, the + # inner message's contents will not be parsed but instead stored in encoded + # form. The inner message will actually be parsed when it is first accessed. + # This is only a hint. Implementations are free to choose whether to use + # eager or lazy parsing regardless of the value of this option. However, + # setting this option true suggests that the protocol author believes that + # using lazy parsing on this field is worth the additional bookkeeping + # overhead typically needed to implement it. This option does not affect the + # public interface of any generated code; all method signatures remain the + # same. Furthermore, thread-safety of the interface is not affected by this + # option; const methods remain safe to call from multiple threads + # concurrently, while non-const methods continue to require exclusive access. + # Note that implementations may choose not to check required fields within a + # lazy sub-message. That is, calling IsInitialized() on the outer message + # may return true even if the inner message has missing required fields. This + # is necessary because otherwise the inner message would have to be parsed in + # order to perform the check, defeating the purpose of lazy parsing. An + # implementation which chooses not to check required fields must be + # consistent about it. That is, for any particular sub-message, the + # implementation must either *always* check its required fields, or *never* + # check its required fields, regardless of whether or not the message has + # been parsed. + lazy: bool = betterproto.bool_field(5) + # Is this field deprecated? Depending on the target platform, this can emit + # Deprecated annotations for accessors, or it will be completely ignored; in + # the very least, this is a formalization for deprecating fields. + deprecated: bool = betterproto.bool_field(3) + # For Google-internal migration only. Do not use. + weak: bool = betterproto.bool_field(10) + # The parser stores options it doesn't recognize here. See above. + uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class OneofOptions(betterproto.Message): + # The parser stores options it doesn't recognize here. See above. + uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class EnumOptions(betterproto.Message): + # Set this option to true to allow mapping different tag names to the same + # value. + allow_alias: bool = betterproto.bool_field(2) + # Is this enum deprecated? Depending on the target platform, this can emit + # Deprecated annotations for the enum, or it will be completely ignored; in + # the very least, this is a formalization for deprecating enums. + deprecated: bool = betterproto.bool_field(3) + # The parser stores options it doesn't recognize here. See above. + uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class EnumValueOptions(betterproto.Message): + # Is this enum value deprecated? Depending on the target platform, this can + # emit Deprecated annotations for the enum value, or it will be completely + # ignored; in the very least, this is a formalization for deprecating enum + # values. + deprecated: bool = betterproto.bool_field(1) + # The parser stores options it doesn't recognize here. See above. + uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class ServiceOptions(betterproto.Message): + # Is this service deprecated? Depending on the target platform, this can emit + # Deprecated annotations for the service, or it will be completely ignored; + # in the very least, this is a formalization for deprecating services. + deprecated: bool = betterproto.bool_field(33) + # The parser stores options it doesn't recognize here. See above. + uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class MethodOptions(betterproto.Message): + # Is this method deprecated? Depending on the target platform, this can emit + # Deprecated annotations for the method, or it will be completely ignored; in + # the very least, this is a formalization for deprecating methods. + deprecated: bool = betterproto.bool_field(33) + idempotency_level: "MethodOptionsIdempotencyLevel" = betterproto.enum_field(34) + # The parser stores options it doesn't recognize here. See above. + uninterpreted_option: List["UninterpretedOption"] = betterproto.message_field(999) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class UninterpretedOption(betterproto.Message): + """ + A message representing a option the parser does not recognize. This only + appears in options protos created by the compiler::Parser class. + DescriptorPool resolves these when building Descriptor objects. Therefore, + options protos in descriptor objects (e.g. returned by + Descriptor::options(), or produced by Descriptor::CopyTo()) will never have + UninterpretedOptions in them. + """ + + name: List["UninterpretedOptionNamePart"] = betterproto.message_field(2) + # The value of the uninterpreted option, in whatever type the tokenizer + # identified it as during parsing. Exactly one of these should be set. + identifier_value: str = betterproto.string_field(3) + positive_int_value: int = betterproto.uint64_field(4) + negative_int_value: int = betterproto.int64_field(5) + double_value: float = betterproto.double_field(6) + string_value: bytes = betterproto.bytes_field(7) + aggregate_value: str = betterproto.string_field(8) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class UninterpretedOptionNamePart(betterproto.Message): + """ + The name of the uninterpreted option. Each string represents a segment in + a dot-separated name. is_extension is true iff a segment represents an + extension (denoted with parentheses in options specs in .proto files). + E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + "foo.(bar.baz).qux". + """ + + name_part: str = betterproto.string_field(1) + is_extension: bool = betterproto.bool_field(2) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class SourceCodeInfo(betterproto.Message): + """ + Encapsulates information about the original source file from which a + FileDescriptorProto was generated. + """ + + # A Location identifies a piece of source code in a .proto file which + # corresponds to a particular definition. This information is intended to be + # useful to IDEs, code indexers, documentation generators, and similar tools. + # For example, say we have a file like: message Foo { optional string + # foo = 1; } Let's look at just the field definition: optional string foo + # = 1; ^ ^^ ^^ ^ ^^^ a bc de f ghi We have the + # following locations: span path represents [a,i) [ 4, + # 0, 2, 0 ] The whole field definition. [a,b) [ 4, 0, 2, 0, 4 ] The + # label (optional). [c,d) [ 4, 0, 2, 0, 5 ] The type (string). [e,f) [ + # 4, 0, 2, 0, 1 ] The name (foo). [g,h) [ 4, 0, 2, 0, 3 ] The number + # (1). Notes: - A location may refer to a repeated field itself (i.e. not to + # any particular index within it). This is used whenever a set of elements + # are logically enclosed in a single code segment. For example, an entire + # extend block (possibly containing multiple extension definitions) will + # have an outer location whose path refers to the "extensions" repeated + # field without an index. - Multiple locations may have the same path. This + # happens when a single logical declaration is spread out across multiple + # places. The most obvious example is the "extend" block again -- there + # may be multiple extend blocks in the same scope, each of which will have + # the same path. - A location's span is not always a subset of its parent's + # span. For example, the "extendee" of an extension declaration appears at + # the beginning of the "extend" block and is shared by all extensions + # within the block. - Just because a location's span is a subset of some + # other location's span does not mean that it is a descendant. For + # example, a "group" defines both a type and a field in a single + # declaration. Thus, the locations corresponding to the type and field and + # their components will overlap. - Code which tries to interpret locations + # should probably be designed to ignore those that it doesn't understand, + # as more types of locations could be recorded in the future. + location: List["SourceCodeInfoLocation"] = betterproto.message_field(1) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class SourceCodeInfoLocation(betterproto.Message): + # Identifies which part of the FileDescriptorProto was defined at this + # location. Each element is a field number or an index. They form a path + # from the root FileDescriptorProto to the place where the definition. For + # example, this path: [ 4, 3, 2, 7, 1 ] refers to: file.message_type(3) + # // 4, 3 .field(7) // 2, 7 .name() // 1 This + # is because FileDescriptorProto.message_type has field number 4: repeated + # DescriptorProto message_type = 4; and DescriptorProto.field has field + # number 2: repeated FieldDescriptorProto field = 2; and + # FieldDescriptorProto.name has field number 1: optional string name = 1; + # Thus, the above path gives the location of a field name. If we removed the + # last element: [ 4, 3, 2, 7 ] this path refers to the whole field + # declaration (from the beginning of the label to the terminating semicolon). + path: List[int] = betterproto.int32_field(1) + # Always has exactly three or four elements: start line, start column, end + # line (optional, otherwise assumed same as start line), end column. These + # are packed into a single field for efficiency. Note that line and column + # numbers are zero-based -- typically you will want to add 1 to each before + # displaying to a user. + span: List[int] = betterproto.int32_field(2) + # If this SourceCodeInfo represents a complete declaration, these are any + # comments appearing before and after the declaration which appear to be + # attached to the declaration. A series of line comments appearing on + # consecutive lines, with no other tokens appearing on those lines, will be + # treated as a single comment. leading_detached_comments will keep paragraphs + # of comments that appear before (but not connected to) the current element. + # Each paragraph, separated by empty lines, will be one comment element in + # the repeated field. Only the comment content is provided; comment markers + # (e.g. //) are stripped out. For block comments, leading whitespace and an + # asterisk will be stripped from the beginning of each line other than the + # first. Newlines are included in the output. Examples: optional int32 foo + # = 1; // Comment attached to foo. // Comment attached to bar. optional + # int32 bar = 2; optional string baz = 3; // Comment attached to baz. + # // Another line attached to baz. // Comment attached to qux. // // + # Another line attached to qux. optional double qux = 4; // Detached + # comment for corge. This is not leading or trailing comments // to qux or + # corge because there are blank lines separating it from // both. // + # Detached comment for corge paragraph 2. optional string corge = 5; /* + # Block comment attached * to corge. Leading asterisks * will be + # removed. */ /* Block comment attached to * grault. */ optional int32 + # grault = 6; // ignored detached comments. + leading_comments: str = betterproto.string_field(3) + trailing_comments: str = betterproto.string_field(4) + leading_detached_comments: List[str] = betterproto.string_field(6) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class GeneratedCodeInfo(betterproto.Message): + """ + Describes the relationship between generated code and its original source + file. A GeneratedCodeInfo message is associated with only one generated + source file, but may contain references to different source .proto files. + """ + + # An Annotation connects some span of text in generated code to an element of + # its generating .proto file. + annotation: List["GeneratedCodeInfoAnnotation"] = betterproto.message_field(1) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class GeneratedCodeInfoAnnotation(betterproto.Message): + # Identifies the element in the original source .proto file. This field is + # formatted the same as SourceCodeInfo.Location.path. + path: List[int] = betterproto.int32_field(1) + # Identifies the filesystem path to the original source .proto. + source_file: str = betterproto.string_field(2) + # Identifies the starting offset in bytes in the generated code that relates + # to the identified object. + begin: int = betterproto.int32_field(3) + # Identifies the ending offset in bytes in the generated code that relates to + # the identified offset. The end offset should be one past the last relevant + # byte (so the length of the text = end - begin). + end: int = betterproto.int32_field(4) + + def __post_init__(self) -> None: + super().__post_init__() diff --git a/src/betterproto/lib/google/protobuf/compiler/__init__.py b/src/betterproto/lib/google/protobuf/compiler/__init__.py new file mode 100644 index 0000000..cfe185b --- /dev/null +++ b/src/betterproto/lib/google/protobuf/compiler/__init__.py @@ -0,0 +1,125 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: google/protobuf/compiler/plugin.proto +# plugin: python-betterproto +from dataclasses import dataclass +from typing import List + +import betterproto + + +@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) + # A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should + # be empty for mainline stable releases. + suffix: str = betterproto.string_field(4) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class CodeGeneratorRequest(betterproto.Message): + """An encoded CodeGeneratorRequest is written to the plugin's stdin.""" + + # 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. + file_to_generate: List[str] = betterproto.string_field(1) + # The generator parameter passed on the command-line. + parameter: str = betterproto.string_field(2) + # 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. + proto_file: List[ + "betterproto_lib_google_protobuf.FileDescriptorProto" + ] = betterproto.message_field(15) + # The version number of protocol compiler. + compiler_version: "Version" = betterproto.message_field(3) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class CodeGeneratorResponse(betterproto.Message): + """The plugin writes an encoded CodeGeneratorResponse to stdout.""" + + # 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. + error: str = betterproto.string_field(1) + file: List["CodeGeneratorResponseFile"] = betterproto.message_field(15) + + def __post_init__(self) -> None: + super().__post_init__() + + +@dataclass(eq=False, repr=False) +class CodeGeneratorResponseFile(betterproto.Message): + """Represents a single generated file.""" + + # 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. + name: str = betterproto.string_field(1) + # 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. + insertion_point: str = betterproto.string_field(2) + # The file contents. + content: str = betterproto.string_field(15) + + def __post_init__(self) -> None: + super().__post_init__() + + +import betterproto.lib.google.protobuf as betterproto_lib_google_protobuf diff --git a/src/betterproto/plugin/main.py b/src/betterproto/plugin/main.py old mode 100644 new mode 100755 index dc9d04c..e0b2557 --- a/src/betterproto/plugin/main.py +++ b/src/betterproto/plugin/main.py @@ -3,9 +3,13 @@ import os import sys -from google.protobuf.compiler import plugin_pb2 as plugin +from betterproto.lib.google.protobuf.compiler import ( + CodeGeneratorRequest, + CodeGeneratorResponse, +) from betterproto.plugin.parser import generate_code +from betterproto.plugin.models import monkey_patch_oneof_index def main() -> None: @@ -13,16 +17,19 @@ def main() -> None: # Read request message from stdin data = sys.stdin.buffer.read() + # Apply Work around for proto2/3 difference in protoc messages + monkey_patch_oneof_index() + # Parse request - request = plugin.CodeGeneratorRequest() - request.ParseFromString(data) + request = CodeGeneratorRequest() + request.parse(data) dump_file = os.getenv("BETTERPROTO_DUMP") if dump_file: dump_request(dump_file, request) # Create response - response = plugin.CodeGeneratorResponse() + response = CodeGeneratorResponse() # Generate code generate_code(request, response) @@ -34,7 +41,7 @@ def main() -> None: sys.stdout.buffer.write(output) -def dump_request(dump_file: str, request: plugin.CodeGeneratorRequest) -> None: +def dump_request(dump_file: str, request: CodeGeneratorRequest) -> None: """ For developers: Supports running plugin.py standalone so its possible to debug it. Run protoc (or generate.py) with BETTERPROTO_DUMP="yourfile.bin" to write the request to a file. diff --git a/src/betterproto/plugin/models.py b/src/betterproto/plugin/models.py index 097c991..4a243a3 100644 --- a/src/betterproto/plugin/models.py +++ b/src/betterproto/plugin/models.py @@ -29,12 +29,37 @@ instantiating field `A` with parent message `B` should add a reference to `A` to `B`'s `fields` attribute. """ + +import betterproto +from betterproto import which_one_of +from betterproto.casing import sanitize_name +from betterproto.compile.importing import ( + get_type_reference, + parse_source_type_name, +) +from betterproto.compile.naming import ( + pythonize_class_name, + pythonize_field_name, + pythonize_method_name, +) +from betterproto.lib.google.protobuf import ( + DescriptorProto, + EnumDescriptorProto, + FileDescriptorProto, + MethodDescriptorProto, + Field, + FieldDescriptorProto, + FieldDescriptorProtoType, + FieldDescriptorProtoLabel, +) +from betterproto.lib.google.protobuf.compiler import CodeGeneratorRequest + + import re import textwrap from dataclasses import dataclass, field from typing import Dict, Iterator, List, Optional, Set, Text, Type, Union - -import betterproto +import sys from ..casing import sanitize_name from ..compile.importing import get_type_reference, parse_source_type_name @@ -44,26 +69,6 @@ from ..compile.naming import ( pythonize_method_name, ) -try: - # betterproto[compiler] specific dependencies - from google.protobuf.compiler import plugin_pb2 as plugin - from google.protobuf.descriptor_pb2 import ( - DescriptorProto, - EnumDescriptorProto, - FieldDescriptorProto, - FileDescriptorProto, - MethodDescriptorProto, - ) -except ImportError as err: - print( - "\033[31m" - f"Unable to import `{err.name}` from betterproto plugin! " - "Please ensure that you've installed betterproto as " - '`pip install "betterproto[compiler]"` so that compiler dependencies ' - "are included." - "\033[0m" - ) - raise SystemExit(1) # Create a unique placeholder to deal with # https://stackoverflow.com/questions/51575931/class-inheritance-in-python-3-7-dataclasses @@ -71,54 +76,75 @@ PLACEHOLDER = object() # Organize proto types into categories PROTO_FLOAT_TYPES = ( - FieldDescriptorProto.TYPE_DOUBLE, # 1 - FieldDescriptorProto.TYPE_FLOAT, # 2 + FieldDescriptorProtoType.TYPE_DOUBLE, # 1 + FieldDescriptorProtoType.TYPE_FLOAT, # 2 ) PROTO_INT_TYPES = ( - FieldDescriptorProto.TYPE_INT64, # 3 - FieldDescriptorProto.TYPE_UINT64, # 4 - FieldDescriptorProto.TYPE_INT32, # 5 - FieldDescriptorProto.TYPE_FIXED64, # 6 - FieldDescriptorProto.TYPE_FIXED32, # 7 - FieldDescriptorProto.TYPE_UINT32, # 13 - FieldDescriptorProto.TYPE_SFIXED32, # 15 - FieldDescriptorProto.TYPE_SFIXED64, # 16 - FieldDescriptorProto.TYPE_SINT32, # 17 - FieldDescriptorProto.TYPE_SINT64, # 18 + FieldDescriptorProtoType.TYPE_INT64, # 3 + FieldDescriptorProtoType.TYPE_UINT64, # 4 + FieldDescriptorProtoType.TYPE_INT32, # 5 + FieldDescriptorProtoType.TYPE_FIXED64, # 6 + FieldDescriptorProtoType.TYPE_FIXED32, # 7 + FieldDescriptorProtoType.TYPE_UINT32, # 13 + FieldDescriptorProtoType.TYPE_SFIXED32, # 15 + FieldDescriptorProtoType.TYPE_SFIXED64, # 16 + FieldDescriptorProtoType.TYPE_SINT32, # 17 + FieldDescriptorProtoType.TYPE_SINT64, # 18 ) -PROTO_BOOL_TYPES = (FieldDescriptorProto.TYPE_BOOL,) # 8 -PROTO_STR_TYPES = (FieldDescriptorProto.TYPE_STRING,) # 9 -PROTO_BYTES_TYPES = (FieldDescriptorProto.TYPE_BYTES,) # 12 +PROTO_BOOL_TYPES = (FieldDescriptorProtoType.TYPE_BOOL,) # 8 +PROTO_STR_TYPES = (FieldDescriptorProtoType.TYPE_STRING,) # 9 +PROTO_BYTES_TYPES = (FieldDescriptorProtoType.TYPE_BYTES,) # 12 PROTO_MESSAGE_TYPES = ( - FieldDescriptorProto.TYPE_MESSAGE, # 11 - FieldDescriptorProto.TYPE_ENUM, # 14 + FieldDescriptorProtoType.TYPE_MESSAGE, # 11 + FieldDescriptorProtoType.TYPE_ENUM, # 14 ) -PROTO_MAP_TYPES = (FieldDescriptorProto.TYPE_MESSAGE,) # 11 +PROTO_MAP_TYPES = (FieldDescriptorProtoType.TYPE_MESSAGE,) # 11 PROTO_PACKED_TYPES = ( - FieldDescriptorProto.TYPE_DOUBLE, # 1 - FieldDescriptorProto.TYPE_FLOAT, # 2 - FieldDescriptorProto.TYPE_INT64, # 3 - FieldDescriptorProto.TYPE_UINT64, # 4 - FieldDescriptorProto.TYPE_INT32, # 5 - FieldDescriptorProto.TYPE_FIXED64, # 6 - FieldDescriptorProto.TYPE_FIXED32, # 7 - FieldDescriptorProto.TYPE_BOOL, # 8 - FieldDescriptorProto.TYPE_UINT32, # 13 - FieldDescriptorProto.TYPE_SFIXED32, # 15 - FieldDescriptorProto.TYPE_SFIXED64, # 16 - FieldDescriptorProto.TYPE_SINT32, # 17 - FieldDescriptorProto.TYPE_SINT64, # 18 + FieldDescriptorProtoType.TYPE_DOUBLE, # 1 + FieldDescriptorProtoType.TYPE_FLOAT, # 2 + FieldDescriptorProtoType.TYPE_INT64, # 3 + FieldDescriptorProtoType.TYPE_UINT64, # 4 + FieldDescriptorProtoType.TYPE_INT32, # 5 + FieldDescriptorProtoType.TYPE_FIXED64, # 6 + FieldDescriptorProtoType.TYPE_FIXED32, # 7 + FieldDescriptorProtoType.TYPE_BOOL, # 8 + FieldDescriptorProtoType.TYPE_UINT32, # 13 + FieldDescriptorProtoType.TYPE_SFIXED32, # 15 + FieldDescriptorProtoType.TYPE_SFIXED64, # 16 + FieldDescriptorProtoType.TYPE_SINT32, # 17 + FieldDescriptorProtoType.TYPE_SINT64, # 18 ) +def monkey_patch_oneof_index(): + """ + The compiler message types are written for proto2, but we read them as proto3. + For this to work in the case of the oneof_index fields, which depend on being able + to tell whether they were set, we have to treat them as oneof fields. This method + monkey patches the generated classes after the fact to force this behaviour. + """ + object.__setattr__( + FieldDescriptorProto.__dataclass_fields__["oneof_index"].metadata[ + "betterproto" + ], + "group", + "oneof_index", + ) + object.__setattr__( + Field.__dataclass_fields__["oneof_index"].metadata["betterproto"], + "group", + "oneof_index", + ) + + def get_comment( proto_file: "FileDescriptorProto", path: List[int], indent: int = 4 ) -> str: pad = " " * indent - for sci in proto_file.source_code_info.location: - if list(sci.path) == path and sci.leading_comments: + for sci_loc in proto_file.source_code_info.location: + if list(sci_loc.path) == path and sci_loc.leading_comments: lines = textwrap.wrap( - sci.leading_comments.strip().replace("\n", ""), width=79 - indent + sci_loc.leading_comments.strip().replace("\n", ""), width=79 - indent ) if path[-2] == 2 and path[-4] != 6: @@ -139,6 +165,7 @@ def get_comment( class ProtoContentBase: """Methods common to MessageCompiler, ServiceCompiler and ServiceMethodCompiler.""" + source_file: FileDescriptorProto path: List[int] comment_indent: int = 4 parent: Union["betterproto.Message", "OutputTemplate"] @@ -156,13 +183,6 @@ class ProtoContentBase: current = current.parent return current - @property - def proto_file(self) -> FieldDescriptorProto: - current = self - while not isinstance(current, OutputTemplate): - current = current.parent - return current.package_proto_obj - @property def request(self) -> "PluginRequestCompiler": current = self @@ -176,14 +196,14 @@ class ProtoContentBase: for this object. """ return get_comment( - proto_file=self.proto_file, path=self.path, indent=self.comment_indent + proto_file=self.source_file, path=self.path, indent=self.comment_indent ) @dataclass class PluginRequestCompiler: - plugin_request_obj: plugin.CodeGeneratorRequest + plugin_request_obj: CodeGeneratorRequest output_packages: Dict[str, "OutputTemplate"] = field(default_factory=dict) @property @@ -253,6 +273,7 @@ class OutputTemplate: class MessageCompiler(ProtoContentBase): """Representation of a protobuf message.""" + source_file: FileDescriptorProto parent: Union["MessageCompiler", OutputTemplate] = PLACEHOLDER proto_obj: DescriptorProto = PLACEHOLDER path: List[int] = PLACEHOLDER @@ -296,7 +317,7 @@ def is_map( proto_field_obj: FieldDescriptorProto, parent_message: DescriptorProto ) -> bool: """True if proto_field_obj is a map, otherwise False.""" - if proto_field_obj.type == FieldDescriptorProto.TYPE_MESSAGE: + if proto_field_obj.type == FieldDescriptorProtoType.TYPE_MESSAGE: # This might be a map... message_type = proto_field_obj.type_name.split(".").pop().lower() map_entry = f"{proto_field_obj.name.replace('_', '').lower()}entry" @@ -311,8 +332,20 @@ def is_map( def is_oneof(proto_field_obj: FieldDescriptorProto) -> bool: - """True if proto_field_obj is a OneOf, otherwise False.""" - return proto_field_obj.HasField("oneof_index") + """ + True if proto_field_obj is a OneOf, otherwise False. + + .. warning:: + Becuase the message from protoc is defined in proto2, and betterproto works with + proto3, and interpreting the FieldDescriptorProto.oneof_index field requires + distinguishing between default and unset values (which proto3 doesn't support), + we have to hack the generated FieldDescriptorProto class for this to work. + The hack consists of setting group="oneof_index" in the field metadata, + essentially making oneof_index the sole member of a one_of group, which allows + us to tell whether it was set, via the which_one_of interface. + """ + + return which_one_of(proto_field_obj, "oneof_index")[0] == "oneof_index" @dataclass @@ -377,7 +410,7 @@ class FieldCompiler(MessageCompiler): def field_wraps(self) -> Optional[str]: """Returns betterproto wrapped field type or None.""" match_wrapper = re.match( - r"\.google\.protobuf\.(.+)Value", self.proto_obj.type_name + r"\.google\.protobuf\.(.+)Value$", self.proto_obj.type_name ) if match_wrapper: wrapped_type = "TYPE_" + match_wrapper.group(1).upper() @@ -388,7 +421,7 @@ class FieldCompiler(MessageCompiler): @property def repeated(self) -> bool: return ( - self.proto_obj.label == FieldDescriptorProto.LABEL_REPEATED + self.proto_obj.label == FieldDescriptorProtoLabel.LABEL_REPEATED and not is_map(self.proto_obj, self.parent) ) @@ -401,7 +434,9 @@ class FieldCompiler(MessageCompiler): def field_type(self) -> str: """String representation of proto field type.""" return ( - self.proto_obj.Type.Name(self.proto_obj.type).lower().replace("type_", "") + FieldDescriptorProtoType(self.proto_obj.type) + .name.lower() + .replace("type_", "") ) @property @@ -495,14 +530,19 @@ class MapEntryCompiler(FieldCompiler): ): # Get Python types self.py_k_type = FieldCompiler( - parent=self, proto_obj=nested.field[0] # key + source_file=self.source_file, + parent=self, + proto_obj=nested.field[0], # key ).py_type self.py_v_type = FieldCompiler( - parent=self, proto_obj=nested.field[1] # value + source_file=self.source_file, + parent=self, + proto_obj=nested.field[1], # value ).py_type + # Get proto types - self.proto_k_type = self.proto_obj.Type.Name(nested.field[0].type) - self.proto_v_type = self.proto_obj.Type.Name(nested.field[1].type) + self.proto_k_type = FieldDescriptorProtoType(nested.field[0].type).name + self.proto_v_type = FieldDescriptorProtoType(nested.field[1].type).name super().__post_init__() # call FieldCompiler-> MessageCompiler __post_init__ @property @@ -544,7 +584,7 @@ class EnumDefinitionCompiler(MessageCompiler): name=sanitize_name(entry_proto_value.name), value=entry_proto_value.number, comment=get_comment( - proto_file=self.proto_file, path=self.path + [2, entry_number] + proto_file=self.source_file, path=self.path + [2, entry_number] ), ) for entry_number, entry_proto_value in enumerate(self.proto_obj.value) diff --git a/src/betterproto/plugin/parser.py b/src/betterproto/plugin/parser.py index a1be268..4be9977 100644 --- a/src/betterproto/plugin/parser.py +++ b/src/betterproto/plugin/parser.py @@ -1,28 +1,19 @@ +from betterproto.lib.google.protobuf import ( + DescriptorProto, + EnumDescriptorProto, + FieldDescriptorProto, + FileDescriptorProto, + ServiceDescriptorProto, +) +from betterproto.lib.google.protobuf.compiler import ( + CodeGeneratorRequest, + CodeGeneratorResponse, + CodeGeneratorResponseFile, +) import itertools import pathlib import sys -from typing import TYPE_CHECKING, Iterator, List, Tuple, Union, Set - -try: - # betterproto[compiler] specific dependencies - from google.protobuf.compiler import plugin_pb2 as plugin - from google.protobuf.descriptor_pb2 import ( - DescriptorProto, - EnumDescriptorProto, - FieldDescriptorProto, - ServiceDescriptorProto, - ) -except ImportError as err: - print( - "\033[31m" - f"Unable to import `{err.name}` from betterproto plugin! " - "Please ensure that you've installed betterproto as " - '`pip install "betterproto[compiler]"` so that compiler dependencies ' - "are included." - "\033[0m" - ) - raise SystemExit(1) - +from typing import Iterator, List, Tuple, TYPE_CHECKING, Union from .compiler import outputfile_compiler from .models import ( EnumDefinitionCompiler, @@ -70,7 +61,7 @@ def traverse( def generate_code( - request: plugin.CodeGeneratorRequest, response: plugin.CodeGeneratorResponse + request: CodeGeneratorRequest, response: CodeGeneratorResponse ) -> None: plugin_options = request.parameter.split(",") if request.parameter else [] @@ -100,7 +91,12 @@ def generate_code( for output_package_name, output_package in request_data.output_packages.items(): for proto_input_file in output_package.input_files: for item, path in traverse(proto_input_file): - read_protobuf_type(item=item, path=path, output_package=output_package) + read_protobuf_type( + source_file=proto_input_file, + item=item, + path=path, + output_package=output_package, + ) # Read Services for output_package_name, output_package in request_data.output_packages.items(): @@ -116,11 +112,13 @@ def generate_code( output_path = pathlib.Path(*output_package_name.split("."), "__init__.py") output_paths.add(output_path) - f: response.File = response.file.add() - f.name = str(output_path) - - # Render and then format the output file - f.content = outputfile_compiler(output_file=output_package) + response.file.append( + CodeGeneratorResponseFile( + name=str(output_path), + # Render and then format the output file + content=outputfile_compiler(output_file=output_package), + ) + ) # Make each output directory a package with __init__ file init_files = { @@ -130,38 +128,53 @@ def generate_code( } - output_paths for init_file in init_files: - init = response.file.add() - init.name = str(init_file) + response.file.append(CodeGeneratorResponseFile(name=str(init_file))) for output_package_name in sorted(output_paths.union(init_files)): print(f"Writing {output_package_name}", file=sys.stderr) def read_protobuf_type( - item: DescriptorProto, path: List[int], output_package: OutputTemplate + item: DescriptorProto, + path: List[int], + source_file: "FileDescriptorProto", + output_package: OutputTemplate, ) -> None: if isinstance(item, DescriptorProto): if item.options.map_entry: # Skip generated map entry messages since we just use dicts return # Process Message - message_data = MessageCompiler(parent=output_package, proto_obj=item, path=path) + message_data = MessageCompiler( + source_file=source_file, parent=output_package, proto_obj=item, path=path + ) for index, field in enumerate(item.field): if is_map(field, item): MapEntryCompiler( - parent=message_data, proto_obj=field, path=path + [2, index] + source_file=source_file, + parent=message_data, + proto_obj=field, + path=path + [2, index], ) elif is_oneof(field): OneOfFieldCompiler( - parent=message_data, proto_obj=field, path=path + [2, index] + source_file=source_file, + parent=message_data, + proto_obj=field, + path=path + [2, index], ) else: FieldCompiler( - parent=message_data, proto_obj=field, path=path + [2, index] + source_file=source_file, + parent=message_data, + proto_obj=field, + path=path + [2, index], ) elif isinstance(item, EnumDescriptorProto): # Enum - EnumDefinitionCompiler(parent=output_package, proto_obj=item, path=path) + EnumDefinitionCompiler( + source_file=source_file, parent=output_package, proto_obj=item, path=path + ) def read_protobuf_service( diff --git a/tests/inputs/example/example.proto b/tests/inputs/example/example.proto index edc4d87..3111058 100644 --- a/tests/inputs/example/example.proto +++ b/tests/inputs/example/example.proto @@ -1,8 +1,909 @@ -syntax = "proto3"; +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -package hello; +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). -// Greeting represents a message you can tell a user. -message Greeting { - string message = 1; + +syntax = "proto2"; + +// package google.protobuf; + +option go_package = "google.golang.org/protobuf/types/descriptorpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.Reflection"; +option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; + + // The syntax of the proto file. + // The supported values are "proto2" and "proto3". + optional string syntax = 12; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + + optional ExtensionRangeOptions options = 3; + } + repeated ExtensionRange extension_range = 5; + + repeated OneofDescriptorProto oneof_decl = 8; + + optional MessageOptions options = 7; + + // Range of reserved tag numbers. Reserved tag numbers may not be used by + // fields or extension ranges in the same message. Reserved ranges may + // not overlap. + message ReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + } + repeated ReservedRange reserved_range = 9; + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + repeated string reserved_name = 10; +} + +message ExtensionRangeOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + // Tag-delimited aggregate. + // Group type is deprecated and not supported in proto3. However, Proto3 + // implementations should still be able to parse the group wire format and + // treat group fields as unknown fields. + TYPE_GROUP = 10; + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + } + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + } + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. + optional int32 oneof_index = 9; + + // JSON name of this field. The value is set by protocol compiler. If the + // user has set a "json_name" option on this field, that option's value + // will be used. Otherwise, it's deduced from the field's name by converting + // it to camelCase. + optional string json_name = 10; + + optional FieldOptions options = 8; + + // If true, this is a proto3 "optional". When a proto3 field is optional, it + // tracks presence regardless of field type. + // + // When proto3_optional is true, this field must be belong to a oneof to + // signal to old proto3 clients that presence is tracked for this field. This + // oneof is known as a "synthetic" oneof, and this field must be its sole + // member (each proto3 optional field gets its own synthetic oneof). Synthetic + // oneofs exist in the descriptor only, and do not generate any API. Synthetic + // oneofs must be ordered after all "real" oneofs. + // + // For message fields, proto3_optional doesn't create any semantic change, + // since non-repeated message fields always track presence. However it still + // indicates the semantic detail of whether the user wrote "optional" or not. + // This can be useful for round-tripping the .proto file. For consistency we + // give message fields a synthetic oneof also, even though it is not required + // to track presence. This is especially important because the parser can't + // tell if a field is a message or an enum, so it must always create a + // synthetic oneof. + // + // Proto2 optional fields do not set this flag, because they already indicate + // optional with `LABEL_OPTIONAL`. + optional bool proto3_optional = 17; +} + +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; + optional OneofOptions options = 2; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; + + // Range of reserved numeric values. Reserved values may not be used by + // entries in the same enum. Reserved ranges may not overlap. + // + // Note that this is distinct from DescriptorProto.ReservedRange in that it + // is inclusive such that it can appropriately represent the entire int32 + // domain. + message EnumReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Inclusive. + } + + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + repeated EnumReservedRange reserved_range = 4; + + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + repeated string reserved_name = 5; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; + + // Identifies if client streams multiple client messages + optional bool client_streaming = 5 [default = false]; + // Identifies if server streams multiple server messages + optional bool server_streaming = 6 [default = false]; +} + + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Objective-C plugin) and your project website (if available) -- there's no +// need to explain how you intend to use them. Usually you only need one +// extension number. You can declare multiple options with only one extension +// number by putting them in a sub-message. See the Custom Options section of +// the docs for examples: +// https://developers.google.com/protocol-buffers/docs/proto#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default = false]; + + // This option does nothing. + optional bool java_generate_equals_and_hash = 20 [deprecated=true]; + + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 + // byte sequence to a string field. + // Message reflection will do the same. + // However, an extension field still accepts non-UTF-8 byte sequences. + // This option has no effect on when used with the lite runtime. + optional bool java_string_check_utf8 = 27 [default = false]; + + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default = SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + optional string go_package = 11; + + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default = false]; + optional bool java_generic_services = 17 [default = false]; + optional bool py_generic_services = 18 [default = false]; + optional bool php_generic_services = 42 [default = false]; + + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default = false]; + + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + optional bool cc_enable_arenas = 31 [default = true]; + + + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + optional string objc_class_prefix = 36; + + // Namespace for generated classes; defaults to the package. + optional string csharp_namespace = 37; + + // By default Swift generators will take the proto package and CamelCase it + // replacing '.' with underscore and use that to prefix the types/symbols + // defined. When this options is provided, they will use this value instead + // to prefix the types/symbols defined. + optional string swift_prefix = 39; + + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + optional string php_class_prefix = 40; + + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + optional string php_namespace = 41; + + // Use this option to change the namespace of php generated metadata classes. + // Default is empty. When this option is empty, the proto file name will be + // used for determining the namespace. + optional string php_metadata_namespace = 44; + + // Use this option to change the package of ruby generated classes. Default + // is empty. When this option is not set, the package name will be used for + // determining the ruby package. + optional string ruby_package = 45; + + + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. + // See the documentation for the "Options" section above. + extensions 1000 to max; + + reserved 38; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default = false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default = false]; + + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default = false]; + + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementations still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + + reserved 8; // javalite_serializable + reserved 9; // javanano_as_lite + + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. + optional bool packed = 2; + + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + // is represented as JavaScript string, which avoids loss of precision that + // can happen when a large value is converted to a floating point JavaScript. + // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + // use the JavaScript "number" type. The behavior of the default option + // JS_NORMAL is implementation dependent. + // + // This option is an enum to permit additional types to be added, e.g. + // goog.math.Integer. + optional JSType jstype = 6 [default = JS_NORMAL]; + enum JSType { + // Use the default type. + JS_NORMAL = 0; + + // Use JavaScript strings. + JS_STRING = 1; + + // Use JavaScript numbers. + JS_NUMBER = 2; + } + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outer message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + optional bool lazy = 5 [default = false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default = false]; + + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default = false]; + + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; + + reserved 4; // removed jtype +} + +message OneofOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to true to allow mapping different tag names to the same + // value. + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default = false]; + + reserved 5; // javanano_as_lite + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default = false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default = false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default = false]; + + // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + // or neither? HTTP based RPC implementation may choose GET verb for safe + // methods, and PUT verb for idempotent methods instead of the default POST. + enum IdempotencyLevel { + IDEMPOTENCY_UNKNOWN = 0; + NO_SIDE_EFFECTS = 1; // implies idempotent + IDEMPOTENT = 2; // idempotent, but may have side effects + } + optional IdempotencyLevel idempotency_level = 34 + [default = IDEMPOTENCY_UNKNOWN]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendant. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed = true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed = true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // // Detached comment for corge. This is not leading or trailing comments + // // to qux or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + // + // // ignored detached comments. + optional string leading_comments = 3; + optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; + } +} + +// Describes the relationship between generated code and its original source +// file. A GeneratedCodeInfo message is associated with only one generated +// source file, but may contain references to different source .proto files. +message GeneratedCodeInfo { + // An Annotation connects some span of text in generated code to an element + // of its generating .proto file. + repeated Annotation annotation = 1; + message Annotation { + // Identifies the element in the original source .proto file. This field + // is formatted the same as SourceCodeInfo.Location.path. + repeated int32 path = 1 [packed = true]; + + // Identifies the filesystem path to the original source .proto. + optional string source_file = 2; + + // Identifies the starting offset in bytes in the generated code + // that relates to the identified object. + optional int32 begin = 3; + + // Identifies the ending offset in bytes in the generated code that + // relates to the identified offset. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). + optional int32 end = 4; + } } diff --git a/tests/inputs/oneof/oneof.json b/tests/inputs/oneof/oneof.json index 0197c99..65cafc5 100644 --- a/tests/inputs/oneof/oneof.json +++ b/tests/inputs/oneof/oneof.json @@ -1,3 +1,3 @@ { - "count": 100 + "pitied": 100 } diff --git a/tests/inputs/oneof/oneof.proto b/tests/inputs/oneof/oneof.proto index 693e5b5..1f9c4b2 100644 --- a/tests/inputs/oneof/oneof.proto +++ b/tests/inputs/oneof/oneof.proto @@ -2,7 +2,15 @@ syntax = "proto3"; message Test { oneof foo { - int32 count = 1; - string name = 2; + int32 pitied = 1; + string pitier = 2; + } + + int32 just_a_regular_field = 3; + + oneof bar { + int32 drinks = 11; + string bar_name = 12; } } + diff --git a/tests/inputs/oneof/oneof_name.json b/tests/inputs/oneof/oneof_name.json index 45960e7..605484b 100644 --- a/tests/inputs/oneof/oneof_name.json +++ b/tests/inputs/oneof/oneof_name.json @@ -1,3 +1,3 @@ { - "name": "foobar" + "pitier": "Mr. T" }