A better Protobuf / gRPC generator & library
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Core message functionality including field creation functions for all protobuf types, dataclass integration, and metadata handling for proper serialization and deserialization.
The Message class serves as the base for all generated protobuf messages, providing serialization, parsing, and conversion methods.
class Message:
"""
A protobuf message base class. Generated code inherits from this and
registers message fields used by serializers and parsers.
"""
def __bytes__(self) -> bytes:
"""Get the binary encoded Protobuf representation of this instance."""
def SerializeToString(self) -> bytes:
"""Compatibility alias for __bytes__."""
def parse(self, data: bytes) -> T:
"""
Parse the binary encoded Protobuf into this message instance.
Returns the instance itself for chaining.
"""
@classmethod
def FromString(cls, data: bytes) -> T:
"""Parse binary data into a new message instance (compatibility method)."""
def to_dict(
self,
casing: Casing = Casing.CAMEL,
include_default_values: bool = False
) -> dict:
"""
Convert message to dictionary representation for JSON serialization.
Args:
casing: Field name casing (CAMEL or SNAKE)
include_default_values: Include fields with default values
Returns:
Dictionary representation of the message
"""
def from_dict(self, value: dict) -> T:
"""
Parse key/value pairs into this message instance.
Returns the instance itself for chaining.
"""
def to_json(self, indent: Union[None, int, str] = None) -> str:
"""Convert message to JSON string representation."""
def from_json(self, value: Union[str, bytes]) -> T:
"""
Parse JSON into this message instance.
Returns the instance itself for chaining.
"""Functions to create dataclass fields with protobuf metadata for primitive types.
def string_field(number: int, group: Optional[str] = None) -> Any:
"""Create a string field with the given protobuf field number."""
def bool_field(number: int, group: Optional[str] = None) -> Any:
"""Create a boolean field with the given protobuf field number."""
def bytes_field(number: int, group: Optional[str] = None) -> Any:
"""Create a bytes field with the given protobuf field number."""Functions to create fields for various integer types with different encoding and size characteristics.
def int32_field(number: int, group: Optional[str] = None) -> Any:
"""Create a signed 32-bit integer field."""
def int64_field(number: int, group: Optional[str] = None) -> Any:
"""Create a signed 64-bit integer field."""
def uint32_field(number: int, group: Optional[str] = None) -> Any:
"""Create an unsigned 32-bit integer field."""
def uint64_field(number: int, group: Optional[str] = None) -> Any:
"""Create an unsigned 64-bit integer field."""
def sint32_field(number: int, group: Optional[str] = None) -> Any:
"""Create a signed 32-bit integer field with zigzag encoding."""
def sint64_field(number: int, group: Optional[str] = None) -> Any:
"""Create a signed 64-bit integer field with zigzag encoding."""
def fixed32_field(number: int, group: Optional[str] = None) -> Any:
"""Create a 32-bit fixed-width integer field."""
def fixed64_field(number: int, group: Optional[str] = None) -> Any:
"""Create a 64-bit fixed-width integer field."""
def sfixed32_field(number: int, group: Optional[str] = None) -> Any:
"""Create a signed 32-bit fixed-width integer field."""
def sfixed64_field(number: int, group: Optional[str] = None) -> Any:
"""Create a signed 64-bit fixed-width integer field."""Functions to create fields for floating-point numbers with different precision levels.
def float_field(number: int, group: Optional[str] = None) -> Any:
"""Create a 32-bit floating-point field."""
def double_field(number: int, group: Optional[str] = None) -> Any:
"""Create a 64-bit floating-point field."""Functions to create fields for messages, maps, and enums.
def message_field(
number: int,
group: Optional[str] = None,
wraps: Optional[str] = None
) -> Any:
"""
Create a nested message field.
Args:
number: Protobuf field number
group: One-of group name if this field is part of a one-of
wraps: Wrapped type for Google protobuf wrapper types
"""
def map_field(
number: int,
key_type: str,
value_type: str,
group: Optional[str] = None
) -> Any:
"""
Create a map field (dictionary in Python).
Args:
number: Protobuf field number
key_type: Protobuf type of map keys
value_type: Protobuf type of map values
group: One-of group name if this field is part of a one-of
"""
def enum_field(number: int, group: Optional[str] = None) -> Any:
"""Create an enumeration field."""The FieldMetadata class stores protobuf-specific information about fields.
@dataclass(frozen=True)
class FieldMetadata:
"""Stores internal metadata used for parsing & serialization."""
number: int # Protobuf field number
proto_type: str # Protobuf type name
map_types: Optional[Tuple[str, str]] = None # Map key/value types
group: Optional[str] = None # One-of group name
wraps: Optional[str] = None # Wrapped type for Google wrappers
@staticmethod
def get(field: dataclasses.Field) -> "FieldMetadata":
"""Returns the field metadata for a dataclass field."""The underlying function used by all field creation functions.
def dataclass_field(
number: int,
proto_type: str,
*,
map_types: Optional[Tuple[str, str]] = None,
group: Optional[str] = None,
wraps: Optional[str] = None,
) -> dataclasses.Field:
"""Creates a dataclass field with attached protobuf metadata."""from dataclasses import dataclass
import betterproto
@dataclass
class Person(betterproto.Message):
name: str = betterproto.string_field(1)
age: int = betterproto.int32_field(2)
is_active: bool = betterproto.bool_field(3)
profile_picture: bytes = betterproto.bytes_field(4)@dataclass
class Contact(betterproto.Message):
# One-of group for contact method
email: str = betterproto.string_field(1, group="contact_method")
phone: str = betterproto.string_field(2, group="contact_method")
# Check which one-of field is set
contact_type, contact_value = betterproto.which_one_of(contact, "contact_method")@dataclass
class Address(betterproto.Message):
street: str = betterproto.string_field(1)
city: str = betterproto.string_field(2)
country: str = betterproto.string_field(3)
@dataclass
class Person(betterproto.Message):
name: str = betterproto.string_field(1)
address: Address = betterproto.message_field(2)
addresses: List[Address] = betterproto.message_field(3) # Repeated field@dataclass
class PhoneBook(betterproto.Message):
# Map from string names to string phone numbers
contacts: Dict[str, str] = betterproto.map_field(1, "string", "string")
# Map from string names to Person messages
people: Dict[str, Person] = betterproto.map_field(2, "string", "message")# Protobuf type constants
TYPE_ENUM: str = "enum"
TYPE_BOOL: str = "bool"
TYPE_INT32: str = "int32"
TYPE_INT64: str = "int64"
TYPE_UINT32: str = "uint32"
TYPE_UINT64: str = "uint64"
TYPE_SINT32: str = "sint32"
TYPE_SINT64: str = "sint64"
TYPE_FLOAT: str = "float"
TYPE_DOUBLE: str = "double"
TYPE_FIXED32: str = "fixed32"
TYPE_SFIXED32: str = "sfixed32"
TYPE_FIXED64: str = "fixed64"
TYPE_SFIXED64: str = "sfixed64"
TYPE_STRING: str = "string"
TYPE_BYTES: str = "bytes"
TYPE_MESSAGE: str = "message"
TYPE_MAP: str = "map"Install with Tessl CLI
npx tessl i tessl/pypi-betterproto