or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

code-generation.mdenumerations.mdgrpc-services.mdindex.mdmessage-fields.mdserialization.mdutilities.md

index.mddocs/

0

# BetterProto

1

2

A modern, idiomatic Python implementation of Protocol Buffers (protobuf) and gRPC code generation that addresses limitations of the official Google protoc plugin. It generates clean, readable Python code using modern language features including dataclasses, async/await, type hints, and timezone-aware datetime objects for Python 3.6+.

3

4

## Package Information

5

6

- **Package Name**: betterproto

7

- **Language**: Python

8

- **Installation**: `pip install betterproto` (runtime) or `pip install "betterproto[compiler]"` (with code generation)

9

10

## Core Imports

11

12

```python

13

import betterproto

14

```

15

16

For message classes and field definitions:

17

18

```python

19

from betterproto import Message, Enum

20

```

21

22

For field creation functions:

23

24

```python

25

from betterproto import (

26

string_field, int32_field, bool_field, message_field,

27

enum_field, bytes_field, map_field

28

)

29

```

30

31

## Basic Usage

32

33

### Defining Messages

34

35

```python

36

from dataclasses import dataclass

37

from typing import List

38

import betterproto

39

40

@dataclass

41

class Person(betterproto.Message):

42

name: str = betterproto.string_field(1)

43

age: int = betterproto.int32_field(2)

44

email: str = betterproto.string_field(3)

45

46

@dataclass

47

class AddressBook(betterproto.Message):

48

people: List[Person] = betterproto.message_field(1)

49

```

50

51

### Serialization and Deserialization

52

53

```python

54

# Create a message

55

person = Person(name="Alice", age=30, email="alice@example.com")

56

57

# Serialize to binary

58

binary_data = bytes(person)

59

60

# Parse from binary

61

parsed_person = Person().parse(binary_data)

62

63

# JSON serialization

64

json_str = person.to_json()

65

person_from_json = Person().from_json(json_str)

66

67

# Dictionary conversion

68

person_dict = person.to_dict()

69

person_from_dict = Person().from_dict(person_dict)

70

```

71

72

### Using with gRPC

73

74

```python

75

import asyncio

76

from grpclib.client import Channel

77

import betterproto

78

79

class GreeterServiceStub(betterproto.ServiceStub):

80

async def say_hello(

81

self,

82

request: HelloRequest,

83

*,

84

timeout: Optional[float] = None,

85

deadline: Optional["Deadline"] = None,

86

metadata: Optional[betterproto._MetadataLike] = None,

87

) -> HelloReply:

88

return await self._unary_unary(

89

"/helloworld.Greeter/SayHello",

90

request,

91

HelloReply,

92

timeout=timeout,

93

deadline=deadline,

94

metadata=metadata,

95

)

96

97

async def main():

98

async with Channel("localhost", 50051) as channel:

99

greeter = GreeterServiceStub(channel)

100

reply = await greeter.say_hello(HelloRequest(name="World"))

101

print(f"Greeting: {reply.message}")

102

```

103

104

## Architecture

105

106

BetterProto's architecture consists of several key components:

107

108

- **Message Base Class**: All generated messages inherit from `betterproto.Message` providing serialization, parsing, and JSON conversion

109

- **Field Metadata System**: `FieldMetadata` dataclass stores protobuf-specific information (field numbers, types, wire formats)

110

- **Code Generator Plugin**: `betterproto.plugin` generates Python dataclasses from `.proto` files

111

- **Wire Format Handling**: Built-in varint encoding/decoding and wire type management compatible with standard protobuf

112

- **gRPC Integration**: `ServiceStub` base class for async gRPC client generation with `grpclib` support

113

114

## Capabilities

115

116

### Message Definition and Field Types

117

118

Core message functionality including field creation functions for all protobuf types, dataclass integration, and metadata handling for proper serialization and deserialization.

119

120

```python { .api }

121

class Message:

122

def __bytes__(self) -> bytes: ...

123

def parse(self, data: bytes) -> T: ...

124

def to_dict(self, casing: Casing = Casing.CAMEL, include_default_values: bool = False) -> dict: ...

125

def from_dict(self, value: dict) -> T: ...

126

def to_json(self, indent: Union[None, int, str] = None) -> str: ...

127

def from_json(self, value: Union[str, bytes]) -> T: ...

128

129

def string_field(number: int, group: Optional[str] = None) -> Any: ...

130

def int32_field(number: int, group: Optional[str] = None) -> Any: ...

131

def int64_field(number: int, group: Optional[str] = None) -> Any: ...

132

def bool_field(number: int, group: Optional[str] = None) -> Any: ...

133

def bytes_field(number: int, group: Optional[str] = None) -> Any: ...

134

def message_field(number: int, group: Optional[str] = None, wraps: Optional[str] = None) -> Any: ...

135

```

136

137

[Message and Field Types](./message-fields.md)

138

139

### Enumerations

140

141

Protobuf enumeration support with integer-based enums that provide string name conversion and integration with the message system.

142

143

```python { .api }

144

class Enum(int, enum.Enum):

145

@classmethod

146

def from_string(cls, name: str) -> int: ...

147

148

def enum_field(number: int, group: Optional[str] = None) -> Any: ...

149

```

150

151

[Enumerations](./enumerations.md)

152

153

### gRPC Service Integration

154

155

Async gRPC client stub generation with support for unary and streaming calls, timeout handling, metadata, and deadline management using grpclib.

156

157

```python { .api }

158

class ServiceStub:

159

def __init__(

160

self,

161

channel: Channel,

162

*,

163

timeout: Optional[float] = None,

164

deadline: Optional[Deadline] = None,

165

metadata: Optional[_MetadataLike] = None,

166

) -> None: ...

167

168

async def _unary_unary(

169

self,

170

route: str,

171

request: IProtoMessage,

172

response_type: Type[T],

173

*,

174

timeout: Optional[float] = None,

175

deadline: Optional[Deadline] = None,

176

metadata: Optional[_MetadataLike] = None,

177

) -> T: ...

178

```

179

180

[gRPC Service Integration](./grpc-services.md)

181

182

### Code Generation

183

184

Protocol buffer compiler plugin that generates clean Python dataclasses from .proto files with proper type hints, async gRPC stubs, and modern Python conventions.

185

186

```python { .api }

187

def main() -> None: ...

188

def generate_code(request, response) -> None: ...

189

```

190

191

[Code Generation](./code-generation.md)

192

193

### Serialization and Wire Format

194

195

Low-level serialization utilities including varint encoding/decoding, wire type handling, and binary format parsing compatible with standard protobuf implementations.

196

197

```python { .api }

198

def encode_varint(value: int) -> bytes: ...

199

def decode_varint(buffer: bytes, pos: int, signed: bool = False) -> Tuple[int, int]: ...

200

def parse_fields(value: bytes) -> Generator[ParsedField, None, None]: ...

201

def serialized_on_wire(message: Message) -> bool: ...

202

```

203

204

[Serialization and Wire Format](./serialization.md)

205

206

### Utility Functions

207

208

Helper functions for message introspection, one-of field handling, and casing conversion to support generated code and user applications.

209

210

```python { .api }

211

def which_one_of(message: Message, group_name: str) -> Tuple[str, Any]: ...

212

def safe_snake_case(value: str) -> str: ...

213

```

214

215

[Utility Functions](./utilities.md)

216

217

## Types

218

219

```python { .api }

220

@dataclass(frozen=True)

221

class FieldMetadata:

222

number: int

223

proto_type: str

224

map_types: Optional[Tuple[str, str]] = None

225

group: Optional[str] = None

226

wraps: Optional[str] = None

227

228

@dataclass(frozen=True)

229

class ParsedField:

230

number: int

231

wire_type: int

232

value: Any

233

raw: bytes

234

235

class Casing(enum.Enum):

236

CAMEL: Callable

237

SNAKE: Callable

238

239

# Type variables and aliases

240

T = TypeVar('T', bound='Message') # Bound type variable for Message subclasses

241

_Value = Union[str, bytes]

242

_MetadataLike = Union[Mapping[str, _Value], Collection[Tuple[str, _Value]]]

243

```